diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 80371d1..fa37555 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -179,4 +179,68 @@ router.post('/change-password', asyncRoute(async (req, res) => { ok(res, '비밀번호가 변경되었습니다.'); })); +router.post('/diagnostics', asyncRoute(async (_req, res) => { + const tableResult = await query<{ + users_table: string | null; + user_roles_table: string | null; + sessions_table: string | null; + }>( + ` + SELECT + to_regclass('public.users')::text AS users_table, + to_regclass('public.user_roles')::text AS user_roles_table, + to_regclass('public.user_sessions')::text AS sessions_table + `, + ); + const tables = tableResult.rows[0]; + let users: Array<{ + username: string; + enabled: boolean; + locked: boolean; + must_change_password: boolean; + password_hash_length: number; + roles: string[]; + }> = []; + let userQueryError: string | undefined; + + if (tables?.users_table && tables.user_roles_table) { + try { + const userResult = await query<{ + username: string; + enabled: boolean; + locked: boolean; + must_change_password: boolean; + password_hash_length: number; + roles: string[]; + }>( + ` + SELECT + u.username, + u.enabled, + u.locked, + u.must_change_password, + length(u.password_hash) AS password_hash_length, + COALESCE(array_agg(ur.role) FILTER (WHERE ur.role IS NOT NULL), '{}') AS roles + FROM users u + LEFT JOIN user_roles ur ON ur.user_id = u.id + WHERE u.username IN ('admin', 'security', 'host', 'a', 's', 'h') + GROUP BY u.id + ORDER BY u.username + `, + ); + users = userResult.rows; + } catch (error) { + userQueryError = error instanceof Error ? error.message : String(error); + } + } + + ok(res, { + authApi: true, + checkedAt: new Date().toISOString(), + tables, + users, + userQueryError, + }); +})); + export const authRouter = router; diff --git a/server/routes/health.ts b/server/routes/health.ts index b569f36..034ca97 100644 --- a/server/routes/health.ts +++ b/server/routes/health.ts @@ -10,6 +10,8 @@ healthRouter.get('/health', (_req, res) => { ok(res, { status: 'UP', service: 'acs-node', + build: 'auth-seed-20260714', + authApi: true, }); });