diff --git a/backend/InTheKnow.Tests/SignInTests.cs b/backend/InTheKnow.Tests/SignInTests.cs index 5785a93..307aa5e 100644 --- a/backend/InTheKnow.Tests/SignInTests.cs +++ b/backend/InTheKnow.Tests/SignInTests.cs @@ -257,6 +257,16 @@ public async Task ResetRequests() Assert.Equal(3, await d.Db.ScalarAsync("SELECT count(*) FROM account_message WHERE kind = 'reset'")); } + // Passwords take any character: only the length is checked (Passwords.cs). + [Fact] + public async Task AnyCharacterInAPassword() + { + await using var d = await SignUpTests.HostAsync(); + const string password = "Zwölf café 🍕 Ωmega 漢字 \"'<&>"; + await Expect(await CompleteAsync(d, await ResetTokenAsync(d, d.S1.Email), password), HttpStatusCode.NoContent); + await Expect(await PasswordSignInAsync(d.H, d.S1.Email, password, "198.51.100.1"), HttpStatusCode.OK); + } + // US3-2, US3-3, SC-009. [Fact] public async Task CompleteReset() diff --git a/frontend/src/lib/components/Field.svelte b/frontend/src/lib/components/Field.svelte index e711990..4736fa0 100644 --- a/frontend/src/lib/components/Field.svelte +++ b/frontend/src/lib/components/Field.svelte @@ -1,6 +1,10 @@ @@ -20,6 +26,13 @@ {#if children} {@render children({ id, describedby, invalid: Boolean(error) })} + {:else if rest.type === 'password'} +
+ + +
{:else} {/if} @@ -67,6 +80,28 @@ .field :global(input:disabled) { background: var(--grey-100); } + .reveal { + position: relative; + } + /* Outweighs the general input rule above, which sets padding on both sides. */ + .field .reveal :global(input:not([type='checkbox'])) { + padding-right: 48px; + } + .reveal button { + position: absolute; + inset: 0 0 0 auto; + width: 48px; + display: grid; + place-items: center; + color: var(--text-muted); + background: none; + border: 0; + border-radius: var(--radius-md); + cursor: pointer; + } + .reveal button:hover { + color: var(--text-strong); + } .hint { font: var(--type-small); color: var(--text-muted); diff --git a/frontend/src/lib/i18n/en.ts b/frontend/src/lib/i18n/en.ts index 4a897b5..1bc937a 100644 --- a/frontend/src/lib/i18n/en.ts +++ b/frontend/src/lib/i18n/en.ts @@ -124,6 +124,7 @@ export const en = { password: 'Password', newPassword: 'New password', language: 'Language', + showPassword: 'Show password', rulesTitle: 'Your password needs:', ruleLength: '12 to 128 characters', ruleCommon: 'not to be a common password', diff --git a/frontend/src/lib/i18n/nl.ts b/frontend/src/lib/i18n/nl.ts index ac8f329..25f57fe 100644 --- a/frontend/src/lib/i18n/nl.ts +++ b/frontend/src/lib/i18n/nl.ts @@ -124,6 +124,7 @@ export const nl: Dict = { email: 'E-mailadres', password: 'Wachtwoord', newPassword: 'Nieuw wachtwoord', + showPassword: 'Wachtwoord tonen', language: 'Taal', rulesTitle: 'Je wachtwoord moet:', ruleLength: '12 tot 128 tekens lang zijn',