From 218caa28b0486a5cbe04c236e69e9657e73a5a5f Mon Sep 17 00:00:00 2001 From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Date: Tue, 8 Dec 2020 13:24:59 -0600 Subject: [PATCH] [Policy] Personal Ownership (#722) * Initial commit of personal ownership policy * Added event handling for modifying policies * I didn't save the merge conflict fix... * Removed unused import * Updated jslib (dcbd09e -> 2d62e10) --- jslib | 2 +- .../manage/policies.component.ts | 29 +++++++++++++++++++ .../manage/policy-edit.component.html | 3 ++ .../organizations/vault/add-edit.component.ts | 7 +++-- src/app/services/event.service.ts | 12 ++++++++ src/app/vault/add-edit.component.ts | 9 ++++-- src/locales/en/messages.json | 21 ++++++++++++++ 7 files changed, 76 insertions(+), 7 deletions(-) diff --git a/jslib b/jslib index dcbd09e7..2d62e10d 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit dcbd09e736b516b359369f9d9fe5b0f5a6c2a928 +Subproject commit 2d62e10d988633b7cd1c58af7e450cfa2150070b diff --git a/src/app/organizations/manage/policies.component.ts b/src/app/organizations/manage/policies.component.ts index 3335c630..cdf8e6b5 100644 --- a/src/app/organizations/manage/policies.component.ts +++ b/src/app/organizations/manage/policies.component.ts @@ -93,8 +93,37 @@ export class PoliciesComponent implements OnInit { enabled: false, display: organization.useSso, }, + { + name: this.i18nService.t('personalOwnership'), + description: this.i18nService.t('personalOwnershipPolicyDesc'), + type: PolicyType.PersonalOwnership, + enabled: false, + display: true, + }, ]; await this.load(); + + // Handle policies component launch from Event message + const queryParamsSub = this.route.queryParams.subscribe(async (qParams) => { + if (qParams.policyId != null) { + const policyIdFromEvents: string = qParams.policyId; + for (const orgPolicy of this.orgPolicies) { + if (orgPolicy.id === policyIdFromEvents) { + for (let i = 0; i < this.policies.length; i++) { + if (this.policies[i].type === orgPolicy.type) { + this.edit(this.policies[i]); + break; + } + } + break; + } + } + } + + if (queryParamsSub != null) { + queryParamsSub.unsubscribe(); + } + }); }); // Remove when removing deprecation warning diff --git a/src/app/organizations/manage/policy-edit.component.html b/src/app/organizations/manage/policy-edit.component.html index 220029a1..d5795fea 100644 --- a/src/app/organizations/manage/policy-edit.component.html +++ b/src/app/organizations/manage/policy-edit.component.html @@ -29,6 +29,9 @@ {{'requireSsoExemption' | i18n}} + + {{'personalOwnershipExemption' | i18n}} +
1) { + if (this.ownershipOptions != null && (this.ownershipOptions.length > 1 || !this.allowPersonal)) { if (this.organization != null) { return this.cloneMode && this.organization.isAdmin; } else { diff --git a/src/app/services/event.service.ts b/src/app/services/event.service.ts index d4912f4e..ffb4c155 100644 --- a/src/app/services/event.service.ts +++ b/src/app/services/event.service.ts @@ -165,6 +165,11 @@ export class EventService { msg = this.i18nService.t('exportedOrganizationVault'); break; */ + // Policies + case EventType.Policy_Updated: + msg = this.i18nService.t('modifiedPolicy', this.formatPolicyId(ev)); + break; + default: break; } @@ -251,6 +256,13 @@ export class EventService { return a.outerHTML; } + private formatPolicyId(ev: EventResponse) { + const shortId = this.getShortId(ev.policyId); + const a = this.makeAnchor(shortId); + a.setAttribute('href', '#/organizations/' + ev.organizationId + '/manage/policies?policyId=' + ev.policyId); + return a.outerHTML; + } + private makeAnchor(shortId: string) { const a = document.createElement('a'); a.title = this.i18nService.t('view'); diff --git a/src/app/vault/add-edit.component.ts b/src/app/vault/add-edit.component.ts index b6c37775..52bd2a24 100644 --- a/src/app/vault/add-edit.component.ts +++ b/src/app/vault/add-edit.component.ts @@ -12,6 +12,7 @@ import { I18nService } from 'jslib/abstractions/i18n.service'; import { MessagingService } from 'jslib/abstractions/messaging.service'; import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { PolicyService } from 'jslib/abstractions/policy.service'; import { StateService } from 'jslib/abstractions/state.service'; import { TotpService } from 'jslib/abstractions/totp.service'; import { UserService } from 'jslib/abstractions/user.service'; @@ -41,9 +42,10 @@ export class AddEditComponent extends BaseAddEditComponent { auditService: AuditService, stateService: StateService, userService: UserService, collectionService: CollectionService, protected totpService: TotpService, protected passwordGenerationService: PasswordGenerationService, - protected messagingService: MessagingService, eventService: EventService) { + protected messagingService: MessagingService, eventService: EventService, + protected policyService: PolicyService) { super(cipherService, folderService, i18nService, platformUtilsService, auditService, stateService, - userService, collectionService, messagingService, eventService); + userService, collectionService, messagingService, eventService, policyService); } async ngOnInit() { @@ -155,7 +157,8 @@ export class AddEditComponent extends BaseAddEditComponent { } protected allowOwnershipAssignment() { - return (!this.editMode || this.cloneMode) && this.ownershipOptions != null && this.ownershipOptions.length > 1; + return (!this.editMode || this.cloneMode) && this.ownershipOptions != null + && (this.ownershipOptions.length > 1 || !this.allowPersonal); } private async totpTick(intervalSeconds: number) { diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index cb2a07e8..468ae794 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -3359,6 +3359,27 @@ "message": "There are no Sends to list.", "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." }, + "personalOwnership": { + "message": "Personal Ownership" + }, + "personalOwnershipPolicyDesc": { + "message": "Require users to save vault items to an organization by removing the personal ownership option." + }, + "personalOwnershipExemption": { + "message": "Organization Owners and Administrators are exempt from this policy's enforcement." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership Option to an organization and choose from available Collections." + }, + "modifiedPolicyId": { + "message": "Modified policy $ID$.", + "placeholders": { + "id": { + "content": "$1", + "example": "Master Password" + } + } + }, "planPrice": { "message": "Plan price" },