223 lines
7.1 KiB
JavaScript
223 lines
7.1 KiB
JavaScript
"use strict";
|
|
/**
|
|
* UsersService - Gestión de usuarios
|
|
*
|
|
* CRUD de usuarios con soporte multi-tenant y RBAC.
|
|
*
|
|
* @module Users
|
|
*/
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || (function () {
|
|
var ownKeys = function(o) {
|
|
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
var ar = [];
|
|
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
return ar;
|
|
};
|
|
return ownKeys(o);
|
|
};
|
|
return function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
})();
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.UsersService = void 0;
|
|
const typeorm_1 = require("typeorm");
|
|
const bcrypt = __importStar(require("bcryptjs"));
|
|
class UsersService {
|
|
userRepository;
|
|
roleRepository;
|
|
userRoleRepository;
|
|
constructor(userRepository, roleRepository, userRoleRepository) {
|
|
this.userRepository = userRepository;
|
|
this.roleRepository = roleRepository;
|
|
this.userRoleRepository = userRoleRepository;
|
|
}
|
|
/**
|
|
* Listar usuarios de un tenant
|
|
*/
|
|
async findAll(options) {
|
|
const { tenantId, page = 1, limit = 20, search, isActive } = options;
|
|
const query = this.userRepository
|
|
.createQueryBuilder('user')
|
|
.leftJoinAndSelect('user.tenant', 'tenant')
|
|
.where('user.tenant_id = :tenantId', { tenantId })
|
|
.andWhere('user.deleted_at IS NULL');
|
|
if (search) {
|
|
query.andWhere('(user.email ILIKE :search OR user.first_name ILIKE :search OR user.last_name ILIKE :search)', { search: `%${search}%` });
|
|
}
|
|
if (isActive !== undefined) {
|
|
query.andWhere('user.is_active = :isActive', { isActive });
|
|
}
|
|
const total = await query.getCount();
|
|
const users = await query
|
|
.skip((page - 1) * limit)
|
|
.take(limit)
|
|
.orderBy('user.created_at', 'DESC')
|
|
.getMany();
|
|
return { users, total };
|
|
}
|
|
/**
|
|
* Obtener usuario por ID
|
|
*/
|
|
async findById(id, tenantId) {
|
|
return this.userRepository.findOne({
|
|
where: { id, tenantId, deletedAt: (0, typeorm_1.IsNull)() },
|
|
relations: ['tenant'],
|
|
});
|
|
}
|
|
/**
|
|
* Obtener usuario por email
|
|
*/
|
|
async findByEmail(email, tenantId) {
|
|
return this.userRepository.findOne({
|
|
where: { email, tenantId, deletedAt: (0, typeorm_1.IsNull)() },
|
|
});
|
|
}
|
|
/**
|
|
* Crear usuario
|
|
*/
|
|
async create(dto, createdBy) {
|
|
// Verificar email único en tenant
|
|
const existing = await this.findByEmail(dto.email, dto.tenantId);
|
|
if (existing) {
|
|
throw new Error('Email already exists in this tenant');
|
|
}
|
|
const passwordHash = await bcrypt.hash(dto.password, 12);
|
|
const user = await this.userRepository.save(this.userRepository.create({
|
|
email: dto.email,
|
|
passwordHash,
|
|
firstName: dto.firstName,
|
|
lastName: dto.lastName,
|
|
tenantId: dto.tenantId,
|
|
defaultTenantId: dto.tenantId,
|
|
isActive: true,
|
|
roles: dto.roles || ['viewer'],
|
|
}));
|
|
// Asignar roles si se especificaron
|
|
if (dto.roles && dto.roles.length > 0) {
|
|
for (const roleCode of dto.roles) {
|
|
await this.assignRole({ userId: user.id, roleCode, tenantId: dto.tenantId }, createdBy);
|
|
}
|
|
}
|
|
return user;
|
|
}
|
|
/**
|
|
* Actualizar usuario
|
|
*/
|
|
async update(id, tenantId, dto) {
|
|
const user = await this.findById(id, tenantId);
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
await this.userRepository.update(id, {
|
|
...dto,
|
|
updatedAt: new Date(),
|
|
});
|
|
return this.findById(id, tenantId);
|
|
}
|
|
/**
|
|
* Soft delete de usuario
|
|
*/
|
|
async delete(id, tenantId, _deletedBy) {
|
|
const user = await this.findById(id, tenantId);
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
await this.userRepository.update(id, {
|
|
deletedAt: new Date(),
|
|
isActive: false,
|
|
});
|
|
}
|
|
/**
|
|
* Activar/Desactivar usuario
|
|
*/
|
|
async setActive(id, tenantId, isActive) {
|
|
const user = await this.findById(id, tenantId);
|
|
if (!user) {
|
|
throw new Error('User not found');
|
|
}
|
|
await this.userRepository.update(id, { isActive });
|
|
return this.findById(id, tenantId);
|
|
}
|
|
/**
|
|
* Asignar rol a usuario
|
|
*/
|
|
async assignRole(dto, assignedBy) {
|
|
const role = await this.roleRepository.findOne({
|
|
where: { code: dto.roleCode, isActive: true },
|
|
});
|
|
if (!role) {
|
|
throw new Error('Role not found');
|
|
}
|
|
// Verificar si ya tiene el rol
|
|
const existing = await this.userRoleRepository.findOne({
|
|
where: { userId: dto.userId, roleId: role.id, tenantId: dto.tenantId },
|
|
});
|
|
if (existing) {
|
|
return existing;
|
|
}
|
|
return this.userRoleRepository.save(this.userRoleRepository.create({
|
|
userId: dto.userId,
|
|
roleId: role.id,
|
|
tenantId: dto.tenantId,
|
|
assignedBy,
|
|
}));
|
|
}
|
|
/**
|
|
* Remover rol de usuario
|
|
*/
|
|
async removeRole(userId, roleCode, tenantId) {
|
|
const role = await this.roleRepository.findOne({
|
|
where: { code: roleCode },
|
|
});
|
|
if (!role) {
|
|
throw new Error('Role not found');
|
|
}
|
|
await this.userRoleRepository.delete({
|
|
userId,
|
|
roleId: role.id,
|
|
tenantId,
|
|
});
|
|
}
|
|
/**
|
|
* Obtener roles de usuario
|
|
*/
|
|
async getUserRoles(userId, tenantId) {
|
|
const userRoles = await this.userRoleRepository.find({
|
|
where: { userId, tenantId },
|
|
relations: ['role'],
|
|
});
|
|
return userRoles.map((ur) => ur.role);
|
|
}
|
|
/**
|
|
* Listar todos los roles disponibles
|
|
*/
|
|
async listRoles() {
|
|
return this.roleRepository.find({
|
|
where: { isActive: true },
|
|
order: { name: 'ASC' },
|
|
});
|
|
}
|
|
}
|
|
exports.UsersService = UsersService;
|
|
//# sourceMappingURL=users.service.js.map
|