From 95d84faf176abef885c40acb631e78bb0a7f4c9a Mon Sep 17 00:00:00 2001 From: sepehr Date: Thu, 2 Jan 2025 20:20:59 +0300 Subject: [PATCH] Bugs: Fixed Firmware download from the Mikrotik website when there are multiple npk available Fixed Mikrowizard system permission error when it is set to None Fixed user device group permissions Some minor UI improvements Fix IP scan for one IP scan / Fix not scanning the last IP in the range Fix manual snippet execution not working when device groups are selected Some minor bug fixes and improvements New: Show background tasks and be able to stop them while running in the background (like an IP scanner) Add support for manual MikroWizard update dashboard/settings page update to version 1.0.5 Enhancement: Show permission error in some pages when the user doesn't have permission for that page/action show better charts/graphs in the dashboard and device interface details show more info on the dashboard about update and version information and license --- src/app/app.module.ts | 4 +- .../default-header.component.html | 43 +++++++ .../default-header.component.ts | 30 ++++- .../default-layout.component.html | 32 +++++- .../default-layout.component.ts | 68 ++++++++++-- src/app/providers/mikrowizard/data.ts | 21 +++- .../views/dashboard/dashboard.component.html | 105 +++++++++++++++--- .../views/dashboard/dashboard.component.ts | 48 ++++++-- src/app/views/dashboard/dashboard.module.ts | 2 + .../views/device_detail/device.component.ts | 27 ++++- src/app/views/devices/devices.component.html | 7 +- src/app/views/devices/devices.component.ts | 93 +++++++++++++++- .../permissions/permissions.component.ts | 19 +++- .../views/settings/settings.component.html | 42 ++++--- .../views/settings/settings.component.scss | 3 + src/app/views/settings/settings.component.ts | 65 ++++++++++- .../views/snippets/snippets.component.html | 3 +- .../user_manager/user_manager.component.ts | 84 +++++++++++++- src/app/views/vault/vault.component.ts | 27 +++++ 19 files changed, 647 insertions(+), 76 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3160f40..bb74798 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -40,6 +40,7 @@ import { SidebarModule, TabsModule, UtilitiesModule, + TableModule, ModalModule } from '@coreui/angular'; @@ -85,7 +86,8 @@ export function loginStatusProviderFactory(provider: loginChecker) { CardModule, NgScrollbarModule, ModalModule, - FontAwesomeModule + FontAwesomeModule, + TableModule ], providers: [ { diff --git a/src/app/containers/default-layout/default-header/default-header.component.html b/src/app/containers/default-layout/default-header/default-header.component.html index adefb87..b83982a 100644 --- a/src/app/containers/default-layout/default-header/default-header.component.html +++ b/src/app/containers/default-layout/default-header/default-header.component.html @@ -49,6 +49,7 @@ --> + | @@ -97,3 +98,45 @@ + + + + +
    +
  • +
    Runnig Background Tasks
    +
  • +
  • + + + + + + + + + + + + + + +
    Task name
    {{i+1}}{{task.name}} + + +
    +
  • +
+
+
+ + diff --git a/src/app/containers/default-layout/default-header/default-header.component.ts b/src/app/containers/default-layout/default-header/default-header.component.ts index e957c15..cd6c204 100644 --- a/src/app/containers/default-layout/default-header/default-header.component.ts +++ b/src/app/containers/default-layout/default-header/default-header.component.ts @@ -15,6 +15,7 @@ export class DefaultHeaderComponent extends HeaderComponent { @Input() sidebarId: string = "sidebar"; @Output() UserModalEvent = new EventEmitter(); + @Output() ConfirmModalEvent = new EventEmitter(); public newMessages = new Array(4) public newTasks = new Array(5) @@ -25,7 +26,9 @@ export class DefaultHeaderComponent extends HeaderComponent { public uname: string; public fname: string; public lname: string; - public UserProfileModalVisible : boolean = false; + public ConfirmModalVisible : boolean = false; + public tasks : any = []; + public timer : any; constructor( private classToggler: ClassToggleService, @@ -53,7 +56,9 @@ export class DefaultHeaderComponent extends HeaderComponent { callParent(action:string): void { this.UserModalEvent.next(action); } - + callParentConfirm(action:string,data:any): void { + this.ConfirmModalEvent.next({action:action,data:data}); + } logout() { this.data_provider.logout().then(res => { this.router.navigate(['login']); @@ -62,6 +67,27 @@ export class DefaultHeaderComponent extends HeaderComponent { ngOnInit(): void { var _self = this; + console.log('DefaultHeaderComponent'); this.get_user_info(); + this.data_provider.get_running_tasks().then(res => { + _self.tasks = res['tasks'].filter((x:any) => x.status); + }) + // get running tasks every 5 seconds + this.timer=setInterval(function(){ + _self.get_running_tasks(); + }, 5000); } + + get_running_tasks(){ + var _self = this; + this.data_provider.get_running_tasks().then(res => { + _self.tasks = res['tasks'].filter((x:any) => x.status); + }) + } + ngOnDestroy(): void { + clearInterval(this.timer); + } + + + } diff --git a/src/app/containers/default-layout/default-layout.component.html b/src/app/containers/default-layout/default-layout.component.html index ea53bfd..83af2f0 100644 --- a/src/app/containers/default-layout/default-layout.component.html +++ b/src/app/containers/default-layout/default-layout.component.html @@ -21,7 +21,7 @@
-
@@ -105,4 +105,34 @@ Close + + + + + +
Please Confirm Stopping Background Task
+
Please Confirm Stopping Background Task
+ +
+ +
+

Are you sure you want to stop the task {{ data['name'] }}?

+
+
+ Stopping this task will cause reload of other background tasks +
+
+ Clear browser cache and Reload the page or hit Ctrl+F5 to load latest Mikrofront version +
+
+ + + + + + +
\ No newline at end of file diff --git a/src/app/containers/default-layout/default-layout.component.ts b/src/app/containers/default-layout/default-layout.component.ts index 67c1d09..8830ab9 100644 --- a/src/app/containers/default-layout/default-layout.component.ts +++ b/src/app/containers/default-layout/default-layout.component.ts @@ -6,6 +6,7 @@ import { navItems } from './_nav'; import { dataProvider } from '../../providers/mikrowizard/data'; import { arch } from 'os'; import { DomSanitizer } from '@angular/platform-browser'; +import { disconnect } from 'process'; @Component({ selector: 'app-dashboard', @@ -23,11 +24,14 @@ export class DefaultLayoutComponent implements OnInit { public ispro: boolean=false; public action: string="password"; public UserProfileModalVisible:boolean; + public ConfirmModalVisible:boolean; public error:any=false; public currentStep:number=1; public qrCode:any=false; public totpCode:string=''; public errorMessage:any=false; + public data:any={}; + public timer:any; public password:any={ 'cupass':'', 'pass1':'', @@ -130,7 +134,41 @@ export class DefaultLayoutComponent implements OnInit { else this.UserProfileModalVisible = true; } - + show_confirm_modal(data:any){ + this.data={}; + if (data.action=='CancelTask'){ + this.action=data.action; + this.data=data.data; + console.dir(this.data); + console.dir(this.action); + //disable submit button + this.data['SubmitDisable']=false; + this.ConfirmModalVisible = true; + } + if (data.action=='update'){ + this.action='update'; + this.data={}; + this.ConfirmModalVisible = true; + } + } + ConfirmAction(){ + var _self=this; + if(this.action=='CancelTask'){ + this.data_provider.stop_task(this.data['signal']).then(res => { + //disable submit button + if(res['status']=='success'){ + setTimeout(function () { + _self.ConfirmModalVisible = false; + }, 5000); + } + this.data['SubmitDisable']=true; + //wait 5 seconds before hiding the modal + }) + } + if(this.action=='update'){ + window.location.href = window.location.href.replace(/#.*$/, '') + } + } submit(){ var _self=this; if(!_self.passvalid['pass2']){ @@ -190,12 +228,28 @@ export class DefaultLayoutComponent implements OnInit { } }); }); - _self.data_provider.get_front_version().then((res:any) => { - if(res['version']!=this.version){ - console.dir("New version is available. Please refresh the page."); - window.location.href = window.location.href.replace(/#.*$/, ''); - } - }); + // check first time after 10 seconds + setTimeout(function(){ + _self.data_provider.get_front_version().then((res:any) => { + if(res['version']!=_self.version){ + console.log("New version is available. Please refresh the page."); + _self.show_confirm_modal({action:'update'}); + // window.location.href = window.location.href.replace(/#.*$/, ''); + } + }); + }, 10000); + // check for new version every 5 seconds + this.timer=setInterval(function(){ + _self.data_provider.get_front_version().then((res:any) => { + if(res['version']!=_self.version){ + console.log("New version is available. Please refresh the page."); + _self.show_confirm_modal({action:'update'}); + // window.location.href = window.location.href.replace(/#.*$/, ''); + } + }); + }, 60000); + } + clearTimer() { clearInterval(this.timer); } } diff --git a/src/app/providers/mikrowizard/data.ts b/src/app/providers/mikrowizard/data.ts index 8553378..b80fbb0 100644 --- a/src/app/providers/mikrowizard/data.ts +++ b/src/app/providers/mikrowizard/data.ts @@ -70,9 +70,10 @@ export class dataProvider { } return this.MikroWizardRPC.sendJsonRequest("/api/user/change_password", data); } - dashboard_stats(versioncheck:boolean){ + dashboard_stats(versioncheck:boolean,front_version:string){ var data={ - 'versioncheck':versioncheck + 'versioncheck':versioncheck, + 'front_version':front_version } return this.MikroWizardRPC.sendJsonRequest("/api/dashboard/stats", data); } @@ -537,7 +538,21 @@ export class dataProvider { return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/save_all", data); } - + get_running_tasks(){ + return this.MikroWizardRPC.sendJsonRequest("/api/tasks/list", {}); + } + stop_task(signal:number){ + var data={ + 'signal':signal + } + return this.MikroWizardRPC.sendJsonRequest("/api/tasks/stop", data); + } + apply_update(action:string){ + var data={ + 'action':action + } + return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/apply_update", data); + } //// //// End api funcs //// diff --git a/src/app/views/dashboard/dashboard.component.html b/src/app/views/dashboard/dashboard.component.html index 2dcc8a7..fb8a721 100644 --- a/src/app/views/dashboard/dashboard.component.html +++ b/src/app/views/dashboard/dashboard.component.html @@ -125,29 +125,72 @@ - - + +
- Serial: {{ stats['serial'] }} - Copy +

Version and Serial information

+
- Not Registred OR Not internet access +
+ Serial: {{ stats['serial'] }} + Copy +
+ Not Registred Learn how to register and get automatic updates!
-
+
+ Unable connect to server/Check server internet connection +
+
+
+ Serial: {{ stats['serial'] }} + Copy +
Registred License Type : {{stats['license']}} + Manual update + Auto update
- +
+ Your Mikroman version : {{stats['version']}} + + + + + Your Mikrofront version : {{front_version}} + + + + +
+ + - - - + + @@ -165,4 +208,38 @@ - \ No newline at end of file + + + + +
Please Confirm Mikroman Update
+
Please Confirm MikroFront Update
+ +
+ +
+

Are you sure you want to apply latest Mikroman Update ver {{ stats['latest_version'] }}?

+

By updating Mikroman the MikroFront update is also get checked and applyed

+

If you made any special changes to configuration files or python files it will be removed automaticlaly

+
+
+ Applying the update will cause reload of the server couple of times +
+
+

Are you sure you want to apply latest MikroFront Update ver {{ stats['front_latest_version'] }}?

+
+
+ Applying the update will cause reload of the page,
+ Also please make sure you have the latest Mikroman before updating MikroFront. + Updating to latest MikroFront without getting latest Mikroman can cause problems
+
+
+ + + + +
\ No newline at end of file diff --git a/src/app/views/dashboard/dashboard.component.ts b/src/app/views/dashboard/dashboard.component.ts index 3d2099c..f5cc1a7 100644 --- a/src/app/views/dashboard/dashboard.component.ts +++ b/src/app/views/dashboard/dashboard.component.ts @@ -14,6 +14,9 @@ export class DashboardComponent implements OnInit { public uname: string; public tz: string; public copy_msg: any = false; + public ConfirmModalVisible: boolean = false; + public action: string = ""; + front_version=require('../../../../package.json').version; constructor( private data_provider: dataProvider, private router: Router, @@ -41,7 +44,9 @@ export class DashboardComponent implements OnInit { trafficRadio: new UntypedFormControl("5m"), }); public chart_data: any = {}; - Chartoptions = { + + public Chartoptions = { + responsive: true, plugins: { tooltip: { callbacks: { @@ -87,17 +92,17 @@ export class DashboardComponent implements OnInit { stacked: true, position: "left", type: "linear", - color: "#17522f", + color: "#4caf50", grid: { - color: "rgba(23, 82, 47, 0.3)", + color: "rgba(76, 175, 79, 0.3)", backgroundColor: "transparent", - borderColor: "#f86c6b", - pointHoverBackgroundColor: "#f86c6b", + borderColor: "#4caf50", + pointHoverBackgroundColor: "#4caf50", borderWidth: 1, borderDash: [8, 5], }, ticks: { - color: "#17522f", + color: "#000000", callback: function (value: any, index: any, ticks: any) { const units = ["bit", "Kib", "Mib", "Gib", "Tib"]; var res = value; @@ -119,10 +124,10 @@ export class DashboardComponent implements OnInit { position: "right", type: "linear", grid: { - color: "rgba(23, 82, 47, 0.3)", + color: "rgba(255, 152, 0, 0.4)", backgroundColor: "transparent", - borderColor: "#f86c6b", - pointHoverBackgroundColor: "#f86c6b", + borderColor: "#ff9800", + pointHoverBackgroundColor: "#ff9800", borderWidth: 1, borderDash: [8, 5], }, @@ -130,7 +135,7 @@ export class DashboardComponent implements OnInit { width: 2, }, ticks: { - color: "#171951", + color: "#000000", callback: function (value: any, index: any, ticks: any) { const units = ["bit", "Kib", "Mib", "Gib", "Tib"]; var res = value; @@ -147,7 +152,7 @@ export class DashboardComponent implements OnInit { elements: { line: { borderWidth: 1, - tension: 0.4, + tension: 0.1, }, point: { radius: 2, @@ -181,7 +186,7 @@ export class DashboardComponent implements OnInit { } initStats() { var _self = this; - this.data_provider.dashboard_stats(true).then((res) => { + this.data_provider.dashboard_stats(true,this.front_version).then((res) => { _self.stats = res; }); } @@ -200,4 +205,23 @@ export class DashboardComponent implements OnInit { this.delta = value; this.initTrafficChart(); } + showConfirmModal(action: string) { + this.action = action; + this.ConfirmModalVisible = true + } + ConfirmAction() { + var _self = this; + this.data_provider.apply_update(this.action).then((res) => { + if (res["status"]=='success') { + if (_self.action=='update_mikroman') { + _self.stats['update_inprogress']=true; + } + if (_self.action=='update_mikrofront') { + _self.stats['front_update_inprogress']=true; + } + _self.action=""; + _self.ConfirmModalVisible = false; + } + }); + } } diff --git a/src/app/views/dashboard/dashboard.module.ts b/src/app/views/dashboard/dashboard.module.ts index c605424..20a6600 100644 --- a/src/app/views/dashboard/dashboard.module.ts +++ b/src/app/views/dashboard/dashboard.module.ts @@ -11,6 +11,7 @@ import { ProgressModule, TemplateIdDirective, BadgeModule, + ModalModule, CarouselModule, } from "@coreui/angular"; @@ -37,6 +38,7 @@ import { ClipboardModule } from "@angular/cdk/clipboard"; CarouselModule, BadgeModule, ClipboardModule, + ModalModule, ], declarations: [DashboardComponent], }) diff --git a/src/app/views/device_detail/device.component.ts b/src/app/views/device_detail/device.component.ts index d77c1e4..64ab631 100644 --- a/src/app/views/device_detail/device.component.ts +++ b/src/app/views/device_detail/device.component.ts @@ -123,8 +123,9 @@ export class DeviceComponent implements OnInit, OnDestroy { type: GuiRowSelectionType.CHECKBOX, mode: GuiRowSelectionMode.MULTIPLE, }; - Chartoptions = { + responsive: true, + _self :this, plugins: { tooltip: { callbacks: { @@ -164,7 +165,19 @@ export class DeviceComponent implements OnInit, OnDestroy { }, maintainAspectRatio: true, scales: { - x: { display: false }, + x: { + + title: { + display: true, + text: 'Time', + color: '#333', + }, + ticks: { + autoSkip: true, + maxTicksLimit: 30, + color: '#333', + } + }, yA: { display: true, stacked: true, @@ -177,7 +190,9 @@ export class DeviceComponent implements OnInit, OnDestroy { }, ticks: { color: "#17522f", - callback: function (value: any, index: any, ticks: any) { + callback: (value: any) => { + if(this.total_type=="pps") + return value + " pps"; const units = ["bit", "Kib", "Mib", "Gib", "Tib"]; var res = value; let unitIndex = 0; @@ -206,7 +221,9 @@ export class DeviceComponent implements OnInit, OnDestroy { }, ticks: { color: "#171951", - callback: function (value: any, index: any, ticks: any) { + callback: (value: any) =>{ + if(this.total_type=="pps") + return value + " pps"; const units = ["bit", "Kib", "Mib", "Gib", "Tib"]; var res = value; let unitIndex = 0; @@ -222,7 +239,7 @@ export class DeviceComponent implements OnInit, OnDestroy { elements: { line: { borderWidth: 1, - tension: 0.4, + tension: 0.1, }, point: { radius: 4, diff --git a/src/app/views/devices/devices.component.html b/src/app/views/devices/devices.component.html index 5a8cf61..cfc5f75 100644 --- a/src/app/views/devices/devices.component.html +++ b/src/app/views/devices/devices.component.html @@ -265,12 +265,11 @@ -
Editing Group
+
Scan History :
-
Group Members :
  {{value}} - - + +   {{value}} diff --git a/src/app/views/devices/devices.component.ts b/src/app/views/devices/devices.component.ts index 8ce0f7f..edb012b 100644 --- a/src/app/views/devices/devices.component.ts +++ b/src/app/views/devices/devices.component.ts @@ -194,7 +194,7 @@ export class DevicesComponent implements OnInit, OnDestroy { this.selected_device = dev; this.data_provider.get_editform(dev.id).then((res) => { if ("error" in res) { - if (res.error.indexOf("Unauthorized")) { + if ("error" in res && res.error.indexOf("Unauthorized")) { _self.show_toast( "Error", "You are not authorized to perform this action", @@ -230,8 +230,17 @@ export class DevicesComponent implements OnInit, OnDestroy { var _self = this; this.ConfirmModalVisible = false; this.data_provider.delete_devices(this.Selectedrows).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.show_toast("Success", "Device Deleted", "success"); this.initGridTable(); + } }); } @@ -314,6 +323,14 @@ export class DevicesComponent implements OnInit, OnDestroy { }); } } + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else _self.scanwizard_step = step; }); } @@ -357,11 +374,20 @@ export class DevicesComponent implements OnInit, OnDestroy { this.data_provider .check_firmware(this.Selectedrows.toString()) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.show_toast("info", "Checking Firmwares", "light"); _self.ConfirmModalVisible = false; setTimeout(function () { if (_self.Selectedrows.length < 1) _self.initGridTable(); }, 1); + } }); } @@ -370,8 +396,16 @@ export class DevicesComponent implements OnInit, OnDestroy { this.data_provider .update_firmware(this.Selectedrows.toString()) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.show_toast("info", "Updating Firmwares Sent", "light"); - _self.initGridTable(); + _self.initGridTable();} }); } @@ -380,8 +414,17 @@ export class DevicesComponent implements OnInit, OnDestroy { this.data_provider .upgrade_firmware(this.Selectedrows.toString()) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.show_toast("info", "Upgrading Firmwares", "light"); _self.initGridTable(); + } }); } @@ -390,19 +433,37 @@ export class DevicesComponent implements OnInit, OnDestroy { this.data_provider .reboot_devices(this.Selectedrows.toString()) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.show_toast("info", "Reboot sent", "light"); _self.ConfirmModalVisible = !_self.ConfirmModalVisible; _self.initGridTable(); + } }); } get_groups() { var _self = this; this.data_provider.get_devgroup_list().then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ if( "status" in res && res.status == 'failed' ) _self.groups = false else _self.groups = res; + } }); } @@ -417,6 +478,14 @@ export class DevicesComponent implements OnInit, OnDestroy { }; _self.data_provider.get_dev_list(data).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.source = res.map((x: any) => { if (x.upgrade_availble) _self.upgrades.push(x); if (x.update_availble) _self.updates.push(x); @@ -424,6 +493,7 @@ export class DevicesComponent implements OnInit, OnDestroy { }); _self.device_interval(); _self.loading = false; + } }); } @@ -516,8 +586,17 @@ export class DevicesComponent implements OnInit, OnDestroy { _self.selected_device['editform']['password']="Loading ..."; if (_self.ispro && !this.show_pass){ _self.data_provider.get_device_pass(this.selected_device['id']).then((res) => { + if ("error" in res && "error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.selected_device['editform']['password']=res['password']; this.show_pass=!this.show_pass; + } }); } else{ @@ -530,7 +609,14 @@ export class DevicesComponent implements OnInit, OnDestroy { this.data_provider .scan_results() .then((res) => { - console.dir(res); + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ let index = 1; _self.ExecutedData= res.data.map((d: any) => { d.index = index; @@ -551,6 +637,7 @@ export class DevicesComponent implements OnInit, OnDestroy { index += 1; return d; }); + } }); } diff --git a/src/app/views/permissions/permissions.component.ts b/src/app/views/permissions/permissions.component.ts index d8fac73..1ce6ac0 100644 --- a/src/app/views/permissions/permissions.component.ts +++ b/src/app/views/permissions/permissions.component.ts @@ -225,17 +225,26 @@ export class PermissionsComponent implements OnInit { } else { var _self = this; this.data_provider.delete_perm(_self.SelectedPerm["id"]).then((res) => { - if (res["status"] == "failed") { + if ("error" in res && res.error.indexOf("Unauthorized")) { _self.show_toast( "Error", - res.err, + "You are not authorized to perform this action", "danger" ); - return; } else{ - _self.initGridTable(); - _self.DeleteConfirmModalVisible = false; + if (res["status"] == "failed") { + _self.show_toast( + "Error", + res.err, + "danger" + ); + return; + } + else{ + _self.initGridTable(); + _self.DeleteConfirmModalVisible = false; + } } }); } diff --git a/src/app/views/settings/settings.component.html b/src/app/views/settings/settings.component.html index b0cc3a5..d3fe44e 100644 --- a/src/app/views/settings/settings.component.html +++ b/src/app/views/settings/settings.component.html @@ -72,7 +72,7 @@ - + * Choose how Mikrowizard should update old v6 firmwares
@@ -85,7 +85,7 @@ - + * The version of firmware to install routers @@ -97,7 +97,7 @@ - + * The version of firmware to install on V6 routers @@ -112,7 +112,7 @@ Rad Secret - + * Radius Secret of Mikrowizard Radius Server @@ -121,7 +121,7 @@ System URL - + * Default system access URl @@ -129,7 +129,7 @@ Default IP - + * Default Mikrowizard Access IP @@ -146,7 +146,7 @@ - + * Default TimeZone for the system @@ -157,20 +157,34 @@ Default password - + * Default username and Password for searching new devices + + + + + + * Choose if Mikrowizard should download updates automaticaly when availble or wait for user to download/apply updates + + License Username - + * The username that you registred in Mikrowizard.com,Required for License Activation - + * Force User Groups under user>groups configuration of each router to match Mikrowizard Permissions and monitor for any change to prevent/fix the configuration. @@ -178,7 +192,7 @@ - + * Force Radius config under radius>client and user>aaa setting of each router that added to Mikrowizard and monitor for any change to prevent/fix the configuration. @@ -186,7 +200,7 @@ - + * Force Syslog config under system>logs setting of each router that added to Mikrowizard and monitor syslog setting for any change to prevent/fix the configuration. @@ -194,7 +208,7 @@ - PRO + PRO * Download and install reqired firmware before installing the target firmware . for example it will install latest 7.12 then upgrade to newer version >7.13 or install Required packages before update @@ -202,7 +216,7 @@ - PRO + PRO * Force login to devices using otp for all users.(you can make exceptions for each user) diff --git a/src/app/views/settings/settings.component.scss b/src/app/views/settings/settings.component.scss index 0185fbf..897c549 100644 --- a/src/app/views/settings/settings.component.scss +++ b/src/app/views/settings/settings.component.scss @@ -7,4 +7,7 @@ } .mdc-line-ripple.mdc-line-ripple--deactivating.ng-star-inserted { display: none!important; +} +.form-check-label{ + font-weight: bold; } \ No newline at end of file diff --git a/src/app/views/settings/settings.component.ts b/src/app/views/settings/settings.component.ts index 394a771..5501013 100644 --- a/src/app/views/settings/settings.component.ts +++ b/src/app/views/settings/settings.component.ts @@ -22,7 +22,6 @@ import { import { ToasterComponent } from "@coreui/angular"; import { AppToastComponent } from "../toast-simple/toast.component"; import { TimeZones } from "./timezones-data"; -import { error } from "console"; @Component({ templateUrl: "settings.component.html", @@ -137,6 +136,14 @@ export class SettingsComponent implements OnInit { _self.currentFirm=firm; if(del){ this.data_provider.delete_firm(this.currentFirm.id).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ if (res.status == true){ _self.DeleteConfirmModalVisible=false; _self.initFirmsTable(); @@ -148,6 +155,7 @@ export class SettingsComponent implements OnInit { "danger" ); } + } }); } else @@ -160,6 +168,14 @@ export class SettingsComponent implements OnInit { this.data_provider .download_firmware_to_repository(this.firmtodownload) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ if (res.status == true) { // show toast that we are already downloading _self.show_toast( @@ -177,6 +193,7 @@ export class SettingsComponent implements OnInit { } _self.ConfirmModalVisible = !_self.ConfirmModalVisible; _self.loading = false; + } }); } @@ -204,14 +221,34 @@ export class SettingsComponent implements OnInit { this.firmwaretoinstallv6 ) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.initFirmsTable(); + } }); } saveSysSetting() { var _self = this; this.data_provider.save_sys_setting(this.sysconfigs).then((res) => { - _self.initsettings(); + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ + _self.show_toast("Settings", "Settings saved", "success"); + _self.initsettings(); + + } }); } @@ -244,6 +281,14 @@ export class SettingsComponent implements OnInit { initsettings(): void { var _self = this; this.data_provider.get_settings().then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.sysconfigs = res.sysconfigs; _self.sysconfigs["default_user"]["value"] = ""; _self.sysconfigs["default_password"]["value"] = ""; @@ -265,7 +310,23 @@ export class SettingsComponent implements OnInit { _self.sysconfigs["otp_force"]["value"] ); } + //check if update_mode is in the sysconfigs + if ("update_mode" in _self.sysconfigs){ + //convert string to json + _self.sysconfigs["update_mode"]["value"] = JSON.parse(_self.sysconfigs["update_mode"]["value"]); + } + else{ + //create default update_mode and set mode to auto + _self.sysconfigs["update_mode"] = { + "value": { + "mode": "auto", + "update_back" : false, + "update_front" : false + } + } + } _self.SysConfigloading = false; + } }); } diff --git a/src/app/views/snippets/snippets.component.html b/src/app/views/snippets/snippets.component.html index 2b68c32..4b3d199 100644 --- a/src/app/views/snippets/snippets.component.html +++ b/src/app/views/snippets/snippets.component.html @@ -159,12 +159,11 @@ -
Editing Group
+
Exec history
-
Group Members :
{ + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ if ("id" in res && !("status" in res)) { _self.initGridTable(); this.EditTaskModalVisible = false; @@ -178,6 +186,7 @@ export class UserManagerComponent implements OnInit { //show error _self.show_toast("Error", res.err, "danger"); } + } }); } else { if (_self.userperms.length > 0) { @@ -187,8 +196,17 @@ export class UserManagerComponent implements OnInit { } _self.SelectedUser["adminperms"] = _self.adminperms; this.data_provider.edit_user(_self.SelectedUser).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.initGridTable(); _self.EditTaskModalVisible = false; + } }); } // @@ -197,14 +215,32 @@ export class UserManagerComponent implements OnInit { editAddUser(item: any, action: string) { var _self = this; this.data_provider.get_perms(1, 1000, "").then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.allPerms = res.map((x: any) => { return { id: x["id"], name: x.name }; }); _self.data_provider.get_devgroup_list().then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.allDevGroups = res.map((x: any) => { return { id: x["id"], name: x.name }; }); + } }); + } }); if (action == "showadd") { this.userperms = []; @@ -241,7 +277,6 @@ export class UserManagerComponent implements OnInit { this.data_provider.get_user_restrictions(this.SelectedUser["id"]).then((res) => { _self.userresttrictions = res; - console.log(_self.userresttrictions); _self.RestrictionsTaskModalVisible = true; }); } @@ -270,13 +305,23 @@ export class UserManagerComponent implements OnInit { } save_sec(){ + var _self=this; this.data_provider.save_user_restrictions(this.SelectedUser.id,this.userresttrictions).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ if('status' in res && res['status']=='success') this.RestrictionsTaskModalVisible = false; else if('status' in res && res['status']=='failed') this.show_toast("Error", res.err, "danger"); else this.show_toast("Error", "Somthing went wrong", "danger"); + } }); } @@ -289,9 +334,18 @@ export class UserManagerComponent implements OnInit { this.devgroup["id"] ) .then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.get_user_perms(_self.SelectedUser["id"]); _self.permission = 0; _self.devgroup = 0; + } }); } @@ -314,8 +368,17 @@ export class UserManagerComponent implements OnInit { } else { var _self = this; this.data_provider.delete_user(_self.SelectedUser["id"]).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.initGridTable(); _self.DeleteConfirmModalVisible = false; + } }); } } @@ -329,8 +392,18 @@ export class UserManagerComponent implements OnInit { } confirm_delete_perm(item: any) { + var _self = this; this.data_provider.Delete_user_perm(item.id).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ this.get_user_perms(this.SelectedUser["id"]); + } }); } @@ -344,11 +417,20 @@ export class UserManagerComponent implements OnInit { var pageSize = 10; var searchstr = ""; this.data_provider.get_users(page, pageSize, searchstr).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.source = res.map((x: any) => { return x; }); _self.SelectedUser = {}; _self.loading = false; + } }); } } diff --git a/src/app/views/vault/vault.component.ts b/src/app/views/vault/vault.component.ts index acf81ee..861e550 100644 --- a/src/app/views/vault/vault.component.ts +++ b/src/app/views/vault/vault.component.ts @@ -201,6 +201,14 @@ export class VaultComponent implements OnInit { get_passwords(){ var _self=this; this.data_provider.get_passwords(this.filters).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.passwords=res.data.map((d: any) => { d.changed = formatInTimeZone( d.changed.split(".")[0] + ".000Z", @@ -209,6 +217,7 @@ export class VaultComponent implements OnInit { ); return d; }); + } }); } @@ -216,8 +225,17 @@ export class VaultComponent implements OnInit { var _self=this; _self.password=""; this.data_provider.reveal_password(devid,username).then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ _self.password=res.password; _self.PasswordModalVisible=true; + } }); } @@ -255,6 +273,14 @@ export class VaultComponent implements OnInit { get_vault_history(){ var _self=this; this.data_provider.vault_history().then((res) => { + if ("error" in res && res.error.indexOf("Unauthorized")) { + _self.show_toast( + "Error", + "You are not authorized to perform this action", + "danger" + ); + } + else{ let index = 1; _self.vault_history=res.data.map((d: any) => { d.index = index; @@ -275,6 +301,7 @@ export class VaultComponent implements OnInit { index += 1; return d; }); + } }); }