Skip to content

Commit

Permalink
Feat: Histórico de suprimentos (#162)
Browse files Browse the repository at this point in the history
1. **Criada Tabela de Registro de Histórico de Supplies dos abrigos**
- Foi criada uma nova tabela no banco de dados para registrar o
histórico de cada supply de cada abrigo, permitindo um melhor
acompanhamento e gerenciamento dos recursos, incluindo dados como ip e
user agent do usuário;

2. **Criado Decorator para Registro de Log de Supplies**
- Implementado um decorator para registro de log, separando a lógica do
controller da lógica de registro de log. Isso melhora a organização e
manutenção do código.

3. **Removido Dependências Desnecessárias do Express**
- As dependências desnecessárias do Express foram removidas,
considerando que o projeto utiliza Fastify. Essa mudança reduz o peso e
possíveis conflitos no projeto.

4. **Atualizado o Hook do Prisma**
- A lógica hard coded de criptografia de senhas de usuários foi removida
do hook do Prisma e movida para um módulo separado. Esse módulo agora
serve como exemplo para futuras implementações relacionadas a hooks do
Prisma.

5. **Adicionada Referência Singleton do Prisma**
- Foi adicionada a referência singleton do Prisma, facilitando o uso em
casos onde era necessário quebrar a cabeça para injetar dependências em
funções utilitárias e afins.

6. **Criado Endpoint para Listar Histórico de Suprimentos**
- Um novo endpoint foi criado para listar o histórico de suprimentos de
um abrigo de forma paginada, melhorando a eficiência na consulta e
visualização dos dados.

---

**Nota:** Essas mudanças visam melhorar a organização do código, a
eficiência do sistema e a manutenção futura do projeto.
  • Loading branch information
fagundesjg authored May 23, 2024
1 parent bc100dd commit d5be560
Show file tree
Hide file tree
Showing 38 changed files with 825 additions and 183 deletions.
364 changes: 237 additions & 127 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-fastify": "^10.3.8",
"@nestjs/swagger": "^7.3.1",
"@prisma/client": "^5.13.0",
"bcrypt": "^5.1.1",
"date-fns": "^3.6.0",
"fastify": "^4.27.0",
"passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
Expand All @@ -44,7 +44,6 @@
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/query-string": "^6.3.0",
Expand Down
17 changes: 17 additions & 0 deletions prisma/migrations/20240522191544_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- CreateTable
CREATE TABLE "supplies_history" (
"id" TEXT NOT NULL,
"shelter_id" TEXT NOT NULL,
"supply_id" TEXT NOT NULL,
"priority" INTEGER,
"quantity" INTEGER,
"created_at" VARCHAR(32) NOT NULL,

CONSTRAINT "supplies_history_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE INDEX "supplies_history_shelter_id_supply_id_idx" ON "supplies_history"("shelter_id", "supply_id");

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_shelter_id_supply_id_fkey" FOREIGN KEY ("shelter_id", "supply_id") REFERENCES "shelter_supplies"("shelter_id", "supply_id") ON DELETE RESTRICT ON UPDATE CASCADE;
26 changes: 26 additions & 0 deletions prisma/migrations/20240522195717_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Warnings:
- A unique constraint covering the columns `[sucessor_id]` on the table `supplies_history` will be added. If there are existing duplicate values, this will fail.
*/
-- DropForeignKey
ALTER TABLE "supplies_history" DROP CONSTRAINT "supplies_history_shelter_id_supply_id_fkey";

-- DropIndex
DROP INDEX "supplies_history_shelter_id_supply_id_idx";

-- AlterTable
ALTER TABLE "supplies_history" ADD COLUMN "sucessor_id" TEXT;

-- CreateIndex
CREATE UNIQUE INDEX "supplies_history_sucessor_id_key" ON "supplies_history"("sucessor_id");

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_sucessor_id_fkey" FOREIGN KEY ("sucessor_id") REFERENCES "supplies_history"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_shelter_id_fkey" FOREIGN KEY ("shelter_id") REFERENCES "shelters"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_supply_id_fkey" FOREIGN KEY ("supply_id") REFERENCES "supplies"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
22 changes: 22 additions & 0 deletions prisma/migrations/20240522200429_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Warnings:
- You are about to drop the column `sucessor_id` on the `supplies_history` table. All the data in the column will be lost.
- A unique constraint covering the columns `[predecessor_id]` on the table `supplies_history` will be added. If there are existing duplicate values, this will fail.
*/
-- DropForeignKey
ALTER TABLE "supplies_history" DROP CONSTRAINT "supplies_history_sucessor_id_fkey";

-- DropIndex
DROP INDEX "supplies_history_sucessor_id_key";

-- AlterTable
ALTER TABLE "supplies_history" DROP COLUMN "sucessor_id",
ADD COLUMN "predecessor_id" TEXT;

-- CreateIndex
CREATE UNIQUE INDEX "supplies_history_predecessor_id_key" ON "supplies_history"("predecessor_id");

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_predecessor_id_fkey" FOREIGN KEY ("predecessor_id") REFERENCES "supplies_history"("id") ON DELETE SET NULL ON UPDATE CASCADE;
3 changes: 3 additions & 0 deletions prisma/migrations/20240522220544_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "supplies_history" ADD COLUMN "ip" TEXT,
ADD COLUMN "user_agent" TEXT;
5 changes: 5 additions & 0 deletions prisma/migrations/20240523211341_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "supplies_history" ADD COLUMN "user_id" TEXT;

-- AddForeignKey
ALTER TABLE "supplies_history" ADD CONSTRAINT "supplies_history_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
24 changes: 24 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ model User {
sessions Session[]
shelterManagers ShelterManagers[]
suppliesHistory SupplyHistory[]
@@map("users")
}
Expand Down Expand Up @@ -85,6 +86,7 @@ model Supply {
supplyCategory SupplyCategory @relation(fields: [supplyCategoryId], references: [id])
shelterSupplies ShelterSupply[]
supplyHistories SupplyHistory[]
@@map("supplies")
}
Expand Down Expand Up @@ -114,6 +116,7 @@ model Shelter {
shelterManagers ShelterManagers[]
shelterSupplies ShelterSupply[]
supplyHistories SupplyHistory[]
@@map("shelters")
}
Expand Down Expand Up @@ -151,3 +154,24 @@ model Supporters {
@@map("supporters")
}

model SupplyHistory {
id String @id @default(uuid())
predecessorId String? @unique @map("predecessor_id")
shelterId String @map("shelter_id")
supplyId String @map("supply_id")
userId String? @map("user_id")
priority Int?
quantity Int?
ip String?
userAgent String? @map("user_agent")
createdAt String @map("created_at") @db.VarChar(32)
predecessor SupplyHistory? @relation("supplyHistory", fields: [predecessorId], references: [id])
successor SupplyHistory? @relation("supplyHistory")
shelter Shelter @relation(fields: [shelterId], references: [id])
supply Supply @relation(fields: [supplyId], references: [id])
user User? @relation(fields: [userId], references: [id])
@@map("supplies_history")
}
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ShelterManagersModule } from './shelter-managers/shelter-managers.modul
import { ShelterSupplyModule } from './shelter-supply/shelter-supply.module';
import { PartnersModule } from './partners/partners.module';
import { SupportersModule } from './supporters/supporters.module';
import { SuppliesHistoryModule } from './supplies-history/supplies-history.module';

@Module({
imports: [
Expand All @@ -26,6 +27,7 @@ import { SupportersModule } from './supporters/supporters.module';
ShelterSupplyModule,
PartnersModule,
SupportersModule,
SuppliesHistoryModule,
],
controllers: [],
providers: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { applyDecorators, UseInterceptors } from '@nestjs/common';

import { ShelterSupplyHistoryAction } from '@/interceptors/interceptors/shelter-supply-history/types';
import { ShelterSupplyHistoryInterceptor } from '@/interceptors/interceptors';

export function RegisterShelterSupplyHistory(
action: ShelterSupplyHistoryAction,
) {
return applyDecorators(
UseInterceptors(new ShelterSupplyHistoryInterceptor(action)),
);
}
3 changes: 3 additions & 0 deletions src/decorators/RegisterShelterSupplyHistory/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { RegisterShelterSupplyHistory } from './RegisterShelterSupplyHistory.decorator';

export { RegisterShelterSupplyHistory };
7 changes: 5 additions & 2 deletions src/guards/admin.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import { AuthGuard } from '@nestjs/passport';
import { AccessLevel } from '@prisma/client';

import { canActivate } from './utils';
import { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class AdminGuard extends AuthGuard('jwt') {
constructor() {
constructor(private readonly prismaService: PrismaService) {
super();
}

async canActivate(context: ExecutionContext): Promise<boolean> {
await super.canActivate(context);
const ok = await canActivate(context, [AccessLevel.Admin]);
const ok = await canActivate(this.prismaService, context, [
AccessLevel.Admin,
]);
if (ok) return true;

throw new HttpException('Acesso não autorizado', 401);
Expand Down
5 changes: 3 additions & 2 deletions src/guards/distribution-center.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { AuthGuard } from '@nestjs/passport';
import { AccessLevel } from '@prisma/client';

import { canActivate } from './utils';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class DistributionCenterGuard extends AuthGuard('jwt') {
constructor() {
constructor(private readonly prismaService: PrismaService) {
super();
}

async canActivate(context: ExecutionContext): Promise<boolean> {
await super.canActivate(context);
const ok = await canActivate(context, [
const ok = await canActivate(this.prismaService, context, [
AccessLevel.Admin,
AccessLevel.DistributionCenter,
]);
Expand Down
5 changes: 3 additions & 2 deletions src/guards/staff.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { AuthGuard } from '@nestjs/passport';
import { AccessLevel } from '@prisma/client';

import { canActivate } from './utils';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class StaffGuard extends AuthGuard('jwt') {
constructor() {
constructor(private readonly prismaService: PrismaService) {
super();
}

async canActivate(context: ExecutionContext): Promise<boolean> {
await super.canActivate(context);
const ok = await canActivate(context, [
const ok = await canActivate(this.prismaService, context, [
AccessLevel.Admin,
AccessLevel.Staff,
]);
Expand Down
5 changes: 3 additions & 2 deletions src/guards/user.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { AuthGuard } from '@nestjs/passport';
import { AccessLevel } from '@prisma/client';

import { canActivate } from './utils';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class UserGuard extends AuthGuard('jwt') {
constructor() {
constructor(private readonly prismaService: PrismaService) {
super();
}

async canActivate(context: ExecutionContext): Promise<boolean> {
await super.canActivate(context);
const ok = await canActivate(context, [
const ok = await canActivate(this.prismaService, context, [
AccessLevel.User,
AccessLevel.Staff,
AccessLevel.DistributionCenter,
Expand Down
13 changes: 8 additions & 5 deletions src/guards/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,32 @@ import { AccessLevel } from '@prisma/client';

import { PrismaService } from '../prisma/prisma.service';

const service = new PrismaService();

async function canActivate(context: ExecutionContext, allowed: AccessLevel[]) {
async function canActivate(
prismaService: PrismaService,
context: ExecutionContext,
allowed: AccessLevel[],
) {
const http = context.switchToHttp();
const request = http.getRequest();
if (request.user) {
const { userId, sessionId } = request.user;

return isRightSessionRole(allowed, sessionId, userId);
return isRightSessionRole(prismaService, allowed, sessionId, userId);
}

return false;
}

async function isRightSessionRole(
prismaService: PrismaService,
allowed: AccessLevel[],
sessionId?: string,
userId?: string,
) {
if (!sessionId) return false;
if (!userId) return false;

const session = await service.session.findUnique({
const session = await prismaService.session.findUnique({
where: { id: sessionId, active: true, user: { id: userId } },
include: {
user: true,
Expand Down
3 changes: 2 additions & 1 deletion src/interceptors/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ServerResponseInterceptor } from './server-response';
import { ShelterSupplyHistoryInterceptor } from './shelter-supply-history';

export { ServerResponseInterceptor };
export { ServerResponseInterceptor, ShelterSupplyHistoryInterceptor };
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Response } from 'express';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { FastifyReply } from 'fastify';

import { ServerResponse } from '@/utils/utils';

Expand All @@ -16,7 +16,7 @@ export class ServerResponseInterceptor implements NestInterceptor {
return next.handle().pipe(
map((result) => {
if (result instanceof ServerResponse) {
const response: Response = context.switchToHttp().getResponse();
const response: FastifyReply = context.switchToHttp().getResponse();
const data = result.data;
response.status(data.statusCode);
return data;
Expand Down
3 changes: 3 additions & 0 deletions src/interceptors/interceptors/shelter-supply-history/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ShelterSupplyHistoryInterceptor } from './shelter-supply-history.interceptor';

export { ShelterSupplyHistoryInterceptor };
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';

import { ShelterSupplyHistoryAction } from './types';
import { handler } from './utils';
import { prisma } from '../../../prisma/prisma.service';

@Injectable()
export class ShelterSupplyHistoryInterceptor implements NestInterceptor {
constructor(private readonly action: ShelterSupplyHistoryAction) {}

intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
handler(prisma, this.action, request);
return next.handle();
}
}
11 changes: 11 additions & 0 deletions src/interceptors/interceptors/shelter-supply-history/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export enum ShelterSupplyHistoryAction {
Create = 'shelter-supply-history-action/create',
Update = 'shelter-supply-history-action/update',
UpdateMany = 'shelter-supply-history-action/update-many',
}

export interface UserIdentity {
ip?: string;
userAgent?: string;
userId?: string;
}
Loading

0 comments on commit d5be560

Please sign in to comment.