👨💼 Flujo de Admin
Visión General
El flujo del ADMIN es el más simple conceptualmente pero el más poderoso: acceso completo a todo el sistema sin restricciones ("Dios mode").
Diagrama de Flujo Completo
Características Principales
1. Acceso Completo
ADMIN tiene acceso a TODO sin restricciones de RBAC:
// En cualquier Server Action
export async function adminAction() {
const user = await getCurrentUser();
requireRole(user, ['ADMIN']);
// No hay más validaciones - acceso completo
// Puede hacer cualquier operación
}
2. Cambiar Roles
ADMIN es el único que puede asignar el rol ADMIN:
export async function updateUserRole(profileId: string, newRole: Role) {
const user = await getCurrentUser();
requireRole(user, ['ADMIN']);
// Solo ADMIN puede asignar ADMIN
if (newRole === 'ADMIN' && user.profile.role !== 'ADMIN') {
throw new Error('Only admins can assign ADMIN role');
}
await db.profile.update({
where: { id: profileId },
data: { role: newRole },
});
}
3. Override de Validaciones
ADMIN puede forzar cambios que normalmente no están permitidos:
export async function forceHackathonStatus(
hackathonId: string,
newStatus: HackathonStatus,
skipValidations: boolean = false
) {
const user = await getCurrentUser();
requireRole(user, ['ADMIN']);
if (skipValidations) {
// ⚠️ PELIGRO: Puede romper reglas de negocio
await db.hackathon.update({
where: { id: hackathonId },
data: { status: newStatus },
});
} else {
// Validaciones normales
// ...
}
}
⚠️ Advertencia en UI: Siempre mostrar advertencia cuando ADMIN hace override.
4. Eliminación con Cascade
ADMIN puede eliminar usuarios y hackathons, lo que elimina en cascade:
export async function deleteUser(profileId: string) {
const user = await getCurrentUser();
requireRole(user, ['ADMIN']);
// ⚠️ CASCADE DELETE:
// - HackathonParticipation
// - TeamMember
// - Score
// - HackathonJudge
// - OrganizationMember
// - Notification
// - etc.
await db.profile.delete({
where: { id: profileId },
});
}
Casos de Uso Detallados
CU-1: Gestionar Usuarios
Actor: ADMIN
Precondiciones: Ninguna (acceso completo)
Flujo Principal:
- ADMIN va a
/admin/users - Ve tabla con todos los usuarios:
name,emailrolecreatedAt
- Puede:
- Filtrar por rol
- Buscar por name/email
- Cambiar rol (dropdown)
- Eliminar usuario
- Para cambiar rol:
- Selecciona nuevo rol
- Si es ADMIN, solo ADMIN puede asignarlo
- Sistema actualiza
Profile.role
- Para eliminar:
- Muestra advertencia de cascade
- Confirma eliminación
- Sistema elimina usuario y todas sus relaciones
CU-2: Gestionar Hackathons
Actor: ADMIN
Precondiciones: Ninguna
Flujo Principal:
- ADMIN va a
/admin/hackathons - Ve TODOS los hackathons (incluido DRAFT)
- Puede:
- Ver cualquier hackathon
- Crear nuevo hackathon
- Editar cualquier campo
- Eliminar hackathon
- Forzar cambio de estado
- Para editar:
- Puede modificar cualquier campo
- Puede override validaciones (con advertencia)
- Sistema aplica cambios
- Para forzar estado:
- Selecciona nuevo estado
- Muestra advertencia
- Confirma override
- Sistema cambia estado sin validar fechas
CU-3: Ver Estadísticas Globales
Actor: ADMIN
Precondiciones: Ninguna
Flujo Principal:
- ADMIN va a
/admin/dashboard - Sistema muestra:
- Usuarios por rol: Count de cada Role
- Hackathons por estado: Count de cada HackathonStatus
- Total equipos: Count de Team
- Total submissions: Count de Submission
- Gráficos básicos (opcional en MVP)
- Puede hacer clic en cualquier métrica para ver detalles
Query:
export async function getGlobalStats() {
const [usersByRole, hackathonsByStatus, totalTeams, totalSubmissions] =
await Promise.all([
db.profile.groupBy({
by: ['role'],
_count: true,
}),
db.hackathon.groupBy({
by: ['status'],
_count: true,
}),
db.team.count(),
db.submission.count(),
]);
return {
usersByRole: usersByRole.reduce(
(acc, item) => ({ ...acc, [item.role]: item._count }),
{}
),
hackathonsByStatus: hackathonsByStatus.reduce(
(acc, item) => ({ ...acc, [item.status]: item._count }),
{}
),
totalTeams,
totalSubmissions,
};
}
Restricciones en MVP
Lo que ADMIN NO puede hacer (por diseño)
- ❌ Nada: ADMIN puede hacer TODO en el MVP
Advertencias Importantes
- Override de validaciones: Siempre mostrar advertencia
- Eliminación con cascade: Mostrar qué se eliminará
- Cambio de roles: Especialmente asignar ADMIN
Futuras Mejoras
Audit Logs
En futuras iteraciones, agregar:
model AuditLog {
id String @id @default(cuid())
adminId String
action String // "UPDATE_USER_ROLE", "DELETE_USER", etc.
resource String // "User", "Hackathon", etc.
resourceId String
oldValue Json?
newValue Json?
createdAt DateTime @default(now())
}
Reglas Específicas
Agregar reglas específicas para ciertas acciones:
- No eliminar último ADMIN
- No eliminar hackathons con submissions evaluadas
- etc.
Diagrama de Permisos Admin
Próximos Pasos
- Development Guide - Setup completo
- Coding Standards - Estándares de código
- Troubleshooting - Solución de problemas
Siguiente: Development Guide