Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
Move policy checks within policyService (#466)
Browse files Browse the repository at this point in the history
* Move policy logic within policyService

* Remove unneeded import

* Clean up unused code

* Fix linting

* Enforce policies from accepting org invite

* Only exempt owner or admin from policies

* Use canManagePolicies as exemption criteria

* Make orgUser status check more semantic

Co-authored-by: Addison Beck <abeck@bitwarden.com>

Co-authored-by: Addison Beck <abeck@bitwarden.com>
  • Loading branch information
eliykat and Addison Beck committed Aug 30, 2021
1 parent f02720a commit 30419a6
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 44 deletions.
20 changes: 6 additions & 14 deletions angular/src/components/add-edit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,28 +164,20 @@ 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.canManagePolicies && 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;
}
}
}
}
});

if (this.allowPersonal && await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership)) {
this.allowPersonal = false;
this.ownershipOptions.splice(0, 1);
}

this.writeableCollections = await this.loadCollections();
}

Expand Down
22 changes: 3 additions & 19 deletions angular/src/components/send/add-edit.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
Output
} from '@angular/core';

import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
import { PolicyType } from 'jslib-common/enums/policyType';
import { SendType } from 'jslib-common/enums/sendType';

Expand Down Expand Up @@ -103,24 +102,9 @@ export class AddEditComponent implements OnInit {
}

async load() {
const disableSendPolicies = await this.policyService.getAll(PolicyType.DisableSend);
const organizations = await this.userService.getAllOrganizations();
this.disableSend = organizations.some(o => {
return o.enabled &&
o.status === OrganizationUserStatusType.Confirmed &&
o.usePolicies &&
!o.canManagePolicies &&
disableSendPolicies.some(p => p.organizationId === o.id && p.enabled);
});

const sendOptionsPolicies = await this.policyService.getAll(PolicyType.SendOptions);
this.disableHideEmail = await organizations.some(o => {
return o.enabled &&
o.status === OrganizationUserStatusType.Confirmed &&
o.usePolicies &&
!o.canManagePolicies &&
sendOptionsPolicies.some(p => p.organizationId === o.id && p.enabled && p.data.disableHideEmail);
});
this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend);
this.disableHideEmail = await this.policyService.policyAppliesToUser(PolicyType.SendOptions,
p => p.data.disableHideEmail);

this.canAccessPremium = await this.userService.canAccessPremium();
this.emailVerified = await this.userService.getEmailVerified();
Expand Down
10 changes: 1 addition & 9 deletions angular/src/components/send/send.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,7 @@ export class SendComponent implements OnInit {
protected policyService: PolicyService, protected userService: UserService) { }

async ngOnInit() {
const policies = await this.policyService.getAll(PolicyType.DisableSend);
const organizations = await this.userService.getAllOrganizations();
this.disableSend = organizations.some(o => {
return o.enabled &&
o.status === OrganizationUserStatusType.Confirmed &&
o.usePolicies &&
!o.canManagePolicies &&
policies.some(p => p.organizationId === o.id && p.enabled);
});
this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend);
}

async load(filter: (send: SendView) => boolean = null) {
Expand Down
6 changes: 4 additions & 2 deletions common/src/abstractions/policy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPoli
import { Policy } from '../models/domain/policy';
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';

import { PolicyType } from '../enums/policyType';

import { ListResponse } from '../models/response/listResponse';
import { PolicyResponse } from '../models/response/policyResponse';

import { PolicyType } from '../enums/policyType';

export abstract class PolicyService {
policyCache: Policy[];

clearCache: () => void;
getAll: (type?: PolicyType) => Promise<Policy[]>;
getPolicyForOrganization: (policyType: PolicyType, organizationId: string) => Promise<Policy>;
replace: (policies: { [id: string]: PolicyData; }) => Promise<any>;
clear: (userId: string) => Promise<any>;
getMasterPasswordPolicyOptions: (policies?: Policy[]) => Promise<MasterPasswordPolicyOptions>;
evaluateMasterPassword: (passwordStrength: number, newPassword: string,
enforcedPolicyOptions?: MasterPasswordPolicyOptions) => boolean;
getResetPasswordPolicyOptions: (policies: Policy[], orgId: string) => [ResetPasswordPolicyOptions, boolean];
mapPoliciesFromToken: (policiesResponse: ListResponse<PolicyResponse>) => Policy[];
policyAppliesToUser: (policyType: PolicyType, policyFilter?: (policy: Policy) => boolean) => Promise<boolean>;
}
4 changes: 4 additions & 0 deletions common/src/models/domain/organization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,8 @@ export class Organization {
get canManageUsersPassword() {
return this.isAdmin || this.permissions.manageResetPassword;
}

get isExemptFromPolicies() {
return this.canManagePolicies;
}
}
31 changes: 31 additions & 0 deletions common/src/services/policy.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPoli
import { Policy } from '../models/domain/policy';
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';

import { OrganizationUserStatusType } from '../enums/organizationUserStatusType';
import { PolicyType } from '../enums/policyType';

import { ListResponse } from '../models/response/listResponse';
Expand Down Expand Up @@ -47,6 +48,11 @@ export class PolicyService implements PolicyServiceAbstraction {
}
}

async getPolicyForOrganization(policyType: PolicyType, organizationId: string): Promise<Policy> {
const policies = await this.getAll(policyType);
return policies.find(p => p.organizationId === organizationId);
}

async replace(policies: { [id: string]: PolicyData; }): Promise<any> {
const userId = await this.userService.getUserId();
await this.storageService.save(Keys.policiesPrefix + userId, policies);
Expand Down Expand Up @@ -164,4 +170,29 @@ export class PolicyService implements PolicyServiceAbstraction {
const policiesData = policiesResponse.data.map(p => new PolicyData(p));
return policiesData.map(p => new Policy(p));
}

async policyAppliesToUser(policyType: PolicyType, policyFilter?: (policy: Policy) => boolean) {
if (policyFilter == null) {
policyFilter = (policy: Policy) => true;
}

const policies = await this.getAll(policyType);
const organizations = await this.userService.getAllOrganizations();

const filteredPolicies = policies
.filter(p =>
p.enabled &&
p.type === policyType &&
policyFilter(p))
.map(p => p.organizationId);

const policySet = new Set(filteredPolicies);

return organizations.some(o =>
o.enabled &&
o.status >= OrganizationUserStatusType.Accepted &&
o.usePolicies &&
!o.isExemptFromPolicies &&
policySet.has(o.id));
}
}

0 comments on commit 30419a6

Please sign in to comment.