196 lines
4.7 KiB
TypeScript
196 lines
4.7 KiB
TypeScript
import bcrypt from 'bcrypt';
|
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { plainToInstance } from 'class-transformer';
|
|
|
|
import { Prisma, Usuario } from 'generated/prisma';
|
|
|
|
import { PrismaService } from '@prisma/prisma.service';
|
|
import { PaginatedResponse } from '@shared/dto/paginated';
|
|
import { UsuariosResponseDto } from './dto/usuarios.response';
|
|
import { CreateUsuarioDto } from './dto/create-usuario-dto';
|
|
|
|
type ListUsuariosFilters = {
|
|
name?: string;
|
|
email?: string;
|
|
};
|
|
|
|
type ListUsuariosPaginatedParams = ListUsuariosFilters & {
|
|
page?: number;
|
|
perPage?: number;
|
|
direction?: 'asc' | 'desc';
|
|
};
|
|
|
|
const SELECT = {
|
|
id: true,
|
|
uuid: true,
|
|
email: true,
|
|
email_verificado: true,
|
|
nome: true,
|
|
sobrenome: true,
|
|
papel: true,
|
|
status: true,
|
|
ultimo_login_em: true,
|
|
ultimo_login_ip: true,
|
|
tentativas_login_falhadas: true,
|
|
bloqueado_ate: true,
|
|
criado_em: true,
|
|
atualizado_em: true,
|
|
} as const;
|
|
|
|
@Injectable()
|
|
export class UsuariosService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
private buildWhere({
|
|
name,
|
|
email,
|
|
}: ListUsuariosFilters): Prisma.UsuarioWhereInput {
|
|
const andConditions: Prisma.UsuarioWhereInput[] = [
|
|
{ email: { not: 'admin@clipperia.com' } },
|
|
];
|
|
|
|
if (name) {
|
|
andConditions.push({
|
|
OR: [
|
|
{ nome: { contains: name, mode: 'insensitive' } },
|
|
{ sobrenome: { contains: name, mode: 'insensitive' } },
|
|
],
|
|
});
|
|
}
|
|
|
|
if (email) {
|
|
andConditions.push({ email: { contains: email, mode: 'insensitive' } });
|
|
}
|
|
|
|
return { AND: andConditions };
|
|
}
|
|
|
|
async list(
|
|
filters: ListUsuariosFilters = {},
|
|
): Promise<UsuariosResponseDto[]> {
|
|
const where = this.buildWhere(filters);
|
|
|
|
const data = await this.prisma.usuario.findMany({
|
|
where,
|
|
orderBy: { id: 'desc' },
|
|
select: SELECT,
|
|
});
|
|
|
|
return plainToInstance(UsuariosResponseDto, data, {
|
|
excludeExtraneousValues: true,
|
|
});
|
|
}
|
|
|
|
async listPaginated(
|
|
params: ListUsuariosPaginatedParams,
|
|
): Promise<PaginatedResponse<UsuariosResponseDto>> {
|
|
const parsedPage = Number(params.page);
|
|
const safePage =
|
|
Number.isFinite(parsedPage) && parsedPage > 0
|
|
? Math.floor(parsedPage)
|
|
: 1;
|
|
|
|
const parsedPerPage = Number(params.perPage);
|
|
const safePerPage =
|
|
Number.isFinite(parsedPerPage) && parsedPerPage > 0
|
|
? Math.floor(parsedPerPage)
|
|
: 10;
|
|
|
|
const safeDirection: 'asc' | 'desc' =
|
|
params.direction === 'asc' ? 'asc' : 'desc';
|
|
|
|
const where = this.buildWhere(params);
|
|
const skip = (safePage - 1) * safePerPage;
|
|
|
|
const [rows, total] = await Promise.all([
|
|
this.prisma.usuario.findMany({
|
|
where,
|
|
orderBy: { id: safeDirection },
|
|
skip,
|
|
take: safePerPage,
|
|
select: SELECT,
|
|
}),
|
|
this.prisma.usuario.count({ where }),
|
|
]);
|
|
|
|
const content: UsuariosResponseDto[] = plainToInstance(
|
|
UsuariosResponseDto,
|
|
rows,
|
|
{ excludeExtraneousValues: true },
|
|
);
|
|
|
|
const totalPages = Math.max(1, Math.ceil(total / safePerPage));
|
|
|
|
return {
|
|
content,
|
|
pagination: {
|
|
page: safePage,
|
|
direction: safeDirection,
|
|
perPage: safePerPage,
|
|
total,
|
|
totalPages,
|
|
hasNext: safePage < totalPages,
|
|
hasPrev: safePage > 1,
|
|
},
|
|
};
|
|
}
|
|
|
|
async get(uuid: string): Promise<UsuariosResponseDto> {
|
|
const row = await this.prisma.usuario.findUnique({
|
|
where: { uuid },
|
|
select: SELECT,
|
|
});
|
|
|
|
if (!row) {
|
|
throw new NotFoundException('Usuário não encontrado');
|
|
}
|
|
|
|
return plainToInstance(UsuariosResponseDto, row, {
|
|
excludeExtraneousValues: true,
|
|
});
|
|
}
|
|
|
|
async update(id: number, data: Prisma.UsuarioUpdateInput): Promise<Usuario> {
|
|
return this.prisma.usuario.update({
|
|
where: { id },
|
|
data,
|
|
});
|
|
}
|
|
|
|
async create(dto: CreateUsuarioDto): Promise<UsuariosResponseDto> {
|
|
const { email, password, nome, sobrenome } = dto;
|
|
|
|
const senhaCriptografada = await bcrypt.hash(password, 10);
|
|
|
|
const usuario = await this.prisma.usuario.create({
|
|
data: {
|
|
email,
|
|
password: senhaCriptografada,
|
|
nome,
|
|
sobrenome,
|
|
},
|
|
});
|
|
|
|
return plainToInstance(UsuariosResponseDto, usuario, {
|
|
excludeExtraneousValues: true,
|
|
});
|
|
}
|
|
|
|
async delete(id: number): Promise<Usuario> {
|
|
return this.prisma.usuario.delete({
|
|
where: { id },
|
|
});
|
|
}
|
|
|
|
async emailVerificado(uuid: string): Promise<UsuariosResponseDto> {
|
|
const usuario = await this.prisma.usuario.update({
|
|
where: { uuid },
|
|
data: { email_verificado: 'V' },
|
|
});
|
|
|
|
return plainToInstance(UsuariosResponseDto, usuario, {
|
|
excludeExtraneousValues: true,
|
|
});
|
|
}
|
|
}
|