From a1542f050dfbacfcd3a0460faf9dbebc29f5d622 Mon Sep 17 00:00:00 2001 From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Date: Wed, 9 Dec 2020 14:11:25 -0600 Subject: [PATCH] [Policy] Personal Ownership (#1481) * Initial commit for personal ownership * Removed TODO // Updated allowPersonalOwnership logic to include necessary org/user checks * Fixed import order * Updated jslib (dcbd09e -> 72bf18f) * Fixed casing for error message --- jslib | 2 +- src/_locales/en/messages.json | 3 +++ src/background/main.background.ts | 6 ++--- src/background/runtime.background.ts | 32 +++++++++++++++++++++++-- src/popup/vault/add-edit.component.html | 2 +- src/popup/vault/add-edit.component.ts | 10 ++++++-- 6 files changed, 46 insertions(+), 9 deletions(-) diff --git a/jslib b/jslib index dcbd09e736..72bf18f369 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit dcbd09e736b516b359369f9d9fe5b0f5a6c2a928 +Subproject commit 72bf18f369068d36767794bdc0ca377f734cf373 diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index bd3b9730f2..946dba4b98 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -1413,5 +1413,8 @@ }, "nativeMessagingInvalidEncryptionTitle": { "message": "Desktop communication interupted" + }, + "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." } } diff --git a/src/background/main.background.ts b/src/background/main.background.ts index 6de29fa43a..c3e235015c 100644 --- a/src/background/main.background.ts +++ b/src/background/main.background.ts @@ -155,9 +155,9 @@ export default class MainBackground { async () => { if (this.nativeMessagingBackground != null) { const promise = this.nativeMessagingBackground.getResponse(); - + try { - await this.nativeMessagingBackground.send({command: 'biometricUnlock'}); + await this.nativeMessagingBackground.send({ command: 'biometricUnlock' }); } catch (e) { return Promise.reject(e); } @@ -243,7 +243,7 @@ export default class MainBackground { this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService, this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService, this.analytics, this.notificationsService, this.systemService, this.vaultTimeoutService, - this.environmentService); + this.environmentService, this.policyService, this.userService); this.nativeMessagingBackground = new NativeMessagingBackground(this.storageService, this.cryptoService, this.cryptoFunctionService, this.vaultTimeoutService, this.runtimeBackground, this.i18nService, this.userService, this.messagingService); this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, diff --git a/src/background/runtime.background.ts b/src/background/runtime.background.ts index 685b4a5dff..c7ef83e954 100644 --- a/src/background/runtime.background.ts +++ b/src/background/runtime.background.ts @@ -12,11 +12,13 @@ import { ConstantsService } from 'jslib/services/constants.service'; import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { NotificationsService } from 'jslib/abstractions/notifications.service'; +import { PolicyService } from 'jslib/abstractions/policy.service'; import { PopupUtilsService } from '../popup/services/popup-utils.service'; import { StateService } from 'jslib/abstractions/state.service'; import { StorageService } from 'jslib/abstractions/storage.service'; import { SyncService } from 'jslib/abstractions/sync.service'; import { SystemService } from 'jslib/abstractions/system.service'; +import { UserService } from 'jslib/abstractions/user.service'; import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service'; import { BrowserApi } from '../browser/browserApi'; @@ -27,6 +29,9 @@ import { NativeMessagingBackground } from './nativeMessaging.background'; import { Analytics } from 'jslib/misc'; import { Utils } from 'jslib/misc/utils'; +import { OrganizationUserStatusType } from 'jslib/enums/organizationUserStatusType'; +import { PolicyType } from 'jslib/enums/policyType'; + export default class RuntimeBackground { private runtime: any; private autofillTimeout: any; @@ -39,7 +44,8 @@ export default class RuntimeBackground { private storageService: StorageService, private i18nService: I18nService, private analytics: Analytics, private notificationsService: NotificationsService, private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService, - private environmentService: EnvironmentService) { + private environmentService: EnvironmentService, private policyService: PolicyService, + private userService: UserService) { this.isSafari = this.platformUtilsService.isSafari(); this.runtime = this.isSafari ? {} : chrome.runtime; @@ -318,6 +324,11 @@ export default class RuntimeBackground { if (disabledAddLogin) { return; } + + if (!(await this.allowPersonalOwnership())) { + return; + } + // remove any old messages for this tab this.removeTabFromNotificationQueue(tab); this.main.notificationQueue.push({ @@ -436,8 +447,9 @@ export default class RuntimeBackground { const responseData: any = {}; if (responseCommand === 'notificationBarDataResponse') { responseData.neverDomains = await this.storageService.get(ConstantsService.neverDomainsKey); - responseData.disabledAddLoginNotification = await this.storageService.get( + const disableAddLoginFromOptions = await this.storageService.get( ConstantsService.disableAddLoginNotificationKey); + responseData.disabledAddLoginNotification = disableAddLoginFromOptions || !(await this.allowPersonalOwnership()); responseData.disabledChangedPasswordNotification = await this.storageService.get( ConstantsService.disableChangedPasswordNotificationKey); } else if (responseCommand === 'autofillerAutofillOnPageLoadEnabledResponse') { @@ -459,4 +471,20 @@ export default class RuntimeBackground { await BrowserApi.tabSendMessageData(tab, responseCommand, responseData); } + + private async allowPersonalOwnership(): Promise { + const personalOwnershipPolicies = await this.policyService.getAll(PolicyType.PersonalOwnership); + if (personalOwnershipPolicies != null) { + for (const policy of personalOwnershipPolicies) { + if (policy.enabled) { + const org = await this.userService.getOrganization(policy.organizationId); + if (org != null && org.enabled && org.usePolicies && !org.isAdmin + && org.status == OrganizationUserStatusType.Confirmed) { + return false; + } + } + } + } + return true; + } } diff --git a/src/popup/vault/add-edit.component.html b/src/popup/vault/add-edit.component.html index 7a4c6c1cd0..65f344e29b 100644 --- a/src/popup/vault/add-edit.component.html +++ b/src/popup/vault/add-edit.component.html @@ -340,7 +340,7 @@ -
+
{{'ownership' | i18n}}
diff --git a/src/popup/vault/add-edit.component.ts b/src/popup/vault/add-edit.component.ts index 5a9872a4fd..fdecd141d8 100644 --- a/src/popup/vault/add-edit.component.ts +++ b/src/popup/vault/add-edit.component.ts @@ -15,6 +15,7 @@ import { FolderService } from 'jslib/abstractions/folder.service'; import { I18nService } from 'jslib/abstractions/i18n.service'; import { MessagingService } from 'jslib/abstractions/messaging.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { PolicyService } from 'jslib/abstractions/policy.service'; import { StateService } from 'jslib/abstractions/state.service'; import { UserService } from 'jslib/abstractions/user.service'; @@ -36,9 +37,9 @@ export class AddEditComponent extends BaseAddEditComponent { userService: UserService, collectionService: CollectionService, messagingService: MessagingService, private route: ActivatedRoute, private router: Router, private location: Location, - eventService: EventService) { + eventService: EventService, policyService: PolicyService) { super(cipherService, folderService, i18nService, platformUtilsService, auditService, stateService, - userService, collectionService, messagingService, eventService); + userService, collectionService, messagingService, eventService, policyService); } async ngOnInit() { @@ -161,4 +162,9 @@ export class AddEditComponent extends BaseAddEditComponent { const u = (uri as any); u.showCurrentUris = !u.showCurrentUris; } + + allowOwnershipOptions(): boolean { + return (!this.editMode || this.cloneMode) && this.ownershipOptions + && (this.ownershipOptions.length > 1 || !this.allowPersonal); + } }