UNPKG

auth-service-nestjs

Version:

Authorization service for lightweight systems

133 lines (130 loc) 3.79 kB
import { ForbiddenException, HttpException, HttpStatus, Injectable, } from '@nestjs/common'; import { GetAllParam, RegisterUser, UserCreate, UserItem, UserList, UserRoles, UserUpdate, } from 'src/users/users.dto'; import { InjectModel } from '@nestjs/sequelize'; import { UsersModel } from 'src/db/models/users.model'; import { Op } from 'sequelize'; import { SessionsModel } from 'src/db/models/sessions.model'; import { getPasswordHash } from 'src/utils/jsutils.cjs'; import { ErrorMessage } from 'src/utils/error'; import { DENY_ADMIN_CHANGE_ADMIN } from 'src/utils/const'; @Injectable() export class UsersService { constructor( @InjectModel(UsersModel) private userRepository: typeof UsersModel, @InjectModel(SessionsModel) private sessionRepository: typeof SessionsModel, ) {} async getAll(query: GetAllParam): Promise<UserList> { const { limit, offset, sort, order, search } = query; const or = search ? { firstName: { [Op.like]: `%${search}%`, }, lastName: { [Op.like]: `%${search}%`, }, login: { [Op.like]: `%${search}%`, }, email: { [Op.like]: `%${search}%`, }, } : undefined; const where = or ? { [Op.or]: or, } : undefined; const data = await this.userRepository.findAndCountAll({ raw: true, where, limit, offset, attributes: { exclude: ['password'] }, order: sort && order ? [[sort, order]] : undefined, }); return { items: data.rows as UserItem[], count: data.count, }; } async getUser(login: string): Promise<UsersModel> { const userInfo = await this.userRepository.findOne({ where: { login }, raw: true, }); if (!userInfo) throw new HttpException( ErrorMessage.UserNotFound, HttpStatus.BAD_REQUEST, ); return userInfo; } async delete(login: string): Promise<number> { const user = await this.getUser(login); if (+DENY_ADMIN_CHANGE_ADMIN && user.role === UserRoles.admin) { throw new ForbiddenException(); } await this.sessionRepository.destroy({ where: { login } }); return this.userRepository.destroy({ where: { login } }); } async update( login: string, { password, ...param }: UserUpdate, tokenLogin: string, ): Promise<[number]> { const userInfo = await this.getUser(login); if (+DENY_ADMIN_CHANGE_ADMIN && userInfo.role === UserRoles.admin) { const blockChangeLock = param.locked !== undefined ? userInfo.locked !== param.locked : false; const byMyself = tokenLogin === login; const blockChangePassword = password !== undefined && !byMyself ? userInfo.password !== getPasswordHash(password) : false; if (blockChangeLock || blockChangePassword) throw new ForbiddenException(); } return this.userRepository.update( { ...param, password: password ? getPasswordHash(password) : undefined, }, { where: { login } }, ); } async create({ password, ...param }: UserCreate): Promise<UsersModel> { return this.userRepository.create({ ...param, password: getPasswordHash(password), }); } async register(registerParams: RegisterUser) { const { login } = (await this.userRepository.findOne({ where: { login: registerParams.login }, raw: true, })) ?? {}; if (login === registerParams.login) { throw new HttpException( ErrorMessage.NotAcceptable, HttpStatus.NOT_ACCEPTABLE, ); } return this.create({ ...registerParams, locked: 1, role: UserRoles.guest }); } }