Added set password flow to browser based SSO
This commit is contained in:
parent
a09bd4a3fe
commit
91ce6527c0
|
@ -0,0 +1,124 @@
|
|||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise">
|
||||
<header>
|
||||
<div class="left">
|
||||
<a routerLink="/home">{{'cancel' | i18n}}</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<span class="title">{{'appName' | i18n}}</span>
|
||||
</div>
|
||||
<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">
|
||||
<app-callout type="tip">{{'ssoCompleteRegistration' | i18n}}</app-callout>
|
||||
<app-callout type="info" *ngIf="enforcedPolicyOptions">
|
||||
{{'masterPasswordPolicyInEffect' | i18n}}
|
||||
<ul>
|
||||
<li *ngIf="enforcedPolicyOptions?.minComplexity > 0">
|
||||
{{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.minLength > 0">
|
||||
{{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}}
|
||||
</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireUpper">{{'policyInEffectUppercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireLower">{{'policyInEffectLowercase' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireNumbers">{{'policyInEffectNumbers' | i18n}}</li>
|
||||
<li *ngIf="enforcedPolicyOptions?.requireSpecial">{{'policyInEffectSpecial' | i18n : '!@#$%^&*'}}
|
||||
</li>
|
||||
</ul>
|
||||
</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">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</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">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</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>
|
||||
</content>
|
||||
</form>
|
||||
|
||||
|
||||
<!-- <div class="content">
|
||||
<img class="logo-image" alt="Bitwarden">
|
||||
<p class="lead">{{'setMasterPassword' | i18n}}</p>
|
||||
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate autocomplete="off">
|
||||
|
||||
<div class="buttons">
|
||||
<button type="submit" class="btn primary block" [disabled]="form.loading">
|
||||
<i *ngIf="form.loading" class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"
|
||||
aria-hidden="true"></i>
|
||||
<span>{{'submit' | i18n}}</span>
|
||||
</button>
|
||||
<button class="btn block" (click)="logOut()">
|
||||
<span>{{'logOut' | i18n}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form> -->
|
|
@ -0,0 +1,60 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { ApiService } from 'jslib/abstractions/api.service';
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { MessagingService } from 'jslib/abstractions/messaging.service';
|
||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
import { PolicyService } from 'jslib/abstractions/policy.service';
|
||||
import { UserService } from 'jslib/abstractions/user.service';
|
||||
|
||||
import {
|
||||
SetPasswordComponent as BaseSetPasswordComponent,
|
||||
} from 'jslib/angular/components/set-password.component';
|
||||
|
||||
@Component({
|
||||
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) {
|
||||
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
|
||||
platformUtilsService, policyService, router, apiService);
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ import { GroupingsComponent } from './vault/groupings.component';
|
|||
import { PasswordHistoryComponent } from './vault/password-history.component';
|
||||
import { ShareComponent } from './vault/share.component';
|
||||
import { ViewComponent } from './vault/view.component';
|
||||
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
|
@ -86,6 +87,11 @@ const routes: Routes = [
|
|||
canActivate: [LaunchGuardService],
|
||||
data: { state: 'sso' },
|
||||
},
|
||||
{
|
||||
path: 'set-password',
|
||||
component: SetPasswordComponent,
|
||||
data: { state: 'set-password' },
|
||||
},
|
||||
{
|
||||
path: 'register',
|
||||
component: RegisterComponent,
|
||||
|
|
|
@ -45,6 +45,7 @@ import { GroupingsComponent } from './vault/groupings.component';
|
|||
import { PasswordHistoryComponent } from './vault/password-history.component';
|
||||
import { ShareComponent } from './vault/share.component';
|
||||
import { ViewComponent } from './vault/view.component';
|
||||
import { SetPasswordComponent } from './accounts/set-password.component';
|
||||
|
||||
import { A11yTitleDirective } from 'jslib/angular/directives/a11y-title.directive';
|
||||
import { ApiActionDirective } from 'jslib/angular/directives/api-action.directive';
|
||||
|
@ -209,6 +210,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
|
|||
TwoFactorComponent,
|
||||
SsoComponent,
|
||||
ViewComponent,
|
||||
SetPasswordComponent
|
||||
],
|
||||
entryComponents: [],
|
||||
providers: [
|
||||
|
|
|
@ -21,7 +21,7 @@ import { AuthService as AuthServiceAbstraction } from 'jslib/abstractions/auth.s
|
|||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { CollectionService } from 'jslib/abstractions/collection.service';
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from 'jslib/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||
import { EventService } from 'jslib/abstractions/event.service';
|
||||
import { ExportService } from 'jslib/abstractions/export.service';
|
||||
|
@ -41,7 +41,6 @@ import { TokenService } from 'jslib/abstractions/token.service';
|
|||
import { TotpService } from 'jslib/abstractions/totp.service';
|
||||
import { UserService } from 'jslib/abstractions/user.service';
|
||||
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
||||
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
|
||||
|
||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||
import BrowserMessagingService from '../../services/browserMessaging.service';
|
||||
|
@ -50,6 +49,7 @@ import { AuthService } from 'jslib/services/auth.service';
|
|||
import { ConstantsService } from 'jslib/services/constants.service';
|
||||
import { SearchService } from 'jslib/services/search.service';
|
||||
import { StateService } from 'jslib/services/state.service';
|
||||
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
|
||||
|
||||
import { Analytics } from 'jslib/misc/analytics';
|
||||
|
||||
|
@ -72,7 +72,7 @@ export const authService = new AuthService(getBgService<CryptoService>('cryptoSe
|
|||
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), null);
|
||||
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||
getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||
export const cryptoFunctionService: CryptoFunctionService = new WebCryptoFunctionService(window,
|
||||
export const cryptoFunctionService = new WebCryptoFunctionService(window,
|
||||
getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||
|
||||
export function initFactory(i18nService: I18nService, storageService: StorageService,
|
||||
|
@ -125,7 +125,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
|||
{ provide: AuthServiceAbstraction, useValue: authService },
|
||||
{ provide: StateServiceAbstraction, useValue: stateService },
|
||||
{ provide: SearchServiceAbstraction, useValue: searchService },
|
||||
{ provide: CryptoFunctionService, useValue: cryptoFunctionService },
|
||||
{ provide: CryptoFunctionServiceAbstraction, useValue: cryptoFunctionService },
|
||||
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
|
||||
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
|
||||
{ provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] },
|
||||
|
@ -135,11 +135,6 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
|||
{ provide: TokenService, useFactory: getBgService<TokenService>('tokenService'), deps: [] },
|
||||
{ provide: I18nService, useFactory: getBgService<I18nService>('i18nService'), deps: [] },
|
||||
{ provide: CryptoService, useFactory: getBgService<CryptoService>('cryptoService'), deps: [] },
|
||||
{
|
||||
provide: CryptoFunctionService,
|
||||
useFactory: getBgService<CryptoFunctionService>('cryptoFunctionService'),
|
||||
deps: [],
|
||||
},
|
||||
{ provide: EventService, useFactory: getBgService<EventService>('eventService'), deps: [] },
|
||||
{ provide: PolicyService, useFactory: getBgService<PolicyService>('policyService'), deps: [] },
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue