diff --git a/test/api/v3/integration/user/auth/POST-auth_reset-password-set-new-one.js b/test/api/v3/integration/user/auth/POST-auth_reset-password-set-new-one.js index ed3cf27e63..51cea8bb89 100644 --- a/test/api/v3/integration/user/auth/POST-auth_reset-password-set-new-one.js +++ b/test/api/v3/integration/user/auth/POST-auth_reset-password-set-new-one.js @@ -189,6 +189,28 @@ describe('POST /user/auth/reset-password-set-new-one', () => { }); }); + it('renders the error page if the password is too short', async () => { + const user = await generateUser(); + + const code = encrypt(JSON.stringify({ + userId: user._id, + expiresAt: moment().add({ days: 1 }), + })); + await user.update({ + 'auth.local.passwordResetCode': code, + }); + + await expect(api.post(`${endpoint}`, { + newPassword: 'short', + confirmPassword: 'short', + code, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); + it('renders the success page and save the user', async () => { const user = await generateUser(); diff --git a/test/api/v3/integration/user/auth/POST-register_local.test.js b/test/api/v3/integration/user/auth/POST-register_local.test.js index 896e20a0c0..e435d77dd0 100644 --- a/test/api/v3/integration/user/auth/POST-register_local.test.js +++ b/test/api/v3/integration/user/auth/POST-register_local.test.js @@ -326,6 +326,24 @@ describe('POST /user/auth/local/register', () => { }); }); + it('requires minimum length for the password', async () => { + const username = generateRandomUserName(); + const email = `${username}@example.com`; + const password = '1234567'; + const confirmPassword = '1234567'; + + await expect(api.post('/user/auth/local/register', { + username, + email, + password, + confirmPassword, + })).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); + it('requires a username', async () => { const email = `${generateRandomUserName()}@example.com`; const password = 'password'; diff --git a/test/api/v3/integration/user/auth/PUT-user_update_password.test.js b/test/api/v3/integration/user/auth/PUT-user_update_password.test.js index a46eb0f916..94fbd4f3e2 100644 --- a/test/api/v3/integration/user/auth/PUT-user_update_password.test.js +++ b/test/api/v3/integration/user/auth/PUT-user_update_password.test.js @@ -82,6 +82,20 @@ describe('PUT /user/auth/update-password', async () => { }); }); + it('returns an error when newPassword is too short', async () => { + const body = { + password, + newPassword: '1234567', + confirmPassword: '1234567', + }; + + await expect(user.put(ENDPOINT, body)).to.eventually.be.rejected.and.eql({ + code: 400, + error: 'BadRequest', + message: t('invalidReqParams'), + }); + }); + it('returns an error when confirmPassword is missing', async () => { const body = { password, diff --git a/website/client/src/assets/scss/button.scss b/website/client/src/assets/scss/button.scss index bc649e1dc5..0a2220a215 100644 --- a/website/client/src/assets/scss/button.scss +++ b/website/client/src/assets/scss/button.scss @@ -20,7 +20,7 @@ @include btn-focus-hover-shadow(); } - &:hover:not(.btn-flat):not(.disabled) { + &:hover:not(.btn-flat):not(.disabled):not(:disabled) { @include btn-focus-hover-shadow(); border-color: transparent; } @@ -49,7 +49,7 @@ background: $purple-200; } - &:hover:not(:disabled), &:active, &.active, &:focus { + &:hover:not(:disabled):not(.disabled), &:active:not(:disabled):not(.disabled), &.active:not(:disabled):not(.disabled), &:focus:not(:disabled):not(.disabled) { background: #5d3b9c !important; color: $white; } @@ -59,7 +59,7 @@ color: $gray-50; background: $white !important; - &:hover:not(:disabled):not(.disabled), &:active, &.active, &:focus { + &:hover:not(:disabled):not(.disabled), &:active:not(:disabled):not(.disabled), &.active:not(:disabled):not(.disabled), &:focus:not(:disabled):not(.disabled) { color: $purple-200 !important; } @@ -80,7 +80,7 @@ background: $green-100; } - &:hover:not(:disabled), &:active, &.active { + &:hover:not(:disabled):not(.disabled), &:active:not(:disabled):not(.disabled), &.active:not(:disabled):not(.disabled) { background: $green-50; } } @@ -96,8 +96,12 @@ background: $blue-50; } - &:hover:not(:disabled), &:active, &.active { - background: $blue-100; + &:hover:not(:disabled):not(.disabled) { + background-color: $blue-100; + } + + &:active:not(:disabled):not(.disabled), &.active:not(:disabled):not(.disabled) { + background: $blue-50; } } @@ -108,7 +112,11 @@ background: $red-50; } - &:hover:not(:disabled), &:active, &.active { + &:hover:not(:disabled):not(.disabled) { + background: $red-100; + } + + &:active:not(:disabled):not(.disabled), &.active:not(:disabled):not(.disabled) { background: $red-100; } } diff --git a/website/client/src/assets/scss/form.scss b/website/client/src/assets/scss/form.scss index 78b7e5397a..2e5934f5d5 100644 --- a/website/client/src/assets/scss/form.scss +++ b/website/client/src/assets/scss/form.scss @@ -65,6 +65,7 @@ input, textarea, input.form-control, textarea.form-control { padding-right: 40px; background-image: url(~@/assets/svg/for-css/alert.svg); background-size: 16px 16px; + border-color: $red-100 !important; } } @@ -276,3 +277,19 @@ $bg-disabled-control: #34303a; .toggle-switch-container.no-margin { margin-top: 0 !important; } + + + +// Disable default style Firefox for invalid elements. +// Selectors taken from view-source:resource://gre-resources/forms.css on Firefox +:not(output):-moz-ui-invalid { + box-shadow: none; +} + +:not(output):-moz-ui-invalid:-moz-focusring { + box-shadow: none; +} + +output:-moz-ui-invalid { + color: inherit; +} diff --git a/website/client/src/components/auth/authForm.vue b/website/client/src/components/auth/authForm.vue index 7d3fa83e7d..993ed9cb10 100644 --- a/website/client/src/components/auth/authForm.vue +++ b/website/client/src/components/auth/authForm.vue @@ -46,6 +46,13 @@ :placeholder="$t('usernamePlaceholder')" :class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}" > +