mikrofront/src/app/views/vault/vault.component.html
sepehr 746711fa24 feat: redesign password vault interface for pro users
- Complete UI/UX redesign of vault module
- Enhanced security interface
- Pro feature improvements
- Better password management workflow
2025-10-16 17:34:05 +03:00

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>