Admin-controlled public registration toggle

User wants the admin to be able to open or close public self-registration
from inside the app instead of removing the registration page entirely.

Changes:
- Added registration_open boolean column to app_settings (default true)
- Exposed registrationOpen in AppSettings + UpdateAppSettingsBody schemas
  in openapi.yaml; regenerated client + zod
- Backend: POST /api/auth/register now returns 403 "Registration is
  closed" when the flag is off (checks settings row before any other work)
- Admin Site Settings panel now has a switch to toggle public
  registration on/off, with bilingual label + helper text
- Login page hides the "Create account" link when registration is closed
- Register page short-circuits to a friendly "registration closed"
  card with a Back to Login button when the flag is off (and redirects
  if the user lands there directly)
- Added bilingual locale keys: registrationOpen, registrationOpenHint,
  registrationClosed

Verified: GET /api/settings returns the new field; POST /api/auth/register
returns 403 when closed and proceeds normally when open. Both typecheck
suites pass.
This commit is contained in:
riyadhafraa
2026-04-20 11:33:06 +00:00
parent fac89031c3
commit 99f2c84a84
10 changed files with 78 additions and 16 deletions
+7
View File
@@ -6,6 +6,7 @@ import {
usersTable,
userRolesTable,
rolesTable,
appSettingsTable,
} from "@workspace/db";
import { requireAuth, getUserRoles } from "../middlewares/auth";
import { RegisterBody, LoginBody, UpdateLanguageBody } from "@workspace/api-zod";
@@ -34,6 +35,12 @@ router.post("/auth/register", async (req, res): Promise<void> => {
return;
}
const [settings] = await db.select().from(appSettingsTable).where(eq(appSettingsTable.id, 1));
if (settings && !settings.registrationOpen) {
res.status(403).json({ error: "Registration is closed" });
return;
}
const { username, email, password, displayNameAr, displayNameEn, preferredLanguage } = parsed.data;
const existing = await db