change orgId input to masterPasswordPolicyOptions (#9833)

This commit is contained in:
rr-bw 2024-06-26 10:06:50 -07:00 committed by GitHub
parent 5a74371672
commit 31e5337ecf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 62 deletions

View File

@ -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">

View File

@ -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({

View File

@ -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 />

View File

@ -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,
}),
}; };

View File

@ -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;
}