Files
boilerplate/apps/backend/src/users/repositories/users.repository.ts
Bastian Wagner c03b2e17f5 bump
2026-07-16 15:23:53 +02:00

113 lines
3.3 KiB
TypeScript

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<UserEntity>,
) {}
findById(id: string, manager?: EntityManager): Promise<UserEntity | null> {
return (manager?.getRepository(UserEntity) ?? this.repo).findOne({
where: { id },
});
}
findByIdentity(issuer: string, subject: string): Promise<UserEntity | null> {
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<UserEntity | null> {
return (manager?.getRepository(UserEntity) ?? this.repo).findOne({
where: { id },
relations: { roles: { permissions: true }, settings: true },
});
}
async save(user: UserEntity, manager?: EntityManager): Promise<UserEntity> {
return (manager?.getRepository(UserEntity) ?? this.repo).save(user);
}
findFirstActiveAdmin(excludedUserId?: string): Promise<UserEntity | null> {
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();
}
}