Move policy checks within policyService (#466)
* 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>
This commit is contained in:
parent
f02720a1c6
commit
30419a625f
|
@ -164,28 +164,20 @@ export class AddEditComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
const policies = await this.policyService.getAll(PolicyType.PersonalOwnership);
|
|
||||||
const myEmail = await this.userService.getEmail();
|
const myEmail = await this.userService.getEmail();
|
||||||
this.ownershipOptions.push({ name: myEmail, value: null });
|
this.ownershipOptions.push({ name: myEmail, value: null });
|
||||||
const orgs = await this.userService.getAllOrganizations();
|
const orgs = await this.userService.getAllOrganizations();
|
||||||
orgs.sort(Utils.getSortFunction(this.i18nService, 'name')).forEach(o => {
|
orgs.sort(Utils.getSortFunction(this.i18nService, 'name')).forEach(o => {
|
||||||
if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) {
|
if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) {
|
||||||
this.ownershipOptions.push({ name: o.name, value: o.id });
|
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();
|
this.writeableCollections = await this.loadCollections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
Output
|
Output
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { OrganizationUserStatusType } from 'jslib-common/enums/organizationUserStatusType';
|
|
||||||
import { PolicyType } from 'jslib-common/enums/policyType';
|
import { PolicyType } from 'jslib-common/enums/policyType';
|
||||||
import { SendType } from 'jslib-common/enums/sendType';
|
import { SendType } from 'jslib-common/enums/sendType';
|
||||||
|
|
||||||
|
@ -103,24 +102,9 @@ export class AddEditComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
const disableSendPolicies = await this.policyService.getAll(PolicyType.DisableSend);
|
this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend);
|
||||||
const organizations = await this.userService.getAllOrganizations();
|
this.disableHideEmail = await this.policyService.policyAppliesToUser(PolicyType.SendOptions,
|
||||||
this.disableSend = organizations.some(o => {
|
p => p.data.disableHideEmail);
|
||||||
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.canAccessPremium = await this.userService.canAccessPremium();
|
this.canAccessPremium = await this.userService.canAccessPremium();
|
||||||
this.emailVerified = await this.userService.getEmailVerified();
|
this.emailVerified = await this.userService.getEmailVerified();
|
||||||
|
|
|
@ -51,15 +51,7 @@ export class SendComponent implements OnInit {
|
||||||
protected policyService: PolicyService, protected userService: UserService) { }
|
protected policyService: PolicyService, protected userService: UserService) { }
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
const policies = await this.policyService.getAll(PolicyType.DisableSend);
|
this.disableSend = await this.policyService.policyAppliesToUser(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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async load(filter: (send: SendView) => boolean = null) {
|
async load(filter: (send: SendView) => boolean = null) {
|
||||||
|
|
|
@ -4,16 +4,17 @@ import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPoli
|
||||||
import { Policy } from '../models/domain/policy';
|
import { Policy } from '../models/domain/policy';
|
||||||
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';
|
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';
|
||||||
|
|
||||||
import { PolicyType } from '../enums/policyType';
|
|
||||||
|
|
||||||
import { ListResponse } from '../models/response/listResponse';
|
import { ListResponse } from '../models/response/listResponse';
|
||||||
import { PolicyResponse } from '../models/response/policyResponse';
|
import { PolicyResponse } from '../models/response/policyResponse';
|
||||||
|
|
||||||
|
import { PolicyType } from '../enums/policyType';
|
||||||
|
|
||||||
export abstract class PolicyService {
|
export abstract class PolicyService {
|
||||||
policyCache: Policy[];
|
policyCache: Policy[];
|
||||||
|
|
||||||
clearCache: () => void;
|
clearCache: () => void;
|
||||||
getAll: (type?: PolicyType) => Promise<Policy[]>;
|
getAll: (type?: PolicyType) => Promise<Policy[]>;
|
||||||
|
getPolicyForOrganization: (policyType: PolicyType, organizationId: string) => Promise<Policy>;
|
||||||
replace: (policies: { [id: string]: PolicyData; }) => Promise<any>;
|
replace: (policies: { [id: string]: PolicyData; }) => Promise<any>;
|
||||||
clear: (userId: string) => Promise<any>;
|
clear: (userId: string) => Promise<any>;
|
||||||
getMasterPasswordPolicyOptions: (policies?: Policy[]) => Promise<MasterPasswordPolicyOptions>;
|
getMasterPasswordPolicyOptions: (policies?: Policy[]) => Promise<MasterPasswordPolicyOptions>;
|
||||||
|
@ -21,4 +22,5 @@ export abstract class PolicyService {
|
||||||
enforcedPolicyOptions?: MasterPasswordPolicyOptions) => boolean;
|
enforcedPolicyOptions?: MasterPasswordPolicyOptions) => boolean;
|
||||||
getResetPasswordPolicyOptions: (policies: Policy[], orgId: string) => [ResetPasswordPolicyOptions, boolean];
|
getResetPasswordPolicyOptions: (policies: Policy[], orgId: string) => [ResetPasswordPolicyOptions, boolean];
|
||||||
mapPoliciesFromToken: (policiesResponse: ListResponse<PolicyResponse>) => Policy[];
|
mapPoliciesFromToken: (policiesResponse: ListResponse<PolicyResponse>) => Policy[];
|
||||||
|
policyAppliesToUser: (policyType: PolicyType, policyFilter?: (policy: Policy) => boolean) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,4 +135,8 @@ export class Organization {
|
||||||
get canManageUsersPassword() {
|
get canManageUsersPassword() {
|
||||||
return this.isAdmin || this.permissions.manageResetPassword;
|
return this.isAdmin || this.permissions.manageResetPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isExemptFromPolicies() {
|
||||||
|
return this.canManagePolicies;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPoli
|
||||||
import { Policy } from '../models/domain/policy';
|
import { Policy } from '../models/domain/policy';
|
||||||
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';
|
import { ResetPasswordPolicyOptions } from '../models/domain/resetPasswordPolicyOptions';
|
||||||
|
|
||||||
|
import { OrganizationUserStatusType } from '../enums/organizationUserStatusType';
|
||||||
import { PolicyType } from '../enums/policyType';
|
import { PolicyType } from '../enums/policyType';
|
||||||
|
|
||||||
import { ListResponse } from '../models/response/listResponse';
|
import { ListResponse } from '../models/response/listResponse';
|
||||||
|
@ -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> {
|
async replace(policies: { [id: string]: PolicyData; }): Promise<any> {
|
||||||
const userId = await this.userService.getUserId();
|
const userId = await this.userService.getUserId();
|
||||||
await this.storageService.save(Keys.policiesPrefix + userId, policies);
|
await this.storageService.save(Keys.policiesPrefix + userId, policies);
|
||||||
|
@ -164,4 +170,29 @@ export class PolicyService implements PolicyServiceAbstraction {
|
||||||
const policiesData = policiesResponse.data.map(p => new PolicyData(p));
|
const policiesData = policiesResponse.data.map(p => new PolicyData(p));
|
||||||
return policiesData.map(p => new Policy(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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue