skailan-core
Version:
Servicio de autenticación y multitenancy para Skailan.
349 lines • 11.3 kB
JavaScript
export class PermissionService {
prisma;
constructor(prisma) {
this.prisma = prisma;
}
/**
* Crear un nuevo permiso
*/
async createPermission(data, organizationId) {
try {
const permission = await this.prisma.permission.create({
data: {
resource: data.resource,
action: data.action,
description: data.description,
organizationId,
},
});
return this.mapToPermissionResponse(permission);
}
catch (error) {
if (error instanceof Error &&
error.message.includes("Unique constraint")) {
throw new Error(`El permiso ${data.resource}:${data.action} ya existe para esta organización`);
}
throw error;
}
}
/**
* Obtener todos los permisos de una organización
*/
async getPermissions(organizationId) {
const permissions = await this.prisma.permission.findMany({
where: {
OR: [
{ organizationId },
{ organizationId: null }, // Permisos globales
],
},
orderBy: [{ resource: "asc" }, { action: "asc" }],
});
return permissions.map(this.mapToPermissionResponse);
}
/**
* Obtener un permiso por ID
*/
async getPermissionById(id) {
const permission = await this.prisma.permission.findUnique({
where: { id },
});
return permission ? this.mapToPermissionResponse(permission) : null;
}
/**
* Actualizar un permiso
*/
async updatePermission(id, data) {
const permission = await this.prisma.permission.update({
where: { id },
data: {
resource: data.resource,
action: data.action,
description: data.description,
},
});
return this.mapToPermissionResponse(permission);
}
/**
* Eliminar un permiso
*/
async deletePermission(id) {
// Primero eliminar todas las asignaciones de roles
await this.prisma.rolePermission.deleteMany({
where: { permissionId: id },
});
// Luego eliminar el permiso
await this.prisma.permission.delete({
where: { id },
});
}
/**
* Asignar un permiso a un rol
*/
async assignPermissionToRole(data, organizationId) {
try {
const rolePermission = await this.prisma.rolePermission.create({
data: {
role: data.role,
permissionId: data.permissionId,
organizationId,
},
include: {
permission: true,
},
});
return this.mapToRolePermissionResponse(rolePermission);
}
catch (error) {
if (error instanceof Error &&
error.message.includes("Unique constraint")) {
throw new Error(`El permiso ya está asignado al rol ${data.role}`);
}
throw error;
}
}
/**
* Revocar un permiso de un rol
*/
async revokePermissionFromRole(role, permissionId, organizationId) {
await this.prisma.rolePermission.deleteMany({
where: {
role: role,
permissionId,
organizationId,
},
});
}
/**
* Obtener permisos de un rol
*/
async getRolePermissions(role, organizationId) {
const rolePermissions = await this.prisma.rolePermission.findMany({
where: {
role: role,
OR: [{ organizationId }, { organizationId: null }],
},
include: {
permission: true,
},
});
return rolePermissions.map((rp) => this.mapToPermissionResponse(rp.permission));
}
/**
* Obtener roles que tienen un permiso específico
*/
async getRolesWithPermission(permissionId, organizationId) {
const rolePermissions = await this.prisma.rolePermission.findMany({
where: {
permissionId,
OR: [{ organizationId }, { organizationId: null }],
},
select: {
role: true,
},
});
return rolePermissions.map((rp) => rp.role);
}
/**
* Asignar múltiples permisos a un rol
*/
async bulkAssignPermissions(data, organizationId) {
const { role, permissions } = data;
const result = {
success: [],
failed: [],
};
for (const permissionId of permissions) {
try {
await this.assignPermissionToRole({ role, permissionId }, organizationId);
result.success.push(permissionId);
}
catch (error) {
result.failed.push({
permissionId,
error: error instanceof Error ? error.message : "Error desconocido",
});
}
}
return result;
}
/**
* Verificar si un usuario tiene un permiso específico
*/
async checkUserPermission(userId, organizationId, requiredPermission) {
// Obtener la membresía del usuario
const membership = await this.prisma.membership.findFirst({
where: {
userId,
organizationId,
status: "ACTIVE",
},
});
if (!membership) {
return {
hasPermission: false,
requiredPermission,
userPermissions: [],
role: "MEMBER",
};
}
// Obtener permisos del rol
const userPermissions = await this.getRolePermissions(membership.role, organizationId);
// Verificar si tiene el permiso requerido
const [resource, action] = requiredPermission.split(":");
const hasPermission = userPermissions.some((p) => p.resource === resource && p.action === action);
return {
hasPermission,
requiredPermission,
userPermissions,
role: membership.role,
};
}
/**
* Obtener todos los permisos de un usuario en una organización
*/
async getUserPermissions(userId, organizationId) {
const membership = await this.prisma.membership.findFirst({
where: {
userId,
organizationId,
status: "ACTIVE",
},
});
if (!membership) {
return [];
}
return this.getRolePermissions(membership.role, organizationId);
}
/**
* Crear permisos por defecto para una organización
*/
async createDefaultPermissions(organizationId) {
const defaultPermissions = [
// Usuarios
{ resource: "users", action: "read", description: "Ver usuarios" },
{
resource: "users",
action: "update",
description: "Actualizar usuarios",
},
// Organizaciones
{
resource: "organizations",
action: "read",
description: "Ver organización",
},
{
resource: "organizations",
action: "update",
description: "Actualizar organización",
},
// Membresías
{
resource: "memberships",
action: "read",
description: "Ver membresías",
},
{
resource: "memberships",
action: "create",
description: "Crear membresías",
},
{
resource: "memberships",
action: "update",
description: "Actualizar membresías",
},
{
resource: "memberships",
action: "delete",
description: "Eliminar membresías",
},
// Pagos
{ resource: "payments", action: "read", description: "Ver pagos" },
{ resource: "payments", action: "create", description: "Crear pagos" },
// Invitaciones
{
resource: "invitations",
action: "read",
description: "Ver invitaciones",
},
{
resource: "invitations",
action: "create",
description: "Crear invitaciones",
},
{
resource: "invitations",
action: "delete",
description: "Eliminar invitaciones",
},
// Permisos
{ resource: "permissions", action: "read", description: "Ver permisos" },
{
resource: "permissions",
action: "manage",
description: "Gestionar permisos",
},
// Configuración
{
resource: "settings",
action: "read",
description: "Ver configuración",
},
{
resource: "settings",
action: "update",
description: "Actualizar configuración",
},
// Reportes
{ resource: "reports", action: "read", description: "Ver reportes" },
{
resource: "reports",
action: "export",
description: "Exportar reportes",
},
// Analytics
{ resource: "analytics", action: "read", description: "Ver analytics" },
{
resource: "analytics",
action: "export",
description: "Exportar analytics",
},
];
for (const permissionData of defaultPermissions) {
try {
await this.createPermission(permissionData, organizationId);
}
catch (error) {
// Ignorar errores de permisos duplicados
console.log(`Permiso ${permissionData.resource}:${permissionData.action} ya existe`);
}
}
}
/**
* Mapear PrismaPermission a PermissionResponse
*/
mapToPermissionResponse(permission) {
return {
id: permission.id,
resource: permission.resource,
action: permission.action,
description: permission.description || undefined,
createdAt: permission.createdAt,
updatedAt: permission.updatedAt,
};
}
/**
* Mapear PrismaRolePermission a RolePermissionResponse
*/
mapToRolePermissionResponse(rolePermission) {
return {
id: rolePermission.id,
role: rolePermission.role,
permission: this.mapToPermissionResponse(rolePermission.permission),
createdAt: rolePermission.createdAt,
};
}
}
//# sourceMappingURL=PermissionService.js.map