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',