Skip to content

Commit

Permalink
fix(foxy-customer-form): align password strength expectations with pa…
Browse files Browse the repository at this point in the history
…ssword generator parameters

Closes #168
  • Loading branch information
pheekus committed Sep 12, 2024
1 parent 770bd34 commit 3c3cab0
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -267,5 +267,15 @@ describe('InternalTextControl', () => {

button.click();
expect(control.testValue).to.match(/^[a-z0-9]{6}\|[a-z0-9]{6}$/);

control.generatorOptions = {
checkStrength: value => value === 'abc',
separator: '',
charset: 'abc',
length: 3,
};

button.click();
expect(control.testValue).to.equal('abc');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,22 @@ export class InternalPasswordControl extends InternalEditableControl {
})}
slot="suffix"
@click=${() => {
this._value = generateRandomPassword(this.generatorOptions ?? void 0);
let isStrong = false;
let newValue: string;
let attempts = 0;
do {
newValue = generateRandomPassword(this.generatorOptions ?? void 0);
isStrong = this.generatorOptions?.checkStrength?.(newValue) ?? true;
attempts++;
} while (!isStrong && attempts < 100);
if (isStrong) {
this._value = newValue;
} else {
throw new Error('Failed to generate a strong password.');
}
const field = this.renderRoot.querySelector('vaadin-password-field');
// @ts-expect-error: this is a private method but it's ok since the version is fixed
field?._setPasswordVisible(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export type GeneratorOptions = { length?: number; charset?: string; separator?: string };
export type GeneratorOptions = {
checkStrength?: (value: string) => boolean;
separator?: string;
charset?: string;
length?: number;
};

export function generateRandomPassword(opts?: GeneratorOptions): string {
const separator = opts?.separator ?? '-';
Expand Down
6 changes: 5 additions & 1 deletion src/elements/public/CustomerForm/CustomerForm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,17 @@ describe('CustomerForm', () => {

it('renders a password field for password', async () => {
const form = await fixture<CustomerForm>(html`<foxy-customer-form></foxy-customer-form>`);
const control = form.renderRoot.querySelector('[infer="password"]');
const control = form.renderRoot.querySelector<InternalPasswordControl>('[infer="password"]');

expect(control).to.exist;
expect(control).to.be.instanceOf(InternalPasswordControl);
expect(control).to.have.attribute('show-generator');
expect(control).to.have.attribute('placeholder', 'password.placeholder');
expect(control).to.have.attribute('helper-text', 'password.helper_text');
expect(control).to.have.property('generatorOptions');
expect(control).to.have.nested.property('generatorOptions.checkStrength');
expect(control?.generatorOptions?.checkStrength?.('123')).to.be.false;
expect(control?.generatorOptions?.checkStrength?.('mFveRh-RZ6ZHm-YlKlqX')).to.be.true;

form.data = await getTestData<Data>('./hapi/customers/0');
await form.requestUpdate();
Expand Down
6 changes: 6 additions & 0 deletions src/elements/public/CustomerForm/CustomerForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { VanillaHCaptchaWebComponent } from 'vanilla-hcaptcha';
import type { Data, Settings } from './types';
import type { PropertyDeclarations } from 'lit-element';
import type { ScopedElementsMap } from '@open-wc/scoped-elements';
import type { GeneratorOptions } from '../../internal/InternalPasswordControl/generateRandomPassword';
import type { TemplateResult } from 'lit-html';
import type { NucleonV8N } from '../NucleonElement/types';

Expand Down Expand Up @@ -83,6 +84,10 @@ export class CustomerForm extends Base<Data> {
/** Full `fx:customer_portal_settings` resource from Customer API. If present, switches this element into the Customer API mode, enabling client verification. */
settings: Settings | null = null;

private readonly __passwordGeneratorOptions: GeneratorOptions = {
checkStrength: value => passwordStrength(value).id >= 2,
};

private readonly __isAnonymousGetValue = () => {
return this.form?.is_anonymous === false ? 'false' : 'true';
};
Expand Down Expand Up @@ -188,6 +193,7 @@ export class CustomerForm extends Base<Data> {
helper-text=${this.__passwordHelperText}
infer="password"
show-generator
.generatorOptions=${this.__passwordGeneratorOptions}
>
</foxy-internal-password-control>
Expand Down

0 comments on commit 3c3cab0

Please sign in to comment.