Enforce master password policy (#79)
* Enforce master password policy * Updated based on requested changes/discussions
This commit is contained in:
parent
0f699515a4
commit
6210396aa9
|
@ -1,6 +1,7 @@
|
|||
import { PolicyData } from '../models/data/policyData';
|
||||
|
||||
import { Policy } from '../models/domain/policy';
|
||||
import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPolicyOptions'
|
||||
import { Policy } from '../models/domain/policy'
|
||||
|
||||
import { PolicyType } from '../enums/policyType';
|
||||
|
||||
|
@ -11,4 +12,7 @@ export abstract class PolicyService {
|
|||
getAll: (type?: PolicyType) => Promise<Policy[]>;
|
||||
replace: (policies: { [id: string]: PolicyData; }) => Promise<any>;
|
||||
clear: (userId: string) => Promise<any>;
|
||||
getMasterPasswordPolicyOptions: () => Promise<MasterPasswordPolicyOptions>;
|
||||
evaluateMasterPassword: (passwordStrength: number, newPassword: string,
|
||||
enforcedPolicyOptions?: MasterPasswordPolicyOptions) => boolean;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import Domain from './domainBase';
|
||||
|
||||
export class MasterPasswordPolicyOptions extends Domain {
|
||||
minComplexity: number = 0;
|
||||
minLength: number = 0;
|
||||
requireUpper: boolean = false;
|
||||
requireLower: boolean = false;
|
||||
requireNumbers: boolean = false;
|
||||
requireSpecial: boolean = false;
|
||||
}
|
|
@ -5,6 +5,7 @@ import { UserService } from '../abstractions/user.service';
|
|||
import { PolicyData } from '../models/data/policyData';
|
||||
|
||||
import { Policy } from '../models/domain/policy';
|
||||
import { MasterPasswordPolicyOptions } from '../models/domain/masterPasswordPolicyOptions'
|
||||
|
||||
import { PolicyType } from '../enums/policyType';
|
||||
|
||||
|
@ -52,4 +53,89 @@ export class PolicyService implements PolicyServiceAbstraction {
|
|||
await this.storageService.remove(Keys.policiesPrefix + userId);
|
||||
this.policyCache = null;
|
||||
}
|
||||
|
||||
async getMasterPasswordPolicyOptions(policies?: Policy[]): Promise<MasterPasswordPolicyOptions> {
|
||||
let enforcedOptions: MasterPasswordPolicyOptions = null;
|
||||
|
||||
if (policies == null) {
|
||||
policies = await this.getAll(PolicyType.MasterPassword);
|
||||
} else {
|
||||
policies = policies.filter((p) => p.type === PolicyType.MasterPassword);
|
||||
}
|
||||
|
||||
if (policies == null || policies.length === 0) {
|
||||
return enforcedOptions;
|
||||
}
|
||||
|
||||
policies.forEach((currentPolicy) => {
|
||||
if (!currentPolicy.enabled || currentPolicy.data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enforcedOptions == null) {
|
||||
enforcedOptions = new MasterPasswordPolicyOptions();
|
||||
}
|
||||
|
||||
if (currentPolicy.data.minComplexity != null
|
||||
&& currentPolicy.data.minComplexity > enforcedOptions.minComplexity) {
|
||||
enforcedOptions.minComplexity = currentPolicy.data.minComplexity;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.minLength != null
|
||||
&& currentPolicy.data.minLength > enforcedOptions.minLength) {
|
||||
enforcedOptions.minLength = currentPolicy.data.minLength;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireUpper) {
|
||||
enforcedOptions.requireUpper = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireLower) {
|
||||
enforcedOptions.requireLower = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireNumbers) {
|
||||
enforcedOptions.requireNumbers = true;
|
||||
}
|
||||
|
||||
if (currentPolicy.data.requireSpecial) {
|
||||
enforcedOptions.requireSpecial = true;
|
||||
}
|
||||
});
|
||||
|
||||
return enforcedOptions;
|
||||
}
|
||||
|
||||
evaluateMasterPassword(passwordStrength: number, newPassword: string,
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions): boolean {
|
||||
if (enforcedPolicyOptions == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.minComplexity > 0 && enforcedPolicyOptions.minComplexity > passwordStrength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.minLength > 0 && enforcedPolicyOptions.minLength > newPassword.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.requireUpper && newPassword.toLocaleLowerCase() === newPassword) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.requireLower && newPassword.toLocaleUpperCase() === newPassword) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.requireNumbers && !(/[0-9]/.test(newPassword))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enforcedPolicyOptions.requireSpecial && !(/[!@#$%\^&*]/g.test(newPassword))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue