diff --git a/apps/cli/src/auth/commands/login.command.ts b/apps/cli/src/auth/commands/login.command.ts index a8e525e2206..597116dd8db 100644 --- a/apps/cli/src/auth/commands/login.command.ts +++ b/apps/cli/src/auth/commands/login.command.ts @@ -540,7 +540,7 @@ export class LoginCommand { ); const enforcedPolicyOptions = await firstValueFrom( - this.policyService.masterPasswordPolicyOptions$(userId), + this.policyService.masterPasswordPolicyOptionsFromSync$(userId), ); // Verify master password meets policy requirements diff --git a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts index 80f0745f6d5..7e6993f64f9 100644 --- a/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts +++ b/apps/web/src/app/admin-console/organizations/members/components/reset-password.component.ts @@ -98,7 +98,7 @@ export class ResetPasswordComponent implements OnInit, OnDestroy { this.accountService.activeAccount$ .pipe( getUserId, - switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)), + switchMap((userId) => this.policyService.masterPasswordPolicyOptionsFromSync$(userId)), takeUntil(this.destroy$), ) .subscribe( diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts index 95ddc74c3c5..f9d3eeafef6 100644 --- a/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts +++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.spec.ts @@ -134,7 +134,7 @@ describe("WebLoginComponentService", () => { resetPasswordPolicyEnabled, ]); - internalPolicyService.masterPasswordPolicyOptions$.mockReturnValue( + internalPolicyService.masterPasswordPolicyOptionsFromSync$.mockReturnValue( of(masterPasswordPolicyOptions), ); diff --git a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts index a9d7de1c562..cfb807f41d0 100644 --- a/apps/web/src/app/auth/core/services/login/web-login-component.service.ts +++ b/apps/web/src/app/auth/core/services/login/web-login-component.service.ts @@ -110,7 +110,7 @@ export class WebLoginComponentService this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.masterPasswordPolicyOptions$(userId, policies), + this.policyService.masterPasswordPolicyOptionsFromSync$(userId, policies), ), ), ); diff --git a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts index fe3b0837aa8..c7e8bd66a64 100644 --- a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts +++ b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts @@ -149,7 +149,9 @@ describe("WebRegistrationFinishService", () => { acceptOrgInviteService.getOrganizationInvite.mockResolvedValue(orgInvite); policyApiService.getPoliciesByToken.mockResolvedValue(masterPasswordPolicies); - policyService.masterPasswordPolicyOptions$.mockReturnValue(of(masterPasswordPolicyOptions)); + policyService.masterPasswordPolicyOptionsFromSync$.mockReturnValue( + of(masterPasswordPolicyOptions), + ); const result = await service.getMasterPasswordPolicyOptsFromOrgInvite(); diff --git a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts index 3d99b3b6712..4f24dc50f55 100644 --- a/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts +++ b/apps/web/src/app/auth/core/services/registration/web-registration-finish.service.ts @@ -70,7 +70,7 @@ export class WebRegistrationFinishService } const masterPasswordPolicyOpts: MasterPasswordPolicyOptions = await firstValueFrom( - this.policyService.masterPasswordPolicyOptions$(null, policies), + this.policyService.masterPasswordPolicyOptionsFromSync$(null, policies), ); return masterPasswordPolicyOpts; diff --git a/apps/web/src/app/auth/settings/emergency-access/takeover/emergency-access-takeover.component.ts b/apps/web/src/app/auth/settings/emergency-access/takeover/emergency-access-takeover.component.ts index d683545db59..b40086c5e7f 100644 --- a/apps/web/src/app/auth/settings/emergency-access/takeover/emergency-access-takeover.component.ts +++ b/apps/web/src/app/auth/settings/emergency-access/takeover/emergency-access-takeover.component.ts @@ -91,7 +91,9 @@ export class EmergencyAccessTakeoverComponent this.accountService.activeAccount$ .pipe( getUserId, - switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId, policies)), + switchMap((userId) => + this.policyService.masterPasswordPolicyOptionsFromSync$(userId, policies), + ), takeUntil(this.destroy$), ) .subscribe((enforcedPolicyOptions) => (this.enforcedPolicyOptions = enforcedPolicyOptions)); diff --git a/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts b/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts index 215035a0d16..36a5e8f91e1 100644 --- a/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts +++ b/apps/web/src/app/billing/trial-initiation/complete-trial-initiation/complete-trial-initiation.component.ts @@ -191,7 +191,9 @@ export class CompleteTrialInitiationComponent implements OnInit, OnDestroy { this.accountService.activeAccount$ .pipe( getUserId, - switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId, policies)), + switchMap((userId) => + this.policyService.masterPasswordPolicyOptionsFromSync$(userId, policies), + ), takeUntil(this.destroy$), ) .subscribe((enforcedPasswordPolicyOptions) => { diff --git a/libs/angular/src/auth/components/change-password.component.ts b/libs/angular/src/auth/components/change-password.component.ts index ca81f741b23..b2d4b0b5860 100644 --- a/libs/angular/src/auth/components/change-password.component.ts +++ b/libs/angular/src/auth/components/change-password.component.ts @@ -56,7 +56,7 @@ export class ChangePasswordComponent implements OnInit, OnDestroy { this.accountService.activeAccount$ .pipe( getUserId, - switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)), + switchMap((userId) => this.policyService.masterPasswordPolicyOptionsFromSync$(userId)), takeUntil(this.destroy$), ) .subscribe( diff --git a/libs/auth/src/angular/change-password/change-password.component.ts b/libs/auth/src/angular/change-password/change-password.component.ts index 90f17fa48c7..45c4166c596 100644 --- a/libs/auth/src/angular/change-password/change-password.component.ts +++ b/libs/auth/src/angular/change-password/change-password.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnInit } from "@angular/core"; import { firstValueFrom } from "rxjs"; -import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; +import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; import { Account, AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; @@ -61,7 +61,7 @@ export class ChangePasswordComponent implements OnInit { private masterPasswordService: InternalMasterPasswordServiceAbstraction, private anonLayoutWrapperDataService: AnonLayoutWrapperDataService, private messagingService: MessagingService, - private policyService: PolicyService, + private policyApiService: PolicyApiServiceAbstraction, private toastService: ToastService, private syncService: SyncService, private dialogService: DialogService, @@ -82,8 +82,8 @@ export class ChangePasswordComponent implements OnInit { throw new Error("userId not found"); } - this.masterPasswordPolicyOptions = await firstValueFrom( - this.policyService.masterPasswordPolicyOptions$(this.userId), + this.masterPasswordPolicyOptions = MasterPasswordPolicyOptions.fromResponse( + await this.policyApiService.getMasterPasswordPoliciesForAcceptedOrConfirmedUser(), ); this.forceSetPasswordReason = await firstValueFrom( diff --git a/libs/common/src/admin-console/abstractions/policy/policy-api.service.abstraction.ts b/libs/common/src/admin-console/abstractions/policy/policy-api.service.abstraction.ts index 4db0fc16750..7e37aceeee3 100644 --- a/libs/common/src/admin-console/abstractions/policy/policy-api.service.abstraction.ts +++ b/libs/common/src/admin-console/abstractions/policy/policy-api.service.abstraction.ts @@ -1,3 +1,5 @@ +import { MasterPasswordPolicyResponse } from "@bitwarden/common/auth/models/response/master-password-policy.response"; + import { ListResponse } from "../../../models/response/list.response"; import { PolicyType } from "../../enums"; import { MasterPasswordPolicyOptions } from "../../models/domain/master-password-policy-options"; @@ -9,6 +11,8 @@ export abstract class PolicyApiServiceAbstraction { abstract getPolicy: (organizationId: string, type: PolicyType) => Promise; abstract getPolicies: (organizationId: string) => Promise>; + abstract getMasterPasswordPoliciesForAcceptedOrConfirmedUser: () => Promise; + abstract getPoliciesByToken: ( organizationId: string, token: string, diff --git a/libs/common/src/admin-console/abstractions/policy/policy.service.abstraction.ts b/libs/common/src/admin-console/abstractions/policy/policy.service.abstraction.ts index 6707af460b6..4cdfdc80573 100644 --- a/libs/common/src/admin-console/abstractions/policy/policy.service.abstraction.ts +++ b/libs/common/src/admin-console/abstractions/policy/policy.service.abstraction.ts @@ -45,7 +45,7 @@ export abstract class PolicyService { * @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 masterPasswordPolicyOptions$: ( + abstract masterPasswordPolicyOptionsFromSync$: ( userId: UserId, policies?: Policy[], ) => Observable; diff --git a/libs/common/src/admin-console/services/policy/default-policy.service.spec.ts b/libs/common/src/admin-console/services/policy/default-policy.service.spec.ts index 7787bdbc943..24fa5c45d7b 100644 --- a/libs/common/src/admin-console/services/policy/default-policy.service.spec.ts +++ b/libs/common/src/admin-console/services/policy/default-policy.service.spec.ts @@ -127,7 +127,9 @@ describe("PolicyService", () => { ]; jest.spyOn(policyService as any, "policies$").mockReturnValue(of(model)); - const result = await firstValueFrom(policyService.masterPasswordPolicyOptions$(userId)); + const result = await firstValueFrom( + policyService.masterPasswordPolicyOptionsFromSync$(userId), + ); expect(result).toEqual({ minComplexity: 5, @@ -152,7 +154,9 @@ describe("PolicyService", () => { ]; jest.spyOn(policyService as any, "policies$").mockReturnValue(of(model)); - const result = await firstValueFrom(policyService.masterPasswordPolicyOptions$(userId)); + const result = await firstValueFrom( + policyService.masterPasswordPolicyOptionsFromSync$(userId), + ); expect(result).toBeUndefined(); }); @@ -169,7 +173,9 @@ describe("PolicyService", () => { ]; jest.spyOn(policyService as any, "policies$").mockReturnValue(of(model)); - const result = await firstValueFrom(policyService.masterPasswordPolicyOptions$(userId)); + const result = await firstValueFrom( + policyService.masterPasswordPolicyOptionsFromSync$(userId), + ); expect(result).toEqual({ minComplexity: 0, diff --git a/libs/common/src/admin-console/services/policy/default-policy.service.ts b/libs/common/src/admin-console/services/policy/default-policy.service.ts index 6abb7f36528..17295fea434 100644 --- a/libs/common/src/admin-console/services/policy/default-policy.service.ts +++ b/libs/common/src/admin-console/services/policy/default-policy.service.ts @@ -82,7 +82,7 @@ export class DefaultPolicyService implements PolicyService { }); } - masterPasswordPolicyOptions$( + masterPasswordPolicyOptionsFromSync$( userId: UserId, policies?: Policy[], ): Observable { diff --git a/libs/common/src/admin-console/services/policy/policy-api.service.ts b/libs/common/src/admin-console/services/policy/policy-api.service.ts index 8f9854f49c4..dad4caff18e 100644 --- a/libs/common/src/admin-console/services/policy/policy-api.service.ts +++ b/libs/common/src/admin-console/services/policy/policy-api.service.ts @@ -1,5 +1,7 @@ import { firstValueFrom, map, switchMap } from "rxjs"; +import { MasterPasswordPolicyResponse } from "@bitwarden/common/auth/models/response/master-password-policy.response"; + import { ApiService } from "../../../abstractions/api.service"; import { AccountService } from "../../../auth/abstractions/account.service"; import { getUserId } from "../../../auth/services/account.service"; @@ -45,6 +47,11 @@ export class PolicyApiService implements PolicyApiServiceAbstraction { return new ListResponse(r, PolicyResponse); } + async getMasterPasswordPoliciesForAcceptedOrConfirmedUser(): Promise { + const r = await this.apiService.send("GET", "/policies/master-password", null, true, true); + return new MasterPasswordPolicyResponse(r); + } + async getPoliciesByToken( organizationId: string, token: string, @@ -100,7 +107,7 @@ export class PolicyApiService implements PolicyApiServiceAbstraction { this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.masterPasswordPolicyOptions$(userId, [masterPasswordPolicy]), + this.policyService.masterPasswordPolicyOptionsFromSync$(userId, [masterPasswordPolicy]), ), map((policy) => policy ?? null), ), diff --git a/libs/key-management-ui/src/lock/components/lock.component.ts b/libs/key-management-ui/src/lock/components/lock.component.ts index ef91f2a03f1..3f738b51786 100644 --- a/libs/key-management-ui/src/lock/components/lock.component.ts +++ b/libs/key-management-ui/src/lock/components/lock.component.ts @@ -601,7 +601,9 @@ export class LockComponent implements OnInit, OnDestroy { this.enforcedMasterPasswordOptions = await firstValueFrom( this.accountService.activeAccount$.pipe( getUserId, - switchMap((userId) => this.policyService.masterPasswordPolicyOptions$(userId)), + switchMap((userId) => + this.policyService.masterPasswordPolicyOptionsFromSync$(userId), + ), ), ); }