80 lines
2.2 KiB
TypeScript
80 lines
2.2 KiB
TypeScript
import { Router } from 'express';
|
|
import { users } from '../db';
|
|
import { requireAuth } from '../middleware/requireAuth';
|
|
import { requireAdmin, requireSuperAdmin } from '../middleware/requireAdmin';
|
|
|
|
const router = Router();
|
|
|
|
// All admin routes require a valid JWT first
|
|
router.use( requireAuth );
|
|
|
|
// GET /api/admin/users — list all users (admin + superadmin)
|
|
router.get( '/users', requireAdmin, ( _req, res ) =>
|
|
{
|
|
const all = users.all().map( u => (
|
|
{
|
|
id: u.id,
|
|
email: u.email,
|
|
roles: u.roles,
|
|
createdAt: u.createdAt
|
|
} ) );
|
|
res.json( all );
|
|
} );
|
|
|
|
// PATCH /api/admin/users/:id/products — set products on a user (superadmin only)
|
|
router.patch( '/users/:id/products', requireSuperAdmin, ( req, res ) =>
|
|
{
|
|
const { id } = req.params;
|
|
const target = users.findById( id );
|
|
if ( !target )
|
|
{
|
|
res.status( 404 ).json( { error: 'User not found' } );
|
|
return;
|
|
}
|
|
|
|
const { products } = req.body as { products?: string[] };
|
|
if ( !Array.isArray( products ) || !products.every( p => typeof p === 'string' ) )
|
|
{
|
|
res.status( 400 ).json( { error: 'products must be an array of strings' } );
|
|
return;
|
|
}
|
|
|
|
const now = new Date().toISOString();
|
|
const userProducts = products.map( productId => ( { id: productId, acquiredAt: now, source: 'manual' } ) );
|
|
users.update( id, { products: userProducts } );
|
|
res.json( { id, products: userProducts } );
|
|
} );
|
|
|
|
// PATCH /api/admin/users/:id/roles — set roles on a user (superadmin only)
|
|
router.patch( '/users/:id/roles', requireSuperAdmin, ( req, res ) =>
|
|
{
|
|
const { id } = req.params;
|
|
|
|
if ( id === req.auth!.userId )
|
|
{
|
|
res.status( 400 ).json( { error: 'Cannot change your own roles' } );
|
|
return;
|
|
}
|
|
|
|
const target = users.findById( id );
|
|
if ( !target )
|
|
{
|
|
res.status( 404 ).json( { error: 'User not found' } );
|
|
return;
|
|
}
|
|
|
|
const { roles } = req.body as { roles?: string[] };
|
|
if ( !Array.isArray( roles ) )
|
|
{
|
|
res.status( 400 ).json( { error: 'roles must be an array' } );
|
|
return;
|
|
}
|
|
|
|
// Always keep 'user' as base role
|
|
const next = roles.includes( 'user' ) ? roles : [ ...roles, 'user' ];
|
|
users.update( id, { roles: next } );
|
|
res.json( { id, roles: next } );
|
|
} );
|
|
|
|
export default router;
|