UI: Add action print backup code
This commit is contained in:
parent
7af89eefb0
commit
152f5bc2a8
@ -80,10 +80,10 @@
|
|||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
.container {
|
.container {
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
margin: 40px 0 24px;
|
margin: 40px 0 8px;
|
||||||
.code {
|
.code {
|
||||||
letter-spacing: 0.25px;
|
letter-spacing: 0.25px;
|
||||||
padding: 0 30px;
|
padding: 0 24px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
font-family: Roboto Mono, "Helvetica Neue", monospace;
|
font-family: Roboto Mono, "Helvetica Neue", monospace;
|
||||||
&.even {
|
&.even {
|
||||||
@ -91,6 +91,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.action-buttons {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& ::ng-deep {
|
& ::ng-deep {
|
||||||
|
|||||||
@ -34,13 +34,18 @@
|
|||||||
{{ code }}
|
{{ code }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="mat-body-1 description" translate>security.2fa.dialog.backup-code-warn</p>
|
<div fxLayout="row" fxLayoutAlign="center start" fxLayoutGap="16px" class="action-buttons">
|
||||||
<div fxLayout="row" fxLayoutAlign="center start" fxLayoutGap="16px">
|
|
||||||
<button type="button" mat-stroked-button color="primary" (click)="downloadFile()">
|
<button type="button" mat-stroked-button color="primary" (click)="downloadFile()">
|
||||||
{{ 'security.2fa.dialog.download-txt' | translate }}
|
{{ 'security.2fa.dialog.download-txt' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" mat-raised-button color="primary">
|
<button type="button" mat-raised-button color="primary" (click)="printCode()">
|
||||||
{{ 'action.print' | translate }}
|
{{ 'action.print' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="mat-body-1 description" translate>security.2fa.dialog.backup-code-warn</p>
|
||||||
|
<div fxLayout="row" fxLayoutAlign="end start">
|
||||||
|
<button type="button" mat-raised-button color="primary" (click)="closeDialog()">
|
||||||
|
{{ 'action.done' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -29,6 +29,9 @@ import {
|
|||||||
} from '@shared/models/two-factor-auth.models';
|
} from '@shared/models/two-factor-auth.models';
|
||||||
import { mergeMap, tap } from 'rxjs/operators';
|
import { mergeMap, tap } from 'rxjs/operators';
|
||||||
import { ImportExportService } from '@home/components/import-export/import-export.service';
|
import { ImportExportService } from '@home/components/import-export/import-export.service';
|
||||||
|
import { deepClone } from '@core/utils';
|
||||||
|
|
||||||
|
import printTemplate from '!raw-loader!./backup-code-print-template.raw';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-backup-code-auth-dialog',
|
selector: 'tb-backup-code-auth-dialog',
|
||||||
@ -62,4 +65,24 @@ export class BackupCodeAuthDialogComponent extends DialogComponent<BackupCodeAut
|
|||||||
downloadFile() {
|
downloadFile() {
|
||||||
this.importExportService.exportText(this.backupCode.codes, 'backup-codes');
|
this.importExportService.exportText(this.backupCode.codes, 'backup-codes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printCode() {
|
||||||
|
const codeTemplate = deepClone(this.backupCode.codes)
|
||||||
|
.map(code => `<div class="code-row"><input type="checkbox"><span class="code">${code}</span></div>`).join('');
|
||||||
|
const printPage = printTemplate.replace('${codesBlock}', codeTemplate);
|
||||||
|
const newWindow = window.open('', 'Print backup code');
|
||||||
|
|
||||||
|
newWindow.document.open();
|
||||||
|
newWindow.document.write(printPage);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
newWindow.print();
|
||||||
|
|
||||||
|
newWindow.document.close();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
newWindow.close();
|
||||||
|
}, 10);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<title>Backup code</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.code-block {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.code-row {
|
||||||
|
margin: 0 6px 8px;
|
||||||
|
display: flex;
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
font: 400 16px / 20px Roboto Mono, "Helvetica Neue", monospace;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
input[type="checkbox"] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
font: inherit;
|
||||||
|
color: currentColor;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
border: 0.1em solid currentColor;
|
||||||
|
border-radius: 0.15em;
|
||||||
|
transform: translateY(0em);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="margin: 0">
|
||||||
|
<div style="margin: 8px; max-width: 286px">
|
||||||
|
<div style="border: #d0d7de solid 1px; border-radius:4px">
|
||||||
|
<h3 style="padding: 16px 24px; margin: 0; font: 500 20px / 24px Roboto, 'Helvetica Neue', sans-serif; text-align: center">
|
||||||
|
Backup codes
|
||||||
|
</h3>
|
||||||
|
<div class="code-block">
|
||||||
|
${codesBlock}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -66,15 +66,15 @@
|
|||||||
<mat-checkbox [value]="provider"
|
<mat-checkbox [value]="provider"
|
||||||
[checked]="useByDefault === provider"
|
[checked]="useByDefault === provider"
|
||||||
(click)="changeDefaultProvider($event, provider)"
|
(click)="changeDefaultProvider($event, provider)"
|
||||||
[disabled]="(isLoading$ | async) || activeSingleProvider"
|
[disabled]="(isLoading$ | async)"
|
||||||
*ngIf="twoFactorAuth.get(provider).value && provider !== twoFactorAuthProviderType.BACKUP_CODE">
|
*ngIf="twoFactorAuth.get(provider).value && provider !== twoFactorAuthProviderType.BACKUP_CODE && !activeSingleProvider">
|
||||||
<span class="checkbox-label" translate>security.2fa.main-2fa-method</span>
|
<span class="checkbox-label" translate>security.2fa.main-2fa-method</span>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
mat-stroked-button color="primary"
|
mat-stroked-button color="primary"
|
||||||
(click)="generateNewBackupCode()"
|
(click)="generateNewBackupCode()"
|
||||||
*ngIf="twoFactorAuth.get(provider).value && provider === twoFactorAuthProviderType.BACKUP_CODE">
|
*ngIf="twoFactorAuth.get(provider).value && provider === twoFactorAuthProviderType.BACKUP_CODE">
|
||||||
Get new code
|
{{ 'security.2fa.get-new-code' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<mat-divider *ngIf="!$last"></mat-divider>
|
<mat-divider *ngIf="!$last"></mat-divider>
|
||||||
|
|||||||
@ -2590,6 +2590,7 @@
|
|||||||
"authenticate-with": "You can authenticate with:",
|
"authenticate-with": "You can authenticate with:",
|
||||||
"disable-2fa-provider-text": "Disabling {{name}} will make your account less secure",
|
"disable-2fa-provider-text": "Disabling {{name}} will make your account less secure",
|
||||||
"disable-2fa-provider-title": "Are you sure you want to disable {{name}}?",
|
"disable-2fa-provider-title": "Are you sure you want to disable {{name}}?",
|
||||||
|
"get-new-code": "Get new code",
|
||||||
"main-2fa-method": "Use as main two-factor authentication method",
|
"main-2fa-method": "Use as main two-factor authentication method",
|
||||||
"dialog": {
|
"dialog": {
|
||||||
"activation-step-description-email": "The next time you login in, you will be prompted to enter the security code that will be sent to your email address.",
|
"activation-step-description-email": "The next time you login in, you will be prompted to enter the security code that will be sent to your email address.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user