feat: add superadmin management
All checks were successful
CI / Validate frontend and API (push) Successful in 1m59s
CI / Build and publish Docker images (push) Successful in 22s

This commit is contained in:
Cauê Faleiros
2026-09-01 09:54:45 -03:00
parent 2dfca33758
commit a5055238b9
21 changed files with 366 additions and 74 deletions

View File

@@ -0,0 +1,49 @@
import type { FastifyPluginAsync } from 'fastify';
import { z } from 'zod';
import { pool } from '../db/pool.js';
const userParamsSchema = z.object({
userId: z.string().uuid(),
});
const updateUserSchema = z.object({
role: z.enum(['student', 'instructor', 'admin']).optional(),
isActive: z.boolean().optional(),
}).refine((input) => input.role !== undefined || input.isActive !== undefined, {
message: 'Provide at least one field to update',
});
export const adminRoutes: FastifyPluginAsync = async (app) => {
const adminAccess = { preHandler: app.requireRoles(['admin']) };
app.get('/users', adminAccess, async () => {
const result = await pool.query(
`select id, email, display_name as name, role, is_active as "isActive",
created_at as "createdAt"
from users
order by created_at desc`,
);
return { data: result.rows };
});
app.patch('/users/:userId', adminAccess, async (request, reply) => {
const { userId } = userParamsSchema.parse(request.params);
const input = updateUserSchema.parse(request.body);
if (userId === request.user.id && (input.role !== undefined && input.role !== 'admin' || input.isActive === false)) {
return reply.code(400).send({ error: 'You cannot remove your own superadmin access' });
}
const result = await pool.query(
`update users
set role = coalesce($2::user_role, role),
is_active = coalesce($3, is_active)
where id = $1
returning id, email, display_name as name, role, is_active as "isActive", created_at as "createdAt"`,
[userId, input.role ?? null, input.isActive ?? null],
);
const account = result.rows[0];
if (!account) return reply.code(404).send({ error: 'User not found' });
return { data: account };
});
};