feat(alertas): add alerts CRUD with stats and management UI
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
107
apps/api/src/services/usuarios.service.ts
Normal file
107
apps/api/src/services/usuarios.service.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { prisma } from '../config/database.js';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import type { UserListItem, UserInvite, UserUpdate } from '@horux/shared';
|
||||
|
||||
export async function getUsuarios(tenantId: string): Promise<UserListItem[]> {
|
||||
const users = await prisma.user.findMany({
|
||||
where: { tenantId },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
nombre: true,
|
||||
role: true,
|
||||
active: true,
|
||||
lastLogin: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
|
||||
return users.map(u => ({
|
||||
...u,
|
||||
lastLogin: u.lastLogin?.toISOString() || null,
|
||||
createdAt: u.createdAt.toISOString(),
|
||||
}));
|
||||
}
|
||||
|
||||
export async function inviteUsuario(tenantId: string, data: UserInvite): Promise<UserListItem> {
|
||||
// Check tenant user limit
|
||||
const tenant = await prisma.tenant.findUnique({
|
||||
where: { id: tenantId },
|
||||
select: { usersLimit: true },
|
||||
});
|
||||
|
||||
const currentCount = await prisma.user.count({ where: { tenantId } });
|
||||
|
||||
if (currentCount >= (tenant?.usersLimit || 1)) {
|
||||
throw new Error('Límite de usuarios alcanzado para este plan');
|
||||
}
|
||||
|
||||
// Generate temporary password
|
||||
const tempPassword = Math.random().toString(36).slice(-8);
|
||||
const passwordHash = await bcrypt.hash(tempPassword, 12);
|
||||
|
||||
const user = await prisma.user.create({
|
||||
data: {
|
||||
tenantId,
|
||||
email: data.email,
|
||||
passwordHash,
|
||||
nombre: data.nombre,
|
||||
role: data.role,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
nombre: true,
|
||||
role: true,
|
||||
active: true,
|
||||
lastLogin: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
// In production, send email with tempPassword
|
||||
console.log(`Temporary password for ${data.email}: ${tempPassword}`);
|
||||
|
||||
return {
|
||||
...user,
|
||||
lastLogin: user.lastLogin?.toISOString() || null,
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateUsuario(
|
||||
tenantId: string,
|
||||
userId: string,
|
||||
data: UserUpdate
|
||||
): Promise<UserListItem> {
|
||||
const user = await prisma.user.update({
|
||||
where: { id: userId, tenantId },
|
||||
data: {
|
||||
...(data.nombre && { nombre: data.nombre }),
|
||||
...(data.role && { role: data.role }),
|
||||
...(data.active !== undefined && { active: data.active }),
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
nombre: true,
|
||||
role: true,
|
||||
active: true,
|
||||
lastLogin: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...user,
|
||||
lastLogin: user.lastLogin?.toISOString() || null,
|
||||
createdAt: user.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteUsuario(tenantId: string, userId: string): Promise<void> {
|
||||
await prisma.user.delete({
|
||||
where: { id: userId, tenantId },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user