change orgId input to masterPasswordPolicyOptions (#9833)
This commit is contained in:
parent
5a74371672
commit
31e5337ecf
|
@ -1,7 +1,7 @@
|
||||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||||
<auth-password-callout
|
<auth-password-callout
|
||||||
*ngIf="masterPasswordPolicy"
|
*ngIf="masterPasswordPolicyOptions"
|
||||||
[policy]="masterPasswordPolicy"
|
[policy]="masterPasswordPolicyOptions"
|
||||||
></auth-password-callout>
|
></auth-password-callout>
|
||||||
|
|
||||||
<div class="tw-mb-6">
|
<div class="tw-mb-6">
|
||||||
|
|
|
@ -3,17 +3,12 @@ import { ReactiveFormsModule, FormBuilder, Validators } from "@angular/forms";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
||||||
import {
|
import { DEFAULT_KDF_CONFIG } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||||
DEFAULT_KDF_CONFIG,
|
|
||||||
PBKDF2KdfConfig,
|
|
||||||
} from "@bitwarden/common/auth/models/domain/kdf-config";
|
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
import { MasterKey } from "@bitwarden/common/types/key";
|
|
||||||
import {
|
import {
|
||||||
AsyncActionsModule,
|
AsyncActionsModule,
|
||||||
ButtonModule,
|
ButtonModule,
|
||||||
|
@ -29,12 +24,7 @@ import { InputsFieldMatch } from "../../../../angular/src/auth/validators/inputs
|
||||||
import { SharedModule } from "../../../../components/src/shared";
|
import { SharedModule } from "../../../../components/src/shared";
|
||||||
import { PasswordCalloutComponent } from "../password-callout/password-callout.component";
|
import { PasswordCalloutComponent } from "../password-callout/password-callout.component";
|
||||||
|
|
||||||
export interface PasswordInputResult {
|
import { PasswordInputResult } from "./password-input-result";
|
||||||
masterKey: MasterKey;
|
|
||||||
masterKeyHash: string;
|
|
||||||
kdfConfig: PBKDF2KdfConfig;
|
|
||||||
hint: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
@ -58,14 +48,13 @@ export class InputPasswordComponent implements OnInit {
|
||||||
|
|
||||||
@Input({ required: true }) email: string;
|
@Input({ required: true }) email: string;
|
||||||
@Input() protected buttonText: string;
|
@Input() protected buttonText: string;
|
||||||
@Input() private orgId: string;
|
@Input() masterPasswordPolicyOptions: MasterPasswordPolicyOptions | null = null;
|
||||||
|
|
||||||
private minHintLength = 0;
|
private minHintLength = 0;
|
||||||
protected maxHintLength = 50;
|
protected maxHintLength = 50;
|
||||||
|
|
||||||
protected minPasswordLength = Utils.minimumPasswordLength;
|
protected minPasswordLength = Utils.minimumPasswordLength;
|
||||||
protected minPasswordMsg = "";
|
protected minPasswordMsg = "";
|
||||||
protected masterPasswordPolicy: MasterPasswordPolicyOptions;
|
|
||||||
protected passwordStrengthResult: any;
|
protected passwordStrengthResult: any;
|
||||||
protected showErrorSummary = false;
|
protected showErrorSummary = false;
|
||||||
protected showPassword = false;
|
protected showPassword = false;
|
||||||
|
@ -106,18 +95,16 @@ export class InputPasswordComponent implements OnInit {
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private policyService: PolicyService,
|
private policyService: PolicyService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private policyApiService: PolicyApiServiceAbstraction,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.masterPasswordPolicy = await this.policyApiService.getMasterPasswordPolicyOptsForOrgUser(
|
if (
|
||||||
this.orgId,
|
this.masterPasswordPolicyOptions != null &&
|
||||||
);
|
this.masterPasswordPolicyOptions.minLength > 0
|
||||||
|
) {
|
||||||
if (this.masterPasswordPolicy != null && this.masterPasswordPolicy.minLength > 0) {
|
|
||||||
this.minPasswordMsg = this.i18nService.t(
|
this.minPasswordMsg = this.i18nService.t(
|
||||||
"characterMinimum",
|
"characterMinimum",
|
||||||
this.masterPasswordPolicy.minLength,
|
this.masterPasswordPolicyOptions.minLength,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.minPasswordMsg = this.i18nService.t("characterMinimum", this.minPasswordLength);
|
this.minPasswordMsg = this.i18nService.t("characterMinimum", this.minPasswordLength);
|
||||||
|
@ -157,11 +144,11 @@ export class InputPasswordComponent implements OnInit {
|
||||||
|
|
||||||
// Check if password meets org policy requirements
|
// Check if password meets org policy requirements
|
||||||
if (
|
if (
|
||||||
this.masterPasswordPolicy != null &&
|
this.masterPasswordPolicyOptions != null &&
|
||||||
!this.policyService.evaluateMasterPassword(
|
!this.policyService.evaluateMasterPassword(
|
||||||
this.passwordStrengthResult.score,
|
this.passwordStrengthResult.score,
|
||||||
password,
|
password,
|
||||||
this.masterPasswordPolicy,
|
this.masterPasswordPolicyOptions,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
|
|
|
@ -22,8 +22,8 @@ the parent component to act on those values as needed.
|
||||||
`InputPasswordComponent` can create a master key.
|
`InputPasswordComponent` can create a master key.
|
||||||
- `buttonText` (optional) - an `i18n` translated string that can be used as button text (default
|
- `buttonText` (optional) - an `i18n` translated string that can be used as button text (default
|
||||||
text is "Set master password").
|
text is "Set master password").
|
||||||
- `orgId` (optional) - used to retreive and enforce the master password policy requirements for an
|
- `masterPasswordPolicyOptions` (optional) - used to display and enforce master password policy
|
||||||
org.
|
requirements.
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@ import { importProvidersFrom } from "@angular/core";
|
||||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||||
import { action } from "@storybook/addon-actions";
|
import { action } from "@storybook/addon-actions";
|
||||||
import { Meta, StoryObj, applicationConfig } from "@storybook/angular";
|
import { Meta, StoryObj, applicationConfig } from "@storybook/angular";
|
||||||
import { of } from "rxjs";
|
|
||||||
import { ZXCVBNResult } from "zxcvbn";
|
import { ZXCVBNResult } from "zxcvbn";
|
||||||
|
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
|
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
|
@ -17,22 +15,10 @@ import { PreloadedEnglishI18nModule } from "../../../../../apps/web/src/app/core
|
||||||
|
|
||||||
import { InputPasswordComponent } from "./input-password.component";
|
import { InputPasswordComponent } from "./input-password.component";
|
||||||
|
|
||||||
const mockMasterPasswordPolicyOptions = {
|
|
||||||
minComplexity: 4,
|
|
||||||
minLength: 14,
|
|
||||||
requireUpper: true,
|
|
||||||
requireLower: true,
|
|
||||||
requireNumbers: true,
|
|
||||||
requireSpecial: true,
|
|
||||||
} as MasterPasswordPolicyOptions;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Auth/Input Password",
|
title: "Auth/Input Password",
|
||||||
component: InputPasswordComponent,
|
component: InputPasswordComponent,
|
||||||
} as Meta;
|
decorators: [
|
||||||
|
|
||||||
const decorators = (options: { hasPolicy?: boolean }) => {
|
|
||||||
return [
|
|
||||||
applicationConfig({
|
applicationConfig({
|
||||||
providers: [
|
providers: [
|
||||||
importProvidersFrom(PreloadedEnglishI18nModule),
|
importProvidersFrom(PreloadedEnglishI18nModule),
|
||||||
|
@ -56,18 +42,9 @@ const decorators = (options: { hasPolicy?: boolean }) => {
|
||||||
openSimpleDialog: () => Promise.resolve(true),
|
openSimpleDialog: () => Promise.resolve(true),
|
||||||
} as Partial<DialogService>,
|
} as Partial<DialogService>,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
provide: PolicyApiServiceAbstraction,
|
|
||||||
useValue: {
|
|
||||||
getMasterPasswordPolicyOptsForOrgUser: () =>
|
|
||||||
options.hasPolicy ? mockMasterPasswordPolicyOptions : null,
|
|
||||||
} as Partial<PolicyService>,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
provide: PolicyService,
|
provide: PolicyService,
|
||||||
useValue: {
|
useValue: {
|
||||||
masterPasswordPolicyOptions$: () =>
|
|
||||||
options.hasPolicy ? of(mockMasterPasswordPolicyOptions) : null,
|
|
||||||
evaluateMasterPassword: (score) => {
|
evaluateMasterPassword: (score) => {
|
||||||
if (score < 4) {
|
if (score < 4) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -81,7 +58,6 @@ const decorators = (options: { hasPolicy?: boolean }) => {
|
||||||
useValue: {
|
useValue: {
|
||||||
getPasswordStrength: (password) => {
|
getPasswordStrength: (password) => {
|
||||||
let score = 0;
|
let score = 0;
|
||||||
|
|
||||||
if (password.length === 0) {
|
if (password.length === 0) {
|
||||||
score = null;
|
score = null;
|
||||||
} else if (password.length <= 4) {
|
} else if (password.length <= 4) {
|
||||||
|
@ -93,7 +69,6 @@ const decorators = (options: { hasPolicy?: boolean }) => {
|
||||||
} else {
|
} else {
|
||||||
score = 4;
|
score = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { score } as ZXCVBNResult;
|
return { score } as ZXCVBNResult;
|
||||||
},
|
},
|
||||||
} as Partial<PasswordStrengthServiceAbstraction>,
|
} as Partial<PasswordStrengthServiceAbstraction>,
|
||||||
|
@ -106,8 +81,18 @@ const decorators = (options: { hasPolicy?: boolean }) => {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
];
|
],
|
||||||
};
|
args: {
|
||||||
|
masterPasswordPolicyOptions: {
|
||||||
|
minComplexity: 4,
|
||||||
|
minLength: 14,
|
||||||
|
requireUpper: true,
|
||||||
|
requireLower: true,
|
||||||
|
requireNumbers: true,
|
||||||
|
requireSpecial: true,
|
||||||
|
} as MasterPasswordPolicyOptions,
|
||||||
|
},
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
type Story = StoryObj<InputPasswordComponent>;
|
type Story = StoryObj<InputPasswordComponent>;
|
||||||
|
|
||||||
|
@ -118,19 +103,13 @@ export const Default: Story = {
|
||||||
<auth-input-password></auth-input-password>
|
<auth-input-password></auth-input-password>
|
||||||
`,
|
`,
|
||||||
}),
|
}),
|
||||||
decorators: decorators({
|
|
||||||
hasPolicy: false,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WithPolicy: Story = {
|
export const WithPolicy: Story = {
|
||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: `
|
template: `
|
||||||
<auth-input-password></auth-input-password>
|
<auth-input-password [masterPasswordPolicyOptions]="masterPasswordPolicyOptions"></auth-input-password>
|
||||||
`,
|
`,
|
||||||
}),
|
}),
|
||||||
decorators: decorators({
|
|
||||||
hasPolicy: true,
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { PBKDF2KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||||
|
import { MasterKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
|
export interface PasswordInputResult {
|
||||||
|
masterKey: MasterKey;
|
||||||
|
masterKeyHash: string;
|
||||||
|
kdfConfig: PBKDF2KdfConfig;
|
||||||
|
hint: string;
|
||||||
|
}
|
Loading…
Reference in New Issue