diff --git a/angular.json b/angular.json index 739942a..817e16e 100644 --- a/angular.json +++ b/angular.json @@ -61,7 +61,7 @@ { "type": "anyComponentStyle", "maximumWarning": "2kb", - "maximumError": "6kb" + "maximumError": "10kb" } ], "outputHashing": "all" diff --git a/package.json b/package.json index 8c63917..b2355b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "MikroWizard", - "version": "1.2.0", + "version": "1.3.0", "copyright": "MikroWizard mikrowizard.com", "license": "AGPL", "author": "MikroWizard Team (https://github.com/MikroWizard)", @@ -19,17 +19,17 @@ }, "private": true, "dependencies": { - "@angular/animations": "^17.3.5", + "@angular/animations": "^18.2.14", "@angular/cdk": "^16.2.9", - "@angular/common": "^17.3.5", - "@angular/compiler": "^17.3.5", - "@angular/core": "^17.3.5", - "@angular/forms": "^17.3.5", - "@angular/language-service": "^17.3.5", + "@angular/common": "^18.2.14", + "@angular/compiler": "^18.2.14", + "@angular/core": "^18.2.14", + "@angular/forms": "^18.2.14", + "@angular/language-service": "^18.2.14", "@angular/material": "^17.3.5", - "@angular/platform-browser": "^17.3.5", - "@angular/platform-browser-dynamic": "^17.3.5", - "@angular/router": "^17.3.5", + "@angular/platform-browser": "^18.2.14", + "@angular/platform-browser-dynamic": "^18.2.14", + "@angular/router": "^18.2.14", "@coreui/angular": "~4.5.27", "@coreui/angular-chartjs": "~4.5.27", "@coreui/chartjs": "^3.1.2", @@ -42,6 +42,7 @@ "@generic-ui/fabric": "^0.19.0", "@generic-ui/hermes": "^0.19.0", "@generic-ui/ngx-grid": "^0.19.0", + "@primeuix/themes": "^2.0.3", "chart.js": "^3.9.1", "date-fns": "^3.6.0", "date-fns-jalali": "^3.6.0-0", @@ -61,17 +62,21 @@ "ngx-material-date-fns-adapter": "^18.0.0", "ngx-scrollbar": "^13.0.3", "ngx-super-select": "^3.17.0", + "primeicons": "^7.0.0", + "primeng": "^18.0.2", "rxjs": "~7.8.1", "tslib": "^2.3.0", "vis-data": "^7.1.9", "vis-network": "^9.1.9", - "zone.js": "~0.14.4" + "vis-util": "^6.0.0", + "zone.js": "~0.14.10" }, "devDependencies": { - "@angular-devkit/build-angular": "^17.3.5", - "@angular/cli": "^17.3.5", - "@angular/compiler-cli": "^17.3.5", - "@angular/localize": "^17.3.5", + "@angular-devkit/build-angular": "^18.2.21", + "@angular/cli": "^18.2.21", + "@angular/compiler-cli": "^18.2.14", + "@angular/localize": "^18.2.14", + "@types/hammerjs": "^2.0.46", "@types/jasmine": "^5.1.1", "@types/lodash-es": "^4.17.10", "@types/node": "^18.19.34", @@ -87,4 +92,4 @@ "node": "^16.14.0 || ^18.10.0", "npm": ">= 6" } -} +} \ No newline at end of file diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 2b30133..3aa9983 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -69,6 +69,11 @@ const routes: Routes = [ loadChildren: () => import('./views/syslog/syslog.module').then((m) => m.SyslogModule) }, + { + path: 'syslog-regex', + loadChildren: () => + import('./views/syslog-regex/syslog-regex.module').then((m) => m.SyslogRegexModule) + }, { path: 'backups', loadChildren: () => @@ -99,6 +104,11 @@ const routes: Routes = [ loadChildren: () => import('./views/snippets/snippets.module').then((m) => m.SnippetsModule) }, + { + path: 'sequences', + loadChildren: () => + import('./views/sequences/sequences.module').then((m) => m.SequencesModule) + }, { path: 'user_manager', loadChildren: () => @@ -109,6 +119,11 @@ const routes: Routes = [ loadChildren: () => import('./views/permissions/permissions.module').then((m) => m.PermissionsModule) }, + { + path: 'vpn', + loadChildren: () => + import('./views/vpn/vpn.module').then((m) => m.VpnModule) + }, { path: 'pages', loadChildren: () => @@ -137,7 +152,7 @@ const routes: Routes = [ title: 'Login Page' } }, - {path: '**', redirectTo: 'dashboard'} + { path: '**', redirectTo: 'dashboard' } ]; @NgModule({ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index bb74798..5f63543 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -2,10 +2,15 @@ import { NgModule ,APP_INITIALIZER} from '@angular/core'; import { HashLocationStrategy, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { BrowserModule, Title } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { providePrimeNG } from 'primeng/config'; +import Aura from '@primeuix/themes/aura'; import { ReactiveFormsModule,FormsModule } from '@angular/forms'; import { NgScrollbarModule } from 'ngx-scrollbar'; -import { HttpClientModule } from '@angular/common/http'; +import { provideHttpClient, withInterceptorsFromDi, HTTP_INTERCEPTORS } from '@angular/common/http'; +import { LicenseService } from './providers/license.service'; +import { LicenseInterceptor } from './providers/license-interceptor.service'; // Import routing module import { AppRoutingModule } from './app-routing.module'; @@ -54,60 +59,69 @@ const APP_CONTAINERS = [ export function loginStatusProviderFactory(provider: loginChecker) { return () => provider.load(); } -@NgModule({ - declarations: [AppComponent, ...APP_CONTAINERS], - imports: [ - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, - AvatarModule, - BreadcrumbModule, - FooterModule, - DropdownModule, - GridModule, - HeaderModule, - SidebarModule, - IconModule, - NavModule, - HttpClientModule, - ButtonModule, - FormModule, - UtilitiesModule, - ButtonGroupModule, - ReactiveFormsModule, - FormsModule, - SidebarModule, - SharedModule, - TabsModule, - ListGroupModule, - ProgressModule, - BadgeModule, - ListGroupModule, - CardModule, - NgScrollbarModule, - ModalModule, - FontAwesomeModule, - TableModule - ], - providers: [ - { - provide: LocationStrategy, - useClass: HashLocationStrategy - }, - MikroWizardProvider, - dataProvider, - loginChecker, - IconSetService, - provideDateFnsAdapter(), - { - provide: APP_INITIALIZER, - useFactory: loginStatusProviderFactory, - deps: [loginChecker], - multi: true, - }, - Title - ], - bootstrap: [AppComponent] -}) +@NgModule({ declarations: [AppComponent, ...APP_CONTAINERS], + bootstrap: [AppComponent], imports: [BrowserModule, + BrowserAnimationsModule, + AppRoutingModule, + AvatarModule, + BreadcrumbModule, + FooterModule, + DropdownModule, + GridModule, + HeaderModule, + SidebarModule, + IconModule, + NavModule, + ButtonModule, + FormModule, + UtilitiesModule, + ButtonGroupModule, + ReactiveFormsModule, + FormsModule, + SidebarModule, + SharedModule, + TabsModule, + ListGroupModule, + ProgressModule, + BadgeModule, + ListGroupModule, + CardModule, + NgScrollbarModule, + ModalModule, + FontAwesomeModule, + TableModule], providers: [ + { + provide: LocationStrategy, + useClass: HashLocationStrategy + }, + MikroWizardProvider, + dataProvider, + loginChecker, + IconSetService, + provideDateFnsAdapter(), + provideAnimationsAsync(), + providePrimeNG({ + theme: { + preset: Aura, + options: { + darkModeSelector: 'none' + } + } + }), + { + provide: APP_INITIALIZER, + useFactory: loginStatusProviderFactory, + deps: [loginChecker], + multi: true, + }, + Title, + LicenseService, + { + provide: HTTP_INTERCEPTORS, + useClass: LicenseInterceptor, + multi: true + }, + provideHttpClient(withInterceptorsFromDi()) + ] }) export class AppModule { } diff --git a/src/app/containers/default-layout/_nav.ts b/src/app/containers/default-layout/_nav.ts index 00c76ce..ef78bee 100644 --- a/src/app/containers/default-layout/_nav.ts +++ b/src/app/containers/default-layout/_nav.ts @@ -5,18 +5,24 @@ export const navItems: INavData[] = [ name: 'Dashboard', url: '/dashboard', iconComponent: { name: 'cil-speedometer' }, - + }, { name: 'Monitoring Wall', url: '/monitoring', - icon:'fa-solid fa-tv', - attributes: { 'pro':true } + icon: 'fa-solid fa-tv', + attributes: { 'pro': true } }, { title: true, name: 'Device Managment' }, + { + name: 'WireGuard Server', + url: '/vpn', + icon: 'fa-solid fa-network-wired', + attributes: { 'pro': true } + }, { name: 'Devices', url: '/devices', @@ -31,8 +37,8 @@ export const navItems: INavData[] = [ { name: 'Network Maps', url: '/maps', - icon:'fa-solid fa-map', - attributes: { 'pro':true } + icon: 'fa-solid fa-map', + attributes: { 'pro': true } }, // { // name: 'Tools', @@ -70,18 +76,24 @@ export const navItems: INavData[] = [ url: '/snippets', icon: 'fa-solid fa-code' }, + { + name: 'Sequences', + url: '/sequences', + icon: 'fa-solid fa-code-branch', + attributes: { 'pro': true } + }, { name: 'Sync and Cloner', url: '/cloner', icon: 'fa-solid fa-rotate', - attributes: { 'pro':true } + attributes: { 'pro': true } }, { name: 'Password Vault', url: '/vault', - icon:'fa-solid fa-vault', - attributes: { 'pro':true } + icon: 'fa-solid fa-vault', + attributes: { 'pro': true } }, // { // name: 'Tools', @@ -133,6 +145,12 @@ export const navItems: INavData[] = [ icon: 'fa-solid fa-person-circle-question', }, + { + name: 'Syslog Custom Regex', + url: '/syslog-regex', + icon: 'fa-solid fa-code-commit', + attributes: { 'pro': true } + }, { title: true, name: 'Users' @@ -140,12 +158,12 @@ export const navItems: INavData[] = [ { name: 'Users Management', url: '/user_manager', - icon: 'fa-solid fa-user-gear' , + icon: 'fa-solid fa-user-gear', }, { name: 'Permissions', url: '/permissions', - icon: 'fa-solid fa-users' , + icon: 'fa-solid fa-users', }, { title: true, @@ -155,7 +173,7 @@ export const navItems: INavData[] = [ { name: 'Settings', url: '/settings', - icon: 'fa-solid fa-gear' , + icon: 'fa-solid fa-gear', }, // { // name: 'Backup', @@ -177,7 +195,7 @@ export const navItems: INavData[] = [ { name: 'Buy Pro', url: 'https://mikrowizard.com/pricing/', - icon:'fa-solid fa-money-check-dollar', - attributes: { 'free':true,target: '_blank' } + icon: 'fa-solid fa-money-check-dollar', + attributes: { 'free': true, target: '_blank' } } ]; diff --git a/src/app/providers/license-interceptor.service.ts b/src/app/providers/license-interceptor.service.ts new file mode 100644 index 0000000..edfbbcd --- /dev/null +++ b/src/app/providers/license-interceptor.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@angular/core'; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor, + HttpResponse +} from '@angular/common/http'; +import { Observable, tap } from 'rxjs'; +import { LicenseService } from './license.service'; + +@Injectable() +export class LicenseInterceptor implements HttpInterceptor { + + // Pro-licensed API endpoints that should be monitored + private readonly proEndpoints = [ + 'monitoring/devs/get', + 'monitoring/events/get', + 'monitoring/eventunfixed/get', + '/api/vpn/status', + 'networkmap/get', + 'snippet/sequence/list', + 'cloner/list', + '/api/pssvault/get', + 'snippet/syslogregex/list' + ]; + + constructor(private licenseService: LicenseService) { } + + private isProEndpoint(url: string): boolean { + return this.proEndpoints.some(endpoint => url.includes(endpoint)); + } + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe( + tap((event: HttpEvent) => { + if (event instanceof HttpResponse && this.isProEndpoint(request.url)) { + const body = event.body; + if ( + body && + body.result && + typeof body.result === 'object' && + body.result.err === 'License Expired' && + body.result.status === 'failed' + ) { + this.licenseService.setExpired(true); + } else { + // Pro endpoint responded without license error — license is valid + this.licenseService.setExpired(false); + } + } + }) + ); + } +} diff --git a/src/app/providers/license.service.ts b/src/app/providers/license.service.ts new file mode 100644 index 0000000..54902bf --- /dev/null +++ b/src/app/providers/license.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class LicenseService { + private isExpiredSubject = new BehaviorSubject(false); + public isExpired$: Observable = this.isExpiredSubject.asObservable(); + + constructor() { } + + setExpired(expired: boolean): void { + if (this.isExpiredSubject.value !== expired) { + this.isExpiredSubject.next(expired); + } + } + + isExpired(): boolean { + return this.isExpiredSubject.value; + } +} diff --git a/src/app/providers/mikrowizard/data.ts b/src/app/providers/mikrowizard/data.ts index 6bc40f6..6aa84be 100644 --- a/src/app/providers/mikrowizard/data.ts +++ b/src/app/providers/mikrowizard/data.ts @@ -8,7 +8,7 @@ import { User } from './user'; @Injectable() export class dataProvider { - + // public serverUrl: string = "/api"; public serverUrl: string = ""; private db: string = "NothingImportant"; @@ -60,60 +60,60 @@ export class dataProvider { //// //// MikroWizard API //// - get_front_version(){ + get_front_version() { return this.MikroWizardRPC.sendHttpGetRequest("/api/frontver/"); } - change_password(oldpass:string,newpass:string){ - var data={ - 'oldpass':oldpass, - 'newpass':newpass + change_password(oldpass: string, newpass: string) { + var data = { + 'oldpass': oldpass, + 'newpass': newpass } return this.MikroWizardRPC.sendJsonRequest("/api/user/change_password", data); } - dashboard_stats(versioncheck:boolean,front_version:string){ - var data={ - 'versioncheck':versioncheck, - 'front_version':front_version + dashboard_stats(versioncheck: boolean, front_version: string) { + var data = { + 'versioncheck': versioncheck, + 'front_version': front_version } return this.MikroWizardRPC.sendJsonRequest("/api/dashboard/stats", data); } - monitoring_devices_events(page:number,textfilter:string=''){ - var data={ - 'page':page, - 'textfilter':textfilter + monitoring_devices_events(page: number, textfilter: string = '') { + var data = { + 'page': page, + 'textfilter': textfilter } - + return this.MikroWizardRPC.sendJsonRequest("/api/monitoring/devs/get", data); } - - monitoring_events_fix(event_id:number){ - var data={ - 'event_id':event_id + + monitoring_events_fix(event_id: number) { + var data = { + 'event_id': event_id } return this.MikroWizardRPC.sendJsonRequest("/api/monitoring/events/fix", data); } - - monitoring_all_events(devid:number,page:number){ - var data={ - 'devid':devid, - 'page':page + + monitoring_all_events(devid: number, page: number) { + var data = { + 'devid': devid, + 'page': page } return this.MikroWizardRPC.sendJsonRequest("/api/monitoring/events/get", data); } - monitoring_unfixed_events(devid:number){ - var data={ - 'devid':devid + monitoring_unfixed_events(devid: number) { + var data = { + 'devid': devid } return this.MikroWizardRPC.sendJsonRequest("/api/monitoring/eventunfixed/get", data); } - dashboard_traffic(delta:string){ - var data={ - 'delta':delta + dashboard_traffic(delta: string) { + var data = { + 'delta': delta } return this.MikroWizardRPC.sendJsonRequest("/api/dashboard/traffic", data); } - get_dev_list(data:any) { + get_dev_list(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/dev/list", data); } @@ -121,442 +121,502 @@ export class dataProvider { return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/list", {}); } - get_devgroup_members(gid:number) { - var data={ - 'gid':gid + get_devgroup_members(gid: number) { + var data = { + 'gid': gid } return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/members", data); } - delete_group(id:number){ - var data={ - 'gid':id + delete_group(id: number) { + var data = { + 'gid': id } return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/delete", data); } - delete_devices(devids:any){ + delete_devices(devids: any) { var data = { - 'devids':devids + 'devids': devids } return this.MikroWizardRPC.sendJsonRequest("/api/dev/delete", data); } get_dev_info(id: number) { - var data={ - 'devid':id + var data = { + 'devid': id } return this.MikroWizardRPC.sendJsonRequest("/api/dev/info", data); } get_editform(id: number) { - var data={ - 'devid':id + var data = { + 'devid': id } return this.MikroWizardRPC.sendJsonRequest("/api/dev/get_editform", data); } - save_editform(data:any){ + save_editform(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/dev/save_editform", data); } - get_dev_sensors(id: number,delta:string="5m",total_type:string="bps") { - var data={ - 'devid':id, - 'delta':delta, - 'total':total_type + get_dev_sensors(id: number, delta: string = "5m", total_type: string = "bps") { + var data = { + 'devid': id, + 'delta': delta, + 'total': total_type } return this.MikroWizardRPC.sendJsonRequest("/api/dev/sensors", data); } - get_dev_radio_sensors(id: number, delta:string="5m"){ - var data={ - 'devid':id, - 'delta':delta + get_dev_radio_sensors(id: number, delta: string = "5m") { + var data = { + 'devid': id, + 'delta': delta } return this.MikroWizardRPC.sendJsonRequest("/api/dev/radio/sensors", data); } - get_dev_dhcp_info(id: number){ - var data={ - 'devid':id, + get_dev_dhcp_info(id: number) { + var data = { + 'devid': id, } return this.MikroWizardRPC.sendJsonRequest("/api/dev/dhcp-server/get", data); } - get_dev_ifstat(id: number,delta:string="5m",iface:string="ether1",type:string="bps") { - var data={ - 'devid':id, - 'delta':delta, - 'type':type, - 'interface':iface + get_dev_ifstat(id: number, delta: string = "5m", iface: string = "ether1", type: string = "bps") { + var data = { + 'devid': id, + 'delta': delta, + 'type': type, + 'interface': iface } return this.MikroWizardRPC.sendJsonRequest("/api/dev/ifstat", data); } - totp(action:string,userid:string){ - var data={ - 'userid':userid, - 'action':action + totp(action: string, userid: string) { + var data = { + 'userid': userid, + 'action': action } return this.MikroWizardRPC.sendJsonRequest("/api/user/totp", data); } - - get_user_restrictions(uid:string){ - var data={ - 'uid':uid + + get_user_restrictions(uid: string) { + var data = { + 'uid': uid } return this.MikroWizardRPC.sendJsonRequest("/api/user/restrictions", data); } - save_user_restrictions(uid:string,restrictions:any){ - var data={ - 'uid':uid, - 'restrictions':restrictions + save_user_restrictions(uid: string, restrictions: any) { + var data = { + 'uid': uid, + 'restrictions': restrictions } return this.MikroWizardRPC.sendJsonRequest("/api/user/save_restrictions", data); } - mytotp(action:string,otp:any=false){ - var data={ - 'action':action, - 'otp':otp + mytotp(action: string, otp: any = false) { + var data = { + 'action': action, + 'otp': otp } return this.MikroWizardRPC.sendJsonRequest("/api/user/mytotp", data); } - get_auth_logs(filters:any) { - var data=filters; + get_auth_logs(filters: any) { + var data = filters; return this.MikroWizardRPC.sendJsonRequest("/api/auth/list", data); } - get_account_logs(filters:any) { - var data=filters; + get_account_logs(filters: any) { + var data = filters; return this.MikroWizardRPC.sendJsonRequest("/api/account/list", data); } - get_dev_logs(filters:any) { - var data=filters; + get_dev_logs(filters: any) { + var data = filters; return this.MikroWizardRPC.sendJsonRequest("/api/devlogs/list", data); } - get_syslog(filters:any) { - var data=filters; + get_syslog(filters: any) { + var data = filters; return this.MikroWizardRPC.sendJsonRequest("/api/syslog/list", data); } - get_details_grouped(devid:number=0){ - var data={ - 'devid':devid + get_details_grouped(devid: number = 0) { + var data = { + 'devid': devid } return this.MikroWizardRPC.sendJsonRequest("/api/devlogs/details/list", data); } - scan_devs(type:string,info:any){ - var data: any={ - 'type':type + scan_devs(type: string, info: any) { + var data: any = { + 'type': type } - if(type=="ip"){ + if (type == "ip") { data = Object.assign(data, info); } return this.MikroWizardRPC.sendJsonRequest("/api/scanner/scan", data); } - scan_results(){ + scan_results() { return this.MikroWizardRPC.sendJsonRequest("/api/scanner/results", {}); } - get_groups(searchstr:string=""){ - var data={ - 'searchstr':searchstr + get_groups(searchstr: string = "") { + var data = { + 'searchstr': searchstr } return this.MikroWizardRPC.sendJsonRequest("/api/search/groups", data); - } + } - get_devices(searchstr:string=""){ - var data={ - 'searchstr':searchstr + get_devices(searchstr: string = "") { + var data = { + 'searchstr': searchstr } return this.MikroWizardRPC.sendJsonRequest("/api/search/devices", data); - } + } - update_save_group(group:any){ - var data={ + update_save_group(group: any) { + var data = { ...group } return this.MikroWizardRPC.sendJsonRequest("/api/devgroup/update_save_group", data); } - get_snippets(name:string,desc:string,content:string,page:number=0,size:number=1000,limit:any=false){ - var data={ - 'name':name, - 'description':desc, - 'content':content, - 'page':page, - 'size':size, - 'limit':limit + get_snippets(name: string, desc: string, content: string, page: number = 0, size: number = 1000, limit: any = false) { + var data = { + 'name': name, + 'description': desc, + 'content': content, + 'page': page, + 'size': size, + 'limit': limit } return this.MikroWizardRPC.sendJsonRequest("/api/snippet/list", data); } - save_snippet(data:any){ - return this.MikroWizardRPC.sendJsonRequest("/api/snippet/save", {...data}); + save_snippet(data: any) { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/save", { ...data }); } - Exec_snipet(data:any,members:any) { - data['members']=members; + Exec_snipet(data: any, members: any) { + data['members'] = members; return this.MikroWizardRPC.sendJsonRequest("/api/snippet/exec", data); } - delete_snippet(id:number){ - var data={ - 'id':id + delete_snippet(id: number) { + var data = { + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/snippet/delete", data); } - get_executed_snipet(id:number){ - var data={ - 'id':id + get_executed_snipet(id: number) { + var data = { + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/snippet/executed", data); } + get_sequences() { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/sequence/list", {}); + } + + save_sequence(data: any) { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/sequence/save", { ...data }); + } + + delete_sequence(id: number) { + var data = { + 'id': id + } + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/sequence/delete", data); + } + + get_sequence_history(id: number) { + var data = { + 'id': id + } + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/sequence/history", data); + } + + exec_sequence(data: any) { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/sequence/exec", data); + } + + get_syslog_regexes() { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/syslogregex/list", {}); + } + + save_syslog_regex(data: any) { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/syslogregex/save", { ...data }); + } + + delete_syslog_regex(id: number) { + var data = { + 'id': id + } + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/syslogregex/delete", data); + } + + get_syslogregex_samples() { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/syslogregex/samples", {}); + } + + get_alerts() { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/alert/list", {}); + } + + save_alert(data: any) { + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/alert/save", { ...data }); + } + + delete_alert(id: number) { + var data = { + 'id': id + } + return this.MikroWizardRPC.sendJsonRequest("/api/snippet/alert/delete", data); + } + get_user_task_list() { return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/list", {}); } - Add_task(data:any,members:any) { - data['members']=members; + Add_task(data: any, members: any) { + data['members'] = members; return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/create", data); } - Delete_task(taskid:Number) { - var data={ - 'taskid':taskid, + Delete_task(taskid: Number) { + var data = { + 'taskid': taskid, } return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/delete", data); } - Edit_task(data:any,members:any) { - data['members']=members; + Edit_task(data: any, members: any) { + data['members'] = members; return this.MikroWizardRPC.sendJsonRequest("/api/user_tasks/edit", data); } - get_task_members(taskid:Number) { - var data={ - 'taskid':taskid, + get_task_members(taskid: Number) { + var data = { + 'taskid': taskid, } return this.MikroWizardRPC.sendJsonRequest("/api/taskmember/details", data); } - get_users(page:Number,size:Number,search:string) { - var data={ - 'page':page, - 'size':size, - 'search':search + get_users(page: Number, size: Number, search: string) { + var data = { + 'page': page, + 'size': size, + 'search': search } return this.MikroWizardRPC.sendJsonRequest("/api/users/list", data); } - get_perms(page:Number,size:Number,search:string) { - var data={ - 'page':page, - 'size':size, - 'search':search + get_perms(page: Number, size: Number, search: string) { + var data = { + 'page': page, + 'size': size, + 'search': search } return this.MikroWizardRPC.sendJsonRequest("/api/perms/list", data); } - - create_perm(name:string,perms:any) { - var data={ - 'name':name, - 'perms':perms + + create_perm(name: string, perms: any) { + var data = { + 'name': name, + 'perms': perms } return this.MikroWizardRPC.sendJsonRequest("/api/perms/create", data); } - edit_perm(id:Number,name:string,perms:any) { - + edit_perm(id: Number, name: string, perms: any) { + var data = { - 'id':id, - 'name':name, - 'perms':perms + 'id': id, + 'name': name, + 'perms': perms } return this.MikroWizardRPC.sendJsonRequest("/api/perms/edit", data); } - - delete_perm(id:number){ - var data={ - 'id':id + + delete_perm(id: number) { + var data = { + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/perms/delete", data); } - get_vault_setting(){ + get_vault_setting() { return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/get", {}); } - vault_task(data:any){ + vault_task(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/task", data); } - vault_history(){ + vault_history() { return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/history", {}); } - exec_vault(){ + exec_vault() { return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/execute", {}); } - reveal_password(devid:number,username:string){ - var data={ - 'devid':devid, - 'username':username + reveal_password(devid: number, username: string) { + var data = { + 'devid': devid, + 'username': username } return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/reveal", data); } - get_passwords(data:any){ + get_passwords(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/get_passwords", data); } - get_device_pass(devid:number){ - var data={ - 'devid':devid + get_device_pass(devid: number) { + var data = { + 'devid': devid } return this.MikroWizardRPC.sendJsonRequest("/api/pssvault/get_device_pass", data); } - user_perms(uid:string) { - + user_perms(uid: string) { + var data = { - 'uid':uid, + 'uid': uid, } return this.MikroWizardRPC.sendJsonRequest("/api/userperms/list", data); } - Add_user_perm(uid:Number,permid:Number,devgroupid:Number){ + Add_user_perm(uid: Number, permid: Number, devgroupid: Number) { var data = { - 'uid':uid, - 'pid':permid, - 'gid':devgroupid + 'uid': uid, + 'pid': permid, + 'gid': devgroupid } return this.MikroWizardRPC.sendJsonRequest("/api/userperms/create", data); } - Delete_user_perm(id:number){ - var data={ - 'id':id + Delete_user_perm(id: number) { + var data = { + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/userperms/delete", data); } - edit_user(data:any) { + edit_user(data: any) { - return this.MikroWizardRPC.sendJsonRequest("/api/user/edit", data); + return this.MikroWizardRPC.sendJsonRequest("/api/user/edit", data); } - create_user(data:any) { + create_user(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/user/create", data); } - delete_user(id:number){ - var data={ - 'uid':id + delete_user(id: number) { + var data = { + 'uid': id } return this.MikroWizardRPC.sendJsonRequest("/api/user/delete", data); } - check_firmware(devids:any) { + check_firmware(devids: any) { var data = { - 'devids':devids + 'devids': devids } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/check_firmware_update", data); } - get_firms(page:Number,size:Number,search:any) { + get_firms(page: Number, size: Number, search: any) { var data = { - 'page':page, - 'size':size, - 'search':search + 'page': page, + 'size': size, + 'search': search } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/get_firms", data); } - delete_firm(id:number){ - var data={ - 'id':id + delete_firm(id: number) { + var data = { + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/delete_from_repository", data); } - - get_backups(data:any) { + + get_backups(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/backup/list", data); } - - get_backup(id:number){ + + get_backup(id: number) { var data = { - 'id':id + 'id': id } return this.MikroWizardRPC.sendJsonRequest("/api/backup/get", data); } - restore_backup(id:number){ + restore_backup(id: number) { var data = { - 'backupid':id + 'backupid': id } return this.MikroWizardRPC.sendJsonRequest("/api/backup/restore", data); } get_downloadable_firms() { - + return this.MikroWizardRPC.sendJsonRequest("/api/firmware/get_downloadable_firms", {}); } - download_firmware_to_repository(version:string){ + download_firmware_to_repository(version: string) { var data = { - 'version':version + 'version': version } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/download_firmware_to_repository", data); } - save_firmware_setting(updatebehavior:string,firmwaretoinstall:string,firmwaretoinstallv6:string){ + save_firmware_setting(updatebehavior: string, firmwaretoinstall: string, firmwaretoinstallv6: string) { var data = { - 'updatebehavior':updatebehavior, - 'firmwaretoinstall':firmwaretoinstall, - 'firmwaretoinstallv6':firmwaretoinstallv6 + 'updatebehavior': updatebehavior, + 'firmwaretoinstall': firmwaretoinstall, + 'firmwaretoinstallv6': firmwaretoinstallv6 } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/update_firmware_settings", data); } - update_firmware(devids:string){ + update_firmware(devids: string) { var data = { - 'devids':devids + 'devids': devids } return this.MikroWizardRPC.sendJsonRequest("/api/firmware/update_firmware", data); } - upgrade_firmware(devids:string){ + upgrade_firmware(devids: string) { var data = { - 'devids':devids + 'devids': devids } - return this.MikroWizardRPC.sendJsonRequest("/api/firmware/upgrade_firmware", data); + return this.MikroWizardRPC.sendJsonRequest("/api/firmware/upgrade_firmware", data); } - reboot_devices(devids:string){ + reboot_devices(devids: string) { var data = { - 'devids':devids + 'devids': devids } - return this.MikroWizardRPC.sendJsonRequest("/api/firmware/reboot_devices", data); + return this.MikroWizardRPC.sendJsonRequest("/api/firmware/reboot_devices", data); } - get_settings(){ + get_settings() { return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/get_all", {}); } - save_sys_setting(data:any){ + save_sys_setting(data: any) { return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/save_all", data); } - - get_running_tasks(){ + + get_running_tasks() { return this.MikroWizardRPC.sendJsonRequest("/api/tasks/list", {}); } - stop_task(signal:number){ - var data={ - 'signal':signal + stop_task(signal: number) { + var data = { + 'signal': signal } return this.MikroWizardRPC.sendJsonRequest("/api/tasks/stop", data); } - apply_update(action:string){ - var data={ - 'action':action + apply_update(action: string) { + var data = { + 'action': action } return this.MikroWizardRPC.sendJsonRequest("/api/sysconfig/apply_update", data); } @@ -566,62 +626,66 @@ export class dataProvider { return this.MikroWizardRPC.sendJsonRequest("/api/cloner/list", {}); } - Add_cloner(data:any,members:any) { - data['members']=members; + Add_cloner(data: any, members: any) { + data['members'] = members; return this.MikroWizardRPC.sendJsonRequest("/api/cloner/create", data); } - Delete_cloner(clonerid:number) { - var data={ - 'clonerid':clonerid, + Delete_cloner(clonerid: number) { + var data = { + 'clonerid': clonerid, } return this.MikroWizardRPC.sendJsonRequest("/api/cloner/delete", data); } - Edit_cloner(data:any,members:any) { - data['members']=members; + Edit_cloner(data: any, members: any) { + data['members'] = members; return this.MikroWizardRPC.sendJsonRequest("/api/cloner/edit", data); } - get_cloner_members(clonerid:number) { - var data={ - 'clonerid':clonerid, + get_cloner_members(clonerid: number) { + var data = { + 'clonerid': clonerid, } return this.MikroWizardRPC.sendJsonRequest("/api/cloner/memberdetails", data); } - killSession(devid:number,item:any){ - var data={ - 'devid':devid, - 'item':item + killSession(devid: number, item: any) { + var data = { + 'devid': devid, + 'item': item } return this.MikroWizardRPC.sendJsonRequest("/api/dev/kill_session", data); } - getDhcpHistory(item:any){ - var data={ - 'item':item + getDhcpHistory(item: any) { + var data = { + 'item': item } return this.MikroWizardRPC.sendJsonRequest("/api/dhcp-history/get", data); } - getNetworkMap(){ + getNetworkMap() { return this.MikroWizardRPC.sendJsonRequest("/api/networkmap/get", {}); } - bulk_add_devices(devices: any[]){ + resetNetworkMap() { + return this.MikroWizardRPC.sendJsonRequest("/api/networkmap/reset", {}); + } + + bulk_add_devices(devices: any[]) { var data = { 'devices': devices } return this.MikroWizardRPC.sendJsonRequest("/api/dev/bulk_add", data); } - bulk_add_status(taskId: string){ + bulk_add_status(taskId: string) { var data = { 'taskId': taskId } return this.MikroWizardRPC.sendJsonRequest("/api/dev/bulk_add_status", data); } - group_firmware_action(groupId: number, action: string){ + group_firmware_action(groupId: number, action: string) { var data = { 'groupId': groupId, 'action': action @@ -637,7 +701,7 @@ export class dataProvider { this.MikroWizardRPC.clearCookeis(); this.MikroWizardRPC.setNewSession(context, session); } - + checkSessionExpired(error: any) { console.log(error); if ('title' in error && error.title == "session_expired") diff --git a/src/app/providers/mikrowizard/provider.ts b/src/app/providers/mikrowizard/provider.ts index ac7deb4..39e39d4 100644 --- a/src/app/providers/mikrowizard/provider.ts +++ b/src/app/providers/mikrowizard/provider.ts @@ -1,6 +1,6 @@ import { Injectable, Inject } from '@angular/core'; -import { HttpClient,HttpResponse } from '@angular/common/http'; +import { HttpClient, HttpResponse } from '@angular/common/http'; class Cookies { // cookies doesn't work with Android default browser / Ionic private session_id: string = ""; diff --git a/src/app/providers/mikrowizard/vpn.service.ts b/src/app/providers/mikrowizard/vpn.service.ts new file mode 100644 index 0000000..b999430 --- /dev/null +++ b/src/app/providers/mikrowizard/vpn.service.ts @@ -0,0 +1,167 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Observable, interval, Subject, catchError, throwError, map, switchMap } from 'rxjs'; + +export interface VpnStats { + last_handshake: number; + rx_bytes: number; + tx_bytes: number; + rx_speed?: number; + tx_speed?: number; + nat_mode: string; + enabled: boolean; + allowed_ips: string; +} + +export interface VpnPeer { + id: number; + public_key: string; + assigned_ip: string; + nat_mode: string; + split_targets: string[]; + dns_server: string | null; + persistent_keepalive: number; + custom_interface: string | null; + linked_device_id: number | null; + is_enabled: boolean; + created_at: string; + stats?: VpnStats; // Joined from the /status API + is_managed?: boolean; + status?: 'online' | 'offline' | 'unreachable'; + name?: string; + description?: string; + scan_status?: 'starting' | 'running' | 'completed' | 'failed' | null; + mt_user: string | null; + mt_pass: string | null; + mt_port: number | null; +} + +export interface VpnServerConfig { + id?: number; + api_endpoint: string; + api_token: string | null; + vpn_subnet: string; + public_server_ip: string | null; +} + +export interface VpnStatusResponse { + status: 'running' | 'setup_required' | 'error' | 'failed'; + peers?: VpnPeer[]; + server_config?: VpnServerConfig; + message?: string; + error?: string; +} + +export interface VpnLiveStatusResponse { + server: { + rx_bytes: number; + tx_bytes: number; + rx_speed: number; + tx_speed: number; + }; + peers: any[]; // The live endpoint returns an array of peer objects with full stats, same as /status +} + +@Injectable({ + providedIn: 'root' +}) +export class VpnService { + private apiUrl = '/api/vpn'; + + constructor(private http: HttpClient) { } + + // System Endpoints + getStatus(): Observable { + return this.http.get<{ result: VpnStatusResponse }>(`${this.apiUrl}/status`).pipe(map(r => r.result)); + } + + getLiveStatus(): Observable { + return this.http.get<{ result: VpnLiveStatusResponse }>(`${this.apiUrl}/status/live`).pipe( + map(res => res.result), + catchError(err => throwError(() => err)) + ); + } + + resetServerCounters(): Observable { + return this.http.post(`${this.apiUrl}/server/reset-counters`, {}).pipe( + catchError(err => throwError(() => err)) + ); + } + + getSystemConfig(): Observable<{ status: string, config: VpnServerConfig }> { + return this.http.get<{ result: { status: string, config: VpnServerConfig } }>(`${this.apiUrl}/system/config`).pipe(map(r => r.result)); + } + + updateSystemConfig(config: Partial): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/system/config`, config).pipe(map(r => r.result)); + } + + flushSystem(wipe_database: boolean): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/system/flush`, { wipe_database }).pipe(map(r => r.result)); + } + + // Peer Endpoints + addPeer(peerData: { + pubkey?: string, + custom_ip?: string, + nat_mode: 'full' | 'split' | 'off', + split_targets: string[], + persistent_keepalive: number, + custom_interface?: string, + name?: string, + description?: string, + mt_user?: string | null, + mt_pass?: string | null, + mt_port?: number | null + }): Observable<{ status: string, peer: VpnPeer }> { + return this.http.post<{ result: { status: string, peer: VpnPeer } }>(`${this.apiUrl}/peers/add`, peerData).pipe(map(r => r.result)); + } + + editPeer(peerData: { + pubkey: string, + custom_ip?: string, + nat_mode?: string, + split_targets?: string[], + persistent_keepalive?: number, + custom_interface?: string, + name?: string, + description?: string, + mt_user?: string | null, + mt_pass?: string | null, + mt_port?: number | null + }): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/peers/edit`, peerData).pipe(map(r => r.result)); + } + + togglePeer(pubkey: string, enabled: boolean): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/peers/toggle`, { pubkey, enabled }).pipe(map(r => r.result)); + } + + deletePeer(pubkey: string): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/peers/delete`, { pubkey }).pipe(map(r => r.result)); + } + + getPeerConfig(pubkey: string): Observable<{ status: string, config: string }> { + return this.http.post<{ result: { status: string, config: string } }>(`${this.apiUrl}/peers/config`, { pubkey }).pipe(map(r => r.result)); + } + + getPeerMikrotikScript(pubkey: string): Observable<{ status: string, script: string }> { + return this.http.post<{ result: { status: string, script: string } }>(`${this.apiUrl}/peers/mikrotik-script`, { pubkey }).pipe(map(r => r.result)); + } + + scanLinkedDevice(pubkey: string): Observable { + return this.http.post<{ result: any }>(`${this.apiUrl}/peers/scan`, { pubkey }).pipe(map(r => r.result)); + } + + getPeerQrCode(pubkey: string): Observable { + return this.http.post(`${this.apiUrl}/peers/qrcode`, { pubkey }, { responseType: 'blob' }); + } + + resetPeerCounters(pubkey: string): Observable { + // pubkey must be url-encoded to safely pass base64 across URL path + return this.http.post(`${this.apiUrl}/peer/${encodeURIComponent(pubkey)}/reset-counters`, {}).pipe( + catchError(err => throwError(() => err)) + ); + } + +} diff --git a/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.html b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.html new file mode 100644 index 0000000..bd74c49 --- /dev/null +++ b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.html @@ -0,0 +1,16 @@ +
+
+
+ +
+

Pro Feature: License Expired

+

This view is restricted to pro-licensed customers. Your license has either expired or is not valid for this + feature.

+ +
+
\ No newline at end of file diff --git a/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.scss b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.scss new file mode 100644 index 0000000..9176e7a --- /dev/null +++ b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.scss @@ -0,0 +1,139 @@ +.license-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.4); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + border-radius: inherit; + animation: fadeIn 0.4s ease-out; + + .overlay-content { + background: rgba(255, 255, 255, 0.95); + padding: 2.5rem; + border-radius: 24px; + text-align: center; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05); + max-width: 480px; + width: 90%; + display: flex; + flex-direction: column; + align-items: center; + transform: translateY(0); + transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); + + &:hover { + transform: translateY(-5px); + } + + .icon-container { + width: 80px; + height: 80px; + background: linear-gradient(135deg, #fde8e8 0%, #f9d2d2 100%); + color: #e55353; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 2.5rem; + margin-bottom: 1.5rem; + position: relative; + + &::after { + content: ''; + position: absolute; + width: 100%; + height: 100%; + border-radius: 50%; + border: 2px solid #e55353; + animation: ping 2s cubic-bezier(0, 0, 0.2, 1) infinite; + opacity: 0; + } + } + + h2 { + color: #1a1c23; + font-weight: 800; + margin-bottom: 0.75rem; + font-size: 1.75rem; + letter-spacing: -0.025em; + } + + p { + color: #4b5563; + line-height: 1.7; + margin-bottom: 2.5rem; + font-size: 1.05rem; + } + + .actions { + display: flex; + gap: 1.25rem; + width: 100%; + + .btn-renew { + flex: 3; + background: linear-gradient(135deg, #e55353 0%, #c53030 100%); + color: white; + padding: 0.875rem 1.5rem; + border-radius: 14px; + text-decoration: none; + font-weight: 700; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + border: none; + cursor: pointer; + font-size: 1rem; + box-shadow: 0 4px 12px rgba(229, 83, 83, 0.3); + + &:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(229, 83, 83, 0.5); + filter: brightness(1.1); + color: white; + } + + &:active { + transform: translateY(0); + } + } + + .btn-dismiss { + flex: 1; + background: #f3f4f6; + color: #6b7280; + padding: 0.875rem 1rem; + border-radius: 14px; + font-weight: 600; + border: 1px solid #e5e7eb; + cursor: pointer; + transition: all 0.2s; + font-size: 0.95rem; + + &:hover { + background: #e5e7eb; + color: #374151; + } + } + } + } +} + +@keyframes fadeIn { + from { opacity: 0; transform: scale(0.95); } + to { opacity: 1; transform: scale(1); } +} + +@keyframes ping { + 0% { transform: scale(1); opacity: 0.5; } + 100% { transform: scale(2); opacity: 0; } +} diff --git a/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.ts b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.ts new file mode 100644 index 0000000..697a332 --- /dev/null +++ b/src/app/shared/components/license-expired-overlay/license-expired-overlay.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit } from '@angular/core'; +import { LicenseService } from '../../../providers/license.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-license-expired-overlay', + templateUrl: './license-expired-overlay.component.html', + styleUrls: ['./license-expired-overlay.component.scss'] +}) +export class LicenseExpiredOverlayComponent implements OnInit { + public isExpired$: Observable; + + constructor(private licenseService: LicenseService) { + this.isExpired$ = this.licenseService.isExpired$; + } + + ngOnInit(): void { + } + + dismiss(): void { + // Locally hide the overlay for the current component session if needed + // But usually, it should stay until the license is fixed. + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts new file mode 100644 index 0000000..c83324e --- /dev/null +++ b/src/app/shared/shared.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { LicenseExpiredOverlayComponent } from './components/license-expired-overlay/license-expired-overlay.component'; + +@NgModule({ + declarations: [ + LicenseExpiredOverlayComponent + ], + imports: [ + CommonModule + ], + exports: [ + LicenseExpiredOverlayComponent + ] +}) +export class SharedModule { } diff --git a/src/app/views/acc_log/acc.component.html b/src/app/views/acc_log/acc.component.html index 3b1b9b8..66e97be 100644 --- a/src/app/views/acc_log/acc.component.html +++ b/src/app/views/acc_log/acc.component.html @@ -1,10 +1,10 @@ - + -
Accunting Logs +
Accounting Logs @@ -14,8 +14,10 @@
Filtered Result For Device ID {{devid}} - - Showing last 24 hours logs by default. Use filters to modify the date and time. + + Showing last 24 hours logs by + default. Use filters to modify the date and time.
@@ -73,49 +75,143 @@
- - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - -
{{value}}
-
-
- - - {{value}} - - - - - {{value}} - - - - - {{value}} - - -
+
+ + + + +
+ + + + + + +
+ #No + +
+ + +
+ Device Name + + + + +
+ + +
+ Device IP + + + + +
+ + +
+ User Name + + + + +
+ + +
+ Action + + + + +
+ + +
+ Section + + + + +
+ + +
+ Date + + + + +
+ + +
+ + + + {{item.index}} + {{item.name}} + {{item.devip}} + {{item.username}} + {{item.action}} + {{item.section}} + {{item.created}} + + + + + + No accounting logs found. + + +
+ + + +
+
Device Info
+
+
{{selectedLog.name}}
+
{{selectedLog.devip}}
+
+ +
Session Details
+
+
User Name:
+
{{selectedLog.username}}
+
+
+
User IP:
+
{{selectedLog.address}}
+
+
+
Section:
+
{{selectedLog.section}}
+
+
+
Action:
+
{{selectedLog.action}}
+
+
+
Exec time:
+
{{selectedLog.created}}
+
+ +
Executed Config
+
+
{{selectedLog.config}}
+
+
+
diff --git a/src/app/views/acc_log/acc.component.ts b/src/app/views/acc_log/acc.component.ts index 2fbf5b7..44e4ba1 100644 --- a/src/app/views/acc_log/acc.component.ts +++ b/src/app/views/acc_log/acc.component.ts @@ -1,19 +1,8 @@ -import { Component, OnInit, ViewEncapsulation,Input } from "@angular/core"; +import { Component, OnInit, ViewChild, ViewEncapsulation, Input } from "@angular/core"; import { dataProvider } from "../../providers/mikrowizard/data"; import { Router, ActivatedRoute } from "@angular/router"; import { loginChecker } from "../../providers/login_checker"; -import { - GuiRowDetail, - GuiSelectedRow, - GuiInfoPanel, - GuiColumn, - GuiColumnMenu, - GuiPaging, - GuiPagingDisplay, - GuiRowSelectionMode, - GuiRowSelection, - GuiRowSelectionType, -} from "@generic-ui/ngx-grid"; +import { Table } from 'primeng/table'; import { formatInTimeZone } from "date-fns-tz"; @@ -26,10 +15,14 @@ import { formatInTimeZone } from "date-fns-tz"; }) export class AccComponent implements OnInit { @Input() component_devid: any=false; - public uid: number; - public uname: string; - public tz: string; - public filterText: string; + public uid!: number; + public uname!: string; + public tz!: string; + public filterText!: string; + public detailsVisible: boolean = false; + public selectedLog: any = null; + + @ViewChild('dt') table!: Table; public reloading: boolean = false; public filters: any = { devid: false, @@ -75,78 +68,20 @@ export class AccComponent implements OnInit { } } public source: Array = []; - public columns: Array = []; public loading: boolean = true; public rows: any = []; - public Selectedrows: any; + public selected_rows: any[] = []; + public Selectedrows: any[] = []; public devid: number = 0; - public sorting = { - enabled: true, - multiSorting: true, - }; - rowDetail: GuiRowDetail = { - enabled: true, - template: (item) => { - return ` -
-

${item.name}

- ${item.devip} - - - - - - - - - - - - - - - - - - - - - -
User Address${item.address}
User Name${item.username}
Connection Type${item.ctype}
Section${item.section}
Exec time${item.created}
-
Executed Config
- - ${item.config} - -
`; - }, - }; - public paging: GuiPaging = { - enabled: true, - page: 1, - pageSize: 10, - pageSizes: [5, 10, 25, 50], - display: GuiPagingDisplay.ADVANCED, - }; + showLogDetails(log: any) { + this.selectedLog = log; + this.detailsVisible = true; + } - public columnMenu: GuiColumnMenu = { - enabled: true, - sort: true, - columnsManager: true, - }; - - public infoPanel: GuiInfoPanel = { - enabled: true, - infoDialog: false, - columnsManager: true, - schemaManager: true, - }; - - public rowSelection: boolean | GuiRowSelection = { - enabled: true, - type: GuiRowSelectionType.CHECKBOX, - mode: GuiRowSelectionMode.MULTIPLE, - }; + applyFilterGlobal($event: any, stringVal: string) { + this.table.filterGlobal(($event.target as HTMLInputElement).value, stringVal); + } reinitgrid(field: string, $event: any) { if (field == "start") this.filters["start_time"] = $event.target.value; @@ -170,9 +105,10 @@ export class AccComponent implements OnInit { this.initGridTable(); } OnDestroy(): void {} - onSelectedRows(rows: Array): void { - this.rows = rows; - this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id); + onSelectionChange(value: any[]) { + this.selected_rows = value; + this.Selectedrows = value.map(item => item.id); + this.rows = value; } removefilter(filter: any) { diff --git a/src/app/views/acc_log/acc.module.ts b/src/app/views/acc_log/acc.module.ts index 1b24182..44bcd50 100644 --- a/src/app/views/acc_log/acc.module.ts +++ b/src/app/views/acc_log/acc.module.ts @@ -13,7 +13,9 @@ import { import { AccRoutingModule } from "./acc-routing.module"; import { AccComponent } from "./acc.component"; -import { GuiGridModule } from "@generic-ui/ngx-grid"; +import { TableModule } from 'primeng/table'; +import { DrawerModule } from 'primeng/drawer'; +import { InputTextModule } from 'primeng/inputtext'; import { MatDatepickerModule } from "@angular/material/datepicker"; import { MatInputModule } from "@angular/material/input"; @@ -32,7 +34,9 @@ import { FormsModule } from "@angular/forms"; ButtonModule, FormModule, ButtonModule, - GuiGridModule, + TableModule, + DrawerModule, + InputTextModule, CollapseModule, MatFormFieldModule, MatInputModule, diff --git a/src/app/views/auth_log/auth.component.html b/src/app/views/auth_log/auth.component.html index 0cee1ea..02502b2 100644 --- a/src/app/views/auth_log/auth.component.html +++ b/src/app/views/auth_log/auth.component.html @@ -1,6 +1,6 @@ - + @@ -14,8 +14,10 @@ Filtered Result For Device ID {{devid}} - - Showing last 24 hours logs by default. Use filters to modify the date and time. + + Showing last 24 hours logs by + default. Use filters to modify the date and time. @@ -95,64 +97,180 @@ - - - - {{value}} - - - - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - -
{{value}}
-
-
- - - {{value}} - - +
+ + + + +
- - - {{value}} - {{item.message}} + - - + + + +
+ #No + +
+ + +
+ Device Name + + + + +
+ + +
+ Device IP + + + + +
+ + +
+ Username + + + + +
+ + +
+ With + + + + +
+ + +
+ IP Address + + + + +
+ + +
+ Time/Msg + + + + +
+ + +
+ State + + +
+ + +
+ Date + + +
+ + +
- - - Logged In - Logged Out - Failed - - - - - {{value}} - - -
+ + + {{item.index}} + + + + {{item.name}} + + {{item.devip}} + {{item.username}} + {{item.by}} + {{item.ip}} + + {{item.duration}} + {{item.message}} + + + Logged In + Logged Out + Failed + + {{item.created}} + + + + + + No authentication logs found. + + + + + + +
+
Session Info
+
+
Device:
+
{{selectedLog.name}} ({{selectedLog.devip}})
+
+
+
User:
+
{{selectedLog.username}}
+
+
+
Method:
+
{{selectedLog.by}}
+
+
+
Status:
+
+ Logged In + Logged Out + Failed +
+
+ +
Connection
+
+
IP/MAC:
+
{{selectedLog.ip}}
+
+
+
Duration:
+
{{selectedLog.duration}}
+
+
+
Date:
+
{{selectedLog.created}}
+
+ +
+
System Message
+
+ {{selectedLog.message}} +
+
+
+
diff --git a/src/app/views/auth_log/auth.component.ts b/src/app/views/auth_log/auth.component.ts index 63f06a4..7e59097 100644 --- a/src/app/views/auth_log/auth.component.ts +++ b/src/app/views/auth_log/auth.component.ts @@ -1,18 +1,8 @@ -import { Component, OnInit, ViewEncapsulation,Input } from "@angular/core"; +import { Component, OnInit, ViewChild, ViewEncapsulation, Input } from "@angular/core"; import { dataProvider } from "../../providers/mikrowizard/data"; import { Router, ActivatedRoute } from "@angular/router"; import { loginChecker } from "../../providers/login_checker"; -import { - GuiSelectedRow, - GuiInfoPanel, - GuiColumn, - GuiColumnMenu, - GuiPaging, - GuiPagingDisplay, - GuiRowSelectionMode, - GuiRowSelection, - GuiRowSelectionType, -} from "@generic-ui/ngx-grid"; +import { Table } from 'primeng/table'; import { formatInTimeZone } from "date-fns-tz"; interface IUser { @@ -37,10 +27,14 @@ interface IUser { }) export class AuthComponent implements OnInit { @Input() component_devid: any=false; - public uid: number; - public uname: string; + public uid!: number; + public uname!: string; public tz: string = "UTC"; - public filterText: string; + public filterText!: string; + public detailsVisible: boolean = false; + public selectedLog: any = null; + + @ViewChild('dt') table!: Table; public devid: number = 0; public reloading: boolean = false; public filters: any = { @@ -87,42 +81,19 @@ export class AuthComponent implements OnInit { } } public source: Array = []; - public columns: Array = []; public loading: boolean = true; public rows: any = []; - public Selectedrows: any; + public selected_rows: any[] = []; // Used by p-table selection + public Selectedrows: any[] = []; // ID array for legacy actions - public sorting = { - enabled: true, - multiSorting: true, - }; + showLogDetails(log: any) { + this.selectedLog = log; + this.detailsVisible = true; + } - public paging: GuiPaging = { - enabled: true, - page: 1, - pageSize: 10, - pageSizes: [5, 10, 25, 50], - display: GuiPagingDisplay.ADVANCED, - }; - - public columnMenu: GuiColumnMenu = { - enabled: true, - sort: true, - columnsManager: true, - }; - - public infoPanel: GuiInfoPanel = { - enabled: true, - infoDialog: false, - columnsManager: true, - schemaManager: true, - }; - - public rowSelection: boolean | GuiRowSelection = { - enabled: true, - type: GuiRowSelectionType.CHECKBOX, - mode: GuiRowSelectionMode.MULTIPLE, - }; + applyFilterGlobal($event: any, stringVal: string) { + this.table.filterGlobal(($event.target as HTMLInputElement).value, stringVal); + } reinitgrid(field: string, $event: any) { if (field == "start") this.filters["start_time"] = $event.target.value; @@ -179,9 +150,10 @@ export class AuthComponent implements OnInit { } this.initGridTable(); } - onSelectedRows(rows: Array): void { - this.rows = rows; - this.Selectedrows = rows.map((m: GuiSelectedRow) => m.source.id); + onSelectionChange(value: any[]) { + this.selected_rows = value; + this.Selectedrows = value.map(item => item.id); + this.rows = value; } removefilter(filter: any) { diff --git a/src/app/views/auth_log/auth.module.ts b/src/app/views/auth_log/auth.module.ts index 163612e..3b39569 100644 --- a/src/app/views/auth_log/auth.module.ts +++ b/src/app/views/auth_log/auth.module.ts @@ -11,7 +11,10 @@ import { } from '@coreui/angular'; import { AuthRoutingModule } from './auth-routing.module'; import { AuthComponent } from './auth.component'; -import { GuiGridModule } from '@generic-ui/ngx-grid'; +import { TableModule } from 'primeng/table'; +import { DrawerModule } from 'primeng/drawer'; +import { InputTextModule } from 'primeng/inputtext'; +import { TooltipModule } from 'primeng/tooltip'; import { FormsModule } from '@angular/forms'; @@ -27,7 +30,10 @@ import {MatSelectModule} from '@angular/material/select'; GridModule, FormsModule, ButtonModule, - GuiGridModule, + TableModule, + DrawerModule, + InputTextModule, + TooltipModule, CollapseModule, MatFormFieldModule, MatInputModule, diff --git a/src/app/views/backups/backups.component.html b/src/app/views/backups/backups.component.html index cd82daa..a4d4f25 100644 --- a/src/app/views/backups/backups.component.html +++ b/src/app/views/backups/backups.component.html @@ -20,15 +20,14 @@ {{compareitems.length}} Selected
- {{item.devname}} -
- @@ -84,8 +83,8 @@ Config Search - + @@ -93,65 +92,104 @@ - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - - {{value}} - - - - -
- - - -
-
-
-
+
+ + + + +
+ + + + + + +
+ #No + +
+ + +
+ Device Name + + + + +
+ + +
+ Device IP + + + + +
+ + +
+ Backup Time + + + + +
+ + +
+ File Size + + + + +
+ + Actions + +
+ + + + {{item.index}} + {{item.devname}} + {{item.devip}} + {{item.createdC}} + {{item.filesize}} + +
+ + + +
+ + +
+ + + + No backups found. + + +
@@ -166,11 +204,12 @@ -
{{codeForHighlightAuto}}
+
{{codeForHighlightAuto}}
-
@@ -230,7 +269,7 @@
Restore Configuration Backup
- +
Backup Details
@@ -276,7 +315,7 @@

To proceed with this critical action, type CONFIRM in the box below:

-
@@ -290,8 +329,7 @@ - diff --git a/src/app/views/backups/backups.component.ts b/src/app/views/backups/backups.component.ts index 68a0b62..b041ff6 100644 --- a/src/app/views/backups/backups.component.ts +++ b/src/app/views/backups/backups.component.ts @@ -1,18 +1,8 @@ -import { Component, OnInit, QueryList, ViewChildren } from "@angular/core"; +import { Component, OnInit, QueryList, ViewChildren, ViewChild } from "@angular/core"; import { dataProvider } from "../../providers/mikrowizard/data"; import { Router, ActivatedRoute } from "@angular/router"; import { loginChecker } from "../../providers/login_checker"; -import { - GuiSearching, - GuiInfoPanel, - GuiColumn, - GuiColumnMenu, - GuiPaging, - GuiPagingDisplay, - GuiRowSelectionMode, - GuiRowSelection, - GuiRowSelectionType, -} from "@generic-ui/ngx-grid"; +import { Table } from 'primeng/table'; import { formatInTimeZone } from "date-fns-tz"; import { ToasterComponent } from "@coreui/angular"; import { AppToastComponent } from "../toast-simple/toast.component"; @@ -22,10 +12,10 @@ import { AppToastComponent } from "../toast-simple/toast.component"; styleUrls: ["backups.component.scss"], }) export class BackupsComponent implements OnInit { - public uid: number; - public uname: string; + public uid: number = 0; + public uname: string = ''; public tz: string = "UTC"; - public filterText: string; + public filterText: string = ''; public filters: any = {}; public codeForHighlightAuto: string = ""; public ispro: boolean = false; @@ -69,34 +59,19 @@ export class BackupsComponent implements OnInit { return value !== undefined && value !== null && value !== ""; } } + @ViewChild("dt") table!: Table; @ViewChildren(ToasterComponent) viewChildren!: QueryList; public source: Array = []; - public columns: Array = []; public loading: boolean = true; - public backuploading : boolean=false; + public backuploading: boolean = false; public rows: any = []; public Selectedrows: any; public BakcupModalVisible: boolean = false; public devid: number = 0; public filters_visible: boolean = false; - public currentBackup:any=false; - public hlang:string=''; - public sorting = { - enabled: true, - multiSorting: true, - }; - searching: GuiSearching = { - enabled: true, - placeholder: "Search Devices", - }; - public paging: GuiPaging = { - enabled: true, - page: 1, - pageSize: 10, - pageSizes: [5, 10, 25, 50], - display: GuiPagingDisplay.ADVANCED, - }; + public currentBackup: any = false; + public hlang: string = ''; toasterForm = { autohide: true, @@ -105,25 +80,10 @@ export class BackupsComponent implements OnInit { fade: true, closeButton: true, }; - - public columnMenu: GuiColumnMenu = { - enabled: true, - sort: true, - columnsManager: true, - }; - public infoPanel: GuiInfoPanel = { - enabled: true, - infoDialog: false, - columnsManager: true, - schemaManager: true, - }; - - public rowSelection: boolean | GuiRowSelection = { - enabled: true, - type: GuiRowSelectionType.CHECKBOX, - mode: GuiRowSelectionMode.MULTIPLE, - }; + applyFilterGlobal($event: any, stringVal: string) { + this.table.filterGlobal(($event.target as HTMLInputElement).value, stringVal); + } ngOnInit(): void { this.devid = Number(this.route.snapshot.paramMap.get("devid")); diff --git a/src/app/views/backups/backups.module.ts b/src/app/views/backups/backups.module.ts index b24187a..5185bfb 100644 --- a/src/app/views/backups/backups.module.ts +++ b/src/app/views/backups/backups.module.ts @@ -17,7 +17,9 @@ import { import { BackupsRoutingModule } from "./backups-routing.module"; import { BackupsComponent } from "./backups.component"; -import { GuiGridModule } from "@generic-ui/ngx-grid"; +import { TableModule } from 'primeng/table'; +import { InputTextModule } from 'primeng/inputtext'; +import { TooltipModule } from 'primeng/tooltip'; import { MatDatepickerModule } from "@angular/material/datepicker"; import { MatInputModule } from "@angular/material/input"; import { MatFormFieldModule } from "@angular/material/form-field"; @@ -35,7 +37,9 @@ import { ClipboardModule } from "@angular/cdk/clipboard"; FormModule, FormsModule, ButtonModule, - GuiGridModule, + TableModule, + InputTextModule, + TooltipModule, CollapseModule, BadgeModule, AlertModule, diff --git a/src/app/views/cloner/cloner.component.html b/src/app/views/cloner/cloner.component.html index 67fd369..da56549 100644 --- a/src/app/views/cloner/cloner.component.html +++ b/src/app/views/cloner/cloner.component.html @@ -1,3 +1,4 @@ +
@@ -13,107 +14,172 @@ - - - - {{value}} - - - - - {{value}} - - - - - {{value == 'twoway' ? 'Two Way' : 'Master Mode'}} - - - - - {{value ? 'Active' : 'Inactive'}} - - - - - {{value}} - - - - - - - - - - +
+ + + + +
+ + + + + + +
+ Name + + + + +
+ + +
+ Description + + + + +
+ + +
+ Direction + + + + +
+ + +
+ Live Mode + + + + +
+ + +
+ Schedule + + + + +
+ + Actions + +
+ + + + {{item.name}} + {{item.description}} + + + {{item.direction == 'twoway' ? 'Two Way' : 'Master Mode'}} + + + + {{item.live_mode ? 'Active' : + 'Inactive'}} + + {{item.desc_cron}} + +
+ + +
+ + +
+ + + + No cloners found. + + +
+ +
- - -
Edit Cloner: {{SelectedCloner['name']}}
-
Add New Cloner
- -
- - -
-
-
Basic Information
-
- - - - - - - - + + +
Edit Cloner: + {{SelectedCloner['name']}}
+
Add New Cloner
+ +
+ + +
+
+
Basic Information
+ + + + + + + + +
- -
-
-
Synchronization Settings
-
- - - - - - - - - - - - - - - - - - + +
+
+
Synchronization Settings
+ + + + + + + + + + + + + + + + + + +
- - + - -
-
-
Commands Configuration
-
-
-