mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
[PM-18566] Wire up vNextPolicyService for Clients (#13678)
* wire up vNext impl * wire up vNextPolicyService for browser * wire up vNextPolicyService for desktop * wire up vNextPolicyService for cli * fix test * fix missed caller * cleanup * fix missing property assignment * fix QA bug for PM-19205 * fix QA bug for PM-19206 * fix QA bug for pm-19228 * cleanup
This commit is contained in:
@@ -207,7 +207,7 @@ const providers = {
|
||||
describe("CredentialGeneratorService", () => {
|
||||
beforeEach(async () => {
|
||||
await accountService.switchAccount(SomeUser);
|
||||
policyService.getAll$.mockImplementation(() => new BehaviorSubject([]).asObservable());
|
||||
policyService.policiesByType$.mockImplementation(() => new BehaviorSubject([]).asObservable());
|
||||
i18nService.t.mockImplementation((key: string) => key);
|
||||
apiService.fetch.mockImplementation(() => Promise.resolve(mock<Response>()));
|
||||
jest.clearAllMocks();
|
||||
@@ -567,7 +567,7 @@ describe("CredentialGeneratorService", () => {
|
||||
// awareness; they exercise the logic without being comprehensive
|
||||
it("enforces the active user's policy", async () => {
|
||||
const policy$ = new BehaviorSubject([passwordOverridePolicy]);
|
||||
policyService.getAll$.mockReturnValue(policy$);
|
||||
policyService.policiesByType$.mockReturnValue(policy$);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -578,15 +578,22 @@ describe("CredentialGeneratorService", () => {
|
||||
|
||||
const result = await firstValueFrom(generator.algorithms$(["password"], { account$ }));
|
||||
|
||||
expect(policyService.getAll$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, SomeUser);
|
||||
expect(policyService.policiesByType$).toHaveBeenCalledWith(
|
||||
PolicyType.PasswordGenerator,
|
||||
SomeUser,
|
||||
);
|
||||
expect(result.some((a) => a.id === Generators.password.id)).toBeTruthy();
|
||||
expect(result.some((a) => a.id === Generators.passphrase.id)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("follows changes to the active user", async () => {
|
||||
const account$ = new BehaviorSubject(accounts[SomeUser]);
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passphraseOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passphraseOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -603,7 +610,7 @@ describe("CredentialGeneratorService", () => {
|
||||
|
||||
const [someResult, anotherResult] = results;
|
||||
|
||||
expect(policyService.getAll$).toHaveBeenNthCalledWith(
|
||||
expect(policyService.policiesByType$).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
PolicyType.PasswordGenerator,
|
||||
SomeUser,
|
||||
@@ -611,7 +618,7 @@ describe("CredentialGeneratorService", () => {
|
||||
expect(someResult.some((a: any) => a.id === Generators.password.id)).toBeTruthy();
|
||||
expect(someResult.some((a: any) => a.id === Generators.passphrase.id)).toBeFalsy();
|
||||
|
||||
expect(policyService.getAll$).toHaveBeenNthCalledWith(
|
||||
expect(policyService.policiesByType$).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
PolicyType.PasswordGenerator,
|
||||
AnotherUser,
|
||||
@@ -621,7 +628,9 @@ describe("CredentialGeneratorService", () => {
|
||||
});
|
||||
|
||||
it("reads an arbitrary user's settings", async () => {
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -633,14 +642,21 @@ describe("CredentialGeneratorService", () => {
|
||||
|
||||
const result = await firstValueFrom(generator.algorithms$("password", { account$ }));
|
||||
|
||||
expect(policyService.getAll$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, AnotherUser);
|
||||
expect(policyService.policiesByType$).toHaveBeenCalledWith(
|
||||
PolicyType.PasswordGenerator,
|
||||
AnotherUser,
|
||||
);
|
||||
expect(result.some((a: any) => a.id === Generators.password.id)).toBeTruthy();
|
||||
expect(result.some((a: any) => a.id === Generators.passphrase.id)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("follows changes to the arbitrary user", async () => {
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passphraseOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passphraseOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -658,17 +674,25 @@ describe("CredentialGeneratorService", () => {
|
||||
sub.unsubscribe();
|
||||
|
||||
const [someResult, anotherResult] = results;
|
||||
expect(policyService.getAll$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, SomeUser);
|
||||
expect(policyService.policiesByType$).toHaveBeenCalledWith(
|
||||
PolicyType.PasswordGenerator,
|
||||
SomeUser,
|
||||
);
|
||||
expect(someResult.some((a: any) => a.id === Generators.password.id)).toBeTruthy();
|
||||
expect(someResult.some((a: any) => a.id === Generators.passphrase.id)).toBeFalsy();
|
||||
|
||||
expect(policyService.getAll$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, AnotherUser);
|
||||
expect(policyService.policiesByType$).toHaveBeenCalledWith(
|
||||
PolicyType.PasswordGenerator,
|
||||
AnotherUser,
|
||||
);
|
||||
expect(anotherResult.some((a: any) => a.id === Generators.passphrase.id)).toBeTruthy();
|
||||
expect(anotherResult.some((a: any) => a.id === Generators.password.id)).toBeFalsy();
|
||||
});
|
||||
|
||||
it("errors when the arbitrary user's stream errors", async () => {
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -692,7 +716,9 @@ describe("CredentialGeneratorService", () => {
|
||||
});
|
||||
|
||||
it("completes when the arbitrary user's stream completes", async () => {
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -716,7 +742,9 @@ describe("CredentialGeneratorService", () => {
|
||||
});
|
||||
|
||||
it("ignores repeated arbitrary user emissions", async () => {
|
||||
policyService.getAll$.mockReturnValueOnce(new BehaviorSubject([passwordOverridePolicy]));
|
||||
policyService.policiesByType$.mockReturnValueOnce(
|
||||
new BehaviorSubject([passwordOverridePolicy]),
|
||||
);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -780,7 +808,7 @@ describe("CredentialGeneratorService", () => {
|
||||
const settings = { foo: "value" };
|
||||
await stateProvider.setUserState(SettingsKey, settings, SomeUser);
|
||||
const policy$ = new BehaviorSubject([somePolicy]);
|
||||
policyService.getAll$.mockReturnValue(policy$);
|
||||
policyService.policiesByType$.mockReturnValue(policy$);
|
||||
const generator = new CredentialGeneratorService(
|
||||
randomizer,
|
||||
policyService,
|
||||
@@ -908,7 +936,7 @@ describe("CredentialGeneratorService", () => {
|
||||
);
|
||||
const account$ = new BehaviorSubject(accounts[SomeUser]).asObservable();
|
||||
const policy$ = new BehaviorSubject([somePolicy]);
|
||||
policyService.getAll$.mockReturnValue(policy$);
|
||||
policyService.policiesByType$.mockReturnValue(policy$);
|
||||
|
||||
const result = await firstValueFrom(generator.policy$(SomeConfiguration, { account$ }));
|
||||
|
||||
@@ -926,7 +954,7 @@ describe("CredentialGeneratorService", () => {
|
||||
const account = new BehaviorSubject(accounts[SomeUser]);
|
||||
const account$ = account.asObservable();
|
||||
const somePolicySubject = new BehaviorSubject([somePolicy]);
|
||||
policyService.getAll$.mockReturnValueOnce(somePolicySubject.asObservable());
|
||||
policyService.policiesByType$.mockReturnValueOnce(somePolicySubject.asObservable());
|
||||
const emissions: GeneratorConstraints<SomeSettings>[] = [];
|
||||
const sub = generator
|
||||
.policy$(SomeConfiguration, { account$ })
|
||||
@@ -954,7 +982,9 @@ describe("CredentialGeneratorService", () => {
|
||||
const account$ = account.asObservable();
|
||||
const somePolicy$ = new BehaviorSubject([somePolicy]).asObservable();
|
||||
const anotherPolicy$ = new BehaviorSubject([]).asObservable();
|
||||
policyService.getAll$.mockReturnValueOnce(somePolicy$).mockReturnValueOnce(anotherPolicy$);
|
||||
policyService.policiesByType$
|
||||
.mockReturnValueOnce(somePolicy$)
|
||||
.mockReturnValueOnce(anotherPolicy$);
|
||||
const emissions: GeneratorConstraints<SomeSettings>[] = [];
|
||||
const sub = generator
|
||||
.policy$(SomeConfiguration, { account$ })
|
||||
|
||||
@@ -114,11 +114,13 @@ export class CredentialGeneratorService {
|
||||
const algorithms$ = dependencies.account$.pipe(
|
||||
distinctUntilChanged(),
|
||||
switchMap((account) => {
|
||||
const policies$ = this.policyService.getAll$(PolicyType.PasswordGenerator, account.id).pipe(
|
||||
map((p) => new Set(availableAlgorithms(p))),
|
||||
// complete policy emissions otherwise `switchMap` holds `algorithms$` open indefinitely
|
||||
takeUntil(anyComplete(dependencies.account$)),
|
||||
);
|
||||
const policies$ = this.policyService
|
||||
.policiesByType$(PolicyType.PasswordGenerator, account.id)
|
||||
.pipe(
|
||||
map((p) => new Set(availableAlgorithms(p))),
|
||||
// complete policy emissions otherwise `switchMap` holds `algorithms$` open indefinitely
|
||||
takeUntil(anyComplete(dependencies.account$)),
|
||||
);
|
||||
return policies$;
|
||||
}),
|
||||
map((available) => {
|
||||
@@ -280,7 +282,7 @@ export class CredentialGeneratorService {
|
||||
switchMap(({ userId, email }) => {
|
||||
// complete policy emissions otherwise `switchMap` holds `policies$` open indefinitely
|
||||
const policies$ = this.policyService
|
||||
.getAll$(configuration.policy.type, userId)
|
||||
.policiesByType$(configuration.policy.type, userId)
|
||||
.pipe(
|
||||
mapPolicyToConstraints(configuration.policy, email),
|
||||
takeUntil(anyComplete(dependencies.account$)),
|
||||
|
||||
@@ -19,7 +19,7 @@ function mockPolicyService(config?: { state?: BehaviorSubject<Policy[]> }) {
|
||||
const service = mock<PolicyService>();
|
||||
|
||||
const stateValue = config?.state ?? new BehaviorSubject<Policy[]>([null]);
|
||||
service.getAll$.mockReturnValue(stateValue);
|
||||
service.policiesByType$.mockReturnValue(stateValue);
|
||||
|
||||
return service;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ describe("Password generator service", () => {
|
||||
|
||||
await firstValueFrom(service.evaluator$(SomeUser));
|
||||
|
||||
expect(policy.getAll$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, SomeUser);
|
||||
expect(policy.policiesByType$).toHaveBeenCalledWith(PolicyType.PasswordGenerator, SomeUser);
|
||||
});
|
||||
|
||||
it("should map the policy using the generation strategy", async () => {
|
||||
@@ -150,7 +150,7 @@ describe("Password generator service", () => {
|
||||
await firstValueFrom(service.evaluator$(SomeUser));
|
||||
await firstValueFrom(service.evaluator$(SomeUser));
|
||||
|
||||
expect(policy.getAll$).toHaveBeenCalledTimes(1);
|
||||
expect(policy.policiesByType$).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should cache the password generator policy for each user", async () => {
|
||||
@@ -161,8 +161,16 @@ describe("Password generator service", () => {
|
||||
await firstValueFrom(service.evaluator$(SomeUser));
|
||||
await firstValueFrom(service.evaluator$(AnotherUser));
|
||||
|
||||
expect(policy.getAll$).toHaveBeenNthCalledWith(1, PolicyType.PasswordGenerator, SomeUser);
|
||||
expect(policy.getAll$).toHaveBeenNthCalledWith(2, PolicyType.PasswordGenerator, AnotherUser);
|
||||
expect(policy.policiesByType$).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
PolicyType.PasswordGenerator,
|
||||
SomeUser,
|
||||
);
|
||||
expect(policy.policiesByType$).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
PolicyType.PasswordGenerator,
|
||||
AnotherUser,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export class DefaultGeneratorService<Options, Policy> implements GeneratorServic
|
||||
}
|
||||
|
||||
private createEvaluator(userId: UserId) {
|
||||
const evaluator$ = this.policy.getAll$(this.strategy.policy, userId).pipe(
|
||||
const evaluator$ = this.policy.policiesByType$(this.strategy.policy, userId).pipe(
|
||||
// create the evaluator from the policies
|
||||
this.strategy.toEvaluator(),
|
||||
);
|
||||
|
||||
@@ -155,7 +155,7 @@ const NoPolicyProfile: CoreProfileMetadata<SomeSettings> = {
|
||||
|
||||
describe("GeneratorProfileProvider", () => {
|
||||
beforeEach(async () => {
|
||||
policyService.getAll$.mockImplementation(() => new BehaviorSubject([]).asObservable());
|
||||
policyService.policiesByType$.mockImplementation(() => new BehaviorSubject([]).asObservable());
|
||||
const encryptor$ = new BehaviorSubject({ userId: SomeUser, encryptor });
|
||||
encryptorProvider.userEncryptor$.mockReturnValue(encryptor$);
|
||||
jest.clearAllMocks();
|
||||
@@ -211,7 +211,7 @@ describe("GeneratorProfileProvider", () => {
|
||||
const profileProvider = new GeneratorProfileProvider(dependencyProvider, policyService);
|
||||
const account$ = new BehaviorSubject(accounts[SomeUser]).asObservable();
|
||||
const policy$ = new BehaviorSubject([somePolicy]);
|
||||
policyService.getAll$.mockReturnValue(policy$);
|
||||
policyService.policiesByType$.mockReturnValue(policy$);
|
||||
|
||||
const result = await firstValueFrom(profileProvider.constraints$(SomeProfile, { account$ }));
|
||||
|
||||
@@ -223,7 +223,7 @@ describe("GeneratorProfileProvider", () => {
|
||||
const account$ = new BehaviorSubject(accounts[SomeUser]).asObservable();
|
||||
const expectedPolicy = [somePolicy];
|
||||
const policy$ = new BehaviorSubject(expectedPolicy);
|
||||
policyService.getAll$.mockReturnValue(policy$);
|
||||
policyService.policiesByType$.mockReturnValue(policy$);
|
||||
|
||||
await firstValueFrom(profileProvider.constraints$(SomeProfile, { account$ }));
|
||||
|
||||
@@ -284,7 +284,7 @@ describe("GeneratorProfileProvider", () => {
|
||||
const account = new BehaviorSubject(accounts[SomeUser]);
|
||||
const account$ = account.asObservable();
|
||||
const somePolicySubject = new BehaviorSubject([somePolicy]);
|
||||
policyService.getAll$.mockReturnValueOnce(somePolicySubject.asObservable());
|
||||
policyService.policiesByType$.mockReturnValueOnce(somePolicySubject.asObservable());
|
||||
const emissions: GeneratorConstraints<SomeSettings>[] = [];
|
||||
const sub = profileProvider
|
||||
.constraints$(SomeProfile, { account$ })
|
||||
|
||||
@@ -86,7 +86,7 @@ export class GeneratorProfileProvider {
|
||||
);
|
||||
|
||||
const policies$ = profile.constraints.type
|
||||
? this.policyService.getAll$(profile.constraints.type, account.id)
|
||||
? this.policyService.policiesByType$(profile.constraints.type, account.id)
|
||||
: of([]);
|
||||
|
||||
const context: ProfileContext<Settings> = {
|
||||
|
||||
Reference in New Issue
Block a user