feat: add global user administration for admin users

Backend:
- Add getAllUsuarios() to get users from all tenants
- Add updateUsuarioGlobal() to edit users and change their tenant
- Add deleteUsuarioGlobal() for global user deletion
- Add global admin check based on tenant RFC
- Add new API routes: /usuarios/global/*

Frontend:
- Add UserListItem.tenantId and tenantName fields
- Add /admin/usuarios page with full user management
- Support filtering by tenant and search
- Inline editing for name, role, and tenant assignment
- Group users by company for better organization
- Add "Admin Usuarios" menu item for admin navigation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Consultoria AS
2026-01-25 01:22:34 +00:00
parent 2655a51a99
commit 69efb585d3
8 changed files with 522 additions and 3 deletions

View File

@@ -105,3 +105,93 @@ export async function deleteUsuario(tenantId: string, userId: string): Promise<v
where: { id: userId, tenantId },
});
}
/**
* Obtiene todos los usuarios de todas las empresas (solo admin global)
*/
export async function getAllUsuarios(): Promise<UserListItem[]> {
const users = await prisma.user.findMany({
select: {
id: true,
email: true,
nombre: true,
role: true,
active: true,
lastLogin: true,
createdAt: true,
tenantId: true,
tenant: {
select: {
nombre: true,
},
},
},
orderBy: [{ tenant: { nombre: 'asc' } }, { createdAt: 'desc' }],
});
return users.map(u => ({
id: u.id,
email: u.email,
nombre: u.nombre,
role: u.role,
active: u.active,
lastLogin: u.lastLogin?.toISOString() || null,
createdAt: u.createdAt.toISOString(),
tenantId: u.tenantId,
tenantName: u.tenant.nombre,
}));
}
/**
* Actualiza un usuario globalmente (puede cambiar de tenant)
*/
export async function updateUsuarioGlobal(
userId: string,
data: UserUpdate & { tenantId?: string }
): Promise<UserListItem> {
const user = await prisma.user.update({
where: { id: userId },
data: {
...(data.nombre && { nombre: data.nombre }),
...(data.role && { role: data.role }),
...(data.active !== undefined && { active: data.active }),
...(data.tenantId && { tenantId: data.tenantId }),
},
select: {
id: true,
email: true,
nombre: true,
role: true,
active: true,
lastLogin: true,
createdAt: true,
tenantId: true,
tenant: {
select: {
nombre: true,
},
},
},
});
return {
id: user.id,
email: user.email,
nombre: user.nombre,
role: user.role,
active: user.active,
lastLogin: user.lastLogin?.toISOString() || null,
createdAt: user.createdAt.toISOString(),
tenantId: user.tenantId,
tenantName: user.tenant.nombre,
};
}
/**
* Elimina un usuario globalmente
*/
export async function deleteUsuarioGlobal(userId: string): Promise<void> {
await prisma.user.delete({
where: { id: userId },
});
}