[Reset Password v1] Update Temp Password (#1015)

This commit is contained in:
Vincent Salucci 2021-08-11 12:49:44 -07:00 committed by GitHub
parent 816249a48a
commit d82378a7a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 188 additions and 8 deletions

View File

@ -21,6 +21,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
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 { UserService } from 'jslib-common/abstractions/user.service';
import { BroadcasterService } from 'jslib-angular/services/broadcaster.service';
@ -46,11 +47,15 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
environmentService: EnvironmentService, passwordGenerationService: PasswordGenerationService,
cryptoFunctionService: CryptoFunctionService, storageService: StorageService,
private broadcasterService: BroadcasterService, private ngZone: NgZone,
private messagingService: MessagingService) {
private messagingService: MessagingService, private userService: UserService) {
super(authService, router, platformUtilsService, i18nService, stateService, environmentService,
passwordGenerationService, cryptoFunctionService, storageService);
super.onSuccessfulLogin = () => {
return syncService.fullSync(true);
return syncService.fullSync(true).then(async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
}
});
};
}

View File

@ -40,6 +40,13 @@ export class SetPasswordComponent extends BaseSetPasswordComponent implements On
private broadcasterService: BroadcasterService, private ngZone: NgZone) {
super(i18nService, cryptoService, messagingService, userService, passwordGenerationService,
platformUtilsService, policyService, router, apiService, syncService, route);
super.onSuccessfulChangePassword = async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
} else {
this.router.navigate([this.successRoute]);
}
};
}
get masterPasswordScoreWidth() {

View File

@ -15,6 +15,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
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 { UserService } from 'jslib-common/abstractions/user.service';
import { SsoComponent as BaseSsoComponent } from 'jslib-angular/components/sso.component';
@ -28,7 +29,7 @@ export class SsoComponent extends BaseSsoComponent {
storageService: StorageService, stateService: StateService,
platformUtilsService: PlatformUtilsService, apiService: ApiService,
cryptoFunctionService: CryptoFunctionService, environmentService: EnvironmentService,
passwordGenerationService: PasswordGenerationService) {
passwordGenerationService: PasswordGenerationService, private userService: UserService) {
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
apiService, cryptoFunctionService, environmentService, passwordGenerationService);
super.onSuccessfulLogin = () => {
@ -36,5 +37,12 @@ export class SsoComponent extends BaseSsoComponent {
};
this.redirectUri = 'bitwarden://sso-callback';
this.clientId = 'desktop';
super.onSuccessfulLoginNavigate = async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
} else {
this.router.navigate([this.successRoute]);
}
};
}
}

View File

@ -22,6 +22,7 @@ import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.se
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 { UserService } from 'jslib-common/abstractions/user.service';
import { ModalComponent } from 'jslib-angular/components/modal.component';
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib-angular/components/two-factor.component';
@ -39,11 +40,16 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
i18nService: I18nService, apiService: ApiService,
platformUtilsService: PlatformUtilsService, syncService: SyncService,
environmentService: EnvironmentService, private componentFactoryResolver: ComponentFactoryResolver,
stateService: StateService, storageService: StorageService, route: ActivatedRoute) {
stateService: StateService, storageService: StorageService, route: ActivatedRoute,
private userService: UserService) {
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
stateService, storageService, route);
super.onSuccessfulLogin = () => {
return syncService.fullSync(true);
return syncService.fullSync(true).then(async () => {
if (await this.userService.getForcePasswordReset()) {
this.router.navigate(['update-temp-password']);
}
});
};
}

View File

@ -0,0 +1,75 @@
<form id="update-temp-password-page" #form (ngSubmit)="submit()" [appApiAction]="formPromise">
<div class="content">
<app-callout type="warning" title="{{'updateMasterPassword' | i18n}}">
{{'updateMasterPasswordWarning' | i18n}}
</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
[appAutofocus]="masterPassword === ''" (input)="updatePasswordStrength()">
</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-{{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 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>
</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 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>
<div class="buttons">
<button type="submit" class="btn primary block" [disabled]="form.loading" appBlurClick>
<b [hidden]="form.loading">{{'submit' | i18n}}</b>
<i class="fa fa-spinner fa-spin" [hidden]="!form.loading" aria-hidden="true"></i>
</button>
<a (click)="logOut()" class="btn block">{{'logOut' | i18n}}</a>
</div>
</div>
</form>

View File

@ -0,0 +1,62 @@
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 { 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 { UserService } from 'jslib-common/abstractions/user.service';
import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from 'jslib-angular/components/update-temp-password.component';
interface MasterPasswordScore {
Color: string;
Text: string;
Width: number;
}
@Component({
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,
};
}
}
constructor(i18nService: I18nService, platformUtilsService: PlatformUtilsService,
passwordGenerationService: PasswordGenerationService, policyService: PolicyService,
cryptoService: CryptoService, userService: UserService,
messagingService: MessagingService, apiService: ApiService) {
super(i18nService, platformUtilsService, passwordGenerationService, policyService, cryptoService,
userService, messagingService, apiService);
}
}

View File

@ -15,6 +15,7 @@ import { RegisterComponent } from './accounts/register.component';
import { SetPasswordComponent } from './accounts/set-password.component';
import { SsoComponent } from './accounts/sso.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
import { SendComponent } from './send/send.component';
@ -48,6 +49,11 @@ const routes: Routes = [
component: SendComponent,
canActivate: [AuthGuardService],
},
{
path: 'update-temp-password',
component: UpdateTempPasswordComponent,
canActivate: [AuthGuardService],
},
];
@NgModule({

View File

@ -26,6 +26,7 @@ import { SettingsComponent } from './accounts/settings.component';
import { SsoComponent } from './accounts/sso.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component';
import { UpdateTempPasswordComponent } from './accounts/update-temp-password.component';
import { CalloutComponent } from 'jslib-angular/components/callout.component';
import { IconComponent } from 'jslib-angular/components/icon.component';
@ -215,6 +216,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
TrueFalseValueDirective,
TwoFactorComponent,
TwoFactorOptionsComponent,
UpdateTempPasswordComponent,
VaultComponent,
ViewComponent,
],

View File

@ -1693,5 +1693,14 @@
},
"passwordConfirmationDesc": {
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
},
"updatedMasterPassword": {
"message": "Updated Master Password"
},
"updateMasterPassword": {
"message": "Update Master Password"
},
"updateMasterPasswordWarning": {
"message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour."
}
}

View File

@ -23,7 +23,7 @@
}
}
#register-page, #hint-page, #two-factor-page {
#register-page, #hint-page, #two-factor-page, #update-temp-password-page {
padding-top: 20px;
.content {
@ -39,7 +39,7 @@
}
}
#login-page, #register-page, #hint-page, #two-factor-page, #lock-page {
#login-page, #register-page, #hint-page, #two-factor-page, #lock-page, #update-temp-password-page {
.content {
width: 300px;
transition: width 0.25s linear;
@ -184,7 +184,7 @@
}
}
#register-page {
#register-page, #update-temp-password-page {
.content {
width: 400px;
}