Merge branch 'main' of git.targo.ca:Targo/targo_backend into dev/matthieu/refactor

This commit is contained in:
Matthieu Haineault 2025-10-30 15:05:20 -04:00
commit 68f29b8842
8 changed files with 76 additions and 70 deletions

View File

@ -17,9 +17,7 @@ ENV AUTHENTIK_AUTH_URL="https://auth.targo.ca/application/o/authorize/"
ENV AUTHENTIK_TOKEN_URL="https://auth.targo.ca/application/o/token/" ENV AUTHENTIK_TOKEN_URL="https://auth.targo.ca/application/o/token/"
ENV AUTHENTIK_USERINFO_URL="https://auth.targo.ca/application/o/userinfo/" ENV AUTHENTIK_USERINFO_URL="https://auth.targo.ca/application/o/userinfo/"
ENV TARGO_FRONTEND_URI_1="http://targo-frontend-nicolas:9000" ENV TARGO_FRONTEND_URI="http://10.100.251.2/"
ENV TARGO_FRONTEND_URI_2="http://targo-frontend-matthieu:9000"
ENV TARGO_FRONTEND_URI_3="http://targo-frontend-lion:9000"
ENV ATTACHMENTS_SERVER_ID="server" ENV ATTACHMENTS_SERVER_ID="server"
ENV ATTACHMENTS_ROOT=C:/ ENV ATTACHMENTS_ROOT=C:/

View File

@ -315,7 +315,7 @@ model AttachmentVariants {
attachment_id Int attachment_id Int
attachment Attachments @relation("attachmentVariantAttachment",fields: [attachment_id], references: [id], onDelete: Cascade) attachment Attachments @relation("attachmentVariantAttachment",fields: [attachment_id], references: [id], onDelete: Cascade)
variant String variant String
patch String path String
bytes Int bytes Int
width Int? width Int?
height Int? height Int?

View File

@ -12,7 +12,7 @@ export class AuthController {
@Get('/callback') @Get('/callback')
@UseGuards(OIDCLoginGuard) @UseGuards(OIDCLoginGuard)
loginCallback(@Req() req: Request, @Res() res: Response) { loginCallback(@Req() req: Request, @Res() res: Response) {
res.redirect('http://localhost:9000/#/login-success'); res.redirect('http://10.100.251.2:9011/#/login-success');
} }
@Get('/me') @Get('/me')

View File

@ -1,10 +1,10 @@
import 'reflect-metadata'; import 'reflect-metadata';
//import and if case for @nestjs/schedule Cron jobs //import and if case for @nestjs/schedule Cron jobs
import * as nodeCrypto from 'crypto'; import * as nodeCrypto from 'crypto';
if(!(globalThis as any).crypto) { if (!(globalThis as any).crypto) {
(globalThis as any).crypto = nodeCrypto; (globalThis as any).crypto = nodeCrypto;
} }
import { ensureAttachmentsTmpDir } from './config/attachment.fs'; import { ensureAttachmentsTmpDir } from './config/attachment.fs';
import { resolveAttachmentsRoot } from './config/attachment.config';// log to be removed post dev import { resolveAttachmentsRoot } from './config/attachment.config';// log to be removed post dev
import { ATT_TMP_DIR } from './config/attachment.config'; // log to be removed post dev import { ATT_TMP_DIR } from './config/attachment.config'; // log to be removed post dev
@ -20,72 +20,72 @@ import * as session from 'express-session';
import * as passport from 'passport'; import * as passport from 'passport';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
const reflector = app.get(Reflector); //setup Reflector for Roles() const reflector = app.get(Reflector); //setup Reflector for Roles()
app.useGlobalGuards( app.useGlobalGuards(
// new JwtAuthGuard(reflector), //Authentification JWT // new JwtAuthGuard(reflector), //Authentification JWT
new RolesGuard(reflector), //deny-by-default and Role-based Access Control new RolesGuard(reflector), //deny-by-default and Role-based Access Control
new OwnershipGuard(reflector, app.get(ModuleRef)), //Global use of OwnershipGuard, not implemented yet new OwnershipGuard(reflector, app.get(ModuleRef)), //Global use of OwnershipGuard, not implemented yet
); );
// Authentication and session // Authentication and session
app.use(session({ app.use(session({
secret: 'This is a super secret dev secret that you cant share with anyone', secret: 'This is a super secret dev secret that you cant share with anyone',
resave: false, resave: false,
saveUninitialized: false, saveUninitialized: false,
rolling: true, rolling: true,
cookie: { cookie: {
maxAge: 30 * 60 * 1000, maxAge: 30 * 60 * 1000,
httpOnly: true, httpOnly: true,
} }
})) }))
app.use(passport.initialize()); app.use(passport.initialize());
app.use(passport.session()); app.use(passport.session());
// Enable CORS // Enable CORS
app.enableCors({ app.enableCors({
origin: [process.env.TARGO_FRONTEND_URI_1, process.env.TARGO_FRONTEND_URI_2, process.env.TARGO_FRONTEND_URI_3], origin: ['http://10.100.251.2:9011', 'http://10.100.251.2:9012', 'http://10.100.251.2:9013'],
credentials: true, credentials: true,
}); });
//swagger config
const config = new DocumentBuilder()
.setTitle('Targo_Backend')
.setDescription('Documentation de l`API REST pour Targo (NestJS + Prisma)')
.setVersion('1.0')
.addBearerAuth({
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
name: 'Authorization',
description: 'Invalid JWT token',
in: 'header',
}, 'access-token')
.addTag('Users')
.addTag('Employees')
.addTag('Customers')
.addTag('Timesheets')
.addTag('Shifts')
.addTag('Leave Requests')
.addTag('Shift Codes')
.addTag('OAuth Access Tokens')
.addTag('Authorization')
.build();
//swagger config
const config = new DocumentBuilder()
.setTitle('Targo_Backend')
.setDescription('Documentation de l`API REST pour Targo (NestJS + Prisma)')
.setVersion('1.0')
.addBearerAuth({
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
name: 'Authorization',
description: 'Invalid JWT token',
in: 'header',
}, 'access-token')
.addTag('Users')
.addTag('Employees')
.addTag('Customers')
.addTag('Timesheets')
.addTag('Shifts')
.addTag('Leave Requests')
.addTag('Shift Codes')
.addTag('OAuth Access Tokens')
.addTag('Authorization')
.build();
//document builder for swagger docs //document builder for swagger docs
const documentFactory = () => SwaggerModule.createDocument(app, config); const documentFactory = () => SwaggerModule.createDocument(app, config);
const document = documentFactory() const document = documentFactory()
SwaggerModule.setup('api/docs', app, document); SwaggerModule.setup('api/docs', app, document);
writeFileSync('./docs/swagger/swagger-spec.json', JSON.stringify(document, null, 2)); writeFileSync('./docs/swagger/swagger-spec.json', JSON.stringify(document, null, 2));
// logs to be removed post dev // logs to be removed post dev
console.log('[ENV.ATTACHMENTS_ROOT]', process.env.ATTACHMENTS_ROOT); console.log('[ENV.ATTACHMENTS_ROOT]', process.env.ATTACHMENTS_ROOT);
console.log('[resolveAttachmentsRoot()]', resolveAttachmentsRoot()); console.log('[resolveAttachmentsRoot()]', resolveAttachmentsRoot());
console.log('[ATT_TMP_DIR()]', ATT_TMP_DIR()); console.log('[ATT_TMP_DIR()]', ATT_TMP_DIR());
await ensureAttachmentsTmpDir(); await ensureAttachmentsTmpDir();
await app.listen(process.env.PORT ?? 3000); await app.listen(process.env.PORT ?? 3000);
} }
bootstrap(); bootstrap();

View File

@ -1,8 +1,8 @@
// import { Injectable, Logger } from "@nestjs/common"; // import { TimesheetArchiveService } from "src/time-and-attendance/modules/time-tracker/timesheets/services/timesheet-archive.service";
// import { Cron } from "@nestjs/schedule";
// import { ExpensesArchivalService } from "src/time-and-attendance/modules/expenses/services/expenses-archival.service"; // import { ExpensesArchivalService } from "src/time-and-attendance/modules/expenses/services/expenses-archival.service";
// import { ShiftsArchivalService } from "src/time-and-attendance/modules/time-tracker/shifts/services/shifts-archival.service"; // import { ShiftsArchivalService } from "src/time-and-attendance/modules/time-tracker/shifts/services/shifts-archival.service";
// import { TimesheetArchiveService } from "src/time-and-attendance/modules/time-tracker/timesheets/services/timesheet-archive.service"; // import { Injectable, Logger } from "@nestjs/common";
// import { Cron } from "@nestjs/schedule";
// @Injectable() // @Injectable()
// export class ArchivalService { // export class ArchivalService {

View File

@ -1,15 +1,19 @@
import { ScheduleModule } from "@nestjs/schedule"; import { ArchivalAttachmentService } from "src/modules/attachments/services/archival-attachment.service";
import { PrismaService } from "src/prisma/prisma.service"; import { GarbargeCollectorService } from "src/modules/attachments/services/garbage-collector.service";
import { ArchivalAttachmentService } from "./services/archival-attachment.service"; import { AttachmentsController } from "src/modules/attachments/controllers/attachments.controller";
import { DiskStorageService } from "src/modules/attachments/services/disk-storage.service";
// import { ScheduleModule } from "@nestjs/schedule";
import { VariantsQueue } from "src/modules/attachments/services/variants.queue";
import { Module } from "@nestjs/common"; import { Module } from "@nestjs/common";
import { GarbargeCollectorService } from "./services/garbage-collector.service";
@Module({ @Module({
imports: [ScheduleModule.forRoot()], // imports: [ScheduleModule.forRoot()],
controllers: [ AttachmentsController],
providers: [ providers: [
PrismaService,
ArchivalAttachmentService, ArchivalAttachmentService,
GarbargeCollectorService, GarbargeCollectorService,
DiskStorageService,
VariantsQueue,
], ],
exports: [ exports: [
ArchivalAttachmentService, ArchivalAttachmentService,

View File

@ -1,3 +1,4 @@
import { Injectable } from '@nestjs/common';
import { createHash } from 'node:crypto'; import { createHash } from 'node:crypto';
import { promises as fsp } from 'node:fs'; import { promises as fsp } from 'node:fs';
import { createWriteStream, statSync, existsSync } from 'node:fs'; import { createWriteStream, statSync, existsSync } from 'node:fs';
@ -7,6 +8,7 @@ import { ATT_TMP_DIR, resolveAttachmentsRoot } from 'src/config/attachment.confi
export type SaveResult = { sha256:string, storage_path:string, size:number}; export type SaveResult = { sha256:string, storage_path:string, size:number};
@Injectable()
export class DiskStorageService { export class DiskStorageService {
private root = resolveAttachmentsRoot(); private root = resolveAttachmentsRoot();
@ -38,7 +40,7 @@ export class DiskStorageService {
const hash = createHash('sha256'); const hash = createHash('sha256');
const tmpOut = createWriteStream(tmpPath); const tmpOut = createWriteStream(tmpPath);
input.on('date', (chunk) => hash.update(chunk)); input.on('data', (chunk) => hash.update(chunk));
await pipeline(input, tmpOut); //await end of writing stream await pipeline(input, tmpOut); //await end of writing stream
const sha = hash.digest('hex'); const sha = hash.digest('hex');

View File

@ -1,5 +1,7 @@
import { Injectable } from "@nestjs/common";
import { Queue } from "bullmq"; import { Queue } from "bullmq";
@Injectable()
export class VariantsQueue { export class VariantsQueue {
private queue : Queue; private queue : Queue;