mirror of
https://github.com/MikroWizard/mikrofront.git
synced 2025-12-24 02:49:30 +00:00
- Complete UI/UX redesign of vault module - Enhanced security interface - Pro feature improvements - Better password management workflow
398 lines
No EOL
19 KiB
HTML
398 lines
No EOL
19 KiB
HTML
<c-card class="mb-4" style="margin-bottom: 0 !important;">
|
|
<c-card-header style="padding: 0;">
|
|
<c-row class="align-items-center">
|
|
<c-col xs="12" md="6">
|
|
<div class="nav nav-underline bg-transparent">
|
|
<div class="nav-item">
|
|
<a [active]="activetab==0" class="nav-link" [cTabContent]="tabContent" (click)="activetab=0" [tabPaneIdx]="0">
|
|
<i class="fas fa-cog me-1"></i>Settings
|
|
</a>
|
|
</div>
|
|
<div class="nav-item">
|
|
<a [active]="activetab==1" class="nav-link" [cTabContent]="tabContent" (click)="get_passwords();activetab=1" [tabPaneIdx]="1">
|
|
<i class="fas fa-key me-1"></i>Passwords
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</c-col>
|
|
<c-col xs="12" md="6" class="text-end mt-2 mt-md-0">
|
|
<button *ngIf="activetab==0" cButton size="sm" class="me-2" (click)="runConfirmModalVisible=!runConfirmModalVisible" color="danger">
|
|
<i class="fas fa-play me-1"></i>Execute Now
|
|
</button>
|
|
<button *ngIf="activetab==1" cButton size="sm" (click)="toggleCollapse()" color="info">
|
|
<i class="fas fa-filter me-1"></i>Filters
|
|
</button>
|
|
</c-col>
|
|
</c-row>
|
|
</c-card-header>
|
|
</c-card>
|
|
<c-tab-content #tabContent="cTabContent">
|
|
<c-tab-pane>
|
|
<c-card class="mb-4" *ngIf="settings" style="border: none;">
|
|
<c-card-body>
|
|
<!-- Settings Tab Header -->
|
|
<div class="tab-info-header mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-cog text-primary me-2 fs-4"></i>
|
|
<div>
|
|
<h5 class="mb-1">Password Vault Settings</h5>
|
|
<p class="text-muted mb-0 small">Configure automated password management for your device groups. Set schedules, define password policies, and manage affected devices.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Password Vault Configuration -->
|
|
<div class="mb-4 pb-4 border-bottom">
|
|
<h6 class="mb-3"><i class="fas fa-shield-alt me-2"></i>Password Vault Configuration</h6>
|
|
<c-row class="g-3">
|
|
<c-col xs="12" md="6" lg="3">
|
|
<label class="form-label small">Status</label>
|
|
<select cSelect size="sm" [(ngModel)]="settings['enable']" class="form-select-sm">
|
|
<option>Choose...</option>
|
|
<option value="enable">Enable</option>
|
|
<option value="disable">Disable</option>
|
|
</select>
|
|
</c-col>
|
|
<c-col xs="12" md="6" lg="3">
|
|
<label class="form-label small">Strategy <i class="fas fa-info-circle text-info ms-1" [cTooltip]="strategyTooltipTemplate" cTooltipPlacement="top"></i></label>
|
|
<select cSelect size="sm" [(ngModel)]="settings['strategy']" class="form-select-sm">
|
|
<option>Choose...</option>
|
|
<option value="all">All Local Users</option>
|
|
<option value="mikrowizard">MikroWizard Users Only</option>
|
|
</select>
|
|
</c-col>
|
|
<c-col xs="12" md="6" lg="3">
|
|
<label class="form-label small">Interval <i class="fas fa-info-circle text-info ms-1" [cTooltip]="intervalTooltipTemplate" cTooltipPlacement="top"></i></label>
|
|
<select cSelect size="sm" [(ngModel)]="settings['interval']" class="form-select-sm">
|
|
<option>Choose...</option>
|
|
<option value="daily">Daily</option>
|
|
<option value="weekly">Weekly</option>
|
|
<option value="monthly">Monthly</option>
|
|
<option value="yearly">Yearly</option>
|
|
<option value="manual">Manual</option>
|
|
<option value="custom">Custom</option>
|
|
</select>
|
|
</c-col>
|
|
<c-col xs="12" md="6" lg="3">
|
|
<label class="form-label small">Password Type <i class="fas fa-info-circle text-info ms-1" [cTooltip]="passwordTypeTooltipTemplate" cTooltipPlacement="top"></i></label>
|
|
<select cSelect size="sm" [(ngModel)]="settings['password_type']" class="form-select-sm">
|
|
<option>Choose...</option>
|
|
<option value="random">Random</option>
|
|
<option value="defined">Pre-defined</option>
|
|
</select>
|
|
</c-col>
|
|
<c-col xs="12" *ngIf="settings['interval']=='custom'">
|
|
<label class="form-label small">Custom Cron Expression</label>
|
|
<input cFormControl size="sm" placeholder="0 0 * * *" [(ngModel)]="settings['cron']" />
|
|
</c-col>
|
|
</c-row>
|
|
</div>
|
|
<!-- User Exceptions -->
|
|
<div class="mb-4 pb-4 border-bottom" *ngIf="settings && settings['strategy']=='all'">
|
|
<c-row class="align-items-center mb-3">
|
|
<c-col>
|
|
<h6 class="mb-0"><i class="fas fa-user-shield me-2"></i>User Exceptions</h6>
|
|
<small class="text-muted">Users excluded from password changes</small>
|
|
</c-col>
|
|
<c-col xs="auto">
|
|
<div class="input-group input-group-sm">
|
|
<input cFormControl size="sm" placeholder="Username" [(ngModel)]="new_exception" />
|
|
<button cButton color="primary" size="sm" (click)="add_exception()">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</c-col>
|
|
</c-row>
|
|
<div *ngIf="settings['exceptions']?.length > 0">
|
|
<gui-grid [autoResizeWidth]="true" [source]="settings['exceptions']" [columnMenu]="columnMenu" [paging]="paging" [sorting]="sorting">
|
|
<gui-grid-column header="Username" field="name">
|
|
<ng-template let-value="item" let-item="item" let-index="index">
|
|
<i class="fas fa-user me-2 text-muted"></i>{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Actions" width="80" field="action" align="center">
|
|
<ng-template let-value="item.id" let-item="item" let-index="index">
|
|
<button (click)="remove_exception(item)" cButton color="danger" size="sm" variant="outline">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</div>
|
|
</div>
|
|
<!-- Pre-defined Passwords -->
|
|
<div class="mb-4 pb-4 border-bottom" *ngIf="settings && settings['password_type']=='defined'">
|
|
<c-row class="align-items-center mb-3">
|
|
<c-col>
|
|
<h6 class="mb-0"><i class="fas fa-key me-2"></i>Password List</h6>
|
|
<small class="text-muted">Pre-defined passwords for rotation</small>
|
|
</c-col>
|
|
<c-col xs="auto">
|
|
<div class="input-group input-group-sm">
|
|
<input cFormControl size="sm" type="password" placeholder="Password" [(ngModel)]="new_password" />
|
|
<button cButton color="primary" size="sm" (click)="add_password()">
|
|
<i class="fas fa-plus"></i>
|
|
</button>
|
|
</div>
|
|
</c-col>
|
|
</c-row>
|
|
<div *ngIf="settings['passwords']?.length > 0">
|
|
<gui-grid [autoResizeWidth]="true" [source]="settings['passwords']" [columnMenu]="columnMenu" [sorting]="sorting" [paging]="paging">
|
|
<gui-grid-column header="Password" field="name">
|
|
<ng-template let-value="item" let-item="item" let-index="index">
|
|
<i class="fas fa-lock me-2 text-muted"></i>••••••••
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Actions" width="80" field="action" align="center">
|
|
<ng-template let-value="item.id" let-item="item" let-index="index">
|
|
<button cButton color="danger" size="sm" variant="outline" (click)="remove_password(item)">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</div>
|
|
</div>
|
|
<!-- Affected Groups -->
|
|
<div class="mb-4 pb-4 border-bottom">
|
|
<c-row class="align-items-center mb-3">
|
|
<c-col>
|
|
<h6 class="mb-0"><i class="fas fa-network-wired me-2"></i>Affected Device Groups</h6>
|
|
<small class="text-muted">Device groups where password changes will be applied</small>
|
|
</c-col>
|
|
<c-col xs="auto">
|
|
<button cButton color="primary" size="sm" (click)="show_new_member_form()">
|
|
<i class="fas fa-plus me-1"></i>Add Groups
|
|
</button>
|
|
</c-col>
|
|
</c-row>
|
|
<div *ngIf="Members?.length > 0" class="mb-3">
|
|
<gui-grid [autoResizeWidth]="true" [source]="Members" [columnMenu]="columnMenu" [sorting]="sorting" [paging]="paging">
|
|
<gui-grid-column header="Group Name" field="name">
|
|
<ng-template let-value="item.name" let-item="item" let-index="index">
|
|
<i class="fas fa-server me-2 text-primary"></i>{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Actions" width="80" field="action" align="center">
|
|
<ng-template let-value="item.id" let-item="item" let-index="index">
|
|
<button (click)="delete_group(item.id)" cButton color="danger" size="sm" variant="outline">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</div>
|
|
<div class="text-end">
|
|
<button cButton color="success" (click)="save_settings()">
|
|
<i class="fas fa-save me-1"></i>Save Configuration
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Execution History -->
|
|
<div *ngIf="vault_history">
|
|
<h6 class="mb-3"><i class="fas fa-history me-2"></i>Execution Reports</h6>
|
|
<gui-grid [autoResizeWidth]="true" [source]="vault_history" [columnMenu]="columnMenu" [sorting]="sorting" [paging]="paging">
|
|
<gui-grid-column header="Start Time" field="started">
|
|
<ng-template let-value="item.started" let-item="item" let-index="index">
|
|
<small>{{value}}</small>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="End Time" field="ended">
|
|
<ng-template let-value="item.ended" let-item="item" let-index="index">
|
|
<small>{{value}}</small>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Results" field="result" align="center" width="100">
|
|
<ng-template let-value="item['result']" let-item="item" let-index="index">
|
|
<button (click)="exportToCsv(value)" color="primary" size="sm" cButton variant="outline">
|
|
<i class="fas fa-download"></i>
|
|
</button>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</div>
|
|
</c-card-body>
|
|
</c-card>
|
|
</c-tab-pane>
|
|
<c-tab-pane>
|
|
<c-card class="mb-4">
|
|
<c-card-body>
|
|
<!-- Passwords Tab Header -->
|
|
<div class="tab-info-header mb-4">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-key text-warning me-2 fs-4"></i>
|
|
<div>
|
|
<h5 class="mb-1">Stored Passwords</h5>
|
|
<p class="text-muted mb-0 small">View and manage passwords stored by the vault system. Use filters to find specific devices or users.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="mb-4 pb-4 border-bottom" [visible]="filters_visible" cCollapse>
|
|
<h6 class="mb-3"><i class="fas fa-filter me-2"></i>Filters</h6>
|
|
<c-row class="g-3">
|
|
<c-col xs="12" md="4" *ngIf="ispro">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label>Username</mat-label>
|
|
<input (ngModelChange)="reinitgrid('username',$event)" [(ngModel)]="filters['username']" matInput>
|
|
</mat-form-field>
|
|
</c-col>
|
|
<c-col xs="12" md="4" *ngIf="ispro">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label>Device IP</mat-label>
|
|
<input (ngModelChange)="reinitgrid('dev_ip',$event)" [(ngModel)]="filters['dev_ip']" matInput>
|
|
</mat-form-field>
|
|
</c-col>
|
|
<c-col xs="12" md="4" *ngIf="ispro">
|
|
<mat-form-field appearance="outline" class="w-100">
|
|
<mat-label>Device Name</mat-label>
|
|
<input (ngModelChange)="reinitgrid('dev_name',$event)" [(ngModel)]="filters['dev_name']" matInput>
|
|
</mat-form-field>
|
|
</c-col>
|
|
</c-row>
|
|
</div>
|
|
|
|
<!-- Stored Passwords -->
|
|
<div *ngIf="passwords">
|
|
<h6 class="mb-3"><i class="fas fa-database me-2"></i>Stored Passwords</h6>
|
|
<gui-grid [autoResizeWidth]="true" [source]="passwords" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel">
|
|
<gui-grid-column header="Device" field="name">
|
|
<ng-template let-value="item.name" let-item="item" let-index="index">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-router me-2 text-primary"></i>
|
|
<div>
|
|
<div class="fw-semibold">{{value}}</div>
|
|
<small class="text-muted">{{item.devip}}</small>
|
|
</div>
|
|
</div>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Username" field="username">
|
|
<ng-template let-value="item.username" let-item="item" let-index="index">
|
|
<i class="fas fa-user me-2 text-muted"></i>{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Last Changed" field="changed">
|
|
<ng-template let-value="item.changed" let-item="item" let-index="index">
|
|
<small>{{value}}</small>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column header="Actions" width="100" field="action" align="center">
|
|
<ng-template let-value="item.id" let-item="item" let-index="index">
|
|
<button cButton *ngIf="ispro" (click)="reveal_password(item.devid,item.username)" color="info" size="sm" variant="outline">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</div>
|
|
</c-card-body>
|
|
</c-card>
|
|
</c-tab-pane>
|
|
</c-tab-content>
|
|
|
|
<!-- Password Reveal Modal -->
|
|
<c-modal #PasswordModal backdrop="static" [(visible)]="PasswordModalVisible" id="PasswordModal">
|
|
<c-modal-header>
|
|
<h6 cModalTitle><i class="fas fa-eye me-2"></i>Password Reveal</h6>
|
|
<button [cModalToggle]="PasswordModal.id" cButtonClose></button>
|
|
</c-modal-header>
|
|
<c-modal-body>
|
|
<div class="alert alert-warning">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
<strong>Security Notice:</strong> Your attempt to reveal this password is logged in the system.
|
|
</div>
|
|
<div class="input-group">
|
|
<span class="input-group-text"><i class="fas fa-key"></i></span>
|
|
<input [value]="password" cFormControl disabled="true" class="form-control"/>
|
|
<button cButton color="secondary" variant="outline" (click)="copyToClipboard(password)">
|
|
<i class="fas fa-copy"></i>
|
|
</button>
|
|
</div>
|
|
</c-modal-body>
|
|
<c-modal-footer>
|
|
<button [cModalToggle]="PasswordModal.id" cButton color="secondary">Close</button>
|
|
</c-modal-footer>
|
|
</c-modal>
|
|
|
|
<!-- Execute Confirmation Modal -->
|
|
<c-modal #runConfirmModal backdrop="static" [(visible)]="runConfirmModalVisible" id="runConfirmModal">
|
|
<c-modal-header>
|
|
<h6 cModalTitle><i class="fas fa-exclamation-triangle me-2 text-warning"></i>Confirm Execution</h6>
|
|
<button [cModalToggle]="runConfirmModal.id" cButtonClose></button>
|
|
</c-modal-header>
|
|
<c-modal-body>
|
|
<div class="alert alert-warning">
|
|
<strong>Warning:</strong> This will execute the password vault job and change passwords on all configured device groups.
|
|
</div>
|
|
<p>Are you sure you want to proceed with the password vault execution?</p>
|
|
</c-modal-body>
|
|
<c-modal-footer>
|
|
<button cButton color="danger" (click)="exec_vault()">
|
|
<i class="fas fa-play me-1"></i>Yes, Execute
|
|
</button>
|
|
<button [cModalToggle]="runConfirmModal.id" cButton color="secondary">Cancel</button>
|
|
</c-modal-footer>
|
|
</c-modal>
|
|
|
|
<!-- Add Device Groups Modal -->
|
|
<c-modal #NewMemberModal backdrop="static" size="lg" [(visible)]="NewMemberModalVisible" id="NewMemberModal">
|
|
<c-modal-header>
|
|
<h6 cModalTitle><i class="fas fa-plus me-2"></i>Add Device Groups</h6>
|
|
<button (click)="NewMemberModalVisible=!NewMemberModalVisible" cButtonClose></button>
|
|
</c-modal-header>
|
|
<c-modal-body>
|
|
<p class="text-muted mb-3">Select device groups to include in the password vault task:</p>
|
|
<gui-grid [autoResizeWidth]="true" *ngIf="NewMemberModalVisible" [searching]="searching"
|
|
[source]="availbleMembers" [columnMenu]="columnMenu" [sorting]="sorting" [infoPanel]="infoPanel"
|
|
[rowSelection]="rowSelection" (selectedRows)="onSelectedRowsNewMembers($event)" [paging]="paging">
|
|
<gui-grid-column header="Group Name" field="name">
|
|
<ng-template let-value="item.name" let-item="item" let-index="index">
|
|
<i class="fas fa-server me-2 text-primary"></i>{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column *ngIf="SelectedTask['selection_type']=='devices'" header="IP Address" field="ip">
|
|
<ng-template let-value="item.ip" let-item="item" let-index="index">
|
|
{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
<gui-grid-column *ngIf="SelectedTask['selection_type']=='devices'" header="MAC Address" field="mac">
|
|
<ng-template let-value="item.mac" let-item="item" let-index="index">
|
|
{{value}}
|
|
</ng-template>
|
|
</gui-grid-column>
|
|
</gui-grid>
|
|
</c-modal-body>
|
|
<c-modal-footer>
|
|
<button *ngIf="NewMemberRows.length != 0" (click)="add_new_members()" cButton color="primary">
|
|
<i class="fas fa-plus me-1"></i>Add {{NewMemberRows.length}} Group(s)
|
|
</button>
|
|
<button (click)="NewMemberModalVisible=!NewMemberModalVisible" cButton color="secondary">Cancel</button>
|
|
</c-modal-footer>
|
|
</c-modal>
|
|
|
|
<!-- Tooltip Templates -->
|
|
<ng-template #strategyTooltipTemplate>
|
|
<strong>All Local Users:</strong><br>
|
|
Changes passwords for all router users except exceptions.<br><br>
|
|
<strong>MikroWizard Users Only:</strong><br>
|
|
Changes only passwords for users defined in MikroWizard system.
|
|
</ng-template>
|
|
|
|
<ng-template #intervalTooltipTemplate>
|
|
<strong>Frequency:</strong><br>
|
|
How often passwords should be changed automatically.<br><br>
|
|
<strong>Manual:</strong><br>
|
|
Only when executed manually.
|
|
</ng-template>
|
|
|
|
<ng-template #passwordTypeTooltipTemplate>
|
|
<strong>Random:</strong><br>
|
|
System generates random passwords.<br><br>
|
|
<strong>Pre-defined:</strong><br>
|
|
Use passwords from your custom list.
|
|
</ng-template>
|
|
|
|
<c-toaster position="fixed" placement="top-end"></c-toaster> |