From 2d62e10d988633b7cd1c58af7e450cfa2150070b Mon Sep 17 00:00:00 2001 From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Date: Tue, 8 Dec 2020 10:10:15 -0600 Subject: [PATCH] [Policy] Personal Ownership (#213) * Initial commit of personal ownership enforcement * Updated policy type enum * Sync'd eventType for Policy_Updated with server enum value * Added policyId to eventResponse model * Removed explicit typing --- src/angular/components/add-edit.component.ts | 26 +++++++++++++++++++- src/enums/eventType.ts | 4 +-- src/enums/policyType.ts | 1 + src/models/response/eventResponse.ts | 2 ++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/angular/components/add-edit.component.ts b/src/angular/components/add-edit.component.ts index 16c0f87540..09cdf1343b 100644 --- a/src/angular/components/add-edit.component.ts +++ b/src/angular/components/add-edit.component.ts @@ -14,6 +14,7 @@ import { CipherType } from '../../enums/cipherType'; import { EventType } from '../../enums/eventType'; import { FieldType } from '../../enums/fieldType'; import { OrganizationUserStatusType } from '../../enums/organizationUserStatusType'; +import { PolicyType } from '../../enums/policyType'; import { SecureNoteType } from '../../enums/secureNoteType'; import { UriMatchType } from '../../enums/uriMatchType'; @@ -25,6 +26,7 @@ import { FolderService } from '../../abstractions/folder.service'; import { I18nService } from '../../abstractions/i18n.service'; import { MessagingService } from '../../abstractions/messaging.service'; import { PlatformUtilsService } from '../../abstractions/platformUtils.service'; +import { PolicyService } from '../../abstractions/policy.service'; import { StateService } from '../../abstractions/state.service'; import { UserService } from '../../abstractions/user.service'; @@ -81,6 +83,7 @@ export class AddEditComponent implements OnInit { uriMatchOptions: any[]; ownershipOptions: any[] = []; currentDate = new Date(); + allowPersonal = true; protected writeableCollections: CollectionView[]; private previousCipherId: string; @@ -89,7 +92,8 @@ export class AddEditComponent implements OnInit { protected i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected auditService: AuditService, protected stateService: StateService, protected userService: UserService, protected collectionService: CollectionService, - protected messagingService: MessagingService, protected eventService: EventService) { + protected messagingService: MessagingService, protected eventService: EventService, + protected policyService: PolicyService) { this.typeOptions = [ { name: i18nService.t('typeLogin'), value: CipherType.Login }, { name: i18nService.t('typeCard'), value: CipherType.Card }, @@ -151,12 +155,26 @@ export class AddEditComponent implements OnInit { } async init() { + const policies = await this.policyService.getAll(PolicyType.PersonalOwnership); const myEmail = await this.userService.getEmail(); this.ownershipOptions.push({ name: myEmail, value: null }); const orgs = await this.userService.getAllOrganizations(); orgs.sort(Utils.getSortFunction(this.i18nService, 'name')).forEach((o) => { if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) { this.ownershipOptions.push({ name: o.name, value: o.id }); + if (policies != null && o.usePolicies && !o.isAdmin && this.allowPersonal) { + for (const policy of policies) { + if (policy.organizationId === o.id && policy.enabled) { + this.allowPersonal = false; + this.ownershipOptions.splice(0, 1); + // Default to the organization who owns this policy for now (if necessary) + if (this.organizationId == null) { + this.organizationId = o.id; + } + break; + } + } + } } }); this.writeableCollections = await this.loadCollections(); @@ -236,6 +254,12 @@ export class AddEditComponent implements OnInit { return false; } + if ((!this.editMode || this.cloneMode) && !this.allowPersonal && this.cipher.organizationId == null) { + this.platformUtilsService.showToast('error', this.i18nService.t('errorOccurred'), + this.i18nService.t('personalOwnershipSubmitError')); + return false; + } + if ((!this.editMode || this.cloneMode) && this.cipher.type === CipherType.Login && this.cipher.login.uris != null && this.cipher.login.uris.length === 1 && (this.cipher.login.uris[0].uri == null || this.cipher.login.uris[0].uri === '')) { diff --git a/src/enums/eventType.ts b/src/enums/eventType.ts index 40f626e751..154a363bcb 100644 --- a/src/enums/eventType.ts +++ b/src/enums/eventType.ts @@ -44,7 +44,5 @@ export enum EventType { Organization_PurgedVault = 1601, // Organization_ClientExportedVault = 1602, - Policy_Created = 1700, - Policy_Updated = 1701, - Policy_Deleted = 1702, + Policy_Updated = 1700, } diff --git a/src/enums/policyType.ts b/src/enums/policyType.ts index 31285a5da2..a01fa7df47 100644 --- a/src/enums/policyType.ts +++ b/src/enums/policyType.ts @@ -4,4 +4,5 @@ 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 } diff --git a/src/models/response/eventResponse.ts b/src/models/response/eventResponse.ts index e3cfa93323..770133720e 100644 --- a/src/models/response/eventResponse.ts +++ b/src/models/response/eventResponse.ts @@ -10,6 +10,7 @@ export class EventResponse extends BaseResponse { cipherId: string; collectionId: string; groupId: string; + policyId: string; organizationUserId: string; actingUserId: string; date: string; @@ -24,6 +25,7 @@ export class EventResponse extends BaseResponse { this.cipherId = this.getResponseProperty('CipherId'); this.collectionId = this.getResponseProperty('CollectionId'); this.groupId = this.getResponseProperty('GroupId'); + this.policyId = this.getResponseProperty('PolicyId'); this.organizationUserId = this.getResponseProperty('OrganizationUserId'); this.actingUserId = this.getResponseProperty('ActingUserId'); this.date = this.getResponseProperty('Date');