-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PM-13348] Browser Extension impacts on Free Bitwarden Family Policy (#…
…12073) * Add changes for enabled policy * Remove unused property * Refactor the changes * remove duplicated across multiple components * Add some test and documentations to service * Correct the comment free family sponsorship for isExemptFromPolicy
- Loading branch information
1 parent
bb09121
commit c52eeb1
Showing
7 changed files
with
159 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { TestBed } from "@angular/core/testing"; | ||
import { mock, MockProxy } from "jest-mock-extended"; | ||
import { firstValueFrom, of } from "rxjs"; | ||
|
||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; | ||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; | ||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; | ||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; | ||
|
||
import { FamiliesPolicyService } from "./families-policy.service"; // Adjust the import as necessary | ||
|
||
describe("FamiliesPolicyService", () => { | ||
let service: FamiliesPolicyService; | ||
let organizationService: MockProxy<OrganizationService>; | ||
let policyService: MockProxy<PolicyService>; | ||
|
||
beforeEach(() => { | ||
organizationService = mock<OrganizationService>(); | ||
policyService = mock<PolicyService>(); | ||
|
||
TestBed.configureTestingModule({ | ||
providers: [ | ||
FamiliesPolicyService, | ||
{ provide: OrganizationService, useValue: organizationService }, | ||
{ provide: PolicyService, useValue: policyService }, | ||
], | ||
}); | ||
|
||
service = TestBed.inject(FamiliesPolicyService); | ||
}); | ||
|
||
it("should return false when there are no enterprise organizations", async () => { | ||
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(false)); | ||
|
||
const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it("should return true when the policy is enabled for the one enterprise organization", async () => { | ||
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true)); | ||
|
||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; | ||
organizationService.getAll$.mockReturnValue(of(organizations)); | ||
|
||
const policies = [{ organizationId: "org1", enabled: true }] as Policy[]; | ||
policyService.getAll$.mockReturnValue(of(policies)); | ||
|
||
const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it("should return false when the policy is not enabled for the one enterprise organization", async () => { | ||
jest.spyOn(service, "hasSingleEnterpriseOrg$").mockReturnValue(of(true)); | ||
|
||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; | ||
organizationService.getAll$.mockReturnValue(of(organizations)); | ||
|
||
const policies = [{ organizationId: "org1", enabled: false }] as Policy[]; | ||
policyService.getAll$.mockReturnValue(of(policies)); | ||
|
||
const result = await firstValueFrom(service.isFreeFamilyPolicyEnabled$()); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it("should return true when there is exactly one enterprise organization that can manage sponsorships", async () => { | ||
const organizations = [{ id: "org1", canManageSponsorships: true }] as Organization[]; | ||
organizationService.getAll$.mockReturnValue(of(organizations)); | ||
|
||
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$()); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it("should return false when there are multiple organizations that can manage sponsorships", async () => { | ||
const organizations = [ | ||
{ id: "org1", canManageSponsorships: true }, | ||
{ id: "org2", canManageSponsorships: true }, | ||
] as Organization[]; | ||
organizationService.getAll$.mockReturnValue(of(organizations)); | ||
|
||
const result = await firstValueFrom(service.hasSingleEnterpriseOrg$()); | ||
expect(result).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { Injectable } from "@angular/core"; | ||
import { map, Observable, of, switchMap } from "rxjs"; | ||
|
||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; | ||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; | ||
import { PolicyType } from "@bitwarden/common/admin-console/enums"; | ||
|
||
@Injectable({ providedIn: "root" }) | ||
export class FamiliesPolicyService { | ||
constructor( | ||
private policyService: PolicyService, | ||
private organizationService: OrganizationService, | ||
) {} | ||
|
||
hasSingleEnterpriseOrg$(): Observable<boolean> { | ||
// Retrieve all organizations the user is part of | ||
return this.organizationService.getAll$().pipe( | ||
map((organizations) => { | ||
// Filter to only those organizations that can manage sponsorships | ||
const sponsorshipOrgs = organizations.filter((org) => org.canManageSponsorships); | ||
|
||
// Check if there is exactly one organization that can manage sponsorships. | ||
// This is important because users that are part of multiple organizations | ||
// may always access free bitwarden family menu. We want to restrict access | ||
// to the policy only when there is a single enterprise organization and the free family policy is turn. | ||
return sponsorshipOrgs.length === 1; | ||
}), | ||
); | ||
} | ||
|
||
isFreeFamilyPolicyEnabled$(): Observable<boolean> { | ||
return this.hasSingleEnterpriseOrg$().pipe( | ||
switchMap((hasSingleEnterpriseOrg) => { | ||
if (!hasSingleEnterpriseOrg) { | ||
return of(false); | ||
} | ||
return this.organizationService.getAll$().pipe( | ||
map((organizations) => organizations.find((org) => org.canManageSponsorships)?.id), | ||
switchMap((enterpriseOrgId) => | ||
this.policyService | ||
.getAll$(PolicyType.FreeFamiliesSponsorshipPolicy) | ||
.pipe( | ||
map( | ||
(policies) => | ||
policies.find((policy) => policy.organizationId === enterpriseOrgId)?.enabled ?? | ||
false, | ||
), | ||
), | ||
), | ||
); | ||
}), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters