feat(registration): add email confirmation UI
Build, Test & Push Frontend / quality-check (push) Successful in 26s
Build, Test & Push Frontend / docker (push) Successful in 31s

New ConfirmEmailPage for users to verify their email and set password.
Resend form on registration and error pages. Registration form no
longer asks for a password. Confirmation requires a button click. The
admin list marks unconfirmed requests and offers only delete for them.
This commit is contained in:
lobo committed 2026-10-01 16:20:51 +02:00
1 parent 249973dd69
commit 6dda186bdf
15 files changed
+416 -50

No files matched your search

+19 -6
View File
@@ -1,5 +1,5 @@
import {describe, expect, it} from 'vitest';
import {registrationSchema, settingsSchema} from './validation.js';
import {confirmEmailSchema, registrationSchema, settingsSchema} from './validation.js';
const settings = () => ({useDarkTheme: true, language: 'de'});
@@ -7,7 +7,7 @@ describe('Steam ID', () => {
it('is no form field any more: it comes only from "Sign in through Steam"', () => {
expect(settingsSchema.parse({...settings(), steamId: '76561198005679788'})).not.toHaveProperty('steamId');
expect(registrationSchema.parse({
email: 'a@b.de', password: 'password1', passwordConfirmation: 'password1',
email: 'a@b.de',
steamId: '76561198005679788',
})).not.toHaveProperty('steamId');
});
@@ -30,11 +30,24 @@ describe('displayName validation', () => {
});
describe('registration password', () => {
describe('confirm page password', () => {
it('rejects a password over 72 UTF-8 bytes, as Auth does', () => {
const password = 'é'.repeat(37);
expect(registrationSchema.safeParse({
email: 'a@b.de', password, passwordConfirmation: password,
}).success).toBe(false);
expect(confirmEmailSchema.safeParse({password, passwordConfirmation: password}).success).toBe(false);
});
it('rejects a short password and one that differs from its repeat', () => {
expect(confirmEmailSchema.safeParse({password: 'short', passwordConfirmation: 'short'}).success).toBe(false);
expect(confirmEmailSchema.safeParse({password: 'password1', passwordConfirmation: 'password2'}).success).toBe(false);
});
it('takes a good password', () => {
expect(confirmEmailSchema.safeParse({password: 'password1', passwordConfirmation: 'password1'}).success).toBe(true);
});
});
describe('registration', () => {
it('has no password field', () => {
expect(registrationSchema.parse({email: 'a@b.de', password: 'password1'})).not.toHaveProperty('password');
});
});