mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
fix(routing): [PM-22995] update routing and tests (#15320)
Updates routing in 2 components to account for feature flag: `PM16117_SetInitialPasswordRefactor`
This commit is contained in:
@@ -23,10 +23,12 @@ import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
|||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response";
|
import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response";
|
||||||
import { ClientType, HttpStatusCode } from "@bitwarden/common/enums";
|
import { ClientType, HttpStatusCode } from "@bitwarden/common/enums";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -116,6 +118,7 @@ export class SsoComponent implements OnInit {
|
|||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private ssoComponentService: SsoComponentService,
|
private ssoComponentService: SsoComponentService,
|
||||||
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
||||||
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
environmentService.environment$.pipe(takeUntilDestroyed()).subscribe((env) => {
|
environmentService.environment$.pipe(takeUntilDestroyed()).subscribe((env) => {
|
||||||
this.redirectUri = env.getWebVaultUrl() + "/sso-connector.html";
|
this.redirectUri = env.getWebVaultUrl() + "/sso-connector.html";
|
||||||
@@ -531,7 +534,12 @@ export class SsoComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleChangePasswordRequired(orgIdentifier: string) {
|
private async handleChangePasswordRequired(orgIdentifier: string) {
|
||||||
await this.router.navigate(["set-password-jit"], {
|
const isSetInitialPasswordRefactorFlagOn = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.PM16117_SetInitialPasswordRefactor,
|
||||||
|
);
|
||||||
|
const route = isSetInitialPasswordRefactorFlagOn ? "set-initial-password" : "set-password-jit";
|
||||||
|
|
||||||
|
await this.router.navigate([route], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
identifier: orgIdentifier,
|
identifier: orgIdentifier,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/ide
|
|||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||||
import { FakeMasterPasswordService } from "@bitwarden/common/key-management/master-password/services/fake-master-password.service";
|
import { FakeMasterPasswordService } from "@bitwarden/common/key-management/master-password/services/fake-master-password.service";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -75,6 +76,7 @@ describe("TwoFactorAuthComponent", () => {
|
|||||||
let mockLoginSuccessHandlerService: MockProxy<LoginSuccessHandlerService>;
|
let mockLoginSuccessHandlerService: MockProxy<LoginSuccessHandlerService>;
|
||||||
let mockTwoFactorAuthCompCacheService: MockProxy<TwoFactorAuthComponentCacheService>;
|
let mockTwoFactorAuthCompCacheService: MockProxy<TwoFactorAuthComponentCacheService>;
|
||||||
let mockAuthService: MockProxy<AuthService>;
|
let mockAuthService: MockProxy<AuthService>;
|
||||||
|
let mockConfigService: MockProxy<ConfigService>;
|
||||||
|
|
||||||
let mockUserDecryptionOpts: {
|
let mockUserDecryptionOpts: {
|
||||||
noMasterPassword: UserDecryptionOptions;
|
noMasterPassword: UserDecryptionOptions;
|
||||||
@@ -110,6 +112,7 @@ describe("TwoFactorAuthComponent", () => {
|
|||||||
mockToastService = mock<ToastService>();
|
mockToastService = mock<ToastService>();
|
||||||
mockTwoFactorAuthCompService = mock<TwoFactorAuthComponentService>();
|
mockTwoFactorAuthCompService = mock<TwoFactorAuthComponentService>();
|
||||||
mockAuthService = mock<AuthService>();
|
mockAuthService = mock<AuthService>();
|
||||||
|
mockConfigService = mock<ConfigService>();
|
||||||
|
|
||||||
mockEnvService = mock<EnvironmentService>();
|
mockEnvService = mock<EnvironmentService>();
|
||||||
mockLoginSuccessHandlerService = mock<LoginSuccessHandlerService>();
|
mockLoginSuccessHandlerService = mock<LoginSuccessHandlerService>();
|
||||||
@@ -209,6 +212,7 @@ describe("TwoFactorAuthComponent", () => {
|
|||||||
useValue: mockTwoFactorAuthCompCacheService,
|
useValue: mockTwoFactorAuthCompCacheService,
|
||||||
},
|
},
|
||||||
{ provide: AuthService, useValue: mockAuthService },
|
{ provide: AuthService, useValue: mockAuthService },
|
||||||
|
{ provide: ConfigService, useValue: mockConfigService },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -225,22 +229,6 @@ describe("TwoFactorAuthComponent", () => {
|
|||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Shared tests
|
|
||||||
const testChangePasswordOnSuccessfulLogin = () => {
|
|
||||||
it("navigates to the component's defined change password route when user doesn't have a MP and key connector isn't enabled", async () => {
|
|
||||||
// Act
|
|
||||||
await component.submit("testToken");
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
|
|
||||||
expect(mockRouter.navigate).toHaveBeenCalledWith(["set-password"], {
|
|
||||||
queryParams: {
|
|
||||||
identifier: component.orgSsoIdentifier,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("Standard 2FA scenarios", () => {
|
describe("Standard 2FA scenarios", () => {
|
||||||
describe("submit", () => {
|
describe("submit", () => {
|
||||||
const token = "testToken";
|
const token = "testToken";
|
||||||
@@ -280,20 +268,76 @@ describe("TwoFactorAuthComponent", () => {
|
|||||||
selectedUserDecryptionOptions.next(mockUserDecryptionOpts.noMasterPassword);
|
selectedUserDecryptionOptions.next(mockUserDecryptionOpts.noMasterPassword);
|
||||||
});
|
});
|
||||||
|
|
||||||
testChangePasswordOnSuccessfulLogin();
|
describe("Given the PM16117_SetInitialPasswordRefactor feature flag is ON", () => {
|
||||||
|
it("navigates to the /set-initial-password route when user doesn't have a MP and key connector isn't enabled", async () => {
|
||||||
|
// Arrange
|
||||||
|
mockConfigService.getFeatureFlag.mockResolvedValue(true);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await component.submit("testToken");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockRouter.navigate).toHaveBeenCalledWith(["set-initial-password"], {
|
||||||
|
queryParams: {
|
||||||
|
identifier: component.orgSsoIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Given the PM16117_SetInitialPasswordRefactor feature flag is OFF", () => {
|
||||||
|
it("navigates to the /set-password route when user doesn't have a MP and key connector isn't enabled", async () => {
|
||||||
|
// Arrange
|
||||||
|
mockConfigService.getFeatureFlag.mockResolvedValue(false);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await component.submit("testToken");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockRouter.navigate).toHaveBeenCalledWith(["set-password"], {
|
||||||
|
queryParams: {
|
||||||
|
identifier: component.orgSsoIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not navigate to the change password route when the user has key connector even if user has no master password", async () => {
|
describe("Given the PM16117_SetInitialPasswordRefactor feature flag is ON", () => {
|
||||||
selectedUserDecryptionOptions.next(
|
it("does not navigate to the /set-initial-password route when the user has key connector even if user has no master password", async () => {
|
||||||
mockUserDecryptionOpts.noMasterPasswordWithKeyConnector,
|
mockConfigService.getFeatureFlag.mockResolvedValue(true);
|
||||||
);
|
|
||||||
|
|
||||||
await component.submit(token, remember);
|
selectedUserDecryptionOptions.next(
|
||||||
|
mockUserDecryptionOpts.noMasterPasswordWithKeyConnector,
|
||||||
|
);
|
||||||
|
|
||||||
expect(mockRouter.navigate).not.toHaveBeenCalledWith(["set-password"], {
|
await component.submit(token, remember);
|
||||||
queryParams: {
|
|
||||||
identifier: component.orgSsoIdentifier,
|
expect(mockRouter.navigate).not.toHaveBeenCalledWith(["set-initial-password"], {
|
||||||
},
|
queryParams: {
|
||||||
|
identifier: component.orgSsoIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Given the PM16117_SetInitialPasswordRefactor feature flag is OFF", () => {
|
||||||
|
it("does not navigate to the /set-password route when the user has key connector even if user has no master password", async () => {
|
||||||
|
mockConfigService.getFeatureFlag.mockResolvedValue(false);
|
||||||
|
|
||||||
|
selectedUserDecryptionOptions.next(
|
||||||
|
mockUserDecryptionOpts.noMasterPasswordWithKeyConnector,
|
||||||
|
);
|
||||||
|
|
||||||
|
await component.submit(token, remember);
|
||||||
|
|
||||||
|
expect(mockRouter.navigate).not.toHaveBeenCalledWith(["set-password"], {
|
||||||
|
queryParams: {
|
||||||
|
identifier: component.orgSsoIdentifier,
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-p
|
|||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
import { InternalMasterPasswordServiceAbstraction } from "@bitwarden/common/key-management/master-password/abstractions/master-password.service.abstraction";
|
||||||
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -169,6 +171,7 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy {
|
|||||||
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
private loginSuccessHandlerService: LoginSuccessHandlerService,
|
||||||
private twoFactorAuthComponentCacheService: TwoFactorAuthComponentCacheService,
|
private twoFactorAuthComponentCacheService: TwoFactorAuthComponentCacheService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
private configService: ConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -559,7 +562,12 @@ export class TwoFactorAuthComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async handleChangePasswordRequired(orgIdentifier: string | undefined) {
|
private async handleChangePasswordRequired(orgIdentifier: string | undefined) {
|
||||||
await this.router.navigate(["set-password"], {
|
const isSetInitialPasswordRefactorFlagOn = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.PM16117_SetInitialPasswordRefactor,
|
||||||
|
);
|
||||||
|
const route = isSetInitialPasswordRefactorFlagOn ? "set-initial-password" : "set-password";
|
||||||
|
|
||||||
|
await this.router.navigate([route], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
identifier: orgIdentifier,
|
identifier: orgIdentifier,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user