Add 2FA, email + password reset, and batch-7 pages

Auth (hand-built on the auth core):
- 2FA: User model gains two_factor_secret/recovery_codes/confirmed_at (+ idempotent
  MariaDB migration). authorize() requires a valid TOTP code when 2FA is confirmed
  (secret decrypted via Laravel APP_KEY, fail-closed). Two-step login (precheckLogin
  reveals the code field). /settings/2fa enable/confirm/disable flow.
- Password reset: nodemailer email service; PasswordReset model + migration;
  /forgot (request, generic response) + /reset (token sha256 + 1h TTL, sets argon2id
  hash). Login links to forgot.

Batch 7 (parallel agents): /admin/commandocentrum (RCON controls + emulator_errors),
social write actions (friend request + guild forum new thread), /help/[category],
/badges (public). env: APP_KEY, APP_URL, SMTP_*. Nav extended.

Verified: tsc exit 0, vitest 48/48, next build exit 0 (64 page routes).
This commit is contained in:
Simo committed 2026-06-28 14:25:19 +02:00
1 parent 486ce51559
commit e668fa85ec
24 files changed
+1223 -34

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
-- Fortify-style 2FA columns on the emulator users table. Idempotent (MariaDB).
-- AtomCMS installs already have these; this only adds them when missing.
ALTER TABLE users
ADD COLUMN IF NOT EXISTS two_factor_secret TEXT NULL,
ADD COLUMN IF NOT EXISTS two_factor_recovery_codes TEXT NULL,
ADD COLUMN IF NOT EXISTS two_factor_confirmed_at TIMESTAMP NULL;
@@ -0,0 +1,7 @@
-- CMS password reset tokens (Laravel-compatible). Idempotent.
CREATE TABLE IF NOT EXISTS password_resets (
email VARCHAR(255) NOT NULL,
token VARCHAR(255) NOT NULL,
created_at TIMESTAMP NULL,
PRIMARY KEY (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+14
View File
@@ -60,6 +60,10 @@ model User {
secretKey String? @map("secret_key") @db.VarChar(40)
pincode String? @db.VarChar(11)
extraRank Int? @map("extra_rank")
// CMS-added (Laravel Fortify) 2FA columns on the users table.
twoFactorSecret String? @map("two_factor_secret") @db.Text
twoFactorRecoveryCodes String? @map("two_factor_recovery_codes") @db.Text
twoFactorConfirmedAt DateTime? @map("two_factor_confirmed_at") @db.Timestamp(0)
@@map("users")
}
@@ -101,6 +105,16 @@ model WebsiteSetting {
@@map("website_settings")
}
/// CMS-owned password reset tokens (Laravel-compatible table). Created via
/// prisma/migrations if absent.
model PasswordReset {
email String @id @db.VarChar(255)
token String @db.VarChar(255)
createdAt DateTime? @map("created_at") @db.Timestamp(0)
@@map("password_resets")
}
// === GENERATED MODELS (assembled from default.sql + Laravel migrations) ===
// 186 tables. Regenerated by assemble-schema.mjs — edit the
// generator instead of hand-editing below.