diff --git a/apps/browser/src/autofill/background/notification.background.ts b/apps/browser/src/autofill/background/notification.background.ts index a798798a980..65c1ca0277f 100644 --- a/apps/browser/src/autofill/background/notification.background.ts +++ b/apps/browser/src/autofill/background/notification.background.ts @@ -1056,7 +1056,7 @@ export default class NotificationBackground { this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ), ); diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts index cb29532c93c..baa34d7bdbe 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.spec.ts @@ -228,10 +228,10 @@ describe("VaultPopupListFiltersService", () => { }); }); - describe("PersonalOwnership policy", () => { - it('calls policyAppliesToUser$ with "PersonalOwnership"', () => { + describe("OrganizationDataOwnership policy", () => { + it('calls policyAppliesToUser$ with "OrganizationDataOwnership"', () => { expect(policyService.policyAppliesToUser$).toHaveBeenCalledWith( - PolicyType.PersonalOwnership, + PolicyType.OrganizationDataOwnership, "userId", ); }); diff --git a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts index ef843939035..610b099952d 100644 --- a/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts +++ b/apps/browser/src/vault/popup/services/vault-popup-list-filters.service.ts @@ -293,30 +293,30 @@ export class VaultPopupListFiltersService { switchMap((userId) => combineLatest([ this.organizationService.memberOrganizations$(userId), - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ]), ), - map(([orgs, personalOwnershipApplies]): [Organization[], boolean] => [ + map(([orgs, organizationDataOwnership]): [Organization[], boolean] => [ orgs.sort(Utils.getSortFunction(this.i18nService, "name")), - personalOwnershipApplies, + organizationDataOwnership, ]), - map(([orgs, personalOwnershipApplies]) => { + map(([orgs, organizationDataOwnership]) => { // When there are no organizations return an empty array, // resulting in the org filter being hidden if (!orgs.length) { return []; } - // When there is only one organization and personal ownership policy applies, + // When there is only one organization and organization data ownership policy applies, // return an empty array, resulting in the org filter being hidden - if (orgs.length === 1 && personalOwnershipApplies) { + if (orgs.length === 1 && organizationDataOwnership) { return []; } const myVaultOrg: ChipSelectOption[] = []; - // Only add "My vault" if personal ownership policy does not apply - if (!personalOwnershipApplies) { + // Only add "My vault" if organization data ownership policy does not apply + if (!organizationDataOwnership) { myVaultOrg.push({ value: { id: MY_VAULT_ID } as Organization, label: this.i18nService.t("myVault"), diff --git a/apps/desktop/src/services/encrypted-message-handler.service.ts b/apps/desktop/src/services/encrypted-message-handler.service.ts index 37a8114c1d1..366a144c021 100644 --- a/apps/desktop/src/services/encrypted-message-handler.service.ts +++ b/apps/desktop/src/services/encrypted-message-handler.service.ts @@ -147,7 +147,7 @@ export class EncryptedMessageHandlerService { const policyApplies$ = this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ); diff --git a/apps/desktop/src/vault/app/vault/vault-filter/filters/organization-filter.component.ts b/apps/desktop/src/vault/app/vault/vault-filter/filters/organization-filter.component.ts index 33a47cdc91f..503c2b2ec6e 100644 --- a/apps/desktop/src/vault/app/vault/vault-filter/filters/organization-filter.component.ts +++ b/apps/desktop/src/vault/app/vault/vault-filter/filters/organization-filter.component.ts @@ -16,7 +16,9 @@ import { ToastService } from "@bitwarden/components"; }) export class OrganizationFilterComponent extends BaseOrganizationFilterComponent { get show() { - const hiddenDisplayModes: DisplayMode[] = ["singleOrganizationAndPersonalOwnershipPolicies"]; + const hiddenDisplayModes: DisplayMode[] = [ + "singleOrganizationAndOrganizatonDataOwnershipPolicies", + ]; return ( !this.hide && this.organizations.length > 0 && diff --git a/apps/desktop/src/vault/app/vault/vault-filter/vault-filter.component.html b/apps/desktop/src/vault/app/vault/vault-filter/vault-filter.component.html index f44fc8f9302..0664e0591ad 100644 --- a/apps/desktop/src/vault/app/vault/vault-filter/vault-filter.component.html +++ b/apps/desktop/src/vault/app/vault/vault-filter/vault-filter.component.html @@ -8,7 +8,7 @@ [activeFilter]="activeFilter" [collapsedFilterNodes]="collapsedFilterNodes" [organizations]="organizations" - [activePersonalOwnershipPolicy]="activePersonalOwnershipPolicy" + [activeOrganizationDataOwnership]="activeOrganizationDataOwnershipPolicy" [activeSingleOrganizationPolicy]="activeSingleOrganizationPolicy" (onNodeCollapseStateChange)="toggleFilterNodeCollapseState($event)" (onFilterChange)="applyFilter($event)" diff --git a/apps/web/src/app/admin-console/organizations/policies/index.ts b/apps/web/src/app/admin-console/organizations/policies/index.ts index 4f4b85fc6c2..828aa8230fa 100644 --- a/apps/web/src/app/admin-console/organizations/policies/index.ts +++ b/apps/web/src/app/admin-console/organizations/policies/index.ts @@ -3,7 +3,7 @@ export { BasePolicy, BasePolicyComponent } from "./base-policy.component"; export { DisableSendPolicy } from "./disable-send.component"; export { MasterPasswordPolicy } from "./master-password.component"; export { PasswordGeneratorPolicy } from "./password-generator.component"; -export { PersonalOwnershipPolicy } from "./personal-ownership.component"; +export { OrganizationDataOwnershipPolicy } from "./organization-data-ownership.component"; export { RequireSsoPolicy } from "./require-sso.component"; export { ResetPasswordPolicy } from "./reset-password.component"; export { SendOptionsPolicy } from "./send-options.component"; diff --git a/apps/web/src/app/admin-console/organizations/policies/personal-ownership.component.html b/apps/web/src/app/admin-console/organizations/policies/organization-data-ownership.component.html similarity index 100% rename from apps/web/src/app/admin-console/organizations/policies/personal-ownership.component.html rename to apps/web/src/app/admin-console/organizations/policies/organization-data-ownership.component.html diff --git a/apps/web/src/app/admin-console/organizations/policies/organization-data-ownership.component.ts b/apps/web/src/app/admin-console/organizations/policies/organization-data-ownership.component.ts new file mode 100644 index 00000000000..1c1710f7662 --- /dev/null +++ b/apps/web/src/app/admin-console/organizations/policies/organization-data-ownership.component.ts @@ -0,0 +1,19 @@ +import { Component } from "@angular/core"; + +import { PolicyType } from "@bitwarden/common/admin-console/enums"; + +import { BasePolicy, BasePolicyComponent } from "./base-policy.component"; + +export class OrganizationDataOwnershipPolicy extends BasePolicy { + name = "organizationDataOwnership"; + description = "personalOwnershipPolicyDesc"; + type = PolicyType.OrganizationDataOwnership; + component = OrganizationDataOwnershipPolicyComponent; +} + +@Component({ + selector: "policy-organization-data-ownership", + templateUrl: "organization-data-ownership.component.html", + standalone: false, +}) +export class OrganizationDataOwnershipPolicyComponent extends BasePolicyComponent {} diff --git a/apps/web/src/app/admin-console/organizations/policies/personal-ownership.component.ts b/apps/web/src/app/admin-console/organizations/policies/personal-ownership.component.ts deleted file mode 100644 index ef92ee90581..00000000000 --- a/apps/web/src/app/admin-console/organizations/policies/personal-ownership.component.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Component } from "@angular/core"; - -import { PolicyType } from "@bitwarden/common/admin-console/enums"; - -import { BasePolicy, BasePolicyComponent } from "./base-policy.component"; - -export class PersonalOwnershipPolicy extends BasePolicy { - name = "personalOwnership"; - description = "personalOwnershipPolicyDesc"; - type = PolicyType.PersonalOwnership; - component = PersonalOwnershipPolicyComponent; -} - -@Component({ - selector: "policy-personal-ownership", - templateUrl: "personal-ownership.component.html", - standalone: false, -}) -export class PersonalOwnershipPolicyComponent extends BasePolicyComponent {} diff --git a/apps/web/src/app/admin-console/organizations/policies/policies.module.ts b/apps/web/src/app/admin-console/organizations/policies/policies.module.ts index 4ecf8d76491..3999f36ecad 100644 --- a/apps/web/src/app/admin-console/organizations/policies/policies.module.ts +++ b/apps/web/src/app/admin-console/organizations/policies/policies.module.ts @@ -4,8 +4,8 @@ import { LooseComponentsModule, SharedModule } from "../../../shared"; import { DisableSendPolicyComponent } from "./disable-send.component"; import { MasterPasswordPolicyComponent } from "./master-password.component"; +import { OrganizationDataOwnershipPolicyComponent } from "./organization-data-ownership.component"; import { PasswordGeneratorPolicyComponent } from "./password-generator.component"; -import { PersonalOwnershipPolicyComponent } from "./personal-ownership.component"; import { PoliciesComponent } from "./policies.component"; import { PolicyEditComponent } from "./policy-edit.component"; import { RemoveUnlockWithPinPolicyComponent } from "./remove-unlock-with-pin.component"; @@ -22,7 +22,7 @@ import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authenticat DisableSendPolicyComponent, MasterPasswordPolicyComponent, PasswordGeneratorPolicyComponent, - PersonalOwnershipPolicyComponent, + OrganizationDataOwnershipPolicyComponent, RequireSsoPolicyComponent, ResetPasswordPolicyComponent, SendOptionsPolicyComponent, @@ -37,7 +37,7 @@ import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authenticat DisableSendPolicyComponent, MasterPasswordPolicyComponent, PasswordGeneratorPolicyComponent, - PersonalOwnershipPolicyComponent, + OrganizationDataOwnershipPolicyComponent, RequireSsoPolicyComponent, ResetPasswordPolicyComponent, SendOptionsPolicyComponent, diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index 15436f3097a..b9f3b8c05b7 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -34,7 +34,7 @@ import { DisableSendPolicy, MasterPasswordPolicy, PasswordGeneratorPolicy, - PersonalOwnershipPolicy, + OrganizationDataOwnershipPolicy, RequireSsoPolicy, ResetPasswordPolicy, SendOptionsPolicy, @@ -243,7 +243,7 @@ export class AppComponent implements OnDestroy, OnInit { new PasswordGeneratorPolicy(), new SingleOrgPolicy(), new RequireSsoPolicy(), - new PersonalOwnershipPolicy(), + new OrganizationDataOwnershipPolicy(), new DisableSendPolicy(), new SendOptionsPolicy(), ]); diff --git a/apps/web/src/app/vault/individual-vault/vault-filter/components/vault-filter.component.ts b/apps/web/src/app/vault/individual-vault/vault-filter/components/vault-filter.component.ts index 72766817eeb..61dd3e9ca80 100644 --- a/apps/web/src/app/vault/individual-vault/vault-filter/components/vault-filter.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-filter/components/vault-filter.component.ts @@ -175,7 +175,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy { merge( this.policyService.policiesByType$(PolicyType.SingleOrg, userId).pipe(getFirstPolicy), this.policyService - .policiesByType$(PolicyType.PersonalOwnership, userId) + .policiesByType$(PolicyType.OrganizationDataOwnership, userId) .pipe(getFirstPolicy), ), ), @@ -268,7 +268,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy { this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ), ); diff --git a/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.spec.ts b/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.spec.ts index 559d0cc60c5..59aa169481e 100644 --- a/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.spec.ts +++ b/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.spec.ts @@ -36,7 +36,7 @@ describe("vault filter service", () => { let folderViews: ReplaySubject; let collectionViews: ReplaySubject; let cipherViews: ReplaySubject; - let personalOwnershipPolicy: ReplaySubject; + let organizationDataOwnershipPolicy: ReplaySubject; let singleOrgPolicy: ReplaySubject; let stateProvider: FakeStateProvider; @@ -59,15 +59,15 @@ describe("vault filter service", () => { folderViews = new ReplaySubject(1); collectionViews = new ReplaySubject(1); cipherViews = new ReplaySubject(1); - personalOwnershipPolicy = new ReplaySubject(1); + organizationDataOwnershipPolicy = new ReplaySubject(1); singleOrgPolicy = new ReplaySubject(1); organizationService.memberOrganizations$.mockReturnValue(organizations); folderService.folderViews$.mockReturnValue(folderViews); collectionService.decryptedCollections$ = collectionViews; policyService.policyAppliesToUser$ - .calledWith(PolicyType.PersonalOwnership, mockUserId) - .mockReturnValue(personalOwnershipPolicy); + .calledWith(PolicyType.OrganizationDataOwnership, mockUserId) + .mockReturnValue(organizationDataOwnershipPolicy); policyService.policyAppliesToUser$ .calledWith(PolicyType.SingleOrg, mockUserId) .mockReturnValue(singleOrgPolicy); @@ -113,7 +113,7 @@ describe("vault filter service", () => { beforeEach(() => { const storedOrgs = [createOrganization("1", "org1"), createOrganization("2", "org2")]; organizations.next(storedOrgs); - personalOwnershipPolicy.next(false); + organizationDataOwnershipPolicy.next(false); singleOrgPolicy.next(false); }); @@ -125,8 +125,8 @@ describe("vault filter service", () => { expect(tree.children.find((o) => o.node.name === "org2")); }); - it("hides My Vault if personal ownership policy is enabled", async () => { - personalOwnershipPolicy.next(true); + it("hides My Vault if organization data ownership policy is enabled", async () => { + organizationDataOwnershipPolicy.next(true); const tree = await firstValueFrom(vaultFilterService.organizationTree$); @@ -144,9 +144,9 @@ describe("vault filter service", () => { expect(tree.children.find((o) => o.node.id === "MyVault")); }); - it("returns 1 organization if both single organization and personal ownership policies are enabled", async () => { + it("returns 1 organization if both single organization and organization data ownership policies are enabled", async () => { singleOrgPolicy.next(true); - personalOwnershipPolicy.next(true); + organizationDataOwnershipPolicy.next(true); const tree = await firstValueFrom(vaultFilterService.organizationTree$); diff --git a/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.ts b/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.ts index 1749cc00ae3..b6548564ec9 100644 --- a/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.ts +++ b/apps/web/src/app/vault/individual-vault/vault-filter/services/vault-filter.service.ts @@ -67,12 +67,12 @@ export class VaultFilterService implements VaultFilterServiceAbstraction { ), this.activeUserId$.pipe( switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ), ]).pipe( - switchMap(([orgs, singleOrgPolicy, personalOwnershipPolicy]) => - this.buildOrganizationTree(orgs, singleOrgPolicy, personalOwnershipPolicy), + switchMap(([orgs, singleOrgPolicy, organizationDataOwnershipPolicy]) => + this.buildOrganizationTree(orgs, singleOrgPolicy, organizationDataOwnershipPolicy), ), ); @@ -166,10 +166,10 @@ export class VaultFilterService implements VaultFilterServiceAbstraction { protected async buildOrganizationTree( orgs: Organization[], singleOrgPolicy: boolean, - personalOwnershipPolicy: boolean, + organizationDataOwnershipPolicy: boolean, ): Promise> { const headNode = this.getOrganizationFilterHead(); - if (!personalOwnershipPolicy) { + if (!organizationDataOwnershipPolicy) { const myVaultNode = this.getOrganizationFilterMyVault(); headNode.children.push(myVaultNode); } diff --git a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts index a4026b7d355..b4eda51435f 100644 --- a/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts +++ b/apps/web/src/app/vault/individual-vault/vault-onboarding/vault-onboarding.component.ts @@ -166,7 +166,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy { .pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), takeUntil(this.destroy$), ) diff --git a/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.spec.ts b/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.spec.ts index 0934a6deb95..11a984c4d52 100644 --- a/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.spec.ts +++ b/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.spec.ts @@ -128,18 +128,18 @@ describe("AdminConsoleCipherFormConfigService", () => { expect(result.admin).toBe(true); }); - it("sets `allowPersonalOwnership`", async () => { + it("sets `organizationDataOwnershipDisabled`", async () => { policyAppliesToUser$.next(true); let result = await adminConsoleConfigService.buildConfig("clone", cipherId); - expect(result.allowPersonalOwnership).toBe(false); + expect(result.organizationDataOwnershipDisabled).toBe(false); policyAppliesToUser$.next(false); result = await adminConsoleConfigService.buildConfig("clone", cipherId); - expect(result.allowPersonalOwnership).toBe(true); + expect(result.organizationDataOwnershipDisabled).toBe(true); }); it("disables personal ownership when not cloning", async () => { @@ -147,15 +147,15 @@ describe("AdminConsoleCipherFormConfigService", () => { let result = await adminConsoleConfigService.buildConfig("add", cipherId); - expect(result.allowPersonalOwnership).toBe(false); + expect(result.organizationDataOwnershipDisabled).toBe(false); result = await adminConsoleConfigService.buildConfig("edit", cipherId); - expect(result.allowPersonalOwnership).toBe(false); + expect(result.organizationDataOwnershipDisabled).toBe(false); result = await adminConsoleConfigService.buildConfig("clone", cipherId); - expect(result.allowPersonalOwnership).toBe(true); + expect(result.organizationDataOwnershipDisabled).toBe(true); }); it("returns all ciphers when cloning a cipher", async () => { diff --git a/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.ts b/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.ts index 15af27ba8d0..5d23f89c822 100644 --- a/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.ts +++ b/apps/web/src/app/vault/org-vault/services/admin-console-cipher-form-config.service.ts @@ -31,10 +31,10 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ private apiService: ApiService = inject(ApiService); private accountService: AccountService = inject(AccountService); - private allowPersonalOwnership$ = this.accountService.activeAccount$.pipe( + private organizationDataOwnershipDisabled$ = this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), map((p) => !p), ); @@ -69,11 +69,11 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ cipherId?: CipherId, cipherType?: CipherType, ): Promise { - const [organization, allowPersonalOwnership, allOrganizations, allCollections] = + const [organization, organizationDataOwnershipDisabled, allOrganizations, allCollections] = await firstValueFrom( combineLatest([ this.organization$, - this.allowPersonalOwnership$, + this.organizationDataOwnershipDisabled$, this.allOrganizations$, this.allCollections$, ]), @@ -84,13 +84,14 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ const organizations = mode === "clone" ? allOrganizations : [organization]; // Only allow the user to assign to their personal vault when cloning and // the policies are enabled for it. - const allowPersonalOwnershipOnlyForClone = mode === "clone" ? allowPersonalOwnership : false; + const disableOrganizationDataOwnershipOnlyForClone = + mode === "clone" ? organizationDataOwnershipDisabled : false; const cipher = await this.getCipher(cipherId, organization); return { mode, cipherType: cipher?.type ?? cipherType ?? CipherType.Login, admin: organization.canEditAllCiphers ?? false, - allowPersonalOwnership: allowPersonalOwnershipOnlyForClone, + organizationDataOwnershipDisabled: disableOrganizationDataOwnershipOnlyForClone, originalCipher: cipher, collections: allCollections, organizations, diff --git a/apps/web/src/locales/en/messages.json b/apps/web/src/locales/en/messages.json index 3c3395179fa..b3f9a5fa64c 100644 --- a/apps/web/src/locales/en/messages.json +++ b/apps/web/src/locales/en/messages.json @@ -5379,6 +5379,9 @@ } } }, + "organizationDataOwnership": { + "message": "Enforce organization data ownership" + }, "personalOwnership": { "message": "Remove individual vault" }, diff --git a/bitwarden_license/bit-web/src/app/billing/policies/free-families-sponsorship.component.ts b/bitwarden_license/bit-web/src/app/billing/policies/free-families-sponsorship.component.ts index 53d2b0ab66c..dd808300988 100644 --- a/bitwarden_license/bit-web/src/app/billing/policies/free-families-sponsorship.component.ts +++ b/bitwarden_license/bit-web/src/app/billing/policies/free-families-sponsorship.component.ts @@ -14,7 +14,7 @@ export class FreeFamiliesSponsorshipPolicy extends BasePolicy { } @Component({ - selector: "policy-personal-ownership", + selector: "policy-free-families-sponsorship", templateUrl: "free-families-sponsorship.component.html", standalone: false, }) diff --git a/libs/angular/src/vault/abstractions/deprecated-vault-filter.service.ts b/libs/angular/src/vault/abstractions/deprecated-vault-filter.service.ts index 3e82641fe90..21528b1ddd5 100644 --- a/libs/angular/src/vault/abstractions/deprecated-vault-filter.service.ts +++ b/libs/angular/src/vault/abstractions/deprecated-vault-filter.service.ts @@ -20,5 +20,5 @@ export abstract class DeprecatedVaultFilterService { buildCollapsedFilterNodes: () => Promise>; storeCollapsedFilterNodes: (collapsedFilterNodes: Set) => Promise; checkForSingleOrganizationPolicy: () => Promise; - checkForPersonalOwnershipPolicy: () => Promise; + checkForOrganizationDataOwnershipPolicy: () => Promise; } diff --git a/libs/angular/src/vault/components/add-edit.component.ts b/libs/angular/src/vault/components/add-edit.component.ts index ec79ac9ef18..3541fa0c8e8 100644 --- a/libs/angular/src/vault/components/add-edit.component.ts +++ b/libs/angular/src/vault/components/add-edit.component.ts @@ -103,7 +103,7 @@ export class AddEditComponent implements OnInit, OnDestroy { protected componentName = ""; protected destroy$ = new Subject(); protected writeableCollections: CollectionView[]; - private personalOwnershipPolicyAppliesToActiveUser: boolean; + private organizationDataOwnershipAppliesToUser: boolean; private previousCipherId: string; get fido2CredentialCreationDateValue(): string { @@ -195,10 +195,10 @@ export class AddEditComponent implements OnInit, OnDestroy { .pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), concatMap(async (policyAppliesToActiveUser) => { - this.personalOwnershipPolicyAppliesToActiveUser = policyAppliesToActiveUser; + this.organizationDataOwnershipAppliesToUser = policyAppliesToActiveUser; await this.init(); }), takeUntil(this.destroy$), @@ -218,7 +218,7 @@ export class AddEditComponent implements OnInit, OnDestroy { if (this.ownershipOptions.length) { this.ownershipOptions = []; } - if (this.personalOwnershipPolicyAppliesToActiveUser) { + if (this.organizationDataOwnershipAppliesToUser) { this.allowPersonal = false; } else { const myEmail = await firstValueFrom( diff --git a/libs/angular/src/vault/vault-filter/components/organization-filter.component.ts b/libs/angular/src/vault/vault-filter/components/organization-filter.component.ts index c0042dcfdff..45198d2bcc5 100644 --- a/libs/angular/src/vault/vault-filter/components/organization-filter.component.ts +++ b/libs/angular/src/vault/vault-filter/components/organization-filter.component.ts @@ -15,7 +15,7 @@ export class OrganizationFilterComponent { @Input() collapsedFilterNodes: Set; @Input() organizations: Organization[]; @Input() activeFilter: VaultFilter; - @Input() activePersonalOwnershipPolicy: boolean; + @Input() activeOrganizationDataOwnership: boolean; @Input() activeSingleOrganizationPolicy: boolean; @Output() onNodeCollapseStateChange: EventEmitter = @@ -26,12 +26,12 @@ export class OrganizationFilterComponent { let displayMode: DisplayMode = "organizationMember"; if (this.organizations == null || this.organizations.length < 1) { displayMode = "noOrganizations"; - } else if (this.activePersonalOwnershipPolicy && !this.activeSingleOrganizationPolicy) { - displayMode = "personalOwnershipPolicy"; - } else if (!this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) { + } else if (this.activeOrganizationDataOwnership && !this.activeSingleOrganizationPolicy) { + displayMode = "organizationDataOwnershipPolicy"; + } else if (!this.activeOrganizationDataOwnership && this.activeSingleOrganizationPolicy) { displayMode = "singleOrganizationPolicy"; - } else if (this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) { - displayMode = "singleOrganizationAndPersonalOwnershipPolicies"; + } else if (this.activeOrganizationDataOwnership && this.activeSingleOrganizationPolicy) { + displayMode = "singleOrganizationAndOrganizatonDataOwnershipPolicies"; } return displayMode; diff --git a/libs/angular/src/vault/vault-filter/components/vault-filter.component.ts b/libs/angular/src/vault/vault-filter/components/vault-filter.component.ts index 83304f8eae9..936d606b936 100644 --- a/libs/angular/src/vault/vault-filter/components/vault-filter.component.ts +++ b/libs/angular/src/vault/vault-filter/components/vault-filter.component.ts @@ -32,7 +32,7 @@ export class VaultFilterComponent implements OnInit { isLoaded = false; collapsedFilterNodes: Set; organizations: Organization[]; - activePersonalOwnershipPolicy: boolean; + activeOrganizationDataOwnershipPolicy: boolean; activeSingleOrganizationPolicy: boolean; collections: DynamicTreeNode; folders$: Observable>; @@ -47,8 +47,8 @@ export class VaultFilterComponent implements OnInit { this.collapsedFilterNodes = await this.vaultFilterService.buildCollapsedFilterNodes(); this.organizations = await this.vaultFilterService.buildOrganizations(); if (this.organizations != null && this.organizations.length > 0) { - this.activePersonalOwnershipPolicy = - await this.vaultFilterService.checkForPersonalOwnershipPolicy(); + this.activeOrganizationDataOwnershipPolicy = + await this.vaultFilterService.checkForOrganizationDataOwnershipPolicy(); this.activeSingleOrganizationPolicy = await this.vaultFilterService.checkForSingleOrganizationPolicy(); } @@ -88,8 +88,8 @@ export class VaultFilterComponent implements OnInit { async reloadOrganizations() { this.organizations = await this.vaultFilterService.buildOrganizations(); - this.activePersonalOwnershipPolicy = - await this.vaultFilterService.checkForPersonalOwnershipPolicy(); + this.activeOrganizationDataOwnershipPolicy = + await this.vaultFilterService.checkForOrganizationDataOwnershipPolicy(); this.activeSingleOrganizationPolicy = await this.vaultFilterService.checkForSingleOrganizationPolicy(); } diff --git a/libs/angular/src/vault/vault-filter/models/display-mode.ts b/libs/angular/src/vault/vault-filter/models/display-mode.ts index 3395df4fbe2..e55d41e5486 100644 --- a/libs/angular/src/vault/vault-filter/models/display-mode.ts +++ b/libs/angular/src/vault/vault-filter/models/display-mode.ts @@ -2,5 +2,5 @@ export type DisplayMode = | "noOrganizations" | "organizationMember" | "singleOrganizationPolicy" - | "personalOwnershipPolicy" - | "singleOrganizationAndPersonalOwnershipPolicies"; + | "organizationDataOwnershipPolicy" + | "singleOrganizationAndOrganizatonDataOwnershipPolicies"; diff --git a/libs/angular/src/vault/vault-filter/services/vault-filter.service.ts b/libs/angular/src/vault/vault-filter/services/vault-filter.service.ts index 9e3312b38ef..a4114e63285 100644 --- a/libs/angular/src/vault/vault-filter/services/vault-filter.service.ts +++ b/libs/angular/src/vault/vault-filter/services/vault-filter.service.ts @@ -123,12 +123,12 @@ export class VaultFilterService implements DeprecatedVaultFilterServiceAbstracti ); } - async checkForPersonalOwnershipPolicy(): Promise { + async checkForOrganizationDataOwnershipPolicy(): Promise { return await firstValueFrom( this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ), ); diff --git a/libs/common/src/admin-console/enums/policy-type.enum.ts b/libs/common/src/admin-console/enums/policy-type.enum.ts index 5607e92c284..91f3a8229f8 100644 --- a/libs/common/src/admin-console/enums/policy-type.enum.ts +++ b/libs/common/src/admin-console/enums/policy-type.enum.ts @@ -6,7 +6,7 @@ export enum PolicyType { PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases SingleOrg = 3, // Allows users to only be apart of one organization RequireSso = 4, // Requires users to authenticate with SSO - PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items + OrganizationDataOwnership = 5, // Enforces organization ownership items added/cloned to the default collection DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow 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 2f079eb2ad1..b6e03ddf257 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 @@ -238,8 +238,8 @@ export class DefaultPolicyService implements PolicyService { case PolicyType.RestrictedItemTypes: // restricted item types policy return false; - case PolicyType.PersonalOwnership: - // individual vault policy applies to everyone except admins and owners + case PolicyType.OrganizationDataOwnership: + // organization data ownership policy applies to everyone except admins and owners return organization.isAdmin; default: return organization.canManagePolicies; diff --git a/libs/importer/src/components/import.component.ts b/libs/importer/src/components/import.component.ts index 34212b8e773..4f2715fe9cf 100644 --- a/libs/importer/src/components/import.component.ts +++ b/libs/importer/src/components/import.component.ts @@ -336,7 +336,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit { this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ), this.organizations$, diff --git a/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.html b/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.html index d6b1bbe216a..398085c135c 100644 --- a/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.html +++ b/libs/tools/export/vault-export/vault-export-ui/src/components/export.component.html @@ -19,7 +19,7 @@ [label]="'myVault' | i18n" value="myVault" icon="bwi-user" - *ngIf="!(disablePersonalOwnershipPolicy$ | async)" + *ngIf="!(organizationDataOwnershipPolicy$ | async)" /> ; - disablePersonalOwnershipPolicy$: Observable; + organizationDataOwnershipPolicy$: Observable; exportForm = this.formBuilder.group({ vaultSelector: [ @@ -209,10 +209,10 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit { ), ); - this.disablePersonalOwnershipPolicy$ = this.accountService.activeAccount$.pipe( + this.organizationDataOwnershipPolicy$ = this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), ); @@ -294,21 +294,21 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit { combineLatest([ this.disablePersonalVaultExportPolicy$, - this.disablePersonalOwnershipPolicy$, + this.organizationDataOwnershipPolicy$, this.organizations$, ]) .pipe( - tap(([disablePersonalVaultExport, disablePersonalOwnership, organizations]) => { + tap(([disablePersonalVaultExport, organizationDataOwnership, organizations]) => { this._disabledByPolicy = disablePersonalVaultExport; - // When personalOwnership is disabled and we have orgs, set the first org as the selected vault - if (disablePersonalOwnership && organizations.length > 0) { + // When organizationDataOwnership is enabled and we have orgs, set the first org as the selected vault + if (organizationDataOwnership && organizations.length > 0) { this.exportForm.enable(); this.exportForm.controls.vaultSelector.setValue(organizations[0].id); } - // When personalOwnership is disabled and we have no orgs, disable the form - if (disablePersonalOwnership && organizations.length === 0) { + // When organizationDataOwnership is enabled and we have no orgs, disable the form + if (organizationDataOwnership && organizations.length === 0) { this.exportForm.disable(); } @@ -318,7 +318,7 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit { } // When neither policy is enabled, enable the form and set the default vault to "myVault" - if (!disablePersonalVaultExport && !disablePersonalOwnership) { + if (!disablePersonalVaultExport && !organizationDataOwnership) { this.exportForm.controls.vaultSelector.setValue("myVault"); } }), diff --git a/libs/vault/src/cipher-form/abstractions/cipher-form-config.service.ts b/libs/vault/src/cipher-form/abstractions/cipher-form-config.service.ts index 71f12340ebc..d1792da422c 100644 --- a/libs/vault/src/cipher-form/abstractions/cipher-form-config.service.ts +++ b/libs/vault/src/cipher-form/abstractions/cipher-form-config.service.ts @@ -77,7 +77,7 @@ type BaseCipherFormConfig = { * Flag to indicate if the user is allowed to create ciphers in their own Vault. If false, configuration must * supply a list of organizations that the user can create ciphers in. */ - allowPersonalOwnership: boolean; + organizationDataOwnershipDisabled: boolean; /** * The original cipher that is being edited or cloned. This can be undefined when creating a new cipher. @@ -131,18 +131,18 @@ type CreateNewCipherConfig = BaseCipherFormConfig & { type CombinedAddEditConfig = ExistingCipherConfig | CreateNewCipherConfig; /** - * Configuration object for the cipher form when personal ownership is allowed. + * Configuration object for the cipher form when organization data ownership is not allowed. */ -type PersonalOwnershipAllowed = CombinedAddEditConfig & { - allowPersonalOwnership: true; +type OrganizationDataOwnershipDisabled = CombinedAddEditConfig & { + organizationDataOwnershipDisabled: true; }; /** - * Configuration object for the cipher form when personal ownership is not allowed. + * Configuration object for the cipher form when organization data ownership is allowed. * Organizations must be provided. */ -type PersonalOwnershipNotAllowed = CombinedAddEditConfig & { - allowPersonalOwnership: false; +type OrganizationDataOwnershipEnabled = CombinedAddEditConfig & { + organizationDataOwnershipDisabled: false; organizations: Organization[]; }; @@ -150,7 +150,7 @@ type PersonalOwnershipNotAllowed = CombinedAddEditConfig & { * Configuration object for the cipher form. * Determines the behavior of the form and the controls that are displayed/enabled. */ -export type CipherFormConfig = PersonalOwnershipAllowed | PersonalOwnershipNotAllowed; +export type CipherFormConfig = OrganizationDataOwnershipDisabled | OrganizationDataOwnershipEnabled; /** * Service responsible for building the configuration object for the cipher form. diff --git a/libs/vault/src/cipher-form/cipher-form.stories.ts b/libs/vault/src/cipher-form/cipher-form.stories.ts index 3d68b7124c1..f46eb457e30 100644 --- a/libs/vault/src/cipher-form/cipher-form.stories.ts +++ b/libs/vault/src/cipher-form/cipher-form.stories.ts @@ -57,7 +57,7 @@ const defaultConfig: CipherFormConfig = { mode: "add", cipherType: CipherType.Login, admin: false, - allowPersonalOwnership: true, + organizationDataOwnershipDisabled: true, collections: [ { id: "col1", @@ -354,13 +354,13 @@ export const WithSubmitButton: Story = { }, }; -export const NoPersonalOwnership: Story = { +export const OrganizationDataOwnershipEnabled: Story = { ...Add, args: { config: { ...defaultConfig, mode: "add", - allowPersonalOwnership: false, + organizationDataOwnershipDisabled: false, originalCipher: defaultConfig.originalCipher, organizations: defaultConfig.organizations!, }, diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html index 5fd3e08f22d..c61312c13eb 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.html @@ -22,7 +22,7 @@ {{ "owner" | i18n }} diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts index 42b29193c85..12fba0c7409 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.spec.ts @@ -93,8 +93,8 @@ describe("ItemDetailsSectionComponent", () => { }); describe("ngOnInit", () => { - it("should throw an error if no organizations are available for ownership and personal ownership is not allowed", async () => { - component.config.allowPersonalOwnership = false; + it("should throw an error if no organizations are available for ownership and organization data ownership is enabled", async () => { + component.config.organizationDataOwnershipDisabled = false; component.config.organizations = []; await expect(component.ngOnInit()).rejects.toThrow( "No organizations available for ownership.", @@ -102,7 +102,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should initialize form with default values if no originalCipher is provided", fakeAsync(async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1" } as Organization]; await component.ngOnInit(); tick(); @@ -120,7 +120,7 @@ describe("ItemDetailsSectionComponent", () => { })); it("should initialize form with values from originalCipher if provided", fakeAsync(async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1" } as Organization]; component.config.collections = [ createMockCollection("col1", "Collection 1", "org1") as CollectionView, @@ -150,7 +150,7 @@ describe("ItemDetailsSectionComponent", () => { })); it("should disable organizationId control if ownership change is not allowed", async () => { - component.config.allowPersonalOwnership = false; + component.config.organizationDataOwnershipDisabled = false; component.config.organizations = [{ id: "org1" } as Organization]; jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(false); @@ -188,15 +188,15 @@ describe("ItemDetailsSectionComponent", () => { expect(component.allowOwnershipChange).toBe(false); }); - it("should allow ownership change if personal ownership is allowed and there is at least one organization", () => { - component.config.allowPersonalOwnership = true; + it("should allow ownership change if organization data ownership is disabled and there is at least one organization", () => { + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1", name: "org1" } as Organization]; fixture.detectChanges(); expect(component.allowOwnershipChange).toBe(true); }); - it("should allow ownership change if personal ownership is not allowed but there is more than one organization", () => { - component.config.allowPersonalOwnership = false; + it("should allow ownership change if organization data ownership is enabled but there is more than one organization", () => { + component.config.organizationDataOwnershipDisabled = false; component.config.organizations = [ { id: "org1", name: "org1" } as Organization, { id: "org2", name: "org2" } as Organization, @@ -207,23 +207,23 @@ describe("ItemDetailsSectionComponent", () => { }); describe("defaultOwner", () => { - it("should return null if personal ownership is allowed", () => { - component.config.allowPersonalOwnership = true; + it("should return null if organization data ownership is disabled", () => { + component.config.organizationDataOwnershipDisabled = true; expect(component.defaultOwner).toBeNull(); }); - it("should return the first organization id if personal ownership is not allowed", () => { - component.config.allowPersonalOwnership = false; + it("should return the first organization id if organization data ownership is enabled", () => { + component.config.organizationDataOwnershipDisabled = false; component.config.organizations = [{ id: "org1", name: "Organization 1" } as Organization]; fixture.detectChanges(); expect(component.defaultOwner).toBe("org1"); }); }); - describe("showPersonalOwnerOption", () => { - it("should show personal ownership when the configuration allows", () => { + describe("showOrganizationDataOwnershipOption", () => { + it("should show organization data ownership when the configuration allows", () => { component.config.mode = "edit"; - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.originalCipherView = {} as CipherView; component.config.organizations = [{ id: "134-433-22" } as Organization]; fixture.detectChanges(); @@ -235,9 +235,9 @@ describe("ItemDetailsSectionComponent", () => { expect(label).toBe("test@example.com"); }); - it("should show personal ownership when the control is disabled", async () => { + it("should show organization data ownership when the control is disabled", async () => { component.config.mode = "edit"; - component.config.allowPersonalOwnership = false; + component.config.organizationDataOwnershipDisabled = false; component.originalCipherView = {} as CipherView; component.config.organizations = [{ id: "134-433-22" } as Organization]; await component.ngOnInit(); @@ -253,7 +253,7 @@ describe("ItemDetailsSectionComponent", () => { describe("showOwnership", () => { it("should return true if ownership change is allowed or in edit mode with at least one organization", () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(true); expect(component.showOwnership).toBe(true); @@ -265,7 +265,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should hide the ownership control if showOwnership is false", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; jest.spyOn(component, "showOwnership", "get").mockReturnValue(false); fixture.detectChanges(); await fixture.whenStable(); @@ -276,7 +276,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should show the ownership control if showOwnership is true", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(true); fixture.detectChanges(); await fixture.whenStable(); @@ -293,7 +293,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should append '- Clone' to the title if in clone mode", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; const cipher = { name: "cipher1", organizationId: null, @@ -312,7 +312,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("does not append clone when the cipher was populated from the cache", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; const cipher = { name: "from cache cipher", organizationId: null, @@ -332,8 +332,8 @@ describe("ItemDetailsSectionComponent", () => { expect(component.itemDetailsForm.controls.name.value).toBe("from cache cipher"); }); - it("should select the first organization if personal ownership is not allowed", async () => { - component.config.allowPersonalOwnership = false; + it("should select the first organization if organization data ownership is enabled", async () => { + component.config.organizationDataOwnershipDisabled = false; component.config.organizations = [ { id: "org1", name: "org1" } as Organization, { id: "org2", name: "org2" } as Organization, @@ -354,7 +354,7 @@ describe("ItemDetailsSectionComponent", () => { describe("collectionOptions", () => { it("should reset and disable/hide collections control when no organization is selected", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.itemDetailsForm.controls.organizationId.setValue(null); fixture.detectChanges(); @@ -370,7 +370,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should enable/show collection control when an organization is selected", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1" } as Organization]; component.config.collections = [ createMockCollection("col1", "Collection 1", "org1") as CollectionView, @@ -421,7 +421,7 @@ describe("ItemDetailsSectionComponent", () => { }); it("should automatically select the first collection if only one is available", async () => { - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1" } as Organization]; component.config.collections = [ createMockCollection("col1", "Collection 1", "org1") as CollectionView, @@ -475,7 +475,7 @@ describe("ItemDetailsSectionComponent", () => { it("should allow all collections to be altered when `config.admin` is true", async () => { component.config.admin = true; - component.config.allowPersonalOwnership = true; + component.config.organizationDataOwnershipDisabled = true; component.config.organizations = [{ id: "org1" } as Organization]; component.config.collections = [ createMockCollection("col1", "Collection 1", "org1", true, false) as CollectionView, @@ -491,7 +491,6 @@ describe("ItemDetailsSectionComponent", () => { expect(component["collectionOptions"].map((c) => c.id)).toEqual(["col1", "col2", "col3"]); }); }); - describe("readonlyCollections", () => { beforeEach(() => { component.config.mode = "edit"; diff --git a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts index 192fac44a2d..1d30edf27e0 100644 --- a/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts +++ b/libs/vault/src/cipher-form/components/item-details/item-details-section.component.ts @@ -92,8 +92,8 @@ export class ItemDetailsSectionComponent implements OnInit { return this.config.mode === "partial-edit"; } - get allowPersonalOwnership() { - return this.config.allowPersonalOwnership; + get organizationDataOwnershipDisabled() { + return this.config.organizationDataOwnershipDisabled; } get collections(): CollectionView[] { @@ -105,14 +105,17 @@ export class ItemDetailsSectionComponent implements OnInit { } /** - * Show the personal ownership option in the Owner dropdown when: - * - Personal ownership is allowed + * Show the organization data ownership option in the Owner dropdown when: + * - organization data ownership is disabled * - The `organizationId` control is disabled. This avoids the scenario * where a the dropdown is empty because the user personally owns the cipher * but cannot edit the ownership. */ - get showPersonalOwnerOption() { - return this.allowPersonalOwnership || !this.itemDetailsForm.controls.organizationId.enabled; + get showOrganizationDataOwnershipOption() { + return ( + this.organizationDataOwnershipDisabled || + !this.itemDetailsForm.controls.organizationId.enabled + ); } constructor( @@ -161,7 +164,7 @@ export class ItemDetailsSectionComponent implements OnInit { } // If personal ownership is allowed and there is at least one organization, allow ownership change. - if (this.allowPersonalOwnership) { + if (this.organizationDataOwnershipDisabled) { return this.organizations.length > 0; } @@ -180,7 +183,7 @@ export class ItemDetailsSectionComponent implements OnInit { } get defaultOwner() { - return this.allowPersonalOwnership ? null : this.organizations[0].id; + return this.organizationDataOwnershipDisabled ? null : this.organizations[0].id; } async ngOnInit() { @@ -188,7 +191,7 @@ export class ItemDetailsSectionComponent implements OnInit { Utils.getSortFunction(this.i18nService, "name"), ); - if (!this.allowPersonalOwnership && this.organizations.length === 0) { + if (!this.organizationDataOwnershipDisabled && this.organizations.length === 0) { throw new Error("No organizations available for ownership."); } @@ -244,7 +247,7 @@ export class ItemDetailsSectionComponent implements OnInit { ); } - if (!this.allowPersonalOwnership && prefillCipher.organizationId == null) { + if (!this.organizationDataOwnershipDisabled && prefillCipher.organizationId == null) { this.itemDetailsForm.controls.organizationId.setValue(this.defaultOwner); } } diff --git a/libs/vault/src/cipher-form/services/default-cipher-form-config.service.ts b/libs/vault/src/cipher-form/services/default-cipher-form-config.service.ts index a91a84e91c1..c47e5842987 100644 --- a/libs/vault/src/cipher-form/services/default-cipher-form-config.service.ts +++ b/libs/vault/src/cipher-form/services/default-cipher-form-config.service.ts @@ -44,7 +44,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService { ): Promise { const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); - const [organizations, collections, allowPersonalOwnership, folders, cipher] = + const [organizations, collections, organizationDataOwnershipDisabled, folders, cipher] = await firstValueFrom( combineLatest([ this.organizations$(activeUserId), @@ -55,7 +55,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService { ), ), ), - this.allowPersonalOwnership$, + this.organizationDataOwnershipDisabled$, this.folderService.folders$(activeUserId).pipe( switchMap((f) => this.folderService.folderViews$(activeUserId).pipe( @@ -71,7 +71,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService { mode, cipherType: cipher?.type ?? cipherType ?? CipherType.Login, admin: false, - allowPersonalOwnership, + organizationDataOwnershipDisabled, originalCipher: cipher, collections, organizations, @@ -91,10 +91,10 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService { ); } - private allowPersonalOwnership$ = this.accountService.activeAccount$.pipe( + private organizationDataOwnershipDisabled$ = this.accountService.activeAccount$.pipe( getUserId, switchMap((userId) => - this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId), + this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId), ), map((p) => !p), );