diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index e42b3f08173..643d21d9135 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -1752,5 +1752,14 @@ }, "emailVerificationRequiredDesc": { "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "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." } } diff --git a/src/popup/accounts/login.component.ts b/src/popup/accounts/login.component.ts index f1152d8aac7..ebace90a8cd 100644 --- a/src/popup/accounts/login.component.ts +++ b/src/popup/accounts/login.component.ts @@ -10,6 +10,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 { LoginComponent as BaseLoginComponent } from 'jslib-angular/components/login.component'; @@ -23,10 +24,14 @@ export class LoginComponent extends BaseLoginComponent { protected stateService: StateService, protected environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService, protected cryptoFunctionService: CryptoFunctionService, storageService: StorageService, - syncService: SyncService) { + syncService: SyncService, private userService: UserService) { super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, storageService); - super.onSuccessfulLogin = () => { - return syncService.fullSync(true); + super.onSuccessfulLogin = async () => { + await syncService.fullSync(true).then(async () => { + if (await this.userService.getForcePasswordReset()) { + this.router.navigate(['update-temp-password']); + } + }); }; super.successRoute = '/tabs/vault'; } diff --git a/src/popup/accounts/set-password.component.ts b/src/popup/accounts/set-password.component.ts index 143bb864c86..8e795f9fe57 100644 --- a/src/popup/accounts/set-password.component.ts +++ b/src/popup/accounts/set-password.component.ts @@ -31,6 +31,13 @@ export class SetPasswordComponent extends BaseSetPasswordComponent { syncService: SyncService, route: ActivatedRoute) { 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() { diff --git a/src/popup/accounts/sso.component.ts b/src/popup/accounts/sso.component.ts index 34b3a77c01a..6536e67068f 100644 --- a/src/popup/accounts/sso.component.ts +++ b/src/popup/accounts/sso.component.ts @@ -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'; import { BrowserApi } from '../../browser/browserApi'; @@ -29,7 +30,7 @@ export class SsoComponent extends BaseSsoComponent { storageService: StorageService, stateService: StateService, platformUtilsService: PlatformUtilsService, apiService: ApiService, cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService, - syncService: SyncService, environmentService: EnvironmentService) { + syncService: SyncService, environmentService: EnvironmentService, private userService: UserService) { super(authService, router, i18nService, route, storageService, stateService, platformUtilsService, apiService, cryptoFunctionService, environmentService, passwordGenerationService); @@ -44,5 +45,13 @@ export class SsoComponent extends BaseSsoComponent { const thisWindow = window.open('', '_self'); thisWindow.close(); }; + + super.onSuccessfulLoginNavigate = async () => { + if (await this.userService.getForcePasswordReset()) { + this.router.navigate(['update-temp-password']); + } else { + this.router.navigate([this.successRoute]); + } + }; } } diff --git a/src/popup/accounts/two-factor.component.ts b/src/popup/accounts/two-factor.component.ts index 7850daa5d91..dd08cd5fbbe 100644 --- a/src/popup/accounts/two-factor.component.ts +++ b/src/popup/accounts/two-factor.component.ts @@ -20,6 +20,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'; @@ -44,11 +45,16 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { environmentService: EnvironmentService, private ngZone: NgZone, private broadcasterService: BroadcasterService, private changeDetectorRef: ChangeDetectorRef, private popupUtilsService: PopupUtilsService, stateService: StateService, - storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService) { + storageService: StorageService, route: ActivatedRoute, private messagingService: MessagingService, + private userService: UserService) { super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService, stateService, storageService, route); - super.onSuccessfulLogin = () => { - return syncService.fullSync(true); + super.onSuccessfulLogin = async () => { + return syncService.fullSync(true).then(async () => { + if (await this.userService.getForcePasswordReset()) { + this.router.navigate(['update-temp-password']); + }; + }); }; super.successRoute = '/tabs/vault'; this.webAuthnNewTab = this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari(); diff --git a/src/popup/accounts/update-temp-password.component.html b/src/popup/accounts/update-temp-password.component.html new file mode 100644 index 00000000000..df888ea1b52 --- /dev/null +++ b/src/popup/accounts/update-temp-password.component.html @@ -0,0 +1,100 @@ +
+
+ +
+ {{'updateMasterPassword' | i18n}} +
+
+ +
+
+ + + {{'updateMasterPasswordWarning' | i18n}} + + + {{'masterPasswordPolicyInEffect' | i18n}} +
    +
  • + {{'policyInEffectMinComplexity' | i18n : getPasswordScoreAlertDisplay()}} +
  • +
  • + {{'policyInEffectMinLength' | i18n : enforcedPolicyOptions?.minLength.toString()}} +
  • +
  • {{'policyInEffectUppercase' | i18n}}
  • +
  • {{'policyInEffectLowercase' | i18n}}
  • +
  • {{'policyInEffectNumbers' | i18n}}
  • +
  • + {{'policyInEffectSpecial' | i18n : '!@#$%^&*'}} +
  • +
+
+
+
+
+
+
+ + +
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ + + +
+
+
+
+
+
+
+ + +
+
+ +
+
+
diff --git a/src/popup/accounts/update-temp-password.component.ts b/src/popup/accounts/update-temp-password.component.ts new file mode 100644 index 00000000000..c1aab92a8e0 --- /dev/null +++ b/src/popup/accounts/update-temp-password.component.ts @@ -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); + } +} diff --git a/src/popup/app-routing.module.ts b/src/popup/app-routing.module.ts index 7fe2ddfeafa..f6558b74845 100644 --- a/src/popup/app-routing.module.ts +++ b/src/popup/app-routing.module.ts @@ -22,6 +22,7 @@ import { SetPasswordComponent } from './accounts/set-password.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 { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component'; import { PasswordGeneratorComponent } from './generator/password-generator.component'; @@ -261,6 +262,12 @@ const routes: Routes = [ canActivate: [AuthGuardService], data: { state: 'edit-send' }, }, + { + path: 'update-temp-password', + component: UpdateTempPasswordComponent, + canActivate: [AuthGuardService], + data: { state: 'update-temp-password' }, + }, { path: 'tabs', component: TabsComponent, diff --git a/src/popup/app.module.ts b/src/popup/app.module.ts index d79aad9b48f..0972131644a 100644 --- a/src/popup/app.module.ts +++ b/src/popup/app.module.ts @@ -20,6 +20,7 @@ import { SetPasswordComponent } from './accounts/set-password.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 { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component'; import { PasswordGeneratorComponent } from './generator/password-generator.component'; @@ -226,8 +227,10 @@ registerLocaleData(localeZhTw, 'zh-TW'); SendGroupingsComponent, SendListComponent, SendTypeComponent, + SetPasswordComponent, SettingsComponent, ShareComponent, + SsoComponent, StopClickDirective, StopPropDirective, SyncComponent, @@ -235,9 +238,8 @@ registerLocaleData(localeZhTw, 'zh-TW'); TrueFalseValueDirective, TwoFactorOptionsComponent, TwoFactorComponent, - SsoComponent, + UpdateTempPasswordComponent, ViewComponent, - SetPasswordComponent, ], entryComponents: [], providers: [