mirror of
https://github.com/bitwarden/browser
synced 2026-02-15 16:05:03 +00:00
refactor(change-password-component): Change Password Update [18720] - Routing changes and policy service changes.
This commit is contained in:
@@ -104,10 +104,7 @@ export class WebLoginComponentService
|
||||
if (
|
||||
await this.configService.getFeatureFlag(FeatureFlag.PM16117_ChangeExistingPasswordRefactor)
|
||||
) {
|
||||
// Properly error if we don't have an org invite
|
||||
enforcedPasswordPolicyOptions = await firstValueFrom(
|
||||
this.policyService.masterPasswordPolicyOptionsPriorToSync$(policies),
|
||||
);
|
||||
enforcedPasswordPolicyOptions = this.policyService.combineMasterPasswordPolicies(policies);
|
||||
} else {
|
||||
enforcedPasswordPolicyOptions = await firstValueFrom(
|
||||
this.accountService.activeAccount$.pipe(
|
||||
|
||||
@@ -14,8 +14,10 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { KeyConnectorService } from "@bitwarden/common/key-management/key-connector/abstractions/key-connector.service";
|
||||
import { MasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
|
||||
export const authGuard: CanActivateFn = async (
|
||||
@@ -28,6 +30,7 @@ export const authGuard: CanActivateFn = async (
|
||||
const keyConnectorService = inject(KeyConnectorService);
|
||||
const accountService = inject(AccountService);
|
||||
const masterPasswordService = inject(MasterPasswordServiceAbstraction);
|
||||
const configService = inject(ConfigService);
|
||||
|
||||
const authStatus = await authService.getAuthStatus();
|
||||
|
||||
@@ -66,10 +69,17 @@ export const authGuard: CanActivateFn = async (
|
||||
}
|
||||
|
||||
if (
|
||||
forceSetPasswordReason !== ForceSetPasswordReason.None &&
|
||||
!routerState.url.includes("update-temp-password")
|
||||
(forceSetPasswordReason !== ForceSetPasswordReason.None &&
|
||||
!routerState.url.includes("update-temp-password")) ||
|
||||
!routerState.url.includes("change-password")
|
||||
) {
|
||||
return router.createUrlTree(["/update-temp-password"]);
|
||||
const SetInitialPasswordRefactorFlagOn = await configService.getFeatureFlag(
|
||||
FeatureFlag.PM16117_ChangeExistingPasswordRefactor,
|
||||
);
|
||||
|
||||
const route = SetInitialPasswordRefactorFlagOn ? "/change-password" : "/update-temp-password";
|
||||
|
||||
return router.createUrlTree([route]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -44,8 +44,6 @@ export abstract class PolicyService {
|
||||
* @param policies The policies to be evaluated; if null or undefined, it will default to using policies from sync data.
|
||||
* @returns a set of options which represent the minimum Master Password settings that the user must
|
||||
* comply with in order to comply with **all** applicable Master Password policies.
|
||||
*
|
||||
* @deprecated Deprecating because the parameters can be made more strict and clear.
|
||||
*/
|
||||
abstract masterPasswordPolicyOptions$: (
|
||||
userId: UserId,
|
||||
@@ -53,27 +51,12 @@ export abstract class PolicyService {
|
||||
) => Observable<MasterPasswordPolicyOptions | undefined>;
|
||||
|
||||
/**
|
||||
* Combines all Master Password policies that apply to the user.
|
||||
* Used for after a login / sync has occurred and the policy state has been set in state.
|
||||
* @param userId The user against whom the policy needs to be enforced.
|
||||
* @returns a set of options which represent the minimum Master Password settings that the user must
|
||||
* comply with in order to comply with **all** applicable Master Password policies.
|
||||
* Combines all Master Password policies that are passed in.
|
||||
* @param policies
|
||||
*/
|
||||
abstract masterPasswordPolicyOptionsByUserId$: (
|
||||
userId: UserId,
|
||||
) => Observable<MasterPasswordPolicyOptions | undefined>;
|
||||
|
||||
/**
|
||||
* Combines all Master Password policies that apply to the user that comes from the policies that
|
||||
* are passed to this function.
|
||||
* This would be used prior to obtaining a user id, such as before login for an org invite.
|
||||
* @param policies The policies to be evaluated.
|
||||
* @returns a set of options which represent the minimum Master Password settings that the user must
|
||||
* comply with in order to comply with **all** applicable Master Password policies.
|
||||
*/
|
||||
abstract masterPasswordPolicyOptionsPriorToSync$: (
|
||||
abstract combineMasterPasswordPolicies(
|
||||
policies: Policy[],
|
||||
) => Observable<MasterPasswordPolicyOptions | undefined>;
|
||||
): MasterPasswordPolicyOptions | undefined;
|
||||
|
||||
/**
|
||||
* Evaluates whether a proposed Master Password complies with all Master Password policies that apply to the user.
|
||||
|
||||
@@ -87,19 +87,62 @@ export class DefaultPolicyService implements PolicyService {
|
||||
policies?: Policy[],
|
||||
): Observable<MasterPasswordPolicyOptions | undefined> {
|
||||
const policies$ = policies ? of(policies) : this.policies$(userId);
|
||||
return policies$.pipe(map((obsPolicies) => this.policyMapping(obsPolicies)));
|
||||
return policies$.pipe(map((obsPolicies) => this.combineMasterPasswordPolicies(obsPolicies)));
|
||||
}
|
||||
|
||||
masterPasswordPolicyOptionsByUserId$(
|
||||
userId: UserId,
|
||||
): Observable<MasterPasswordPolicyOptions | undefined> {
|
||||
return this.policies$(userId).pipe(map((obsPolicies) => this.policyMapping(obsPolicies)));
|
||||
}
|
||||
combineMasterPasswordPolicies(policies: Policy[]): MasterPasswordPolicyOptions | undefined {
|
||||
let enforcedOptions: MasterPasswordPolicyOptions | undefined = undefined;
|
||||
const filteredPolicies = policies.filter((p) => p.type === PolicyType.MasterPassword) ?? [];
|
||||
|
||||
masterPasswordPolicyOptionsPriorToSync$(
|
||||
policies: Policy[],
|
||||
): Observable<MasterPasswordPolicyOptions | undefined> {
|
||||
return of(policies).pipe(map((obsPolicies) => this.policyMapping(obsPolicies)));
|
||||
if (filteredPolicies.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
filteredPolicies.forEach((currentPolicy) => {
|
||||
if (!currentPolicy.enabled || !currentPolicy.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enforcedOptions) {
|
||||
enforcedOptions = new MasterPasswordPolicyOptions();
|
||||
}
|
||||
|
||||
if (
|
||||
currentPolicy.data.minComplexity != null &&
|
||||
currentPolicy.data.minComplexity > enforcedOptions.minComplexity
|
||||
) {
|
||||
enforcedOptions.minComplexity = currentPolicy.data.minComplexity;
|
||||
}
|
||||
|
||||
if (
|
||||
currentPolicy.data.minLength != null &&
|
||||
currentPolicy.data.minLength > enforcedOptions.minLength
|
||||
) {
|
||||
enforcedOptions.minLength = currentPolicy.data.minLength;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireUpper) {
|
||||
enforcedOptions.requireUpper = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireLower) {
|
||||
enforcedOptions.requireLower = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireNumbers) {
|
||||
enforcedOptions.requireNumbers = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireSpecial) {
|
||||
enforcedOptions.requireSpecial = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.enforceOnLogin) {
|
||||
enforcedOptions.enforceOnLogin = true;
|
||||
}
|
||||
});
|
||||
|
||||
return enforcedOptions;
|
||||
}
|
||||
|
||||
evaluateMasterPassword(
|
||||
@@ -197,59 +240,4 @@ export class DefaultPolicyService implements PolicyService {
|
||||
return organization.canManagePolicies;
|
||||
}
|
||||
}
|
||||
|
||||
private policyMapping(obsPolicies: Policy[]): MasterPasswordPolicyOptions | undefined {
|
||||
let enforcedOptions: MasterPasswordPolicyOptions | undefined = undefined;
|
||||
const filteredPolicies = obsPolicies.filter((p) => p.type === PolicyType.MasterPassword) ?? [];
|
||||
|
||||
if (filteredPolicies.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
filteredPolicies.forEach((currentPolicy) => {
|
||||
if (!currentPolicy.enabled || !currentPolicy.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enforcedOptions) {
|
||||
enforcedOptions = new MasterPasswordPolicyOptions();
|
||||
}
|
||||
|
||||
if (
|
||||
currentPolicy.data.minComplexity != null &&
|
||||
currentPolicy.data.minComplexity > enforcedOptions.minComplexity
|
||||
) {
|
||||
enforcedOptions.minComplexity = currentPolicy.data.minComplexity;
|
||||
}
|
||||
|
||||
if (
|
||||
currentPolicy.data.minLength != null &&
|
||||
currentPolicy.data.minLength > enforcedOptions.minLength
|
||||
) {
|
||||
enforcedOptions.minLength = currentPolicy.data.minLength;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireUpper) {
|
||||
enforcedOptions.requireUpper = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireLower) {
|
||||
enforcedOptions.requireLower = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireNumbers) {
|
||||
enforcedOptions.requireNumbers = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireSpecial) {
|
||||
enforcedOptions.requireSpecial = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.enforceOnLogin) {
|
||||
enforcedOptions.enforceOnLogin = true;
|
||||
}
|
||||
});
|
||||
|
||||
return enforcedOptions;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user