2026-04-14 13:17:31 +04:00

66 lines
1.9 KiB
JavaScript

const db = require('../db/models');
const UsersDBApi = require('../db/api/users');
const { createEntityService } = require('../factories/service.factory');
const ValidationError = require('./notifications/errors/validation');
const config = require('../config');
const AuthService = require('./auth');
// Generate base service from factory
const BaseUsersService = createEntityService(UsersDBApi, {
entityName: 'Users',
});
/**
* Users service with email invitation functionality
* Extends factory-generated service with custom user logic
*/
class UsersService extends BaseUsersService {
/**
* Create user with email validation and optional invitation
*/
static async create(data, currentUser, sendInvitationEmails = true, host) {
const transaction = await db.sequelize.transaction();
const email = data.email;
try {
if (!email) {
throw new ValidationError('iam.errors.emailRequired');
}
const existingUser = await UsersDBApi.findBy({ email }, { transaction });
if (existingUser) {
throw new ValidationError('iam.errors.userAlreadyExists');
}
await UsersDBApi.create({ data }, { currentUser, transaction });
await transaction.commit();
// Send invitation email after successful commit
if (sendInvitationEmails) {
AuthService.sendPasswordResetEmail(email, 'invitation', host);
}
} catch (error) {
await transaction.rollback();
throw error;
}
}
/**
* Remove user with self-deletion and permission checks
*/
static async remove(id, currentUser) {
if (currentUser.id === id) {
throw new ValidationError('iam.errors.deletingHimself');
}
if (currentUser.app_role?.name !== config.roles.admin) {
throw new ValidationError('errors.forbidden.message');
}
// Delegate to parent (factory) implementation
return super.remove(id, currentUser);
}
}
module.exports = UsersService;