diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index e42b3f0817..643d21d913 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 f1152d8aac..ffcf9c375a 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,12 +24,19 @@ 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.successRoute = '/tabs/vault'; + super.onSuccessfulLoginNavigate = async () => { + if (await this.userService.getForcePasswordReset()) { + this.router.navigate(['update-temp-password']); + } else { + this.router.navigate([this.successRoute]); + } + }; } settings() { diff --git a/src/popup/accounts/set-password.component.ts b/src/popup/accounts/set-password.component.ts index 143bb864c8..8e795f9fe5 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 34b3a77c01..6536e67068 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 7850daa5d9..409591f10c 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,7 +45,8 @@ 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 = () => { @@ -52,6 +54,17 @@ export class TwoFactorComponent extends BaseTwoFactorComponent { }; super.successRoute = '/tabs/vault'; this.webAuthnNewTab = this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari(); + super.onSuccessfulLoginNavigate = async () => { + if (await this.userService.getForcePasswordReset()) { + this.router.navigate(['update-temp-password']); + } else { + this.router.navigate([this.successRoute], { + queryParams: { + identifier: this.identifier, + }, + }); + } + } } async ngOnInit() { 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 0000000000..5154590c8b --- /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 0000000000..2ae6746464 --- /dev/null +++ b/src/popup/accounts/update-temp-password.component.ts @@ -0,0 +1,27 @@ +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'; + +@Component({ + selector: 'app-update-temp-password', + templateUrl: 'update-temp-password.component.html', +}) + +export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent { + 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 7fe2ddfeaf..f6558b7484 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 a36a8a5627..15c8f40a38 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'; @@ -224,8 +225,10 @@ registerLocaleData(localeZhTw, 'zh-TW'); SendGroupingsComponent, SendListComponent, SendTypeComponent, + SetPasswordComponent, SettingsComponent, ShareComponent, + SsoComponent, StopClickDirective, StopPropDirective, SyncComponent, @@ -233,9 +236,8 @@ registerLocaleData(localeZhTw, 'zh-TW'); TrueFalseValueDirective, TwoFactorOptionsComponent, TwoFactorComponent, - SsoComponent, + UpdateTempPasswordComponent, ViewComponent, - SetPasswordComponent, ], entryComponents: [], providers: [