Ajustes e add usurios
This commit is contained in:
10
package.json
10
package.json
@@ -25,7 +25,7 @@
|
||||
"@nestjs/core": "11.0.1",
|
||||
"@nestjs/passport": "11.0.5",
|
||||
"@nestjs/platform-express": "11.0.1",
|
||||
"@prisma/client": "6.14.0",
|
||||
"@prisma/client": "6.18.0",
|
||||
"axios": "1.12.0",
|
||||
"bcrypt": "6.0.0",
|
||||
"class-transformer": "0.5.1",
|
||||
@@ -34,12 +34,8 @@
|
||||
"dayjs": "1.11.13",
|
||||
"jwks-rsa": "3.2.0",
|
||||
"lodash": "4.17.21",
|
||||
"ollama": "0.6.0",
|
||||
"openai": "6.1.0",
|
||||
"passport": "0.7.0",
|
||||
"passport-jwt": "4.0.1",
|
||||
"reflect-metadata": "0.2.2",
|
||||
"rxjs": "7.8.1"
|
||||
"passport-jwt": "4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "3.2.0",
|
||||
@@ -60,7 +56,7 @@
|
||||
"globals": "16.0.0",
|
||||
"jest": "30.0.0",
|
||||
"prettier": "3.4.2",
|
||||
"prisma": "6.14.0",
|
||||
"prisma": "6.18.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"supertest": "7.0.0",
|
||||
"ts-jest": "29.2.5",
|
||||
|
||||
@@ -36,21 +36,21 @@ enum eboolean {
|
||||
}
|
||||
|
||||
model videos {
|
||||
id Int @id @default(autoincrement())
|
||||
uuid String @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
datetime_download DateTime? @db.Timestamp(6)
|
||||
datetime_convert DateTime? @db.Timestamp(6)
|
||||
url String @db.VarChar(244)
|
||||
situation video_situation
|
||||
error_message String? @db.VarChar(244)
|
||||
id Int @id @default(autoincrement())
|
||||
uuid String @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
datetime_download DateTime? @db.Timestamp(6)
|
||||
datetime_convert DateTime? @db.Timestamp(6)
|
||||
url String @db.VarChar(244)
|
||||
situation video_situation @default(FILA)
|
||||
error_message String? @db.VarChar(244)
|
||||
clips_quantity Int?
|
||||
duration String? @db.VarChar(16)
|
||||
title String? @db.VarChar(244)
|
||||
filename String? @db.VarChar(244)
|
||||
videoid String? @db.VarChar(244)
|
||||
datetime_posted DateTime? @db.Timestamp(6)
|
||||
duration String? @db.VarChar(16)
|
||||
title String? @db.VarChar(244)
|
||||
filename String? @db.VarChar(244)
|
||||
videoid String? @db.VarChar(244)
|
||||
datetime_posted DateTime? @db.Timestamp(6)
|
||||
usuario_id Int?
|
||||
usuario Usuario? @relation(fields: [usuario_id], references: [id])
|
||||
usuario Usuario? @relation(fields: [usuario_id], references: [id])
|
||||
|
||||
@@map("videos")
|
||||
}
|
||||
|
||||
35
src/modules/usuarios/dto/list-usuarios-query.dto.ts
Normal file
35
src/modules/usuarios/dto/list-usuarios-query.dto.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsNumber, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
const trimString = ({ value }: { value: unknown }): string | undefined =>
|
||||
typeof value === 'string' ? value.trim() : undefined;
|
||||
|
||||
export class ListUsuariosQueryDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(trimString)
|
||||
name?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@Transform(trimString)
|
||||
email?: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => (value ? Number(value) : 1))
|
||||
page?: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => (value ? Number(value) : 10))
|
||||
perPage?: number = 10;
|
||||
|
||||
@IsOptional()
|
||||
direction: 'asc' | 'desc' = 'desc';
|
||||
|
||||
@Transform(({ value }) => value !== 'false')
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
pageable: boolean = true;
|
||||
}
|
||||
@@ -1,24 +1,42 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
Body,
|
||||
Query,
|
||||
UsePipes,
|
||||
ValidationPipe,
|
||||
Patch,
|
||||
} from '@nestjs/common';
|
||||
import { UsuariosService } from './usuarios.service';
|
||||
import { UsuariosResponseDto } from './dto/usuarios.response';
|
||||
import { CreateUsuarioDto } from './dto/create-usuario-dto';
|
||||
import { PaginatedResponse } from '@shared/dto/paginated';
|
||||
import { ListUsuariosQueryDto } from './dto/list-usuarios-query.dto';
|
||||
|
||||
@Controller('usuarios')
|
||||
export class UsuariosController {
|
||||
constructor(private readonly usuariosService: UsuariosService) {}
|
||||
|
||||
@Get()
|
||||
async list(): Promise<UsuariosResponseDto[]> {
|
||||
return this.usuariosService.list();
|
||||
async list(
|
||||
@Query() query: ListUsuariosQueryDto,
|
||||
): Promise<PaginatedResponse<UsuariosResponseDto> | UsuariosResponseDto[]> {
|
||||
if (query.pageable || query.page || query.perPage) {
|
||||
return this.usuariosService.listPaginated({
|
||||
page: query.page,
|
||||
perPage: query.perPage,
|
||||
direction: query.direction,
|
||||
name: query.name,
|
||||
email: query.email,
|
||||
});
|
||||
}
|
||||
|
||||
return this.usuariosService.list({
|
||||
name: query.name,
|
||||
email: query.email,
|
||||
});
|
||||
}
|
||||
|
||||
@Get(':uuid')
|
||||
|
||||
@@ -9,6 +9,17 @@ 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,
|
||||
@@ -30,9 +41,37 @@ const SELECT = {
|
||||
export class UsuariosService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async list(): Promise<UsuariosResponseDto[]> {
|
||||
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: { email: { not: 'admin@clipperia.com' } },
|
||||
where,
|
||||
orderBy: { id: 'desc' },
|
||||
select: SELECT,
|
||||
});
|
||||
@@ -43,20 +82,35 @@ export class UsuariosService {
|
||||
}
|
||||
|
||||
async listPaginated(
|
||||
page: number,
|
||||
perPage: number,
|
||||
direction: 'asc' | 'desc' = 'desc',
|
||||
params: ListUsuariosPaginatedParams,
|
||||
): Promise<PaginatedResponse<UsuariosResponseDto>> {
|
||||
const skip = page >= 1 ? page * perPage : 0;
|
||||
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({
|
||||
orderBy: { id: direction },
|
||||
where,
|
||||
orderBy: { id: safeDirection },
|
||||
skip,
|
||||
take: perPage ?? 1,
|
||||
take: safePerPage,
|
||||
select: SELECT,
|
||||
}),
|
||||
this.prisma.usuario.count(),
|
||||
this.prisma.usuario.count({ where }),
|
||||
]);
|
||||
|
||||
const content: UsuariosResponseDto[] = plainToInstance(
|
||||
@@ -65,18 +119,18 @@ export class UsuariosService {
|
||||
{ excludeExtraneousValues: true },
|
||||
);
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(total / perPage));
|
||||
const totalPages = Math.max(1, Math.ceil(total / safePerPage));
|
||||
|
||||
return {
|
||||
content,
|
||||
pagination: {
|
||||
page,
|
||||
direction,
|
||||
perPage,
|
||||
page: safePage,
|
||||
direction: safeDirection,
|
||||
perPage: safePerPage,
|
||||
total,
|
||||
totalPages,
|
||||
hasNext: page < totalPages,
|
||||
hasPrev: page > 1,
|
||||
hasNext: safePage < totalPages,
|
||||
hasPrev: safePage > 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ export class VideosService {
|
||||
}
|
||||
|
||||
async createNewVideo(data: CreateVideoDto): Promise<void> {
|
||||
const { url, videoid, duration, qualidade, title, timestamp } = data;
|
||||
const { url, videoid, duration, qualidade, title } = data;
|
||||
|
||||
const query: Prisma.videosWhereInput = { url };
|
||||
|
||||
@@ -194,23 +194,19 @@ export class VideosService {
|
||||
createData.duration = formattedDuration;
|
||||
}
|
||||
|
||||
if (typeof timestamp === 'number' && Number.isFinite(timestamp)) {
|
||||
createData.datetime_download = new Date(timestamp * 1000);
|
||||
}
|
||||
|
||||
await this.prisma.videos.create({
|
||||
data: createData,
|
||||
});
|
||||
|
||||
// const params = {
|
||||
// url,
|
||||
// videoid,
|
||||
// qualidade: qualidade === 'automatic' ? 'medium' : qualidade,
|
||||
// };
|
||||
const params = {
|
||||
url,
|
||||
videoid,
|
||||
qualidade: qualidade === 'automatic' ? 'medium' : qualidade,
|
||||
};
|
||||
|
||||
// await axios.get(`${N8N_REMOTE_SERVER}/webhook/download-video`, {
|
||||
// params,
|
||||
// });
|
||||
await axios.get(`${N8N_REMOTE_SERVER}/webhook/download-video`, {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
async update(id: number, data: Prisma.videosUpdateInput): Promise<videos> {
|
||||
|
||||
Reference in New Issue
Block a user