feat: permite rechazar (eliminar) usuarios en pending_verification
Antes solo se podia rechazar un usuario en pending_approval. Una cuenta autorregistrada que nunca confirmo su correo quedaba en pending_verification para siempre, sin ninguna accion disponible en Usuarios para quitarla. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
# Changelog - project.linkedcorp.net
|
||||
|
||||
## [1.9.0] - 2026-09-10
|
||||
### Added
|
||||
- Organización → Usuarios: ahora se puede "Rechazar" (eliminar) también a un usuario en
|
||||
`pending_verification` (autorregistro que nunca confirmó su correo) — antes esa acción solo
|
||||
existía para `pending_approval`, así que una cuenta abandonada antes de verificar el correo no
|
||||
tenía ninguna forma de quitarse desde la UI.
|
||||
|
||||
## [1.8.1] - 2026-09-10
|
||||
### Fixed
|
||||
- "Agregar dependencia" en una actividad no daba ninguna señal cuando no había otra actividad del
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "project-linkedcorp-backend",
|
||||
"version": "1.8.1",
|
||||
"version": "1.9.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/server.js",
|
||||
|
||||
@@ -79,10 +79,15 @@ export async function approveUser(id, payload, actorId) {
|
||||
return user;
|
||||
}
|
||||
|
||||
// Rechaza y borra una cuenta que aun no esta activa: tanto la que ya paso la verificacion de
|
||||
// correo y espera aprobacion, como la que nunca llego a confirmar su correo (quedo abandonada en
|
||||
// 'pending_verification' — antes no habia forma de quitarla desde la UI).
|
||||
export async function rejectUser(id, actorId) {
|
||||
const existing = await repo.findById(id);
|
||||
if (!existing) throw new HttpError(404, 'Usuario no encontrado');
|
||||
if (existing.status !== 'pending_approval') throw new HttpError(400, 'El usuario no esta pendiente de aprobacion');
|
||||
await logAudit({ userId: actorId, action: 'reject', entityType: 'user', entityId: id, detail: { email: existing.email } });
|
||||
if (!['pending_approval', 'pending_verification'].includes(existing.status)) {
|
||||
throw new HttpError(400, 'El usuario no esta pendiente de aprobacion ni de verificacion');
|
||||
}
|
||||
await logAudit({ userId: actorId, action: 'reject', entityType: 'user', entityId: id, detail: { email: existing.email, status: existing.status } });
|
||||
await repo.remove(id);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "project-linkedcorp-frontend",
|
||||
"private": true,
|
||||
"version": "1.8.1",
|
||||
"version": "1.9.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -132,19 +132,23 @@ export default function UsersPanel() {
|
||||
getSearchHaystack={(u) => `${u.name} ${u.email} ${u.role_name} ${u.department_name || ''}`}
|
||||
getRowKey={(u) => u.id}
|
||||
onRowClick={canManage ? startEdit : undefined}
|
||||
rowActions={canManage ? (u) => (
|
||||
u.status === 'pending_approval'
|
||||
? [
|
||||
rowActions={canManage ? (u) => {
|
||||
if (u.status === 'pending_approval') {
|
||||
return [
|
||||
{ label: t('user_approve'), icon: Check, onClick: () => startApprove(u) },
|
||||
{ label: t('user_reject'), icon: XIcon, danger: true, onClick: () => confirmReject(u) },
|
||||
]
|
||||
: [
|
||||
];
|
||||
}
|
||||
if (u.status === 'pending_verification') {
|
||||
return [{ label: t('user_reject'), icon: XIcon, danger: true, onClick: () => confirmReject(u) }];
|
||||
}
|
||||
return [
|
||||
{ label: t('common_edit'), onClick: () => startEdit(u) },
|
||||
u.is_active
|
||||
? { label: t('common_inactive'), icon: UserX, danger: true, onClick: () => toggleActive(u) }
|
||||
: { label: t('common_active'), icon: UserCheck, onClick: () => toggleActive(u) },
|
||||
]
|
||||
) : undefined}
|
||||
];
|
||||
} : undefined}
|
||||
/>
|
||||
|
||||
<DetailPopup open={editing} title={selected ? t('common_edit') : t('user_new')} onClose={() => setEditing(false)} width={560} height={440}>
|
||||
|
||||
Reference in New Issue
Block a user