mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 21:00:39 +08:00
Update 2fa Styling
- Add copy button for secret
This commit is contained in:
parent
90bff782b5
commit
ae05bdb653
3 changed files with 333 additions and 227 deletions
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
|
||||
<div class='container'>
|
||||
<div class='row'>
|
||||
<div class='row mb-3'>
|
||||
<div class='col'>
|
||||
<scrm-widget-panel [title]="appMethodHeaderLabel">
|
||||
<span widget-header-icon-area>
|
||||
|
@ -64,52 +64,64 @@
|
|||
<div class='d-flex col-md-12 pl-4 pr-4 pt-2 pb-2'>
|
||||
<scrm-label labelKey='LBL_OTP_SETUP' class='small'></scrm-label>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="isQrCodeGenerated()">
|
||||
<div *ngIf="qrCodeSvg" class='qr-code-container'>
|
||||
<div *ngIf="!showSecret()" class='qr-code'>
|
||||
<div [innerHTML]="qrCodeSvg | trustHtml">
|
||||
</div>
|
||||
<div>
|
||||
<a class="small show-secret-link pl-1" (click)="setShowSecret(true)">
|
||||
<scrm-label labelKey='LBL_USE_SECRET'>
|
||||
</scrm-label>
|
||||
</a>
|
||||
<div *ngIf="isQrCodeGenerated()" class="row-container">
|
||||
<div class="qr-code-container">
|
||||
<div class="col">
|
||||
<div *ngIf="qrCodeSvg" class='qr-code-col'>
|
||||
<div class='qr-code'>
|
||||
<div [innerHTML]="qrCodeSvg | trustHtml">
|
||||
</div>
|
||||
<div *ngIf="!showSecret()" class="secret-container">
|
||||
<a class="small show-secret-link pl-1"
|
||||
(click)="setShowSecret(true)">
|
||||
<scrm-label labelKey='LBL_USE_SECRET'>
|
||||
</scrm-label>
|
||||
</a>
|
||||
</div>
|
||||
<div *ngIf="showSecret()" class="secret-container">
|
||||
<a class="small show-secret-link pl-1"
|
||||
(click)="setShowSecret(false)">
|
||||
<scrm-label labelKey='LBL_HIDE_SECRET'>
|
||||
</scrm-label>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="showSecret()" class='qr-code'>
|
||||
<scrm-label class="pb-3" labelKey='LBL_USE_SECRET_DESC'>
|
||||
</scrm-label>
|
||||
<div class="col">
|
||||
<div *ngIf="showSecret()" class='qr-code-secret'>
|
||||
<scrm-label class="pb-3" labelKey='LBL_USE_SECRET_DESC'>
|
||||
</scrm-label>
|
||||
|
||||
<span class="small font-weight-bold pb-3 secret">{{ secret }}</span>
|
||||
<span class="font-weight-bold pb-2 secret">{{ secret }}</span>
|
||||
|
||||
<div>
|
||||
<a class="small show-secret-link" (click)="setShowSecret(false)">
|
||||
<scrm-label labelKey='LBL_SHOW_QR_CODE'>
|
||||
</scrm-label>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<scrm-label labelKey='LBL_QR_CODE_HELP'
|
||||
class='pl-3 d-inline-block qr-code-label'>
|
||||
</scrm-label>
|
||||
<div class='d-flex flex-column pt-4 align-items-center'>
|
||||
<input [(ngModel)]="authCode"
|
||||
id='auth_code'
|
||||
type='text'
|
||||
name='auth_code'
|
||||
autocomplete='off'
|
||||
class='mb-3 auth-input'/>
|
||||
|
||||
<scrm-button id='submit-2fa-code'
|
||||
[config]="verifyCodeButtonConfig">
|
||||
</scrm-button>
|
||||
<scrm-button class="pb-2"
|
||||
[config]="copySecretButtonConfig"></scrm-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div>
|
||||
<scrm-label labelKey='LBL_QR_CODE_HELP'
|
||||
class='pl-3 d-inline-block qr-code-label'>
|
||||
</scrm-label>
|
||||
<div class='d-flex flex-column pt-4 align-items-center'>
|
||||
<input [(ngModel)]="authCode"
|
||||
id='auth_code'
|
||||
type='text'
|
||||
name='auth_code'
|
||||
autocomplete='off'
|
||||
class='mb-3 auth-input'/>
|
||||
|
||||
<scrm-button id='submit-2fa-code'
|
||||
[config]="verifyCodeButtonConfig">
|
||||
</scrm-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</scrm-widget-panel>
|
||||
</div>
|
||||
|
@ -137,7 +149,7 @@
|
|||
|
||||
<ng-container *ngIf="areRecoveryCodesGenerated() && backupCodes">
|
||||
<div class='d-flex flex-column'>
|
||||
<scrm-button [config]="copyButtonConfig"></scrm-button>
|
||||
<scrm-button [config]="copyBackupButtonConfig"></scrm-button>
|
||||
</div>
|
||||
<div class='d-flex col-md-12 pl-4 pr-4 pt-2 pb-3'>
|
||||
<div>
|
||||
|
|
|
@ -62,7 +62,8 @@ export class TwoFactorComponent implements OnInit {
|
|||
cancelAppMethodButtonConfig: ButtonInterface;
|
||||
regenerateBackupCodesButtonConfig: ButtonInterface;
|
||||
verifyCodeButtonConfig: ButtonInterface;
|
||||
copyButtonConfig: ButtonInterface;
|
||||
copyBackupButtonConfig: ButtonInterface;
|
||||
copySecretButtonConfig: ButtonInterface;
|
||||
recoveryCodesHeaderLabel: string = '';
|
||||
|
||||
@HostListener('keyup.control.enter')
|
||||
|
@ -175,6 +176,10 @@ export class TwoFactorComponent implements OnInit {
|
|||
this.clipboard.copy(this.backupCodes);
|
||||
}
|
||||
|
||||
public copySecret(): void {
|
||||
this.clipboard.copy(this.secret);
|
||||
}
|
||||
|
||||
public generateCodes(): void {
|
||||
this.backupCodes = null;
|
||||
this.generateBackupCodesService.generate().subscribe({
|
||||
|
@ -248,7 +253,7 @@ export class TwoFactorComponent implements OnInit {
|
|||
} as ButtonInterface;
|
||||
|
||||
this.verifyCodeButtonConfig = {
|
||||
klass: 'btn btn-sm btn-main',
|
||||
klass: 'btn btn-sm btn-main mb-2',
|
||||
onClick: ((): void => {
|
||||
this.finalize2fa()
|
||||
}) as ButtonCallback,
|
||||
|
@ -256,7 +261,7 @@ export class TwoFactorComponent implements OnInit {
|
|||
titleKey: ''
|
||||
} as ButtonInterface;
|
||||
|
||||
this.copyButtonConfig = {
|
||||
this.copyBackupButtonConfig = {
|
||||
klass: 'btn btn-sm btn-main copy-button',
|
||||
onClick: ((): void => {
|
||||
this.copyBackupCodes()
|
||||
|
@ -265,5 +270,15 @@ export class TwoFactorComponent implements OnInit {
|
|||
titleKey: '',
|
||||
icon: 'clipboard'
|
||||
} as ButtonInterface;
|
||||
|
||||
this.copySecretButtonConfig = {
|
||||
klass: 'btn btn-sm btn-main ml-0',
|
||||
onClick: ((): void => {
|
||||
this.copySecret()
|
||||
}) as ButtonCallback,
|
||||
labelKey: 'LBL_COPY',
|
||||
titleKey: '',
|
||||
icon: 'clipboard'
|
||||
} as ButtonInterface;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,50 +12,266 @@
|
|||
}
|
||||
|
||||
@media (min-width: 991px) {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 10px;
|
||||
#two-factor {
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
|
||||
.col {
|
||||
|
||||
.backup-code-warning {
|
||||
width: fit-content;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.qr-code-col {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code-secret {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
padding-left: .25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.qr-code .show-secret-link,
|
||||
.qr-code-secret .show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
|
||||
.qr-code .show-secret-link:hover,
|
||||
.qr-code-secret .show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auth-input {
|
||||
border: .03em solid $nepal-grey;
|
||||
padding: .45em;
|
||||
margin: 0 1em 0 0;
|
||||
color: #666;
|
||||
font-size: .8em;
|
||||
background-color: #fff;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.row-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.qr-code-label {
|
||||
font-size: 95%;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 991px) {
|
||||
#two-factor {
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.col {
|
||||
.backup-code-warning {
|
||||
width: fit-content;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
flex: 0 0 41.666667%;
|
||||
max-width: 41.666667%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.qr-code-col {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.qr-code-secret {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
padding-left: .25rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.qr-code .show-secret-link,
|
||||
.qr-code-secret .show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
|
||||
.qr-code .show-secret-link:hover,
|
||||
.qr-code-secret .show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auth-input {
|
||||
border: .03em solid $nepal-grey;
|
||||
padding: .45em;
|
||||
margin: 0 1em 0 0;
|
||||
color: #666;
|
||||
font-size: .8em;
|
||||
background-color: #fff;
|
||||
width: 30%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.row-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.qr-code-label {
|
||||
font-size: 95%;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@media(max-width: 767px) {
|
||||
#two-factor {
|
||||
|
||||
.container {
|
||||
.row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.col {
|
||||
.backup-code-warning {
|
||||
width: fit-content;
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.secret-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
padding: .25rem 1.5rem .5rem 1.5rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
|
||||
.qr-code-col {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
.qr-code-secret {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
padding-left: .25rem;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex-direction: column;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
.qr-code .show-secret-link,
|
||||
.qr-code-secret .show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
|
||||
.show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
.qr-code .show-secret-link:hover,
|
||||
.qr-code-secret .show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auth-input {
|
||||
|
@ -69,96 +285,25 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code-label {
|
||||
font-size: 95%;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.row {
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 10px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
.row-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.qr-code-label {
|
||||
font-size: 95%;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 375px) and (max-width: 767px) {
|
||||
#two-factor {
|
||||
|
||||
.container {
|
||||
.row {
|
||||
.col {
|
||||
.backup-code-warning {
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .25rem 1.5rem .5rem 1.5rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.auth-input {
|
||||
border: .03em solid $nepal-grey;
|
||||
padding: .75rem .5rem;
|
||||
margin: 0 1em 0 0;
|
||||
color: #666;
|
||||
font-size: .8em;
|
||||
background-color: #fff;
|
||||
width: 75%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: .25rem;
|
||||
|
||||
.secret {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
|
||||
.show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code-label {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 374px) {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
@ -170,91 +315,25 @@
|
|||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: .5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: .5rem;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: 374px) {
|
||||
#two-factor {
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.container {
|
||||
.row {
|
||||
.col {
|
||||
.backup-code-warning {
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: .25rem 1.5rem .5rem 1.5rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.auth-input {
|
||||
border: .03em solid $nepal-grey;
|
||||
padding: .75rem .5rem;
|
||||
margin: 0 1em 0 0;
|
||||
color: #666;
|
||||
font-size: .8em;
|
||||
background-color: #fff;
|
||||
width: 75%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: .25rem;
|
||||
|
||||
.secret {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.show-secret-link {
|
||||
clear: both;
|
||||
color: $coral-pink;
|
||||
}
|
||||
|
||||
.show-secret-link:hover {
|
||||
color: $light-orange;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.qr-code-label {
|
||||
font-size: 80%;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.backup-codes-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
.backup-codes {
|
||||
padding: 5px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: .5rem;
|
||||
width: fit-content;
|
||||
.backup-codes {
|
||||
padding: 5px;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue