import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { EntityManager, Repository } from 'typeorm'; import type { AdminUserActiveFilter, AdminUserSortField, } from '../dto/user.dto'; import { UserEntity } from '../entities/user.entity'; @Injectable() export class UsersRepository { constructor( @InjectRepository(UserEntity) private readonly repo: Repository, ) {} findById(id: string, manager?: EntityManager): Promise { return (manager?.getRepository(UserEntity) ?? this.repo).findOne({ where: { id }, }); } findByIdentity(issuer: string, subject: string): Promise { return this.repo.findOne({ where: { issuer, subject } }); } async search( query: string | undefined, page: number, pageSize: number, ): Promise<[UserEntity[], number]> { const qb = this.repo .createQueryBuilder('user') .leftJoinAndSelect('user.roles', 'role'); if (query) { qb.where('user.name LIKE :query OR user.email LIKE :query', { query: `%${query}%`, }); } return qb .orderBy('user.createdAt', 'DESC') .skip((page - 1) * pageSize) .take(pageSize) .getManyAndCount(); } async adminSearch( query: { search?: string; active: AdminUserActiveFilter; roleId?: string; sort: AdminUserSortField; direction: 'ASC' | 'DESC'; page: number; pageSize: number; }, manager?: EntityManager, ): Promise<[UserEntity[], number]> { const repo = manager?.getRepository(UserEntity) ?? this.repo; const qb = repo .createQueryBuilder('user') .leftJoinAndSelect('user.roles', 'role') .leftJoinAndSelect('role.permissions', 'permission'); if (query.search) { qb.andWhere('user.name LIKE :search OR user.email LIKE :search', { search: `%${query.search}%`, }); } if (query.active !== 'all') { qb.andWhere('user.active = :active', { active: query.active === 'active', }); } if (query.roleId) { qb.andWhere( 'EXISTS (SELECT 1 FROM user_roles ur WHERE ur.user_id = user.id AND ur.role_id = :roleId)', { roleId: query.roleId }, ); } return qb .orderBy(`user.${query.sort}`, query.direction) .skip((query.page - 1) * query.pageSize) .take(query.pageSize) .getManyAndCount(); } findByIdWithRoles( id: string, manager?: EntityManager, ): Promise { return (manager?.getRepository(UserEntity) ?? this.repo).findOne({ where: { id }, relations: { roles: { permissions: true }, settings: true }, }); } async save(user: UserEntity, manager?: EntityManager): Promise { return (manager?.getRepository(UserEntity) ?? this.repo).save(user); } findFirstActiveAdmin(excludedUserId?: string): Promise { const qb = this.repo .createQueryBuilder('user') .innerJoin('user.roles', 'role') .where('user.active = :active', { active: true }) .andWhere('role.name = :role', { role: 'admin' }) .orderBy('user.createdAt', 'ASC'); if (excludedUserId) { qb.andWhere('user.id <> :excludedUserId', { excludedUserId }); } return qb.getOne(); } }