mirror of
https://github.com/bitwarden/browser
synced 2025-12-23 11:43:46 +00:00
Apply Prettier (#2238)
This commit is contained in:
@@ -1,67 +1,104 @@
|
||||
<form #form (ngSubmit)="submit()">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'close' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{ "close" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "appName" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "save" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<h2 class="box-header">
|
||||
{{ "selfHostedEnvironment" | i18n }}
|
||||
</h2>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="baseUrl">{{ "baseUrl" | i18n }}</label>
|
||||
<input
|
||||
id="baseUrl"
|
||||
type="text"
|
||||
name="BaseUrl"
|
||||
[(ngModel)]="baseUrl"
|
||||
placeholder="ex. https://bitwarden.company.com"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'appName' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'save' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "selfHostedEnvironmentFooter" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h2 class="box-header">
|
||||
{{ "customEnvironment" | i18n }}
|
||||
</h2>
|
||||
<div class="box-content" [hidden]="!showCustom">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="webVaultUrl">{{ "webVaultUrl" | i18n }}</label>
|
||||
<input
|
||||
id="webVaultUrl"
|
||||
type="text"
|
||||
name="WebVaultUrl"
|
||||
[(ngModel)]="webVaultUrl"
|
||||
inputmode="url"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<h2 class="box-header">
|
||||
{{'selfHostedEnvironment' | i18n}}
|
||||
</h2>
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="baseUrl">{{'baseUrl' | i18n}}</label>
|
||||
<input id="baseUrl" type="text" name="BaseUrl" [(ngModel)]="baseUrl"
|
||||
placeholder="ex. https://bitwarden.company.com" appInputVerbatim>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'selfHostedEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="apiUrl">{{ "apiUrl" | i18n }}</label>
|
||||
<input
|
||||
id="apiUrl"
|
||||
type="text"
|
||||
name="ApiUrl"
|
||||
[(ngModel)]="apiUrl"
|
||||
inputmode="url"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h2 class="box-header">
|
||||
{{'customEnvironment' | i18n}}
|
||||
</h2>
|
||||
<div class="box-content" [hidden]="!showCustom">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="webVaultUrl">{{'webVaultUrl' | i18n}}</label>
|
||||
<input id="webVaultUrl" type="text" name="WebVaultUrl" [(ngModel)]="webVaultUrl" inputmode="url"
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="apiUrl">{{'apiUrl' | i18n}}</label>
|
||||
<input id="apiUrl" type="text" name="ApiUrl" [(ngModel)]="apiUrl" inputmode="url" appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="identityUrl">{{'identityUrl' | i18n}}</label>
|
||||
<input id="identityUrl" type="text" name="IdentityUrl" [(ngModel)]="identityUrl" inputmode="url"
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="notificationsUrl">{{'notificationsUrl' | i18n}}</label>
|
||||
<input id="notificationsUrl" type="text" name="NotificationsUrl" inputmode="url"
|
||||
[(ngModel)]="notificationsUrl" appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="iconsUrl">{{'iconsUrl' | i18n}}</label>
|
||||
<input id="iconsUrl" type="text" name="IconsUrl" [(ngModel)]="iconsUrl" inputmode="url"
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer" [hidden]="!showCustom">
|
||||
{{'customEnvironmentFooter' | i18n}}
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="identityUrl">{{ "identityUrl" | i18n }}</label>
|
||||
<input
|
||||
id="identityUrl"
|
||||
type="text"
|
||||
name="IdentityUrl"
|
||||
[(ngModel)]="identityUrl"
|
||||
inputmode="url"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
</content>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="notificationsUrl">{{ "notificationsUrl" | i18n }}</label>
|
||||
<input
|
||||
id="notificationsUrl"
|
||||
type="text"
|
||||
name="NotificationsUrl"
|
||||
inputmode="url"
|
||||
[(ngModel)]="notificationsUrl"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="iconsUrl">{{ "iconsUrl" | i18n }}</label>
|
||||
<input
|
||||
id="iconsUrl"
|
||||
type="text"
|
||||
name="IconsUrl"
|
||||
[(ngModel)]="iconsUrl"
|
||||
inputmode="url"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer" [hidden]="!showCustom">
|
||||
{{ "customEnvironmentFooter" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { EnvironmentComponent as BaseEnvironmentComponent } from 'jslib-angular/components/environment.component';
|
||||
import { EnvironmentComponent as BaseEnvironmentComponent } from "jslib-angular/components/environment.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-environment',
|
||||
templateUrl: 'environment.component.html',
|
||||
selector: "app-environment",
|
||||
templateUrl: "environment.component.html",
|
||||
})
|
||||
export class EnvironmentComponent extends BaseEnvironmentComponent {
|
||||
constructor(platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
|
||||
i18nService: I18nService, private router: Router) {
|
||||
super(platformUtilsService, environmentService, i18nService);
|
||||
this.showCustom = true;
|
||||
}
|
||||
constructor(
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
environmentService: EnvironmentService,
|
||||
i18nService: I18nService,
|
||||
private router: Router
|
||||
) {
|
||||
super(platformUtilsService, environmentService, i18nService);
|
||||
this.showCustom = true;
|
||||
}
|
||||
|
||||
saved() {
|
||||
super.saved();
|
||||
this.router.navigate(['']);
|
||||
}
|
||||
saved() {
|
||||
super.saved();
|
||||
this.router.navigate([""]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,38 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{'cancel' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "passwordHint" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "submit" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{ "emailAddress" | i18n }}</label>
|
||||
<input
|
||||
id="email"
|
||||
type="text"
|
||||
name="Email"
|
||||
[(ngModel)]="email"
|
||||
required
|
||||
appAutofocus
|
||||
inputmode="email"
|
||||
appInputVerbatim="false"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'passwordHint' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required appAutofocus
|
||||
inputmode="email" appInputVerbatim="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'enterEmailToGetHint' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "enterEmailToGetHint" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import { HintComponent as BaseHintComponent } from 'jslib-angular/components/hint.component';
|
||||
import { HintComponent as BaseHintComponent } from "jslib-angular/components/hint.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-hint',
|
||||
templateUrl: 'hint.component.html',
|
||||
selector: "app-hint",
|
||||
templateUrl: "hint.component.html",
|
||||
})
|
||||
export class HintComponent extends BaseHintComponent {
|
||||
constructor(router: Router, platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService, apiService: ApiService, logService: LogService) {
|
||||
super(router, i18nService, apiService, platformUtilsService, logService);
|
||||
}
|
||||
constructor(
|
||||
router: Router,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService,
|
||||
apiService: ApiService,
|
||||
logService: LogService
|
||||
) {
|
||||
super(router, i18nService, apiService, platformUtilsService, logService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<div class="center-content">
|
||||
<div class="content">
|
||||
<div class="logo-image"></div>
|
||||
<p class="lead text-center">{{'loginOrCreateNewAccount' | i18n}}</p>
|
||||
<a class="btn primary block" routerLink="/login"><b>{{'login' | i18n}}</b></a>
|
||||
<button type="button" (click)="launchSsoBrowser()" class="btn block">
|
||||
<i class="fa fa-bank" aria-hidden="true"></i> {{'enterpriseSingleSignOn' | i18n}}
|
||||
</button>
|
||||
<a class="btn block" routerLink="/register">{{'createAccount' | i18n}}</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="logo-image"></div>
|
||||
<p class="lead text-center">{{ "loginOrCreateNewAccount" | i18n }}</p>
|
||||
<a class="btn primary block" routerLink="/login"
|
||||
><b>{{ "login" | i18n }}</b></a
|
||||
>
|
||||
<button type="button" (click)="launchSsoBrowser()" class="btn block">
|
||||
<i class="fa fa-bank" aria-hidden="true"></i> {{ "enterpriseSingleSignOn" | i18n }}
|
||||
</button>
|
||||
<a class="btn block" routerLink="/register">{{ "createAccount" | i18n }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<a routerLink="/environment" class="settings-icon">
|
||||
<i class="fa fa-cog fa-lg" aria-hidden="true"></i><span> {{'settings' | i18n}}</span>
|
||||
<i class="fa fa-cog fa-lg" aria-hidden="true"></i><span> {{ "settings" | i18n }}</span>
|
||||
</a>
|
||||
|
||||
@@ -1,53 +1,66 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
import { ConstantsService } from "jslib-common/services/constants.service";
|
||||
|
||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
|
||||
import { Utils } from 'jslib-common/misc/utils';
|
||||
import { Utils } from "jslib-common/misc/utils";
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: 'home.component.html',
|
||||
selector: "app-home",
|
||||
templateUrl: "home.component.html",
|
||||
})
|
||||
export class HomeComponent {
|
||||
constructor(protected platformUtilsService: PlatformUtilsService,
|
||||
private passwordGenerationService: PasswordGenerationService, private storageService: StorageService,
|
||||
private cryptoFunctionService: CryptoFunctionService, private environmentService: EnvironmentService) { }
|
||||
constructor(
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
private passwordGenerationService: PasswordGenerationService,
|
||||
private storageService: StorageService,
|
||||
private cryptoFunctionService: CryptoFunctionService,
|
||||
private environmentService: EnvironmentService
|
||||
) {}
|
||||
|
||||
async launchSsoBrowser() {
|
||||
// Generate necessary sso params
|
||||
const passwordOptions: any = {
|
||||
type: 'password',
|
||||
length: 64,
|
||||
uppercase: true,
|
||||
lowercase: true,
|
||||
numbers: true,
|
||||
special: false,
|
||||
};
|
||||
async launchSsoBrowser() {
|
||||
// Generate necessary sso params
|
||||
const passwordOptions: any = {
|
||||
type: "password",
|
||||
length: 64,
|
||||
uppercase: true,
|
||||
lowercase: true,
|
||||
numbers: true,
|
||||
special: false,
|
||||
};
|
||||
|
||||
const state = (await this.passwordGenerationService.generatePassword(passwordOptions)) + ':clientId=browser';
|
||||
const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions);
|
||||
const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, 'sha256');
|
||||
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
|
||||
const state =
|
||||
(await this.passwordGenerationService.generatePassword(passwordOptions)) +
|
||||
":clientId=browser";
|
||||
const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions);
|
||||
const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256");
|
||||
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
|
||||
|
||||
await this.storageService.save(ConstantsService.ssoCodeVerifierKey, codeVerifier);
|
||||
await this.storageService.save(ConstantsService.ssoStateKey, state);
|
||||
await this.storageService.save(ConstantsService.ssoCodeVerifierKey, codeVerifier);
|
||||
await this.storageService.save(ConstantsService.ssoStateKey, state);
|
||||
|
||||
let url = this.environmentService.getWebVaultUrl();
|
||||
if (url == null) {
|
||||
url = 'https://vault.bitwarden.com';
|
||||
}
|
||||
|
||||
const redirectUri = url + '/sso-connector.html';
|
||||
|
||||
// Launch browser
|
||||
this.platformUtilsService.launchUri(url + '/#/sso?clientId=browser' +
|
||||
'&redirectUri=' + encodeURIComponent(redirectUri) +
|
||||
'&state=' + state + '&codeChallenge=' + codeChallenge);
|
||||
let url = this.environmentService.getWebVaultUrl();
|
||||
if (url == null) {
|
||||
url = "https://vault.bitwarden.com";
|
||||
}
|
||||
|
||||
const redirectUri = url + "/sso-connector.html";
|
||||
|
||||
// Launch browser
|
||||
this.platformUtilsService.launchUri(
|
||||
url +
|
||||
"/#/sso?clientId=browser" +
|
||||
"&redirectUri=" +
|
||||
encodeURIComponent(redirectUri) +
|
||||
"&state=" +
|
||||
state +
|
||||
"&codeChallenge=" +
|
||||
codeChallenge
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,74 @@
|
||||
<form (ngSubmit)="submit()">
|
||||
<header>
|
||||
<div class="left"></div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'verifyIdentity' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick *ngIf="!hideInput">{{'unlock' | i18n}}</button>
|
||||
<header>
|
||||
<div class="left"></div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "verifyIdentity" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick *ngIf="!hideInput">{{ "unlock" | i18n }}</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow *ngIf="!hideInput">
|
||||
<div class="row-main" *ngIf="pinLock">
|
||||
<label for="pin">{{ "pin" | i18n }}</label>
|
||||
<input
|
||||
id="pin"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="PIN"
|
||||
class="monospaced"
|
||||
[(ngModel)]="pin"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="row-main" *ngIf="!pinLock">
|
||||
<label for="masterPassword">{{ "masterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword()"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow *ngIf="!hideInput">
|
||||
<div class="row-main" *ngIf="pinLock">
|
||||
<label for="pin">{{'pin' | i18n}}</label>
|
||||
<input id="pin" type="{{showPassword ? 'text' : 'password'}}" name="PIN" class="monospaced"
|
||||
[(ngModel)]="pin" required appInputVerbatim>
|
||||
</div>
|
||||
<div class="row-main" *ngIf="!pinLock">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"
|
||||
aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<p>{{'yourVaultIsLocked' | i18n}}</p>
|
||||
{{'loggedInAsOn' | i18n : email : webVaultHostname}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="biometricLock">
|
||||
<div class="box-footer">
|
||||
<button type="button" class="btn primary block" (click)="unlockBiometric()"
|
||||
appStopClick>{{'unlockWithBiometrics' | i18n}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<button type="button" appStopClick (click)="logOut()">{{'logOut' | i18n}}</button>
|
||||
</p>
|
||||
</content>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<p>{{ "yourVaultIsLocked" | i18n }}</p>
|
||||
{{ "loggedInAsOn" | i18n: email:webVaultHostname }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="biometricLock">
|
||||
<div class="box-footer">
|
||||
<button type="button" class="btn primary block" (click)="unlockBiometric()" appStopClick>
|
||||
{{ "unlockWithBiometrics" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<button type="button" appStopClick (click)="logOut()">{{ "logOut" | i18n }}</button>
|
||||
</p>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,87 +1,107 @@
|
||||
import {
|
||||
Component,
|
||||
NgZone,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import Swal from 'sweetalert2';
|
||||
import { Component, NgZone } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
import Swal from "sweetalert2";
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
import { ConstantsService } from "jslib-common/services/constants.service";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { KeyConnectorService } from 'jslib-common/abstractions/keyConnector.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
import { UserService } from "jslib-common/abstractions/user.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { LockComponent as BaseLockComponent } from 'jslib-angular/components/lock.component';
|
||||
import { LockComponent as BaseLockComponent } from "jslib-angular/components/lock.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-lock',
|
||||
templateUrl: 'lock.component.html',
|
||||
selector: "app-lock",
|
||||
templateUrl: "lock.component.html",
|
||||
})
|
||||
export class LockComponent extends BaseLockComponent {
|
||||
private isInitialLockScreen: boolean;
|
||||
private isInitialLockScreen: boolean;
|
||||
|
||||
constructor(router: Router, i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
|
||||
userService: UserService, cryptoService: CryptoService,
|
||||
storageService: StorageService, vaultTimeoutService: VaultTimeoutService,
|
||||
environmentService: EnvironmentService, stateService: StateService,
|
||||
apiService: ApiService, logService: LogService, keyConnectorService: KeyConnectorService,
|
||||
ngZone: NgZone) {
|
||||
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
|
||||
storageService, vaultTimeoutService, environmentService, stateService, apiService, logService,
|
||||
keyConnectorService, ngZone);
|
||||
this.successRoute = '/tabs/current';
|
||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||
}
|
||||
constructor(
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
messagingService: MessagingService,
|
||||
userService: UserService,
|
||||
cryptoService: CryptoService,
|
||||
storageService: StorageService,
|
||||
vaultTimeoutService: VaultTimeoutService,
|
||||
environmentService: EnvironmentService,
|
||||
stateService: StateService,
|
||||
apiService: ApiService,
|
||||
logService: LogService,
|
||||
keyConnectorService: KeyConnectorService,
|
||||
ngZone: NgZone
|
||||
) {
|
||||
super(
|
||||
router,
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
messagingService,
|
||||
userService,
|
||||
cryptoService,
|
||||
storageService,
|
||||
vaultTimeoutService,
|
||||
environmentService,
|
||||
stateService,
|
||||
apiService,
|
||||
logService,
|
||||
keyConnectorService,
|
||||
ngZone
|
||||
);
|
||||
this.successRoute = "/tabs/current";
|
||||
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
const disableAutoBiometricsPrompt = await this.storageService.get<boolean>(
|
||||
ConstantsService.disableAutoBiometricsPromptKey) ?? true;
|
||||
async ngOnInit() {
|
||||
await super.ngOnInit();
|
||||
const disableAutoBiometricsPrompt =
|
||||
(await this.storageService.get<boolean>(ConstantsService.disableAutoBiometricsPromptKey)) ??
|
||||
true;
|
||||
|
||||
window.setTimeout(async () => {
|
||||
document.getElementById(this.pinLock ? 'pin' : 'masterPassword').focus();
|
||||
if (this.biometricLock && !disableAutoBiometricsPrompt && this.isInitialLockScreen) {
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
await this.unlockBiometric();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
async unlockBiometric(): Promise<boolean> {
|
||||
if (!this.biometricLock) {
|
||||
return;
|
||||
window.setTimeout(async () => {
|
||||
document.getElementById(this.pinLock ? "pin" : "masterPassword").focus();
|
||||
if (this.biometricLock && !disableAutoBiometricsPrompt && this.isInitialLockScreen) {
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
await this.unlockBiometric();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<div class="swal2-text">${this.i18nService.t('awaitDesktop')}</div>`;
|
||||
|
||||
Swal.fire({
|
||||
heightAuto: false,
|
||||
buttonsStyling: false,
|
||||
html: div,
|
||||
showCancelButton: true,
|
||||
cancelButtonText: this.i18nService.t('cancel'),
|
||||
showConfirmButton: false,
|
||||
});
|
||||
|
||||
const success = await super.unlockBiometric();
|
||||
|
||||
// Avoid closing the error dialogs
|
||||
if (success) {
|
||||
Swal.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
async unlockBiometric(): Promise<boolean> {
|
||||
if (!this.biometricLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.innerHTML = `<div class="swal2-text">${this.i18nService.t("awaitDesktop")}</div>`;
|
||||
|
||||
Swal.fire({
|
||||
heightAuto: false,
|
||||
buttonsStyling: false,
|
||||
html: div,
|
||||
showCancelButton: true,
|
||||
cancelButtonText: this.i18nService.t("cancel"),
|
||||
showConfirmButton: false,
|
||||
});
|
||||
|
||||
const success = await super.unlockBiometric();
|
||||
|
||||
// Avoid closing the error dialogs
|
||||
if (success) {
|
||||
Swal.close();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,71 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'cancel' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "appName" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "login" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{ "emailAddress" | i18n }}</label>
|
||||
<input
|
||||
id="email"
|
||||
type="text"
|
||||
name="Email"
|
||||
[(ngModel)]="email"
|
||||
required
|
||||
inputmode="email"
|
||||
appInputVerbatim="false"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'appName' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'login' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{ "masterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword()"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required inputmode="email"
|
||||
appInputVerbatim="false">
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}" name="MasterPassword"
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"
|
||||
aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" [hidden]="!showCaptcha()">
|
||||
<iframe id="hcaptcha_iframe" height="80"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" [hidden]="!showCaptcha()">
|
||||
<iframe id="hcaptcha_iframe" height="80"></iframe>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<a routerLink="/hint">{{'getMasterPasswordHint' | i18n}}</a>
|
||||
</p>
|
||||
</content>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<a routerLink="/hint">{{ "getMasterPasswordHint" | i18n }}</a>
|
||||
</p>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,42 +1,58 @@
|
||||
import {
|
||||
Component,
|
||||
NgZone,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, NgZone } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from 'jslib-angular/components/login.component';
|
||||
import { LoginComponent as BaseLoginComponent } from "jslib-angular/components/login.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: 'login.component.html',
|
||||
selector: "app-login",
|
||||
templateUrl: "login.component.html",
|
||||
})
|
||||
export class LoginComponent extends BaseLoginComponent {
|
||||
constructor(authService: AuthService, router: Router,
|
||||
protected platformUtilsService: PlatformUtilsService, protected i18nService: I18nService,
|
||||
protected stateService: StateService, protected environmentService: EnvironmentService,
|
||||
protected passwordGenerationService: PasswordGenerationService,
|
||||
protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
|
||||
syncService: SyncService, logService: LogService, ngZone: NgZone) {
|
||||
super(authService, router, platformUtilsService, i18nService, stateService, environmentService,
|
||||
passwordGenerationService, cryptoFunctionService, storageService, logService, ngZone);
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
};
|
||||
super.successRoute = '/tabs/vault';
|
||||
}
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected i18nService: I18nService,
|
||||
protected stateService: StateService,
|
||||
protected environmentService: EnvironmentService,
|
||||
protected passwordGenerationService: PasswordGenerationService,
|
||||
protected cryptoFunctionService: CryptoFunctionService,
|
||||
storageService: StorageService,
|
||||
syncService: SyncService,
|
||||
logService: LogService,
|
||||
ngZone: NgZone
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
router,
|
||||
platformUtilsService,
|
||||
i18nService,
|
||||
stateService,
|
||||
environmentService,
|
||||
passwordGenerationService,
|
||||
cryptoFunctionService,
|
||||
storageService,
|
||||
logService,
|
||||
ngZone
|
||||
);
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
};
|
||||
super.successRoute = "/tabs/vault";
|
||||
}
|
||||
|
||||
settings() {
|
||||
this.router.navigate(['environment']);
|
||||
}
|
||||
settings() {
|
||||
this.router.navigate(["environment"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,100 +1,160 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'cancel' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "createAccount" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "submit" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{ "emailAddress" | i18n }}</label>
|
||||
<input
|
||||
id="email"
|
||||
type="text"
|
||||
name="Email"
|
||||
[(ngModel)]="email"
|
||||
required
|
||||
[appAutofocus]="email === ''"
|
||||
inputmode="email"
|
||||
appInputVerbatim="false"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'createAccount' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">
|
||||
{{ "masterPass" | i18n }}
|
||||
<strong
|
||||
class="sub-label text-{{ masterPasswordScoreColor }}"
|
||||
*ngIf="masterPasswordScoreText"
|
||||
>
|
||||
{{ masterPasswordScoreText }}
|
||||
</strong>
|
||||
</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
[appAutofocus]="email !== ''"
|
||||
appInputVerbatim
|
||||
(input)="updatePasswordStrength()"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(false)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div
|
||||
class="progress-bar bg-{{ masterPasswordScoreColor }}"
|
||||
role="progressbar"
|
||||
aria-valuenow="0"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
[ngStyle]="{ width: masterPasswordScoreWidth + '%' }"
|
||||
attr.aria-valuenow="{{ masterPasswordScoreWidth }}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "masterPassDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{ "reTypeMasterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPasswordRetype"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPasswordRetype"
|
||||
class="monospaced"
|
||||
[(ngModel)]="confirmMasterPassword"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(true)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="email">{{'emailAddress' | i18n}}</label>
|
||||
<input id="email" type="text" name="Email" [(ngModel)]="email" required
|
||||
[appAutofocus]="email === ''" inputmode="email" appInputVerbatim="false">
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">
|
||||
{{'masterPass' | i18n}}
|
||||
<strong class="sub-label text-{{masterPasswordScoreColor}}"
|
||||
*ngIf="masterPasswordScoreText">
|
||||
{{masterPasswordScoreText}}
|
||||
</strong>
|
||||
</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
|
||||
[appAutofocus]="email !== ''" appInputVerbatim (input)="updatePasswordStrength()">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{masterPasswordScoreColor}}" role="progressbar" aria-valuenow="0"
|
||||
aria-valuemin="0" aria-valuemax="100" [ngStyle]="{width: (masterPasswordScoreWidth + '%')}"
|
||||
attr.aria-valuenow="{{masterPasswordScoreWidth}}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassDesc' | i18n}}
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{ "masterPassHint" | i18n }}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint" />
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="confirmMasterPassword" required
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "masterPassHintDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<div [hidden]="!showCaptcha()"><iframe id="hcaptcha_iframe" height="80"></iframe></div>
|
||||
<div class="box last" *ngIf="showTerms">
|
||||
<div class="box-content">
|
||||
<div
|
||||
class="box-content-row box-content-row-checkbox box-content-row-checkbox-left box-content-row-word-break"
|
||||
appBoxRow
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="acceptPolicies"
|
||||
[(ngModel)]="acceptPolicies"
|
||||
name="AcceptPolicies"
|
||||
/>
|
||||
<label for="acceptPolicies">
|
||||
{{ "acceptPolicies" | i18n }}<br />
|
||||
<a href="https://bitwarden.com/terms/" target="_blank" rel="noopener">{{
|
||||
"termsOfService" | i18n
|
||||
}}</a
|
||||
>,
|
||||
<a href="https://bitwarden.com/privacy/" target="_blank" rel="noopener">{{
|
||||
"privacyPolicy" | i18n
|
||||
}}</a>
|
||||
</label>
|
||||
</div>
|
||||
<div [hidden]="!showCaptcha()"><iframe id="hcaptcha_iframe" height="80"></iframe></div>
|
||||
<div class="box last" *ngIf="showTerms">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox box-content-row-checkbox-left box-content-row-word-break"
|
||||
appBoxRow>
|
||||
<input type="checkbox" id="acceptPolicies" [(ngModel)]="acceptPolicies" name="AcceptPolicies">
|
||||
<label for="acceptPolicies">
|
||||
{{'acceptPolicies' | i18n}}<br>
|
||||
<a href="https://bitwarden.com/terms/" target="_blank"
|
||||
rel="noopener">{{'termsOfService' | i18n}}</a>,
|
||||
<a href="https://bitwarden.com/privacy/" target="_blank"
|
||||
rel="noopener">{{'privacyPolicy' | i18n}}</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,29 +1,46 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
|
||||
import { RegisterComponent as BaseRegisterComponent } from 'jslib-angular/components/register.component';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { RegisterComponent as BaseRegisterComponent } from "jslib-angular/components/register.component";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-register',
|
||||
templateUrl: 'register.component.html',
|
||||
selector: "app-register",
|
||||
templateUrl: "register.component.html",
|
||||
})
|
||||
export class RegisterComponent extends BaseRegisterComponent {
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, cryptoService: CryptoService,
|
||||
apiService: ApiService, stateService: StateService, platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService, environmentService: EnvironmentService,
|
||||
logService: LogService) {
|
||||
super(authService, router, i18nService, cryptoService, apiService, stateService, platformUtilsService,
|
||||
passwordGenerationService, environmentService, logService);
|
||||
}
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
apiService: ApiService,
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
environmentService: EnvironmentService,
|
||||
logService: LogService
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
router,
|
||||
i18nService,
|
||||
cryptoService,
|
||||
apiService,
|
||||
stateService,
|
||||
platformUtilsService,
|
||||
passwordGenerationService,
|
||||
environmentService,
|
||||
logService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,49 @@
|
||||
<header>
|
||||
<div class="left"></div>
|
||||
<div class="center">
|
||||
<span class="title">{{'removeMasterPassword' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
<div class="left"></div>
|
||||
<div class="center">
|
||||
<span class="title">{{ "removeMasterPassword" | i18n }}</span>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<p>{{'convertOrganizationEncryptionDesc' | i18n : organization.name}}</p>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button type="button" class="btn block primary" (click)="convert()" [disabled]="actionPromise">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true" *ngIf="continuing"></i>
|
||||
{{'removeMasterPassword' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button type="button" class="btn btn-outline-secondary block" (click)="leave()" [disabled]="actionPromise">
|
||||
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true" *ngIf="leaving"></i>
|
||||
{{'leaveOrganization' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<p>{{ "convertOrganizationEncryptionDesc" | i18n: organization.name }}</p>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button
|
||||
type="button"
|
||||
class="btn block primary"
|
||||
(click)="convert()"
|
||||
[disabled]="actionPromise"
|
||||
>
|
||||
<i
|
||||
class="fa fa-spinner fa-spin"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
*ngIf="continuing"
|
||||
></i>
|
||||
{{ "removeMasterPassword" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-content-row">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary block"
|
||||
(click)="leave()"
|
||||
[disabled]="actionPromise"
|
||||
>
|
||||
<i
|
||||
class="fa fa-spinner fa-spin"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
*ngIf="leaving"
|
||||
></i>
|
||||
{{ "leaveOrganization" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { RemovePasswordComponent as BaseRemovePasswordComponent } from 'jslib-angular/components/remove-password.component';
|
||||
import { RemovePasswordComponent as BaseRemovePasswordComponent } from "jslib-angular/components/remove-password.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-remove-password',
|
||||
templateUrl: 'remove-password.component.html',
|
||||
selector: "app-remove-password",
|
||||
templateUrl: "remove-password.component.html",
|
||||
})
|
||||
export class RemovePasswordComponent extends BaseRemovePasswordComponent {
|
||||
}
|
||||
export class RemovePasswordComponent extends BaseRemovePasswordComponent {}
|
||||
|
||||
@@ -1,100 +1,150 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'setMasterPassword' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="full-loading-spinner" *ngIf="syncLoading">
|
||||
<i class="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div *ngIf="!syncLoading">
|
||||
<div class="box">
|
||||
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||
<app-callout type="warning" title="{{'resetPasswordPolicyAutoEnroll' | i18n}}"
|
||||
*ngIf="resetPasswordAutoEnroll">
|
||||
{{'resetPasswordAutoEnrollInviteWarning' | i18n}}
|
||||
</app-callout>
|
||||
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
|
||||
</app-callout>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{ "cancel" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "setMasterPassword" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "submit" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="full-loading-spinner" *ngIf="syncLoading">
|
||||
<i class="fa fa-spinner fa-spin fa-3x" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div *ngIf="!syncLoading">
|
||||
<div class="box">
|
||||
<app-callout type="tip">{{ "ssoCompleteRegistration" | i18n }}</app-callout>
|
||||
<app-callout
|
||||
type="warning"
|
||||
title="{{ 'resetPasswordPolicyAutoEnroll' | i18n }}"
|
||||
*ngIf="resetPasswordAutoEnroll"
|
||||
>
|
||||
{{ "resetPasswordAutoEnrollInviteWarning" | i18n }}
|
||||
</app-callout>
|
||||
<app-callout
|
||||
type="info"
|
||||
[enforcedPolicyOptions]="enforcedPolicyOptions"
|
||||
*ngIf="enforcedPolicyOptions"
|
||||
>
|
||||
</app-callout>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword"
|
||||
>{{ "masterPass" | i18n }}
|
||||
<strong
|
||||
class="sub-label text-{{ masterPasswordScoreColor }}"
|
||||
*ngIf="masterPasswordScoreText"
|
||||
>
|
||||
{{ masterPasswordScoreText }}
|
||||
</strong>
|
||||
</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
(input)="updatePasswordStrength()"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(false)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">{{'masterPass' | i18n}}
|
||||
<strong class="sub-label text-{{masterPasswordScoreColor}}"
|
||||
*ngIf="masterPasswordScoreText">
|
||||
{{masterPasswordScoreText}}
|
||||
</strong>
|
||||
</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
|
||||
(input)="updatePasswordStrength()" appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{masterPasswordScoreColor}}" role="progressbar"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
|
||||
[ngStyle]="{width: (masterPasswordScoreWidth + '%')}"
|
||||
attr.aria-valuenow="{{masterPasswordScoreWidth}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="password" name="MasterPasswordRetype"
|
||||
class="monospaced" [(ngModel)]="masterPasswordRetype" required appInputVerbatim
|
||||
autocomplete="new-password">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div
|
||||
class="progress-bar bg-{{ masterPasswordScoreColor }}"
|
||||
role="progressbar"
|
||||
aria-valuenow="0"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
[ngStyle]="{ width: masterPasswordScoreWidth + '%' }"
|
||||
attr.aria-valuenow="{{ masterPasswordScoreWidth }}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
<div class="box-footer">
|
||||
{{ "masterPassDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{ "reTypeMasterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPasswordRetype"
|
||||
type="password"
|
||||
name="MasterPasswordRetype"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPasswordRetype"
|
||||
required
|
||||
appInputVerbatim
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
role="button"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(true)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box last">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{ "masterPassHint" | i18n }}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "masterPassHintDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,65 +1,79 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import {
|
||||
ActivatedRoute,
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { UserService } from "jslib-common/abstractions/user.service";
|
||||
|
||||
import {
|
||||
SetPasswordComponent as BaseSetPasswordComponent,
|
||||
} from 'jslib-angular/components/set-password.component';
|
||||
import { SetPasswordComponent as BaseSetPasswordComponent } from "jslib-angular/components/set-password.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-set-password',
|
||||
templateUrl: 'set-password.component.html',
|
||||
selector: "app-set-password",
|
||||
templateUrl: "set-password.component.html",
|
||||
})
|
||||
export class SetPasswordComponent extends BaseSetPasswordComponent {
|
||||
constructor(apiService: ApiService, i18nService: I18nService,
|
||||
cryptoService: CryptoService, messagingService: MessagingService,
|
||||
userService: UserService, passwordGenerationService: PasswordGenerationService,
|
||||
platformUtilsService: PlatformUtilsService, policyService: PolicyService, router: Router,
|
||||
syncService: SyncService, route: ActivatedRoute) {
|
||||
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
|
||||
platformUtilsService, policyService, router, apiService, syncService, route);
|
||||
}
|
||||
constructor(
|
||||
apiService: ApiService,
|
||||
i18nService: I18nService,
|
||||
cryptoService: CryptoService,
|
||||
messagingService: MessagingService,
|
||||
userService: UserService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
policyService: PolicyService,
|
||||
router: Router,
|
||||
syncService: SyncService,
|
||||
route: ActivatedRoute
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
cryptoService,
|
||||
messagingService,
|
||||
userService,
|
||||
passwordGenerationService,
|
||||
platformUtilsService,
|
||||
policyService,
|
||||
router,
|
||||
apiService,
|
||||
syncService,
|
||||
route
|
||||
);
|
||||
}
|
||||
|
||||
get masterPasswordScoreWidth() {
|
||||
return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||
}
|
||||
get masterPasswordScoreWidth() {
|
||||
return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||
}
|
||||
|
||||
get masterPasswordScoreColor() {
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return 'success';
|
||||
case 3:
|
||||
return 'primary';
|
||||
case 2:
|
||||
return 'warning';
|
||||
default:
|
||||
return 'danger';
|
||||
}
|
||||
get masterPasswordScoreColor() {
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return "success";
|
||||
case 3:
|
||||
return "primary";
|
||||
case 2:
|
||||
return "warning";
|
||||
default:
|
||||
return "danger";
|
||||
}
|
||||
}
|
||||
|
||||
get masterPasswordScoreText() {
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return this.i18nService.t('strong');
|
||||
case 3:
|
||||
return this.i18nService.t('good');
|
||||
case 2:
|
||||
return this.i18nService.t('weak');
|
||||
default:
|
||||
return this.masterPasswordScore != null ? this.i18nService.t('weak') : null;
|
||||
}
|
||||
get masterPasswordScoreText() {
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return this.i18nService.t("strong");
|
||||
case 3:
|
||||
return this.i18nService.t("good");
|
||||
case 2:
|
||||
return this.i18nService.t("weak");
|
||||
default:
|
||||
return this.masterPasswordScore != null ? this.i18nService.t("weak") : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,73 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import {
|
||||
ActivatedRoute,
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { CryptoFunctionService } from 'jslib-common/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { VaultTimeoutService } from 'jslib-common/abstractions/vaultTimeout.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
import { SsoComponent as BaseSsoComponent } from "jslib-angular/components/sso.component";
|
||||
import { BrowserApi } from "../../browser/browserApi";
|
||||
|
||||
@Component({
|
||||
selector: 'app-sso',
|
||||
templateUrl: 'sso.component.html',
|
||||
selector: "app-sso",
|
||||
templateUrl: "sso.component.html",
|
||||
})
|
||||
export class SsoComponent extends BaseSsoComponent {
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, route: ActivatedRoute,
|
||||
storageService: StorageService, stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService, apiService: ApiService,
|
||||
cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService,
|
||||
syncService: SyncService, environmentService: EnvironmentService, logService: LogService,
|
||||
private vaultTimeoutService: VaultTimeoutService) {
|
||||
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
|
||||
apiService, cryptoFunctionService, environmentService, passwordGenerationService, logService);
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
route: ActivatedRoute,
|
||||
storageService: StorageService,
|
||||
stateService: StateService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
apiService: ApiService,
|
||||
cryptoFunctionService: CryptoFunctionService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
syncService: SyncService,
|
||||
environmentService: EnvironmentService,
|
||||
logService: LogService,
|
||||
private vaultTimeoutService: VaultTimeoutService
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
router,
|
||||
i18nService,
|
||||
route,
|
||||
storageService,
|
||||
stateService,
|
||||
platformUtilsService,
|
||||
apiService,
|
||||
cryptoFunctionService,
|
||||
environmentService,
|
||||
passwordGenerationService,
|
||||
logService
|
||||
);
|
||||
|
||||
const url = this.environmentService.getWebVaultUrl();
|
||||
const url = this.environmentService.getWebVaultUrl();
|
||||
|
||||
this.redirectUri = url + '/sso-connector.html';
|
||||
this.clientId = 'browser';
|
||||
this.redirectUri = url + "/sso-connector.html";
|
||||
this.clientId = "browser";
|
||||
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
// If the vault is unlocked then this will clear keys from memory, which we don't want to do
|
||||
BrowserApi.reloadOpenWindows();
|
||||
}
|
||||
super.onSuccessfulLogin = async () => {
|
||||
await syncService.fullSync(true);
|
||||
if (await this.vaultTimeoutService.isLocked()) {
|
||||
// If the vault is unlocked then this will clear keys from memory, which we don't want to do
|
||||
BrowserApi.reloadOpenWindows();
|
||||
}
|
||||
|
||||
const thisWindow = window.open('', '_self');
|
||||
thisWindow.close();
|
||||
};
|
||||
}
|
||||
const thisWindow = window.open("", "_self");
|
||||
thisWindow.close();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/2fa">{{'close' | i18n}}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'twoStepOptions' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right"></div>
|
||||
<div class="left">
|
||||
<a routerLink="/2fa">{{ "close" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "twoStepOptions" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right"></div>
|
||||
</header>
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<button type="button" appStopClick *ngFor="let p of providers" class="box-content-row" (click)="choose(p)">
|
||||
<span class="text">{{p.name}}</span>
|
||||
<span class="detail">{{p.description}}</span>
|
||||
</button>
|
||||
<button type="button" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{'recoveryCodeTitle' | i18n}}</span>
|
||||
<span class="detail">{{'recoveryCodeDesc' | i18n}}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<button
|
||||
type="button"
|
||||
appStopClick
|
||||
*ngFor="let p of providers"
|
||||
class="box-content-row"
|
||||
(click)="choose(p)"
|
||||
>
|
||||
<span class="text">{{ p.name }}</span>
|
||||
<span class="detail">{{ p.description }}</span>
|
||||
</button>
|
||||
<button type="button" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{ "recoveryCodeTitle" | i18n }}</span>
|
||||
<span class="detail">{{ "recoveryCodeDesc" | i18n }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from "@angular/core";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
|
||||
import {
|
||||
TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent,
|
||||
} from 'jslib-angular/components/two-factor-options.component';
|
||||
import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jslib-angular/components/two-factor-options.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-two-factor-options',
|
||||
templateUrl: 'two-factor-options.component.html',
|
||||
selector: "app-two-factor-options",
|
||||
templateUrl: "two-factor-options.component.html",
|
||||
})
|
||||
export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent {
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, platformUtilsService: PlatformUtilsService) {
|
||||
super(authService, router, i18nService, platformUtilsService, window);
|
||||
}
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService
|
||||
) {
|
||||
super(authService, router, i18nService, platformUtilsService, window);
|
||||
}
|
||||
|
||||
choose(p: any) {
|
||||
super.choose(p);
|
||||
this.authService.selectedTwoFactorProviderType = p.type;
|
||||
this.router.navigate(['2fa']);
|
||||
}
|
||||
choose(p: any) {
|
||||
super.choose(p);
|
||||
this.authService.selectedTwoFactorProviderType = p.type;
|
||||
this.router.navigate(["2fa"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,106 +1,141 @@
|
||||
<form id="two-factor-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{'back' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/login">{{ "back" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ title }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button
|
||||
type="submit"
|
||||
appBlurClick
|
||||
[disabled]="form.loading"
|
||||
*ngIf="
|
||||
selectedProviderType != null &&
|
||||
selectedProviderType !== providerType.Duo &&
|
||||
selectedProviderType !== providerType.OrganizationDuo &&
|
||||
(selectedProviderType !== providerType.WebAuthn || form.loading)
|
||||
"
|
||||
>
|
||||
<span [hidden]="form.loading">{{ "continue" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
selectedProviderType === providerType.Authenticator ||
|
||||
selectedProviderType === providerType.Email
|
||||
"
|
||||
>
|
||||
<div class="content text-center">
|
||||
<span *ngIf="selectedProviderType === providerType.Authenticator">
|
||||
{{ "enterVerificationCodeApp" | i18n }}
|
||||
</span>
|
||||
<span *ngIf="selectedProviderType === providerType.Email">
|
||||
{{ "enterVerificationCodeEmail" | i18n: twoFactorEmail }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="box first">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code">{{ "verificationCode" | i18n }}</label>
|
||||
<input
|
||||
id="code"
|
||||
type="text"
|
||||
name="Code"
|
||||
[(ngModel)]="token"
|
||||
required
|
||||
appAutofocus
|
||||
inputmode="tel"
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{ "rememberMe" | i18n }}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember" />
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{title}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading" *ngIf="selectedProviderType != null && selectedProviderType !== providerType.Duo &&
|
||||
selectedProviderType !== providerType.OrganizationDuo &&
|
||||
(selectedProviderType !== providerType.WebAuthn || form.loading)">
|
||||
<span [hidden]="form.loading">{{'continue' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Yubikey">
|
||||
<div class="content text-center">
|
||||
<p class="text-center">{{ "insertYubiKey" | i18n }}</p>
|
||||
<img src="../images/yubikey.jpg" class="img-rounded img-responsive" alt="" />
|
||||
</div>
|
||||
<div class="box first">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code" class="sr-only">{{ "verificationCode" | i18n }}</label>
|
||||
<input
|
||||
id="code"
|
||||
type="password"
|
||||
name="Code"
|
||||
[(ngModel)]="token"
|
||||
required
|
||||
appAutofocus
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{ "rememberMe" | i18n }}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember" />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Authenticator ||
|
||||
selectedProviderType === providerType.Email">
|
||||
<div class="content text-center">
|
||||
<span *ngIf="selectedProviderType === providerType.Authenticator">
|
||||
{{'enterVerificationCodeApp' | i18n}}
|
||||
</span>
|
||||
<span *ngIf="selectedProviderType === providerType.Email">
|
||||
{{'enterVerificationCodeEmail' | i18n : twoFactorEmail}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="box first">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code">{{'verificationCode' | i18n}}</label>
|
||||
<input id="code" type="text" name="Code" [(ngModel)]="token" required appAutofocus
|
||||
inputmode="tel" appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Yubikey">
|
||||
<div class="content text-center">
|
||||
<p class="text-center">{{'insertYubiKey' | i18n}}</p>
|
||||
<img src="../images/yubikey.jpg" class="img-rounded img-responsive" alt="">
|
||||
</div>
|
||||
<div class="box first">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="code" class="sr-only">{{'verificationCode' | i18n}}</label>
|
||||
<input id="code" type="password" name="Code" [(ngModel)]="token" required appAutofocus
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && !webAuthnNewTab">
|
||||
<div id="web-authn-frame"><iframe id="webauthn_iframe" [allow]="webAuthnAllow"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && webAuthnNewTab">
|
||||
<div class="content text-center" *ngIf="webAuthnNewTab">
|
||||
<p class="text-center">{{'webAuthnNewTab' | i18n}}</p>
|
||||
<button type="button" class="btn primary block" (click)="authWebAuthn()" appStopClick>{{'webAuthnNewTabOpen' | i18n}}</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Duo ||
|
||||
selectedProviderType === providerType.OrganizationDuo">
|
||||
<div id="duo-frame"><iframe id="duo_iframe"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{'rememberMe' | i18n}}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="content" *ngIf="selectedProviderType == null">
|
||||
<p class="text-center">{{'noTwoStepProviders' | i18n}}</p>
|
||||
<p class="text-center">{{'noTwoStepProviders2' | i18n}}</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && !webAuthnNewTab">
|
||||
<div id="web-authn-frame"><iframe id="webauthn_iframe" [allow]="webAuthnAllow"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{ "rememberMe" | i18n }}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content no-vpad" *ngIf="selectedProviderType != null">
|
||||
<p class="text-center">
|
||||
<button type="button" appStopClick (click)="anotherMethod()">{{'useAnotherTwoStepMethod' | i18n}}</button>
|
||||
</p>
|
||||
<p *ngIf="selectedProviderType === providerType.Email" class="text-center">
|
||||
<button type="button" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise">
|
||||
{{'sendVerificationCodeEmailAgain' | i18n}}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && webAuthnNewTab">
|
||||
<div class="content text-center" *ngIf="webAuthnNewTab">
|
||||
<p class="text-center">{{ "webAuthnNewTab" | i18n }}</p>
|
||||
<button type="button" class="btn primary block" (click)="authWebAuthn()" appStopClick>
|
||||
{{ "webAuthnNewTabOpen" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container
|
||||
*ngIf="
|
||||
selectedProviderType === providerType.Duo ||
|
||||
selectedProviderType === providerType.OrganizationDuo
|
||||
"
|
||||
>
|
||||
<div id="duo-frame"><iframe id="duo_iframe"></iframe></div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||
<label for="remember">{{ "rememberMe" | i18n }}</label>
|
||||
<input id="remember" type="checkbox" name="Remember" [(ngModel)]="remember" />
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="content" *ngIf="selectedProviderType == null">
|
||||
<p class="text-center">{{ "noTwoStepProviders" | i18n }}</p>
|
||||
<p class="text-center">{{ "noTwoStepProviders2" | i18n }}</p>
|
||||
</div>
|
||||
<div class="content no-vpad" *ngIf="selectedProviderType != null">
|
||||
<p class="text-center">
|
||||
<button type="button" appStopClick (click)="anotherMethod()">
|
||||
{{ "useAnotherTwoStepMethod" | i18n }}
|
||||
</button>
|
||||
</p>
|
||||
<p *ngIf="selectedProviderType === providerType.Email" class="text-center">
|
||||
<button type="button" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise">
|
||||
{{ "sendVerificationCodeEmailAgain" | i18n }}
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,116 +1,140 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
ActivatedRoute,
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { Component } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { TwoFactorProviderType } from 'jslib-common/enums/twoFactorProviderType';
|
||||
import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { AuthService } from 'jslib-common/abstractions/auth.service';
|
||||
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
|
||||
import { EnvironmentService } from 'jslib-common/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib-common/abstractions/state.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { AuthService } from "jslib-common/abstractions/auth.service";
|
||||
import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { StorageService } from "jslib-common/abstractions/storage.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib-angular/components/two-factor.component';
|
||||
import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component";
|
||||
|
||||
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||
import { PopupUtilsService } from "../services/popup-utils.service";
|
||||
|
||||
import { BrowserApi } from '../../browser/browserApi';
|
||||
import { BrowserApi } from "../../browser/browserApi";
|
||||
|
||||
const BroadcasterSubscriptionId = 'TwoFactorComponent';
|
||||
const BroadcasterSubscriptionId = "TwoFactorComponent";
|
||||
|
||||
@Component({
|
||||
selector: 'app-two-factor',
|
||||
templateUrl: 'two-factor.component.html',
|
||||
selector: "app-two-factor",
|
||||
templateUrl: "two-factor.component.html",
|
||||
})
|
||||
export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
showNewWindowMessage = false;
|
||||
showNewWindowMessage = false;
|
||||
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, apiService: ApiService,
|
||||
platformUtilsService: PlatformUtilsService, private syncService: SyncService,
|
||||
environmentService: EnvironmentService, private broadcasterService: BroadcasterService,
|
||||
private popupUtilsService: PopupUtilsService, stateService: StateService,
|
||||
storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService,
|
||||
logService: LogService) {
|
||||
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
|
||||
stateService, storageService, route, logService);
|
||||
constructor(
|
||||
authService: AuthService,
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
apiService: ApiService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
private syncService: SyncService,
|
||||
environmentService: EnvironmentService,
|
||||
private broadcasterService: BroadcasterService,
|
||||
private popupUtilsService: PopupUtilsService,
|
||||
stateService: StateService,
|
||||
storageService: StorageService,
|
||||
route: ActivatedRoute,
|
||||
private messagingService: MessagingService,
|
||||
logService: LogService
|
||||
) {
|
||||
super(
|
||||
authService,
|
||||
router,
|
||||
i18nService,
|
||||
apiService,
|
||||
platformUtilsService,
|
||||
window,
|
||||
environmentService,
|
||||
stateService,
|
||||
storageService,
|
||||
route,
|
||||
logService
|
||||
);
|
||||
super.onSuccessfulLogin = () => {
|
||||
return syncService.fullSync(true);
|
||||
};
|
||||
super.successRoute = "/tabs/vault";
|
||||
this.webAuthnNewTab =
|
||||
this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari();
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
if (this.route.snapshot.paramMap.has("webAuthnResponse")) {
|
||||
// WebAuthn fallback response
|
||||
this.selectedProviderType = TwoFactorProviderType.WebAuthn;
|
||||
this.token = this.route.snapshot.paramMap.get("webAuthnResponse");
|
||||
super.onSuccessfulLogin = async () => {
|
||||
this.syncService.fullSync(true);
|
||||
this.messagingService.send("reloadPopup");
|
||||
window.close();
|
||||
};
|
||||
this.remember = this.route.snapshot.paramMap.get("remember") === "true";
|
||||
await this.doSubmit();
|
||||
return;
|
||||
}
|
||||
|
||||
await super.ngOnInit();
|
||||
if (this.selectedProviderType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WebAuthn prompt appears inside the popup on linux, and requires a larger popup width
|
||||
// than usual to avoid cutting off the dialog.
|
||||
if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && (await this.isLinux())) {
|
||||
document.body.classList.add("linux-webauthn");
|
||||
}
|
||||
|
||||
if (
|
||||
this.selectedProviderType === TwoFactorProviderType.Email &&
|
||||
this.popupUtilsService.inPopup(window)
|
||||
) {
|
||||
const confirmed = await this.platformUtilsService.showDialog(
|
||||
this.i18nService.t("popup2faCloseMessage"),
|
||||
null,
|
||||
this.i18nService.t("yes"),
|
||||
this.i18nService.t("no")
|
||||
);
|
||||
if (confirmed) {
|
||||
this.popupUtilsService.popOut(window);
|
||||
}
|
||||
}
|
||||
|
||||
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
||||
if (qParams.sso === "true") {
|
||||
super.onSuccessfulLogin = () => {
|
||||
return syncService.fullSync(true);
|
||||
BrowserApi.reloadOpenWindows();
|
||||
const thisWindow = window.open("", "_self");
|
||||
thisWindow.close();
|
||||
return this.syncService.fullSync(true);
|
||||
};
|
||||
super.successRoute = '/tabs/vault';
|
||||
this.webAuthnNewTab = this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnDestroy() {
|
||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||
|
||||
if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && (await this.isLinux())) {
|
||||
document.body.classList.remove("linux-webauthn");
|
||||
}
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
if (this.route.snapshot.paramMap.has('webAuthnResponse')) {
|
||||
// WebAuthn fallback response
|
||||
this.selectedProviderType = TwoFactorProviderType.WebAuthn;
|
||||
this.token = this.route.snapshot.paramMap.get('webAuthnResponse');
|
||||
super.onSuccessfulLogin = async () => {
|
||||
this.syncService.fullSync(true);
|
||||
this.messagingService.send('reloadPopup');
|
||||
window.close();
|
||||
};
|
||||
this.remember = this.route.snapshot.paramMap.get('remember') === 'true';
|
||||
await this.doSubmit();
|
||||
return;
|
||||
}
|
||||
anotherMethod() {
|
||||
this.router.navigate(["2fa-options"]);
|
||||
}
|
||||
|
||||
await super.ngOnInit();
|
||||
if (this.selectedProviderType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WebAuthn prompt appears inside the popup on linux, and requires a larger popup width
|
||||
// than usual to avoid cutting off the dialog.
|
||||
if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && await this.isLinux()) {
|
||||
document.body.classList.add('linux-webauthn');
|
||||
}
|
||||
|
||||
if (this.selectedProviderType === TwoFactorProviderType.Email &&
|
||||
this.popupUtilsService.inPopup(window)) {
|
||||
const confirmed = await this.platformUtilsService.showDialog(this.i18nService.t('popup2faCloseMessage'),
|
||||
null, this.i18nService.t('yes'), this.i18nService.t('no'));
|
||||
if (confirmed) {
|
||||
this.popupUtilsService.popOut(window);
|
||||
}
|
||||
}
|
||||
|
||||
this.route.queryParams.pipe(first()).subscribe(async qParams => {
|
||||
if (qParams.sso === 'true') {
|
||||
super.onSuccessfulLogin = () => {
|
||||
BrowserApi.reloadOpenWindows();
|
||||
const thisWindow = window.open('', '_self');
|
||||
thisWindow.close();
|
||||
return this.syncService.fullSync(true);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnDestroy() {
|
||||
this.broadcasterService.unsubscribe(BroadcasterSubscriptionId);
|
||||
|
||||
if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && await this.isLinux()) {
|
||||
document.body.classList.remove('linux-webauthn');
|
||||
}
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
anotherMethod() {
|
||||
this.router.navigate(['2fa-options']);
|
||||
}
|
||||
|
||||
async isLinux() {
|
||||
return (await BrowserApi.getPlatformInfo()).os === 'linux';
|
||||
}
|
||||
async isLinux() {
|
||||
return (await BrowserApi.getPlatformInfo()).os === "linux";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,130 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a (click)="logOut()">{{'logOut' | i18n}}</a>
|
||||
<header>
|
||||
<div class="left">
|
||||
<a (click)="logOut()">{{ "logOut" | i18n }}</a>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "updateMasterPassword" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{ "submit" | i18n }}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<app-callout type="warning" title="{{ 'updateMasterPassword' | i18n }}">
|
||||
{{ "updateMasterPasswordWarning" | i18n }}
|
||||
</app-callout>
|
||||
<app-callout
|
||||
type="info"
|
||||
[enforcedPolicyOptions]="enforcedPolicyOptions"
|
||||
*ngIf="enforcedPolicyOptions"
|
||||
>
|
||||
</app-callout>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">
|
||||
{{ "masterPass" | i18n }}
|
||||
<strong
|
||||
class="sub-label text-{{ masterPasswordScoreStyle.Color }}"
|
||||
*ngIf="masterPasswordScoreStyle.Text"
|
||||
>
|
||||
{{ masterPasswordScoreStyle.Text }}
|
||||
</strong>
|
||||
</label>
|
||||
<input
|
||||
id="masterPassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPassword"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPassword"
|
||||
required
|
||||
appInputVerbatim
|
||||
(input)="updatePasswordStrength()"
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(false)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div
|
||||
class="progress-bar bg-{{ masterPasswordScoreStyle.Color }}"
|
||||
role="progressbar"
|
||||
aria-valuenow="0"
|
||||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
[ngStyle]="{ width: masterPasswordScoreStyle.Width + '%' }"
|
||||
attr.aria-valuenow="{{ masterPasswordScoreStyle.Width }}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{'updateMasterPassword' | i18n}}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button type="submit" appBlurClick [disabled]="form.loading">
|
||||
<span [hidden]="form.loading">{{'submit' | i18n}}</span>
|
||||
<i class="fa fa-spinner fa-lg fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{ "reTypeMasterPass" | i18n }}</label>
|
||||
<input
|
||||
id="masterPasswordRetype"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="MasterPasswordRetype"
|
||||
class="monospaced"
|
||||
[(ngModel)]="masterPasswordRetype"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="row-btn"
|
||||
appStopClick
|
||||
appBlurClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword(true)"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
>
|
||||
<i
|
||||
class="fa fa-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'fa-eye': !showPassword, 'fa-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<content>
|
||||
<app-callout type="warning" title="{{'updateMasterPassword' | i18n}}">
|
||||
{{'updateMasterPasswordWarning' | i18n}}
|
||||
</app-callout>
|
||||
<app-callout type="info" [enforcedPolicyOptions]="enforcedPolicyOptions" *ngIf="enforcedPolicyOptions">
|
||||
</app-callout>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<div class="box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<label for="masterPassword">
|
||||
{{'masterPass' | i18n}}
|
||||
<strong class="sub-label text-{{masterPasswordScoreStyle.Color}}"
|
||||
*ngIf="masterPasswordScoreStyle.Text">
|
||||
{{masterPasswordScoreStyle.Text}}
|
||||
</strong>
|
||||
</label>
|
||||
<input id="masterPassword" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPassword" class="monospaced" [(ngModel)]="masterPassword" required
|
||||
appInputVerbatim (input)="updatePasswordStrength()">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-{{masterPasswordScoreStyle.Color}}" role="progressbar"
|
||||
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
|
||||
[ngStyle]="{width: (masterPasswordScoreStyle.Width + '%')}"
|
||||
attr.aria-valuenow="{{masterPasswordScoreStyle.Width}}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{ "masterPassHint" | i18n }}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint" />
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row box-content-row-flex" appBoxRow>
|
||||
<div class="row-main">
|
||||
<label for="masterPasswordRetype">{{'reTypeMasterPass' | i18n}}</label>
|
||||
<input id="masterPasswordRetype" type="{{showPassword ? 'text' : 'password'}}"
|
||||
name="MasterPasswordRetype" class="monospaced" [(ngModel)]="masterPasswordRetype" required
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)" [attr.aria-pressed]="showPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<div class="box-content-row" appBoxRow>
|
||||
<label for="hint">{{'masterPassHint' | i18n}}</label>
|
||||
<input id="hint" type="text" name="Hint" [(ngModel)]="hint">
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'masterPassHintDesc' | i18n}}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{ "masterPassHintDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
@@ -1,65 +1,82 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { ApiService } from 'jslib-common/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib-common/abstractions/crypto.service';
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
import { LogService } from 'jslib-common/abstractions/log.service';
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PasswordGenerationService } from 'jslib-common/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib-common/abstractions/policy.service';
|
||||
import { SyncService } from 'jslib-common/abstractions/sync.service';
|
||||
import { UserService } from 'jslib-common/abstractions/user.service';
|
||||
import { ApiService } from "jslib-common/abstractions/api.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "jslib-common/abstractions/policy.service";
|
||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||
import { UserService } from "jslib-common/abstractions/user.service";
|
||||
|
||||
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from 'jslib-angular/components/update-temp-password.component';
|
||||
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from "jslib-angular/components/update-temp-password.component";
|
||||
|
||||
interface MasterPasswordScore {
|
||||
Color: string;
|
||||
Text: string;
|
||||
Width: number;
|
||||
Color: string;
|
||||
Text: string;
|
||||
Width: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-update-temp-password',
|
||||
templateUrl: 'update-temp-password.component.html',
|
||||
selector: "app-update-temp-password",
|
||||
templateUrl: "update-temp-password.component.html",
|
||||
})
|
||||
export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent {
|
||||
get masterPasswordScoreStyle(): MasterPasswordScore {
|
||||
const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return {
|
||||
Color: 'bg-success',
|
||||
Text: 'strong',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 3:
|
||||
return {
|
||||
Color: 'bg-primary',
|
||||
Text: 'good',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 2:
|
||||
return {
|
||||
Color: 'bg-warning',
|
||||
Text: 'weak',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
Color: 'bg-danger',
|
||||
Text: 'weak',
|
||||
Width: scoreWidth,
|
||||
};
|
||||
}
|
||||
get masterPasswordScoreStyle(): MasterPasswordScore {
|
||||
const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20;
|
||||
switch (this.masterPasswordScore) {
|
||||
case 4:
|
||||
return {
|
||||
Color: "bg-success",
|
||||
Text: "strong",
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 3:
|
||||
return {
|
||||
Color: "bg-primary",
|
||||
Text: "good",
|
||||
Width: scoreWidth,
|
||||
};
|
||||
case 2:
|
||||
return {
|
||||
Color: "bg-warning",
|
||||
Text: "weak",
|
||||
Width: scoreWidth,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
Color: "bg-danger",
|
||||
Text: "weak",
|
||||
Width: scoreWidth,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService, policyService: PolicyService,
|
||||
cryptoService: CryptoService, userService: UserService,
|
||||
messagingService: MessagingService, apiService: ApiService,
|
||||
syncService: SyncService, logService: LogService) {
|
||||
super(i18nService, platformUtilsService, passwordGenerationService, policyService, cryptoService,
|
||||
userService, messagingService, apiService, syncService, logService);
|
||||
}
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
passwordGenerationService: PasswordGenerationService,
|
||||
policyService: PolicyService,
|
||||
cryptoService: CryptoService,
|
||||
userService: UserService,
|
||||
messagingService: MessagingService,
|
||||
apiService: ApiService,
|
||||
syncService: SyncService,
|
||||
logService: LogService
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
passwordGenerationService,
|
||||
policyService,
|
||||
cryptoService,
|
||||
userService,
|
||||
messagingService,
|
||||
apiService,
|
||||
syncService,
|
||||
logService
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user