mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
[PM-20633] rename personal ownership (#15228)
* sensible renames * renames * clean up comments
This commit is contained in:
@@ -1056,7 +1056,7 @@ export default class NotificationBackground {
|
|||||||
this.accountService.activeAccount$.pipe(
|
this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -228,10 +228,10 @@ describe("VaultPopupListFiltersService", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("PersonalOwnership policy", () => {
|
describe("OrganizationDataOwnership policy", () => {
|
||||||
it('calls policyAppliesToUser$ with "PersonalOwnership"', () => {
|
it('calls policyAppliesToUser$ with "OrganizationDataOwnership"', () => {
|
||||||
expect(policyService.policyAppliesToUser$).toHaveBeenCalledWith(
|
expect(policyService.policyAppliesToUser$).toHaveBeenCalledWith(
|
||||||
PolicyType.PersonalOwnership,
|
PolicyType.OrganizationDataOwnership,
|
||||||
"userId",
|
"userId",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -293,30 +293,30 @@ export class VaultPopupListFiltersService {
|
|||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.organizationService.memberOrganizations$(userId),
|
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")),
|
orgs.sort(Utils.getSortFunction(this.i18nService, "name")),
|
||||||
personalOwnershipApplies,
|
organizationDataOwnership,
|
||||||
]),
|
]),
|
||||||
map(([orgs, personalOwnershipApplies]) => {
|
map(([orgs, organizationDataOwnership]) => {
|
||||||
// When there are no organizations return an empty array,
|
// When there are no organizations return an empty array,
|
||||||
// resulting in the org filter being hidden
|
// resulting in the org filter being hidden
|
||||||
if (!orgs.length) {
|
if (!orgs.length) {
|
||||||
return [];
|
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
|
// return an empty array, resulting in the org filter being hidden
|
||||||
if (orgs.length === 1 && personalOwnershipApplies) {
|
if (orgs.length === 1 && organizationDataOwnership) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const myVaultOrg: ChipSelectOption<Organization>[] = [];
|
const myVaultOrg: ChipSelectOption<Organization>[] = [];
|
||||||
|
|
||||||
// Only add "My vault" if personal ownership policy does not apply
|
// Only add "My vault" if organization data ownership policy does not apply
|
||||||
if (!personalOwnershipApplies) {
|
if (!organizationDataOwnership) {
|
||||||
myVaultOrg.push({
|
myVaultOrg.push({
|
||||||
value: { id: MY_VAULT_ID } as Organization,
|
value: { id: MY_VAULT_ID } as Organization,
|
||||||
label: this.i18nService.t("myVault"),
|
label: this.i18nService.t("myVault"),
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export class EncryptedMessageHandlerService {
|
|||||||
const policyApplies$ = this.accountService.activeAccount$.pipe(
|
const policyApplies$ = this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import { ToastService } from "@bitwarden/components";
|
|||||||
})
|
})
|
||||||
export class OrganizationFilterComponent extends BaseOrganizationFilterComponent {
|
export class OrganizationFilterComponent extends BaseOrganizationFilterComponent {
|
||||||
get show() {
|
get show() {
|
||||||
const hiddenDisplayModes: DisplayMode[] = ["singleOrganizationAndPersonalOwnershipPolicies"];
|
const hiddenDisplayModes: DisplayMode[] = [
|
||||||
|
"singleOrganizationAndOrganizatonDataOwnershipPolicies",
|
||||||
|
];
|
||||||
return (
|
return (
|
||||||
!this.hide &&
|
!this.hide &&
|
||||||
this.organizations.length > 0 &&
|
this.organizations.length > 0 &&
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
[activeFilter]="activeFilter"
|
[activeFilter]="activeFilter"
|
||||||
[collapsedFilterNodes]="collapsedFilterNodes"
|
[collapsedFilterNodes]="collapsedFilterNodes"
|
||||||
[organizations]="organizations"
|
[organizations]="organizations"
|
||||||
[activePersonalOwnershipPolicy]="activePersonalOwnershipPolicy"
|
[activeOrganizationDataOwnership]="activeOrganizationDataOwnershipPolicy"
|
||||||
[activeSingleOrganizationPolicy]="activeSingleOrganizationPolicy"
|
[activeSingleOrganizationPolicy]="activeSingleOrganizationPolicy"
|
||||||
(onNodeCollapseStateChange)="toggleFilterNodeCollapseState($event)"
|
(onNodeCollapseStateChange)="toggleFilterNodeCollapseState($event)"
|
||||||
(onFilterChange)="applyFilter($event)"
|
(onFilterChange)="applyFilter($event)"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ export { BasePolicy, BasePolicyComponent } from "./base-policy.component";
|
|||||||
export { DisableSendPolicy } from "./disable-send.component";
|
export { DisableSendPolicy } from "./disable-send.component";
|
||||||
export { MasterPasswordPolicy } from "./master-password.component";
|
export { MasterPasswordPolicy } from "./master-password.component";
|
||||||
export { PasswordGeneratorPolicy } from "./password-generator.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 { RequireSsoPolicy } from "./require-sso.component";
|
||||||
export { ResetPasswordPolicy } from "./reset-password.component";
|
export { ResetPasswordPolicy } from "./reset-password.component";
|
||||||
export { SendOptionsPolicy } from "./send-options.component";
|
export { SendOptionsPolicy } from "./send-options.component";
|
||||||
|
|||||||
@@ -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 {}
|
||||||
@@ -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 {}
|
|
||||||
@@ -4,8 +4,8 @@ import { LooseComponentsModule, SharedModule } from "../../../shared";
|
|||||||
|
|
||||||
import { DisableSendPolicyComponent } from "./disable-send.component";
|
import { DisableSendPolicyComponent } from "./disable-send.component";
|
||||||
import { MasterPasswordPolicyComponent } from "./master-password.component";
|
import { MasterPasswordPolicyComponent } from "./master-password.component";
|
||||||
|
import { OrganizationDataOwnershipPolicyComponent } from "./organization-data-ownership.component";
|
||||||
import { PasswordGeneratorPolicyComponent } from "./password-generator.component";
|
import { PasswordGeneratorPolicyComponent } from "./password-generator.component";
|
||||||
import { PersonalOwnershipPolicyComponent } from "./personal-ownership.component";
|
|
||||||
import { PoliciesComponent } from "./policies.component";
|
import { PoliciesComponent } from "./policies.component";
|
||||||
import { PolicyEditComponent } from "./policy-edit.component";
|
import { PolicyEditComponent } from "./policy-edit.component";
|
||||||
import { RemoveUnlockWithPinPolicyComponent } from "./remove-unlock-with-pin.component";
|
import { RemoveUnlockWithPinPolicyComponent } from "./remove-unlock-with-pin.component";
|
||||||
@@ -22,7 +22,7 @@ import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authenticat
|
|||||||
DisableSendPolicyComponent,
|
DisableSendPolicyComponent,
|
||||||
MasterPasswordPolicyComponent,
|
MasterPasswordPolicyComponent,
|
||||||
PasswordGeneratorPolicyComponent,
|
PasswordGeneratorPolicyComponent,
|
||||||
PersonalOwnershipPolicyComponent,
|
OrganizationDataOwnershipPolicyComponent,
|
||||||
RequireSsoPolicyComponent,
|
RequireSsoPolicyComponent,
|
||||||
ResetPasswordPolicyComponent,
|
ResetPasswordPolicyComponent,
|
||||||
SendOptionsPolicyComponent,
|
SendOptionsPolicyComponent,
|
||||||
@@ -37,7 +37,7 @@ import { TwoFactorAuthenticationPolicyComponent } from "./two-factor-authenticat
|
|||||||
DisableSendPolicyComponent,
|
DisableSendPolicyComponent,
|
||||||
MasterPasswordPolicyComponent,
|
MasterPasswordPolicyComponent,
|
||||||
PasswordGeneratorPolicyComponent,
|
PasswordGeneratorPolicyComponent,
|
||||||
PersonalOwnershipPolicyComponent,
|
OrganizationDataOwnershipPolicyComponent,
|
||||||
RequireSsoPolicyComponent,
|
RequireSsoPolicyComponent,
|
||||||
ResetPasswordPolicyComponent,
|
ResetPasswordPolicyComponent,
|
||||||
SendOptionsPolicyComponent,
|
SendOptionsPolicyComponent,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import {
|
|||||||
DisableSendPolicy,
|
DisableSendPolicy,
|
||||||
MasterPasswordPolicy,
|
MasterPasswordPolicy,
|
||||||
PasswordGeneratorPolicy,
|
PasswordGeneratorPolicy,
|
||||||
PersonalOwnershipPolicy,
|
OrganizationDataOwnershipPolicy,
|
||||||
RequireSsoPolicy,
|
RequireSsoPolicy,
|
||||||
ResetPasswordPolicy,
|
ResetPasswordPolicy,
|
||||||
SendOptionsPolicy,
|
SendOptionsPolicy,
|
||||||
@@ -243,7 +243,7 @@ export class AppComponent implements OnDestroy, OnInit {
|
|||||||
new PasswordGeneratorPolicy(),
|
new PasswordGeneratorPolicy(),
|
||||||
new SingleOrgPolicy(),
|
new SingleOrgPolicy(),
|
||||||
new RequireSsoPolicy(),
|
new RequireSsoPolicy(),
|
||||||
new PersonalOwnershipPolicy(),
|
new OrganizationDataOwnershipPolicy(),
|
||||||
new DisableSendPolicy(),
|
new DisableSendPolicy(),
|
||||||
new SendOptionsPolicy(),
|
new SendOptionsPolicy(),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
|
|||||||
merge(
|
merge(
|
||||||
this.policyService.policiesByType$(PolicyType.SingleOrg, userId).pipe(getFirstPolicy),
|
this.policyService.policiesByType$(PolicyType.SingleOrg, userId).pipe(getFirstPolicy),
|
||||||
this.policyService
|
this.policyService
|
||||||
.policiesByType$(PolicyType.PersonalOwnership, userId)
|
.policiesByType$(PolicyType.OrganizationDataOwnership, userId)
|
||||||
.pipe(getFirstPolicy),
|
.pipe(getFirstPolicy),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -268,7 +268,7 @@ export class VaultFilterComponent implements OnInit, OnDestroy {
|
|||||||
this.accountService.activeAccount$.pipe(
|
this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ describe("vault filter service", () => {
|
|||||||
let folderViews: ReplaySubject<FolderView[]>;
|
let folderViews: ReplaySubject<FolderView[]>;
|
||||||
let collectionViews: ReplaySubject<CollectionView[]>;
|
let collectionViews: ReplaySubject<CollectionView[]>;
|
||||||
let cipherViews: ReplaySubject<CipherView[]>;
|
let cipherViews: ReplaySubject<CipherView[]>;
|
||||||
let personalOwnershipPolicy: ReplaySubject<boolean>;
|
let organizationDataOwnershipPolicy: ReplaySubject<boolean>;
|
||||||
let singleOrgPolicy: ReplaySubject<boolean>;
|
let singleOrgPolicy: ReplaySubject<boolean>;
|
||||||
let stateProvider: FakeStateProvider;
|
let stateProvider: FakeStateProvider;
|
||||||
|
|
||||||
@@ -59,15 +59,15 @@ describe("vault filter service", () => {
|
|||||||
folderViews = new ReplaySubject<FolderView[]>(1);
|
folderViews = new ReplaySubject<FolderView[]>(1);
|
||||||
collectionViews = new ReplaySubject<CollectionView[]>(1);
|
collectionViews = new ReplaySubject<CollectionView[]>(1);
|
||||||
cipherViews = new ReplaySubject<CipherView[]>(1);
|
cipherViews = new ReplaySubject<CipherView[]>(1);
|
||||||
personalOwnershipPolicy = new ReplaySubject<boolean>(1);
|
organizationDataOwnershipPolicy = new ReplaySubject<boolean>(1);
|
||||||
singleOrgPolicy = new ReplaySubject<boolean>(1);
|
singleOrgPolicy = new ReplaySubject<boolean>(1);
|
||||||
|
|
||||||
organizationService.memberOrganizations$.mockReturnValue(organizations);
|
organizationService.memberOrganizations$.mockReturnValue(organizations);
|
||||||
folderService.folderViews$.mockReturnValue(folderViews);
|
folderService.folderViews$.mockReturnValue(folderViews);
|
||||||
collectionService.decryptedCollections$ = collectionViews;
|
collectionService.decryptedCollections$ = collectionViews;
|
||||||
policyService.policyAppliesToUser$
|
policyService.policyAppliesToUser$
|
||||||
.calledWith(PolicyType.PersonalOwnership, mockUserId)
|
.calledWith(PolicyType.OrganizationDataOwnership, mockUserId)
|
||||||
.mockReturnValue(personalOwnershipPolicy);
|
.mockReturnValue(organizationDataOwnershipPolicy);
|
||||||
policyService.policyAppliesToUser$
|
policyService.policyAppliesToUser$
|
||||||
.calledWith(PolicyType.SingleOrg, mockUserId)
|
.calledWith(PolicyType.SingleOrg, mockUserId)
|
||||||
.mockReturnValue(singleOrgPolicy);
|
.mockReturnValue(singleOrgPolicy);
|
||||||
@@ -113,7 +113,7 @@ describe("vault filter service", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const storedOrgs = [createOrganization("1", "org1"), createOrganization("2", "org2")];
|
const storedOrgs = [createOrganization("1", "org1"), createOrganization("2", "org2")];
|
||||||
organizations.next(storedOrgs);
|
organizations.next(storedOrgs);
|
||||||
personalOwnershipPolicy.next(false);
|
organizationDataOwnershipPolicy.next(false);
|
||||||
singleOrgPolicy.next(false);
|
singleOrgPolicy.next(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -125,8 +125,8 @@ describe("vault filter service", () => {
|
|||||||
expect(tree.children.find((o) => o.node.name === "org2"));
|
expect(tree.children.find((o) => o.node.name === "org2"));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("hides My Vault if personal ownership policy is enabled", async () => {
|
it("hides My Vault if organization data ownership policy is enabled", async () => {
|
||||||
personalOwnershipPolicy.next(true);
|
organizationDataOwnershipPolicy.next(true);
|
||||||
|
|
||||||
const tree = await firstValueFrom(vaultFilterService.organizationTree$);
|
const tree = await firstValueFrom(vaultFilterService.organizationTree$);
|
||||||
|
|
||||||
@@ -144,9 +144,9 @@ describe("vault filter service", () => {
|
|||||||
expect(tree.children.find((o) => o.node.id === "MyVault"));
|
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);
|
singleOrgPolicy.next(true);
|
||||||
personalOwnershipPolicy.next(true);
|
organizationDataOwnershipPolicy.next(true);
|
||||||
|
|
||||||
const tree = await firstValueFrom(vaultFilterService.organizationTree$);
|
const tree = await firstValueFrom(vaultFilterService.organizationTree$);
|
||||||
|
|
||||||
|
|||||||
@@ -67,12 +67,12 @@ export class VaultFilterService implements VaultFilterServiceAbstraction {
|
|||||||
),
|
),
|
||||||
this.activeUserId$.pipe(
|
this.activeUserId$.pipe(
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(([orgs, singleOrgPolicy, personalOwnershipPolicy]) =>
|
switchMap(([orgs, singleOrgPolicy, organizationDataOwnershipPolicy]) =>
|
||||||
this.buildOrganizationTree(orgs, singleOrgPolicy, personalOwnershipPolicy),
|
this.buildOrganizationTree(orgs, singleOrgPolicy, organizationDataOwnershipPolicy),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -166,10 +166,10 @@ export class VaultFilterService implements VaultFilterServiceAbstraction {
|
|||||||
protected async buildOrganizationTree(
|
protected async buildOrganizationTree(
|
||||||
orgs: Organization[],
|
orgs: Organization[],
|
||||||
singleOrgPolicy: boolean,
|
singleOrgPolicy: boolean,
|
||||||
personalOwnershipPolicy: boolean,
|
organizationDataOwnershipPolicy: boolean,
|
||||||
): Promise<TreeNode<OrganizationFilter>> {
|
): Promise<TreeNode<OrganizationFilter>> {
|
||||||
const headNode = this.getOrganizationFilterHead();
|
const headNode = this.getOrganizationFilterHead();
|
||||||
if (!personalOwnershipPolicy) {
|
if (!organizationDataOwnershipPolicy) {
|
||||||
const myVaultNode = this.getOrganizationFilterMyVault();
|
const myVaultNode = this.getOrganizationFilterMyVault();
|
||||||
headNode.children.push(myVaultNode);
|
headNode.children.push(myVaultNode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export class VaultOnboardingComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
.pipe(
|
.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
takeUntil(this.destroy$),
|
takeUntil(this.destroy$),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -128,18 +128,18 @@ describe("AdminConsoleCipherFormConfigService", () => {
|
|||||||
expect(result.admin).toBe(true);
|
expect(result.admin).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets `allowPersonalOwnership`", async () => {
|
it("sets `organizationDataOwnershipDisabled`", async () => {
|
||||||
policyAppliesToUser$.next(true);
|
policyAppliesToUser$.next(true);
|
||||||
|
|
||||||
let result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
let result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
||||||
|
|
||||||
expect(result.allowPersonalOwnership).toBe(false);
|
expect(result.organizationDataOwnershipDisabled).toBe(false);
|
||||||
|
|
||||||
policyAppliesToUser$.next(false);
|
policyAppliesToUser$.next(false);
|
||||||
|
|
||||||
result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
||||||
|
|
||||||
expect(result.allowPersonalOwnership).toBe(true);
|
expect(result.organizationDataOwnershipDisabled).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disables personal ownership when not cloning", async () => {
|
it("disables personal ownership when not cloning", async () => {
|
||||||
@@ -147,15 +147,15 @@ describe("AdminConsoleCipherFormConfigService", () => {
|
|||||||
|
|
||||||
let result = await adminConsoleConfigService.buildConfig("add", cipherId);
|
let result = await adminConsoleConfigService.buildConfig("add", cipherId);
|
||||||
|
|
||||||
expect(result.allowPersonalOwnership).toBe(false);
|
expect(result.organizationDataOwnershipDisabled).toBe(false);
|
||||||
|
|
||||||
result = await adminConsoleConfigService.buildConfig("edit", cipherId);
|
result = await adminConsoleConfigService.buildConfig("edit", cipherId);
|
||||||
|
|
||||||
expect(result.allowPersonalOwnership).toBe(false);
|
expect(result.organizationDataOwnershipDisabled).toBe(false);
|
||||||
|
|
||||||
result = await adminConsoleConfigService.buildConfig("clone", cipherId);
|
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 () => {
|
it("returns all ciphers when cloning a cipher", async () => {
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
|
|||||||
private apiService: ApiService = inject(ApiService);
|
private apiService: ApiService = inject(ApiService);
|
||||||
private accountService: AccountService = inject(AccountService);
|
private accountService: AccountService = inject(AccountService);
|
||||||
|
|
||||||
private allowPersonalOwnership$ = this.accountService.activeAccount$.pipe(
|
private organizationDataOwnershipDisabled$ = this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
map((p) => !p),
|
map((p) => !p),
|
||||||
);
|
);
|
||||||
@@ -69,11 +69,11 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
|
|||||||
cipherId?: CipherId,
|
cipherId?: CipherId,
|
||||||
cipherType?: CipherType,
|
cipherType?: CipherType,
|
||||||
): Promise<CipherFormConfig> {
|
): Promise<CipherFormConfig> {
|
||||||
const [organization, allowPersonalOwnership, allOrganizations, allCollections] =
|
const [organization, organizationDataOwnershipDisabled, allOrganizations, allCollections] =
|
||||||
await firstValueFrom(
|
await firstValueFrom(
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.organization$,
|
this.organization$,
|
||||||
this.allowPersonalOwnership$,
|
this.organizationDataOwnershipDisabled$,
|
||||||
this.allOrganizations$,
|
this.allOrganizations$,
|
||||||
this.allCollections$,
|
this.allCollections$,
|
||||||
]),
|
]),
|
||||||
@@ -84,13 +84,14 @@ export class AdminConsoleCipherFormConfigService implements CipherFormConfigServ
|
|||||||
const organizations = mode === "clone" ? allOrganizations : [organization];
|
const organizations = mode === "clone" ? allOrganizations : [organization];
|
||||||
// Only allow the user to assign to their personal vault when cloning and
|
// Only allow the user to assign to their personal vault when cloning and
|
||||||
// the policies are enabled for it.
|
// 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);
|
const cipher = await this.getCipher(cipherId, organization);
|
||||||
return {
|
return {
|
||||||
mode,
|
mode,
|
||||||
cipherType: cipher?.type ?? cipherType ?? CipherType.Login,
|
cipherType: cipher?.type ?? cipherType ?? CipherType.Login,
|
||||||
admin: organization.canEditAllCiphers ?? false,
|
admin: organization.canEditAllCiphers ?? false,
|
||||||
allowPersonalOwnership: allowPersonalOwnershipOnlyForClone,
|
organizationDataOwnershipDisabled: disableOrganizationDataOwnershipOnlyForClone,
|
||||||
originalCipher: cipher,
|
originalCipher: cipher,
|
||||||
collections: allCollections,
|
collections: allCollections,
|
||||||
organizations,
|
organizations,
|
||||||
|
|||||||
@@ -5379,6 +5379,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"organizationDataOwnership": {
|
||||||
|
"message": "Enforce organization data ownership"
|
||||||
|
},
|
||||||
"personalOwnership": {
|
"personalOwnership": {
|
||||||
"message": "Remove individual vault"
|
"message": "Remove individual vault"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class FreeFamiliesSponsorshipPolicy extends BasePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "policy-personal-ownership",
|
selector: "policy-free-families-sponsorship",
|
||||||
templateUrl: "free-families-sponsorship.component.html",
|
templateUrl: "free-families-sponsorship.component.html",
|
||||||
standalone: false,
|
standalone: false,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ export abstract class DeprecatedVaultFilterService {
|
|||||||
buildCollapsedFilterNodes: () => Promise<Set<string>>;
|
buildCollapsedFilterNodes: () => Promise<Set<string>>;
|
||||||
storeCollapsedFilterNodes: (collapsedFilterNodes: Set<string>) => Promise<void>;
|
storeCollapsedFilterNodes: (collapsedFilterNodes: Set<string>) => Promise<void>;
|
||||||
checkForSingleOrganizationPolicy: () => Promise<boolean>;
|
checkForSingleOrganizationPolicy: () => Promise<boolean>;
|
||||||
checkForPersonalOwnershipPolicy: () => Promise<boolean>;
|
checkForOrganizationDataOwnershipPolicy: () => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
|||||||
protected componentName = "";
|
protected componentName = "";
|
||||||
protected destroy$ = new Subject<void>();
|
protected destroy$ = new Subject<void>();
|
||||||
protected writeableCollections: CollectionView[];
|
protected writeableCollections: CollectionView[];
|
||||||
private personalOwnershipPolicyAppliesToActiveUser: boolean;
|
private organizationDataOwnershipAppliesToUser: boolean;
|
||||||
private previousCipherId: string;
|
private previousCipherId: string;
|
||||||
|
|
||||||
get fido2CredentialCreationDateValue(): string {
|
get fido2CredentialCreationDateValue(): string {
|
||||||
@@ -195,10 +195,10 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
|||||||
.pipe(
|
.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
concatMap(async (policyAppliesToActiveUser) => {
|
concatMap(async (policyAppliesToActiveUser) => {
|
||||||
this.personalOwnershipPolicyAppliesToActiveUser = policyAppliesToActiveUser;
|
this.organizationDataOwnershipAppliesToUser = policyAppliesToActiveUser;
|
||||||
await this.init();
|
await this.init();
|
||||||
}),
|
}),
|
||||||
takeUntil(this.destroy$),
|
takeUntil(this.destroy$),
|
||||||
@@ -218,7 +218,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
|||||||
if (this.ownershipOptions.length) {
|
if (this.ownershipOptions.length) {
|
||||||
this.ownershipOptions = [];
|
this.ownershipOptions = [];
|
||||||
}
|
}
|
||||||
if (this.personalOwnershipPolicyAppliesToActiveUser) {
|
if (this.organizationDataOwnershipAppliesToUser) {
|
||||||
this.allowPersonal = false;
|
this.allowPersonal = false;
|
||||||
} else {
|
} else {
|
||||||
const myEmail = await firstValueFrom(
|
const myEmail = await firstValueFrom(
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class OrganizationFilterComponent {
|
|||||||
@Input() collapsedFilterNodes: Set<string>;
|
@Input() collapsedFilterNodes: Set<string>;
|
||||||
@Input() organizations: Organization[];
|
@Input() organizations: Organization[];
|
||||||
@Input() activeFilter: VaultFilter;
|
@Input() activeFilter: VaultFilter;
|
||||||
@Input() activePersonalOwnershipPolicy: boolean;
|
@Input() activeOrganizationDataOwnership: boolean;
|
||||||
@Input() activeSingleOrganizationPolicy: boolean;
|
@Input() activeSingleOrganizationPolicy: boolean;
|
||||||
|
|
||||||
@Output() onNodeCollapseStateChange: EventEmitter<ITreeNodeObject> =
|
@Output() onNodeCollapseStateChange: EventEmitter<ITreeNodeObject> =
|
||||||
@@ -26,12 +26,12 @@ export class OrganizationFilterComponent {
|
|||||||
let displayMode: DisplayMode = "organizationMember";
|
let displayMode: DisplayMode = "organizationMember";
|
||||||
if (this.organizations == null || this.organizations.length < 1) {
|
if (this.organizations == null || this.organizations.length < 1) {
|
||||||
displayMode = "noOrganizations";
|
displayMode = "noOrganizations";
|
||||||
} else if (this.activePersonalOwnershipPolicy && !this.activeSingleOrganizationPolicy) {
|
} else if (this.activeOrganizationDataOwnership && !this.activeSingleOrganizationPolicy) {
|
||||||
displayMode = "personalOwnershipPolicy";
|
displayMode = "organizationDataOwnershipPolicy";
|
||||||
} else if (!this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) {
|
} else if (!this.activeOrganizationDataOwnership && this.activeSingleOrganizationPolicy) {
|
||||||
displayMode = "singleOrganizationPolicy";
|
displayMode = "singleOrganizationPolicy";
|
||||||
} else if (this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) {
|
} else if (this.activeOrganizationDataOwnership && this.activeSingleOrganizationPolicy) {
|
||||||
displayMode = "singleOrganizationAndPersonalOwnershipPolicies";
|
displayMode = "singleOrganizationAndOrganizatonDataOwnershipPolicies";
|
||||||
}
|
}
|
||||||
|
|
||||||
return displayMode;
|
return displayMode;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export class VaultFilterComponent implements OnInit {
|
|||||||
isLoaded = false;
|
isLoaded = false;
|
||||||
collapsedFilterNodes: Set<string>;
|
collapsedFilterNodes: Set<string>;
|
||||||
organizations: Organization[];
|
organizations: Organization[];
|
||||||
activePersonalOwnershipPolicy: boolean;
|
activeOrganizationDataOwnershipPolicy: boolean;
|
||||||
activeSingleOrganizationPolicy: boolean;
|
activeSingleOrganizationPolicy: boolean;
|
||||||
collections: DynamicTreeNode<CollectionView>;
|
collections: DynamicTreeNode<CollectionView>;
|
||||||
folders$: Observable<DynamicTreeNode<FolderView>>;
|
folders$: Observable<DynamicTreeNode<FolderView>>;
|
||||||
@@ -47,8 +47,8 @@ export class VaultFilterComponent implements OnInit {
|
|||||||
this.collapsedFilterNodes = await this.vaultFilterService.buildCollapsedFilterNodes();
|
this.collapsedFilterNodes = await this.vaultFilterService.buildCollapsedFilterNodes();
|
||||||
this.organizations = await this.vaultFilterService.buildOrganizations();
|
this.organizations = await this.vaultFilterService.buildOrganizations();
|
||||||
if (this.organizations != null && this.organizations.length > 0) {
|
if (this.organizations != null && this.organizations.length > 0) {
|
||||||
this.activePersonalOwnershipPolicy =
|
this.activeOrganizationDataOwnershipPolicy =
|
||||||
await this.vaultFilterService.checkForPersonalOwnershipPolicy();
|
await this.vaultFilterService.checkForOrganizationDataOwnershipPolicy();
|
||||||
this.activeSingleOrganizationPolicy =
|
this.activeSingleOrganizationPolicy =
|
||||||
await this.vaultFilterService.checkForSingleOrganizationPolicy();
|
await this.vaultFilterService.checkForSingleOrganizationPolicy();
|
||||||
}
|
}
|
||||||
@@ -88,8 +88,8 @@ export class VaultFilterComponent implements OnInit {
|
|||||||
|
|
||||||
async reloadOrganizations() {
|
async reloadOrganizations() {
|
||||||
this.organizations = await this.vaultFilterService.buildOrganizations();
|
this.organizations = await this.vaultFilterService.buildOrganizations();
|
||||||
this.activePersonalOwnershipPolicy =
|
this.activeOrganizationDataOwnershipPolicy =
|
||||||
await this.vaultFilterService.checkForPersonalOwnershipPolicy();
|
await this.vaultFilterService.checkForOrganizationDataOwnershipPolicy();
|
||||||
this.activeSingleOrganizationPolicy =
|
this.activeSingleOrganizationPolicy =
|
||||||
await this.vaultFilterService.checkForSingleOrganizationPolicy();
|
await this.vaultFilterService.checkForSingleOrganizationPolicy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ export type DisplayMode =
|
|||||||
| "noOrganizations"
|
| "noOrganizations"
|
||||||
| "organizationMember"
|
| "organizationMember"
|
||||||
| "singleOrganizationPolicy"
|
| "singleOrganizationPolicy"
|
||||||
| "personalOwnershipPolicy"
|
| "organizationDataOwnershipPolicy"
|
||||||
| "singleOrganizationAndPersonalOwnershipPolicies";
|
| "singleOrganizationAndOrganizatonDataOwnershipPolicies";
|
||||||
|
|||||||
@@ -123,12 +123,12 @@ export class VaultFilterService implements DeprecatedVaultFilterServiceAbstracti
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkForPersonalOwnershipPolicy(): Promise<boolean> {
|
async checkForOrganizationDataOwnershipPolicy(): Promise<boolean> {
|
||||||
return await firstValueFrom(
|
return await firstValueFrom(
|
||||||
this.accountService.activeAccount$.pipe(
|
this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export enum PolicyType {
|
|||||||
PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases
|
PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases
|
||||||
SingleOrg = 3, // Allows users to only be apart of one organization
|
SingleOrg = 3, // Allows users to only be apart of one organization
|
||||||
RequireSso = 4, // Requires users to authenticate with SSO
|
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
|
DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends
|
||||||
SendOptions = 7, // Sets restrictions or defaults for 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
|
ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow
|
||||||
|
|||||||
@@ -238,8 +238,8 @@ export class DefaultPolicyService implements PolicyService {
|
|||||||
case PolicyType.RestrictedItemTypes:
|
case PolicyType.RestrictedItemTypes:
|
||||||
// restricted item types policy
|
// restricted item types policy
|
||||||
return false;
|
return false;
|
||||||
case PolicyType.PersonalOwnership:
|
case PolicyType.OrganizationDataOwnership:
|
||||||
// individual vault policy applies to everyone except admins and owners
|
// organization data ownership policy applies to everyone except admins and owners
|
||||||
return organization.isAdmin;
|
return organization.isAdmin;
|
||||||
default:
|
default:
|
||||||
return organization.canManagePolicies;
|
return organization.canManagePolicies;
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ export class ImportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
this.accountService.activeAccount$.pipe(
|
this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
this.organizations$,
|
this.organizations$,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
[label]="'myVault' | i18n"
|
[label]="'myVault' | i18n"
|
||||||
value="myVault"
|
value="myVault"
|
||||||
icon="bwi-user"
|
icon="bwi-user"
|
||||||
*ngIf="!(disablePersonalOwnershipPolicy$ | async)"
|
*ngIf="!(organizationDataOwnershipPolicy$ | async)"
|
||||||
/>
|
/>
|
||||||
<bit-option
|
<bit-option
|
||||||
*ngFor="let o of organizations$ | async"
|
*ngFor="let o of organizations$ | async"
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disablePersonalVaultExportPolicy$: Observable<boolean>;
|
disablePersonalVaultExportPolicy$: Observable<boolean>;
|
||||||
disablePersonalOwnershipPolicy$: Observable<boolean>;
|
organizationDataOwnershipPolicy$: Observable<boolean>;
|
||||||
|
|
||||||
exportForm = this.formBuilder.group({
|
exportForm = this.formBuilder.group({
|
||||||
vaultSelector: [
|
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,
|
getUserId,
|
||||||
switchMap((userId) =>
|
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([
|
combineLatest([
|
||||||
this.disablePersonalVaultExportPolicy$,
|
this.disablePersonalVaultExportPolicy$,
|
||||||
this.disablePersonalOwnershipPolicy$,
|
this.organizationDataOwnershipPolicy$,
|
||||||
this.organizations$,
|
this.organizations$,
|
||||||
])
|
])
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(([disablePersonalVaultExport, disablePersonalOwnership, organizations]) => {
|
tap(([disablePersonalVaultExport, organizationDataOwnership, organizations]) => {
|
||||||
this._disabledByPolicy = disablePersonalVaultExport;
|
this._disabledByPolicy = disablePersonalVaultExport;
|
||||||
|
|
||||||
// When personalOwnership is disabled and we have orgs, set the first org as the selected vault
|
// When organizationDataOwnership is enabled and we have orgs, set the first org as the selected vault
|
||||||
if (disablePersonalOwnership && organizations.length > 0) {
|
if (organizationDataOwnership && organizations.length > 0) {
|
||||||
this.exportForm.enable();
|
this.exportForm.enable();
|
||||||
this.exportForm.controls.vaultSelector.setValue(organizations[0].id);
|
this.exportForm.controls.vaultSelector.setValue(organizations[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When personalOwnership is disabled and we have no orgs, disable the form
|
// When organizationDataOwnership is enabled and we have no orgs, disable the form
|
||||||
if (disablePersonalOwnership && organizations.length === 0) {
|
if (organizationDataOwnership && organizations.length === 0) {
|
||||||
this.exportForm.disable();
|
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"
|
// 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");
|
this.exportForm.controls.vaultSelector.setValue("myVault");
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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
|
* 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.
|
* 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.
|
* 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;
|
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 & {
|
type OrganizationDataOwnershipDisabled = CombinedAddEditConfig & {
|
||||||
allowPersonalOwnership: true;
|
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.
|
* Organizations must be provided.
|
||||||
*/
|
*/
|
||||||
type PersonalOwnershipNotAllowed = CombinedAddEditConfig & {
|
type OrganizationDataOwnershipEnabled = CombinedAddEditConfig & {
|
||||||
allowPersonalOwnership: false;
|
organizationDataOwnershipDisabled: false;
|
||||||
organizations: Organization[];
|
organizations: Organization[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ type PersonalOwnershipNotAllowed = CombinedAddEditConfig & {
|
|||||||
* Configuration object for the cipher form.
|
* Configuration object for the cipher form.
|
||||||
* Determines the behavior of the form and the controls that are displayed/enabled.
|
* 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.
|
* Service responsible for building the configuration object for the cipher form.
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const defaultConfig: CipherFormConfig = {
|
|||||||
mode: "add",
|
mode: "add",
|
||||||
cipherType: CipherType.Login,
|
cipherType: CipherType.Login,
|
||||||
admin: false,
|
admin: false,
|
||||||
allowPersonalOwnership: true,
|
organizationDataOwnershipDisabled: true,
|
||||||
collections: [
|
collections: [
|
||||||
{
|
{
|
||||||
id: "col1",
|
id: "col1",
|
||||||
@@ -354,13 +354,13 @@ export const WithSubmitButton: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NoPersonalOwnership: Story = {
|
export const OrganizationDataOwnershipEnabled: Story = {
|
||||||
...Add,
|
...Add,
|
||||||
args: {
|
args: {
|
||||||
config: {
|
config: {
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
mode: "add",
|
mode: "add",
|
||||||
allowPersonalOwnership: false,
|
organizationDataOwnershipDisabled: false,
|
||||||
originalCipher: defaultConfig.originalCipher,
|
originalCipher: defaultConfig.originalCipher,
|
||||||
organizations: defaultConfig.organizations!,
|
organizations: defaultConfig.organizations!,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<bit-label>{{ "owner" | i18n }}</bit-label>
|
<bit-label>{{ "owner" | i18n }}</bit-label>
|
||||||
<bit-select formControlName="organizationId">
|
<bit-select formControlName="organizationId">
|
||||||
<bit-option
|
<bit-option
|
||||||
*ngIf="showPersonalOwnerOption"
|
*ngIf="showOrganizationDataOwnershipOption"
|
||||||
[value]="null"
|
[value]="null"
|
||||||
[label]="userEmail$ | async"
|
[label]="userEmail$ | async"
|
||||||
></bit-option>
|
></bit-option>
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("ngOnInit", () => {
|
describe("ngOnInit", () => {
|
||||||
it("should throw an error if no organizations are available for ownership and personal ownership is not allowed", async () => {
|
it("should throw an error if no organizations are available for ownership and organization data ownership is enabled", async () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.organizationDataOwnershipDisabled = false;
|
||||||
component.config.organizations = [];
|
component.config.organizations = [];
|
||||||
await expect(component.ngOnInit()).rejects.toThrow(
|
await expect(component.ngOnInit()).rejects.toThrow(
|
||||||
"No organizations available for ownership.",
|
"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 () => {
|
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];
|
component.config.organizations = [{ id: "org1" } as Organization];
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
tick();
|
tick();
|
||||||
@@ -120,7 +120,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it("should initialize form with values from originalCipher if provided", fakeAsync(async () => {
|
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.organizations = [{ id: "org1" } as Organization];
|
||||||
component.config.collections = [
|
component.config.collections = [
|
||||||
createMockCollection("col1", "Collection 1", "org1") as CollectionView,
|
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 () => {
|
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];
|
component.config.organizations = [{ id: "org1" } as Organization];
|
||||||
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(false);
|
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(false);
|
||||||
|
|
||||||
@@ -188,15 +188,15 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
expect(component.allowOwnershipChange).toBe(false);
|
expect(component.allowOwnershipChange).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow ownership change if personal ownership is allowed and there is at least one organization", () => {
|
it("should allow ownership change if organization data ownership is disabled and there is at least one organization", () => {
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
component.config.organizations = [{ id: "org1", name: "org1" } as Organization];
|
component.config.organizations = [{ id: "org1", name: "org1" } as Organization];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.allowOwnershipChange).toBe(true);
|
expect(component.allowOwnershipChange).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow ownership change if personal ownership is not allowed but there is more than one organization", () => {
|
it("should allow ownership change if organization data ownership is enabled but there is more than one organization", () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.organizationDataOwnershipDisabled = false;
|
||||||
component.config.organizations = [
|
component.config.organizations = [
|
||||||
{ id: "org1", name: "org1" } as Organization,
|
{ id: "org1", name: "org1" } as Organization,
|
||||||
{ id: "org2", name: "org2" } as Organization,
|
{ id: "org2", name: "org2" } as Organization,
|
||||||
@@ -207,23 +207,23 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("defaultOwner", () => {
|
describe("defaultOwner", () => {
|
||||||
it("should return null if personal ownership is allowed", () => {
|
it("should return null if organization data ownership is disabled", () => {
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
expect(component.defaultOwner).toBeNull();
|
expect(component.defaultOwner).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return the first organization id if personal ownership is not allowed", () => {
|
it("should return the first organization id if organization data ownership is enabled", () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.organizationDataOwnershipDisabled = false;
|
||||||
component.config.organizations = [{ id: "org1", name: "Organization 1" } as Organization];
|
component.config.organizations = [{ id: "org1", name: "Organization 1" } as Organization];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(component.defaultOwner).toBe("org1");
|
expect(component.defaultOwner).toBe("org1");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("showPersonalOwnerOption", () => {
|
describe("showOrganizationDataOwnershipOption", () => {
|
||||||
it("should show personal ownership when the configuration allows", () => {
|
it("should show organization data ownership when the configuration allows", () => {
|
||||||
component.config.mode = "edit";
|
component.config.mode = "edit";
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
component.originalCipherView = {} as CipherView;
|
component.originalCipherView = {} as CipherView;
|
||||||
component.config.organizations = [{ id: "134-433-22" } as Organization];
|
component.config.organizations = [{ id: "134-433-22" } as Organization];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -235,9 +235,9 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
expect(label).toBe("test@example.com");
|
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.mode = "edit";
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.organizationDataOwnershipDisabled = false;
|
||||||
component.originalCipherView = {} as CipherView;
|
component.originalCipherView = {} as CipherView;
|
||||||
component.config.organizations = [{ id: "134-433-22" } as Organization];
|
component.config.organizations = [{ id: "134-433-22" } as Organization];
|
||||||
await component.ngOnInit();
|
await component.ngOnInit();
|
||||||
@@ -253,7 +253,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
|
|
||||||
describe("showOwnership", () => {
|
describe("showOwnership", () => {
|
||||||
it("should return true if ownership change is allowed or in edit mode with at least one organization", () => {
|
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);
|
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(true);
|
||||||
expect(component.showOwnership).toBe(true);
|
expect(component.showOwnership).toBe(true);
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should hide the ownership control if showOwnership is false", async () => {
|
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);
|
jest.spyOn(component, "showOwnership", "get").mockReturnValue(false);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@@ -276,7 +276,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should show the ownership control if showOwnership is true", async () => {
|
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);
|
jest.spyOn(component, "allowOwnershipChange", "get").mockReturnValue(true);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@@ -293,7 +293,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should append '- Clone' to the title if in clone mode", async () => {
|
it("should append '- Clone' to the title if in clone mode", async () => {
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
const cipher = {
|
const cipher = {
|
||||||
name: "cipher1",
|
name: "cipher1",
|
||||||
organizationId: null,
|
organizationId: null,
|
||||||
@@ -312,7 +312,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not append clone when the cipher was populated from the cache", async () => {
|
it("does not append clone when the cipher was populated from the cache", async () => {
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
const cipher = {
|
const cipher = {
|
||||||
name: "from cache cipher",
|
name: "from cache cipher",
|
||||||
organizationId: null,
|
organizationId: null,
|
||||||
@@ -332,8 +332,8 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
expect(component.itemDetailsForm.controls.name.value).toBe("from cache cipher");
|
expect(component.itemDetailsForm.controls.name.value).toBe("from cache cipher");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should select the first organization if personal ownership is not allowed", async () => {
|
it("should select the first organization if organization data ownership is enabled", async () => {
|
||||||
component.config.allowPersonalOwnership = false;
|
component.config.organizationDataOwnershipDisabled = false;
|
||||||
component.config.organizations = [
|
component.config.organizations = [
|
||||||
{ id: "org1", name: "org1" } as Organization,
|
{ id: "org1", name: "org1" } as Organization,
|
||||||
{ id: "org2", name: "org2" } as Organization,
|
{ id: "org2", name: "org2" } as Organization,
|
||||||
@@ -354,7 +354,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
|
|
||||||
describe("collectionOptions", () => {
|
describe("collectionOptions", () => {
|
||||||
it("should reset and disable/hide collections control when no organization is selected", async () => {
|
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);
|
component.itemDetailsForm.controls.organizationId.setValue(null);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -370,7 +370,7 @@ describe("ItemDetailsSectionComponent", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should enable/show collection control when an organization is selected", async () => {
|
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.organizations = [{ id: "org1" } as Organization];
|
||||||
component.config.collections = [
|
component.config.collections = [
|
||||||
createMockCollection("col1", "Collection 1", "org1") as CollectionView,
|
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 () => {
|
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.organizations = [{ id: "org1" } as Organization];
|
||||||
component.config.collections = [
|
component.config.collections = [
|
||||||
createMockCollection("col1", "Collection 1", "org1") as CollectionView,
|
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 () => {
|
it("should allow all collections to be altered when `config.admin` is true", async () => {
|
||||||
component.config.admin = true;
|
component.config.admin = true;
|
||||||
component.config.allowPersonalOwnership = true;
|
component.config.organizationDataOwnershipDisabled = true;
|
||||||
component.config.organizations = [{ id: "org1" } as Organization];
|
component.config.organizations = [{ id: "org1" } as Organization];
|
||||||
component.config.collections = [
|
component.config.collections = [
|
||||||
createMockCollection("col1", "Collection 1", "org1", true, false) as CollectionView,
|
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"]);
|
expect(component["collectionOptions"].map((c) => c.id)).toEqual(["col1", "col2", "col3"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("readonlyCollections", () => {
|
describe("readonlyCollections", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.config.mode = "edit";
|
component.config.mode = "edit";
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
return this.config.mode === "partial-edit";
|
return this.config.mode === "partial-edit";
|
||||||
}
|
}
|
||||||
|
|
||||||
get allowPersonalOwnership() {
|
get organizationDataOwnershipDisabled() {
|
||||||
return this.config.allowPersonalOwnership;
|
return this.config.organizationDataOwnershipDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
get collections(): CollectionView[] {
|
get collections(): CollectionView[] {
|
||||||
@@ -105,14 +105,17 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the personal ownership option in the Owner dropdown when:
|
* Show the organization data ownership option in the Owner dropdown when:
|
||||||
* - Personal ownership is allowed
|
* - organization data ownership is disabled
|
||||||
* - The `organizationId` control is disabled. This avoids the scenario
|
* - The `organizationId` control is disabled. This avoids the scenario
|
||||||
* where a the dropdown is empty because the user personally owns the cipher
|
* where a the dropdown is empty because the user personally owns the cipher
|
||||||
* but cannot edit the ownership.
|
* but cannot edit the ownership.
|
||||||
*/
|
*/
|
||||||
get showPersonalOwnerOption() {
|
get showOrganizationDataOwnershipOption() {
|
||||||
return this.allowPersonalOwnership || !this.itemDetailsForm.controls.organizationId.enabled;
|
return (
|
||||||
|
this.organizationDataOwnershipDisabled ||
|
||||||
|
!this.itemDetailsForm.controls.organizationId.enabled
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
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 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;
|
return this.organizations.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +183,7 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get defaultOwner() {
|
get defaultOwner() {
|
||||||
return this.allowPersonalOwnership ? null : this.organizations[0].id;
|
return this.organizationDataOwnershipDisabled ? null : this.organizations[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
@@ -188,7 +191,7 @@ export class ItemDetailsSectionComponent implements OnInit {
|
|||||||
Utils.getSortFunction(this.i18nService, "name"),
|
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.");
|
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);
|
this.itemDetailsForm.controls.organizationId.setValue(this.defaultOwner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
|||||||
): Promise<CipherFormConfig> {
|
): Promise<CipherFormConfig> {
|
||||||
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||||
|
|
||||||
const [organizations, collections, allowPersonalOwnership, folders, cipher] =
|
const [organizations, collections, organizationDataOwnershipDisabled, folders, cipher] =
|
||||||
await firstValueFrom(
|
await firstValueFrom(
|
||||||
combineLatest([
|
combineLatest([
|
||||||
this.organizations$(activeUserId),
|
this.organizations$(activeUserId),
|
||||||
@@ -55,7 +55,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
this.allowPersonalOwnership$,
|
this.organizationDataOwnershipDisabled$,
|
||||||
this.folderService.folders$(activeUserId).pipe(
|
this.folderService.folders$(activeUserId).pipe(
|
||||||
switchMap((f) =>
|
switchMap((f) =>
|
||||||
this.folderService.folderViews$(activeUserId).pipe(
|
this.folderService.folderViews$(activeUserId).pipe(
|
||||||
@@ -71,7 +71,7 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
|||||||
mode,
|
mode,
|
||||||
cipherType: cipher?.type ?? cipherType ?? CipherType.Login,
|
cipherType: cipher?.type ?? cipherType ?? CipherType.Login,
|
||||||
admin: false,
|
admin: false,
|
||||||
allowPersonalOwnership,
|
organizationDataOwnershipDisabled,
|
||||||
originalCipher: cipher,
|
originalCipher: cipher,
|
||||||
collections,
|
collections,
|
||||||
organizations,
|
organizations,
|
||||||
@@ -91,10 +91,10 @@ export class DefaultCipherFormConfigService implements CipherFormConfigService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private allowPersonalOwnership$ = this.accountService.activeAccount$.pipe(
|
private organizationDataOwnershipDisabled$ = this.accountService.activeAccount$.pipe(
|
||||||
getUserId,
|
getUserId,
|
||||||
switchMap((userId) =>
|
switchMap((userId) =>
|
||||||
this.policyService.policyAppliesToUser$(PolicyType.PersonalOwnership, userId),
|
this.policyService.policyAppliesToUser$(PolicyType.OrganizationDataOwnership, userId),
|
||||||
),
|
),
|
||||||
map((p) => !p),
|
map((p) => !p),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user