User account management in ARCA follows a strict hierarchical permission model where users can only manage accounts with equal or lower privilege levels. This page covers CRUD operations for user accounts and their business rules.
All user management operations are protected by the JwtAuthGuard and enforce role-based access control.
async create(createUserDto: CreateUserDto, creator: TokenDto) { // Verifica se o criador tem permissão para criar usuários if ( // 1. A regra geral: proíbe se o novo usuário tiver acesso igual ou superior createUserDto.roleId <= creator.access && // 2. A exceção: a regra acima NÃO se aplica se for um Admin (1) criando outro Admin (1) !(creator.access === 1 && createUserDto.roleId === 1) ) { throw new ForbiddenException( 'Você não tem permissão para criar um usuário com nível de acesso igual ou superior ao seu.', ); } // Verifica se o email já existe const existingUser = await this.prisma.usuario.findUnique({ where: { email: createUserDto.email }, }); if (existingUser) { throw new BadRequestException('E-mail já cadastrado.'); } const passwordHash = await this.HashingService.hash(createUserDto.senha); return this.prisma.usuario.create({ data: { nome: createUserDto.nome, email: createUserDto.email, senhaHash: passwordHash, roleId: createUserDto.roleId, }, select: { id_User: true, nome: true, email: true, senhaHash: false, // Never return password hash roleId: true, }, });}
Key Rules:
Users cannot create accounts with higher or equal privilege (except Admins creating Admins)
Email addresses must be unique
Passwords are automatically hashed with bcrypt before storage
Password hashes are never returned in API responses
async findAll(creator: TokenDto) { // Lista apenas os usuários com nível de acesso menor ou igual ao do criador const users = await this.prisma.usuario.findMany({ where: { roleId: { gte: creator.access, // Greater than or equal to creator's role ID }, }, select: { id_User: true, nome: true, email: true, senhaHash: false, roleId: true, role: { select: { id_Role: true, role: true, descricao: true, }, }, }, }); if (!users) { throw new BadGatewayException(`Erro ao buscar usuários.`); } else if (users.length === 0) { throw new NotFoundException(`Nenhum usuário encontrado.`); } return users;}
Users can only see accounts with equal or lower privilege levels. For example, a Supervisor (roleId=3) can only see other Supervisors and Estagiários, not Admins or Secretários.
curl -X GET http://localhost:3000/users/550e8400-e29b-41d4-a716-446655440000 \ -H "Authorization: Bearer <token>"
apps/backend/src/users/users.service.ts
async findOne(id: UUID, creator: TokenDto) { // Lista apenas o usuário com nível de acesso menor ao do criador const user = await this.prisma.usuario.findFirst({ where: { id_User: id, roleId: { gte: creator.access, }, }, select: { id_User: true, nome: true, email: true, senhaHash: false, roleId: true, }, }); if (!user) { throw new NotFoundException( `Usuário não encontrado ou acesso não permitido.`, ); } return user;}
async update(id: UUID, updateUserDto: UpdateUserDto, creator: TokenDto) { const user = await this.prisma.usuario.findFirst({ where: { id_User: id }, }); if (!user) { throw new NotFoundException(`Usuário não encontrado.`); } // REGRA 1: Você não pode editar um usuário com nível igual ou superior ao seu const canEditUser = creator.access < user.roleId || (creator.access === 1 && user.roleId === 1); if (!canEditUser) { throw new ForbiddenException( 'Você não tem permissão para editar um usuário com nível de acesso igual ou superior ao seu.', ); } // Verifica se o email já existe if (updateUserDto.email && updateUserDto.email !== user.email) { const existingUser = await this.prisma.usuario.findFirst({ where: { email: updateUserDto.email, id_User: { not: id }, }, }); if (existingUser) { throw new BadRequestException( 'O e-mail informado já está em uso por outro usuário.', ); } } // Preparar dados para atualização - excluir roleId const dataToUpdate: Prisma.UsuarioUpdateInput = { nome: updateUserDto.nome, email: updateUserDto.email, }; if (updateUserDto.senha) { dataToUpdate.senhaHash = await this.HashingService.hash( updateUserDto.senha, ); } return this.prisma.usuario.update({ where: { id_User: id }, data: dataToUpdate, select: { id_User: true, nome: true, email: true, roleId: true, }, });}
Key Rules:
Users cannot edit accounts with higher or equal privilege (except Admins editing Admins)
async remove(id: UUID, creator: TokenDto) { // 1. Busca o usuário que será deletado const user = await this.prisma.usuario.findUnique({ where: { id_User: id }, }); if (!user) { throw new NotFoundException(`Usuário não encontrado.`); } // Você não pode deletar a si mesmo. if (creator.sub === user.id_User) { throw new ForbiddenException('Você não pode deletar sua própria conta.'); } // Você não pode deletar um usuário com nível de acesso igual ou superior. const canDelete = creator.access < user.roleId || (creator.access === 1 && user.roleId === 1); if (!canDelete) { throw new ForbiddenException( 'Você não tem permissão para deletar um usuário com nível de acesso igual ou superior ao seu.', ); } await this.prisma.usuario.delete({ where: { id_User: id }, }); return { message: `Usuário com ID ${id} removido com sucesso.` };}
Critical Rules:
Users cannot delete themselves
Users cannot delete accounts with higher or equal privilege (except Admins deleting Admins)
Related records are handled by database CASCADE rules
Cause: Attempting to manage a user account with higher or equal privilege level.Solution: Only Admins can manage other Admins. Secretários can manage Supervisors and Estagiários. Supervisors can only manage Estagiários.
BadRequestException: E-mail já cadastrado
Cause: Email address already exists in the system.Solution: Use a different email address. Email addresses must be unique.
NotFoundException: Usuário não encontrado ou acesso não permitido
Cause: User doesn’t exist or you don’t have permission to view them.Solution: Verify the user ID and ensure you have sufficient privileges to access this user.
ForbiddenException: Você não pode deletar sua própria conta
Cause: Attempting to delete your own user account.Solution: Ask another administrator to delete your account if needed.
Validation errors
Cause: Invalid data in request body (e.g., email format, password length).Solution: