mirror of
https://github.com/recklessop/zroc.git
synced 2026-07-02 21:13:15 -04:00
0500ac171c
- 61 files across zroc-ui/ and zroc-ova/ directories - Full content written for: config, auth, API layers, CSS, build files, OVA scripts, backend routes, charts, hooks, constants - Stubs in place for: page components, Sidebar, TopBar, docker-compose, authentik client, blueprint YAML, packer HCL, workflows, setup wizard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
118 lines
4.2 KiB
JavaScript
118 lines
4.2 KiB
JavaScript
// backend/routes/admin/users.js
|
|
'use strict';
|
|
|
|
const express = require('express');
|
|
const { authenticate, requireAdmin } = require('../../middleware/authenticate');
|
|
const authentik = require('../../authentik');
|
|
const logger = require('../../logger');
|
|
|
|
const router = express.Router();
|
|
|
|
router.use(authenticate, requireAdmin);
|
|
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
const { search = '', page = '1', pageSize = '50' } = req.query;
|
|
const result = await authentik.listUsers({
|
|
search,
|
|
page: parseInt(page, 10),
|
|
pageSize: parseInt(pageSize, 10),
|
|
});
|
|
res.json(result);
|
|
} catch (err) {
|
|
logger.error('[Users] List failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to list users', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.get('/:id', async (req, res) => {
|
|
try {
|
|
const user = await authentik.getUser(req.params.id);
|
|
res.json(user);
|
|
} catch (err) {
|
|
const status = err.response?.status === 404 ? 404 : 502;
|
|
res.status(status).json({ error: 'User not found', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.post('/', async (req, res) => {
|
|
try {
|
|
const { username, name, email, isActive = true, groups = [], password } = req.body;
|
|
if (!username || !name || !email) {
|
|
return res.status(400).json({ error: 'username, name, and email are required' });
|
|
}
|
|
const user = await authentik.createUser({ username, name, email, isActive, groups, password });
|
|
logger.info(`[Users] ${req.user.username} created user ${username}`);
|
|
res.status(201).json(user);
|
|
} catch (err) {
|
|
const detail = err.response?.data || err.message;
|
|
logger.error('[Users] Create failed:', detail);
|
|
res.status(err.response?.status === 400 ? 400 : 502).json({ error: 'Failed to create user', detail });
|
|
}
|
|
});
|
|
|
|
router.patch('/:id', async (req, res) => {
|
|
try {
|
|
const { name, email, isActive, groups } = req.body;
|
|
const user = await authentik.updateUser(req.params.id, { name, email, isActive, groups });
|
|
logger.info(`[Users] ${req.user.username} updated user ${user.username}`);
|
|
res.json(user);
|
|
} catch (err) {
|
|
logger.error('[Users] Update failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to update user', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.delete('/:id', async (req, res) => {
|
|
try {
|
|
const targetId = parseInt(req.params.id, 10);
|
|
if (String(targetId) === String(req.user.id) || req.user.username === 'akadmin') {
|
|
return res.status(400).json({ error: 'Cannot delete your own account or the akadmin account' });
|
|
}
|
|
await authentik.deleteUser(targetId);
|
|
logger.info(`[Users] ${req.user.username} deleted user ${targetId}`);
|
|
res.status(204).send();
|
|
} catch (err) {
|
|
logger.error('[Users] Delete failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to delete user', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.post('/:id/set-password', async (req, res) => {
|
|
try {
|
|
const { password } = req.body;
|
|
if (!password || password.length < 8) {
|
|
return res.status(400).json({ error: 'Password must be at least 8 characters' });
|
|
}
|
|
await authentik.setPassword(req.params.id, password);
|
|
logger.info(`[Users] ${req.user.username} reset password for user ${req.params.id}`);
|
|
res.json({ success: true });
|
|
} catch (err) {
|
|
logger.error('[Users] Password reset failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to set password', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.post('/:id/setup-2fa', async (req, res) => {
|
|
try {
|
|
const { setupUrl, qrDataUrl } = await authentik.generateTwoFactorSetupLink(req.params.id);
|
|
logger.info(`[Users] ${req.user.username} generated 2FA setup link for user ${req.params.id}`);
|
|
res.json({ setupUrl, qrDataUrl });
|
|
} catch (err) {
|
|
logger.error('[Users] 2FA setup failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to generate 2FA setup link', detail: err.message });
|
|
}
|
|
});
|
|
|
|
router.get('/meta/groups', async (req, res) => {
|
|
try {
|
|
const groups = await authentik.listGroups();
|
|
res.json(groups);
|
|
} catch (err) {
|
|
logger.error('[Users] Groups list failed:', err.message);
|
|
res.status(502).json({ error: 'Failed to list groups', detail: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|