refactor(auth): remove dead duplicate admin routes from auth.cts
The 'ADMIN ROUTES (MOUNTED AT /api/admin)' section was false — auth.cts is mounted only at /api/auth, and the client calls the canonical copies in admin.cts via /api/admin/*. The duplicates were unreachable dead code, and /api/auth/has-users was additionally exposed without authentication. Verified: no callers of /api/auth/has-users or /api/auth/users anywhere. (QA-B17-01) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3c82c30f3c
commit
73915d38ce
|
|
@ -31,7 +31,7 @@ const {
|
|||
} = require('../services/authService.cts');
|
||||
const { decryptSecret } = require('../services/encryptionService.cts');
|
||||
const { getCsrfToken } = require('../middleware/csrf.cts');
|
||||
const { requireAuth, requireAdmin } = require('../middleware/requireAuth.cts');
|
||||
const { requireAuth } = require('../middleware/requireAuth.cts');
|
||||
const { getPublicOidcInfo } = require('../services/oidcService.cts');
|
||||
const { ValidationError, formatError } = require('../utils/apiError.cts');
|
||||
const { standardizeError } = require('../middleware/errorFormatter.cts');
|
||||
|
|
@ -537,76 +537,6 @@ router.post('/change-password', passwordLimiter, requireAuth, async (req: Req, r
|
|||
}
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────
|
||||
// ADMIN ROUTES (MOUNTED AT /api/admin)
|
||||
// ─────────────────────────────────────────
|
||||
|
||||
// GET /api/admin/has-users
|
||||
router.get('/has-users', (req: Req, res: Res) => {
|
||||
const count = getDb().prepare("SELECT COUNT(*) AS n FROM users WHERE role = 'user'").get().n;
|
||||
|
||||
res.json({ has_users: count > 0 });
|
||||
});
|
||||
|
||||
// GET /api/admin/users
|
||||
router.get('/users', requireAuth, requireAdmin, (req: Req, res: Res) => {
|
||||
const users = getDb()
|
||||
.prepare(
|
||||
'SELECT id, username, role, must_change_password, first_login, created_at FROM users ORDER BY role DESC, username ASC',
|
||||
)
|
||||
.all();
|
||||
|
||||
res.json(users);
|
||||
});
|
||||
|
||||
// POST /api/admin/users
|
||||
router.post('/users', requireAuth, requireAdmin, async (req: Req, res: Res) => {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!username || username.length < 3) {
|
||||
return res
|
||||
.status(400)
|
||||
.json(
|
||||
standardizeError('Username must be at least 3 characters', 'VALIDATION_ERROR', 'username'),
|
||||
);
|
||||
}
|
||||
|
||||
if (!password || password.length < 8) {
|
||||
return res
|
||||
.status(400)
|
||||
.json(
|
||||
standardizeError('Password must be at least 8 characters', 'VALIDATION_ERROR', 'password'),
|
||||
);
|
||||
}
|
||||
|
||||
const db = getDb();
|
||||
|
||||
const existing = db.prepare('SELECT id FROM users WHERE username = ?').get(username);
|
||||
if (existing)
|
||||
return res.status(409).json(standardizeError('Username already taken', 'CONFLICT', 'username'));
|
||||
|
||||
try {
|
||||
const hash = await hashPassword(password);
|
||||
|
||||
const result = db
|
||||
.prepare(
|
||||
"INSERT INTO users (username, password_hash, role, first_login, last_seen_version) VALUES (?, ?, 'user', 1, ?)",
|
||||
)
|
||||
.run(username, hash, getAppVersion());
|
||||
|
||||
const created = db
|
||||
.prepare(
|
||||
'SELECT id, username, role, must_change_password, first_login, created_at FROM users WHERE id = ?',
|
||||
)
|
||||
.get(result.lastInsertRowid);
|
||||
|
||||
res.status(201).json(created);
|
||||
} catch (err) {
|
||||
log.error('[auth] create-user error:', err.message);
|
||||
res.status(500).json(standardizeError('Failed to create user', 'SERVER_ERROR'));
|
||||
}
|
||||
});
|
||||
|
||||
// ── WebAuthn / FIDO2 security key ─────────────────────────────────────────────
|
||||
|
||||
const {
|
||||
|
|
|
|||
Loading…
Reference in New Issue