feat(usuarios): supervisor puede invitar usuarios cliente

- Backend inviteUsuario: permite owner, cfo y supervisor
- Backend valida que supervisor solo pueda invitar rol cliente
- Backend addClienteAcceso: supervisor solo puede asignar contribuyentes
  que tenga visibles (getEntidadesVisibles)
- Frontend: supervisor ve botón Invitar Usuario y solo puede seleccionar
  rol Cliente en el dropdown
This commit is contained in:
Horux Dev
2026-05-29 21:32:12 +00:00
parent 5dd53cebac
commit 6e54efe5e4
3 changed files with 22 additions and 4 deletions

View File

@@ -170,6 +170,15 @@ export async function addClienteAcceso(req: Request, res: Response, next: NextFu
const { userId } = req.body;
if (!userId || typeof userId !== 'string') return next(new AppError(400, 'userId requerido'));
const entidadId = String(req.params.id);
// Seguridad: supervisor solo puede asignar contribuyentes que supervise
if (req.user!.role === 'supervisor') {
const visibleIds = await getEntidadesVisibles(req.tenantPool!, req.user!.userId, req.user!.role);
if (!visibleIds.includes(entidadId)) {
return next(new AppError(403, 'No tienes acceso a este contribuyente'));
}
}
await req.tenantPool!.query(
'INSERT INTO cliente_accesos (user_id, entidad_id) VALUES ($1, $2) ON CONFLICT DO NOTHING',
[userId, entidadId],

View File

@@ -65,11 +65,16 @@ export async function getAllUsuarios(req: Request, res: Response, next: NextFunc
export async function inviteUsuario(req: Request, res: Response, next: NextFunction) {
try {
if (req.user!.role !== 'owner') {
throw new AppError(403, 'Solo los dueños pueden invitar usuarios');
if (!['owner', 'cfo', 'supervisor'].includes(req.user!.role)) {
throw new AppError(403, 'No autorizado para invitar usuarios');
}
const data = inviteSchema.parse(req.body);
// Los supervisores solo pueden invitar clientes
if (req.user!.role === 'supervisor' && data.role !== 'cliente') {
throw new AppError(403, 'Los supervisores solo pueden invitar clientes');
}
// Validate: auxiliar requires a supervisor
if (data.role === 'auxiliar' && !data.supervisorUserId) {
throw new AppError(400, 'Debes asignar un supervisor al auxiliar');