feat(auth): migrate frontend from username to email-only authentication

- Login page: email input replaces username field (type=email, name=email)
- Login server action: reads email, uses i18n error for missing credentials
- AccountSection: email input (type=email) replaces username text field
- New user server action: sends email as required field, drops username
- UsersListPanel: displays and searches by email instead of username
- Admin edit user page: heading and delete confirm use email
- Profile page: fullName fallback uses email, drops @username display
- app.d.ts: email required on User, username removed
- Generated API types: AppUser.email required, username removed; CreateUserRequest.email required, username removed
- i18n: login_label_email, login_error_missing_credentials, admin_col_login updated (de/en/es)
- errors.ts: MISSING_CREDENTIALS → login_error_missing_credentials

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-18 21:34:46 +02:00
committed by marcel
parent 5e01db1c74
commit d816e94a90
19 changed files with 64 additions and 55 deletions

View File

@@ -33,6 +33,7 @@ export type ErrorCode =
| 'TAG_NOT_FOUND'
| 'TAG_MERGE_SELF'
| 'TAG_MERGE_INVALID_TARGET'
| 'MISSING_CREDENTIALS'
| 'UNAUTHORIZED'
| 'FORBIDDEN'
| 'VALIDATION_ERROR'
@@ -118,6 +119,8 @@ export function getErrorMessage(code: ErrorCode | string | undefined): string {
return m.error_tag_merge_self();
case 'TAG_MERGE_INVALID_TARGET':
return m.error_tag_merge_invalid_target();
case 'MISSING_CREDENTIALS':
return m.login_error_missing_credentials();
case 'UNAUTHORIZED':
return m.error_unauthorized();
case 'FORBIDDEN':

View File

@@ -1253,13 +1253,12 @@ export interface components {
AppUser: {
/** Format: uuid */
id: string;
username: string;
password?: string;
firstName?: string;
lastName?: string;
/** Format: date */
birthDate?: string;
email?: string;
email: string;
contact?: string;
enabled: boolean;
notifyOnReply: boolean;
@@ -1406,8 +1405,7 @@ export interface components {
blockIds?: string[];
};
CreateUserRequest: {
username?: string;
email?: string;
email: string;
initialPassword?: string;
groupIds?: string[];
firstName?: string;