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"
},