Skip to content

Commit f49653f

Browse files
committed
feat: protegendo as rotas de upload pdf e pagina web com JWT
1 parent a0e2550 commit f49653f

10 files changed

Lines changed: 86 additions & 20 deletions

File tree

src/common/guards/auth.guard.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
2+
import {
3+
CanActivate,
4+
ExecutionContext,
5+
Injectable,
6+
UnauthorizedException,
7+
} from '@nestjs/common'
8+
import { JwtService } from '@nestjs/jwt'
9+
import { Request } from 'express'
10+
import { ConfigService } from '@nestjs/config'
11+
import { TokenInvalidoException } from '@/errors/auth/token-invalido.exception'
12+
13+
@Injectable()
14+
export class AuthGuard implements CanActivate {
15+
constructor(
16+
private jwtService: JwtService,
17+
private configService: ConfigService,
18+
) {}
19+
20+
async canActivate(context: ExecutionContext): Promise<boolean> {
21+
const request = context.switchToHttp().getRequest()
22+
const token = this.extractTokenFromHeader(request)
23+
if (!token) {
24+
throw new TokenInvalidoException()
25+
}
26+
try {
27+
const payload = await this.jwtService.verifyAsync(token, {
28+
secret: this.configService.get<string>('JWT_SECRET'),
29+
})
30+
request['user'] = payload
31+
} catch {
32+
throw new UnauthorizedException()
33+
}
34+
return true
35+
}
36+
37+
private extractTokenFromHeader(request: Request): string | undefined {
38+
const [type, token] = request.headers.authorization?.split(' ') ?? []
39+
return type === 'Bearer' ? token : undefined
40+
}
41+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface UserPayload {
2+
sub: string
3+
username: string
4+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Request } from 'express'
2+
import { UserPayload } from './user-payload.props'
3+
4+
export interface UserRequest extends Request {
5+
user: UserPayload
6+
}

src/controllers/__tests__/unit/document.controller.spec.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/* eslint-disable @typescript-eslint/no-unused-vars */
2-
/* eslint-disable @typescript-eslint/unbound-method */
3-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
2+
43
import { Test, TestingModule } from '@nestjs/testing'
54
import { DocumentController } from '../../document.controller'
65
import { DocumentService } from '../../../services/document.service'
76
import { PdfProcessingService } from '../../../services/pdf-processing.service'
87
import { ClientService } from '../../../services/client.service'
98
import { WebProcessingService } from '@/services/web-processing.service'
109
import { HttpModule } from '@nestjs/axios'
10+
import { JwtModule } from '@nestjs/jwt'
11+
import { ConfigModule } from '@nestjs/config'
1112

1213
describe('DocumentController', () => {
1314
let controller: DocumentController
@@ -17,7 +18,7 @@ describe('DocumentController', () => {
1718

1819
beforeEach(async () => {
1920
const module: TestingModule = await Test.createTestingModule({
20-
imports: [HttpModule],
21+
imports: [HttpModule, JwtModule, ConfigModule],
2122
controllers: [DocumentController],
2223
providers: [
2324
WebProcessingService,
@@ -57,6 +58,7 @@ describe('DocumentController', () => {
5758
expect(controller).toBeDefined()
5859
})
5960

61+
/*
6062
describe('create', () => {
6163
it('should call service.create and return the result', async () => {
6264
const dto = { title: 'Test', content: 'Content', clientId: '1' } as any
@@ -69,4 +71,5 @@ describe('DocumentController', () => {
6971
expect(result).toEqual(createdDocument)
7072
})
7173
})
74+
*/
7275
})

src/controllers/document.controller.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@ import {
88
Delete,
99
UseInterceptors,
1010
UploadedFile,
11+
UseGuards,
12+
Req,
1113
} from '@nestjs/common'
1214
import { DocumentService } from '../services/document.service'
13-
import { CreateDocumentDto } from '@/dtos/document/create-document.dto'
1415
import { UpdateDocumentDto } from '@/dtos/document/update-document.dto'
1516
import { FileInterceptor } from '@nestjs/platform-express'
1617
import { PdfProcessingService } from '@/services/pdf-processing.service'
1718
import { ClientService } from '@/services/client.service'
1819
import { WebDocumentDto } from '@/dtos/document/web-document.dto'
1920
import { WebProcessingService } from '@/services/web-processing.service'
21+
import { AuthGuard } from '@/common/guards/auth.guard'
22+
import { UserRequest } from '@/contracts/user-request.interface'
2023

2124
@Controller('document')
2225
export class DocumentController {
@@ -27,39 +30,36 @@ export class DocumentController {
2730
private readonly clientService: ClientService,
2831
) {}
2932

30-
@Post()
31-
async create(@Body() createDocumentDto: CreateDocumentDto) {
32-
return await this.documentService.create(createDocumentDto)
33-
}
34-
35-
@Post('pdf/:id')
33+
@Post('pdf')
34+
@UseGuards(AuthGuard)
3635
@UseInterceptors(FileInterceptor('file'))
3736
async createPdfDocument(
3837
@UploadedFile() file: Express.Multer.File,
39-
@Param('id') clientId: string,
38+
@Req() request: UserRequest,
4039
) {
4140
const { title, content } =
4241
await this.pdfProcessingService.extractTitleAndContent(file)
4342

44-
await this.clientService.findOne(clientId)
43+
await this.clientService.findOne(request.user.sub)
4544
return await this.documentService.createPdfDocument(
4645
{ title, content },
47-
clientId,
46+
request.user.sub,
4847
)
4948
}
5049

51-
@Post('web/:id')
50+
@Post('web')
51+
@UseGuards(AuthGuard)
5252
async createWebDocument(
5353
@Body() webDocumentDto: WebDocumentDto,
54-
@Param('id') clientId: string,
54+
@Req() request: UserRequest,
5555
) {
5656
const { title, content } =
5757
await this.webProcessingService.extractTitleAndContent(webDocumentDto.url)
5858

59-
await this.clientService.findOne(clientId)
59+
await this.clientService.findOne(request.user.sub)
6060
return await this.documentService.createWebDocument(
6161
{ title, content },
62-
clientId,
62+
request.user.sub,
6363
)
6464
}
6565

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { HttpException, HttpStatus } from '@nestjs/common'
2+
3+
export class TokenInvalidoException extends HttpException {
4+
constructor() {
5+
super('Token de acesso inválido', HttpStatus.UNAUTHORIZED)
6+
}
7+
}

src/modules/auth.module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config'
88
@Module({
99
imports: [
1010
ClientModule,
11+
ConfigModule,
1112
JwtModule.registerAsync({
1213
imports: [ConfigModule],
1314
inject: [ConfigService],

src/modules/client.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { ClientService } from '../services/client.service'
33
import { ClientController } from '../controllers/client.controller'
44
import { ClientRepository } from '../repositories/client.repository'
55
import { DatabaseModule } from '@/modules/database.module'
6+
import { JwtModule } from '@nestjs/jwt'
67

78
@Module({
8-
imports: [DatabaseModule],
9+
imports: [DatabaseModule, JwtModule],
910
controllers: [ClientController],
1011
providers: [ClientService, ClientRepository],
1112
exports: [ClientService, ClientRepository],

src/modules/document.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import { ClientModule } from './client.module'
77
import { PdfProcessingService } from '@/services/pdf-processing.service'
88
import { HttpModule } from '@nestjs/axios'
99
import { WebProcessingService } from '@/services/web-processing.service'
10+
import { JwtModule } from '@nestjs/jwt'
11+
import { ConfigModule } from '@nestjs/config'
1012

1113
@Module({
12-
imports: [DatabaseModule, ClientModule, HttpModule],
14+
imports: [DatabaseModule, ClientModule, HttpModule, JwtModule, ConfigModule],
1315
controllers: [DocumentController],
1416
providers: [
1517
DocumentService,

src/services/__tests__/unit/pdf-processing.service.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DocumentModule } from '@/modules/document.module'
55
import { ClientModule } from '@/modules/client.module'
66
import { DocumentoPdfInvalidoException } from '@/errors/document/documento-pdf-invalido.exception'
77
import { DocumentoConteudoInvalidoException } from '@/errors/document/documento-conteudo-invalido.exception'
8+
import { ConfigModule } from '@nestjs/config'
89

910
jest.mock('pdf-parse', () => ({
1011
__esModule: true,
@@ -20,7 +21,7 @@ describe('PdfProcessingService', () => {
2021

2122
beforeEach(async () => {
2223
const module: TestingModule = await Test.createTestingModule({
23-
imports: [DocumentModule, ClientModule],
24+
imports: [DocumentModule, ClientModule, ConfigModule],
2425
providers: [PdfProcessingService],
2526
}).compile()
2627

0 commit comments

Comments
 (0)