Closed trolliama closed 1 year ago
O que você acha de removermos a responsabilidade de pesquisa ao banco do controller e passarmos para um service, assim poderemos reultilizar em outras partes do código, caso necessário, bem como criar um controller só para os tickets. O Ticket tem mais argumentos, retornados do sympla, como o nome do usuário, email, o texto do código qr, temos que conferir o que vale a pena ser salvo no banco. E uma das coisas que mais me preocupam, é que se um usuário malicioso chegar até essa rota, ele pode registrar todos os ingressos com seu user id, por não termos muitos filtros por agora, como autenticação, segue a discussão 84 onde o ponto é levantado!
@trolliama Podemos usar um findUnique direto pelo userId já que cada usuário só terá um ingresso no máximo evitando a necessidade do front-end enviar o número do ingresso.
Sobre o service, podemos separar pra tirar do controller sim, mas acho que, como falei, por enquanto, quando mais simples melhor.
@diego3g Nesse caso o back apenas retornaria o número do ingresso do usuário correto? Imagino que, após isso, a partir dele será criado o qr code e este será validado a partir da api do sympla?
@diego3g @trolliama essa questão da segurança, posso tentar fazer um auth guard integrado ao clark (referenciado na live de Setup) e já fazer um pull para deixar essa feature dos tickets mais segura. O que acham?
e:
@diego3g Nesse caso o back apenas retornaria o número do ingresso do usuário correto? Imagino que, após isso, a partir dele será criado o qr code e este será validado a partir da api do sympla?
o retorno do ingresso pode ser só na rota get, para pegar o ingresso, e o envio poderia ser só na rota post, que cria o vinculo do ingresso. Para as rotas delete e get poderia ser enviado só o user id e no caso de integração de auth guard, o header de autorização!
edit 1: Fiz o guarda, e a fim de demonstrar o que quero dizer, o mesmo está presente na solicitação de Pull Request 94.
@eletroswing Acho uma ótima ideia e vi que o pull request foi aceito. Quanto a questão de apenas mandar o id do usuario para pegar e deletar o ticket, a ideia é exatamente essa eu que acabei não entendendo corretamente mas já irei ajeitar
@diego3g e @eletroswing Fiz as mudanças usando o auth guard. Por favor deem uma checada e assim que for possível eu faço os testes necessários e abro uma PR.
// app.controller.ts
import { Controller, Get, Param, Req, UseGuards } from '@nestjs/common'
import { PrismaService } from './database/prisma.service'
import { ClerkAuthGuard } from './clerk/clerk.guard'
import { RequestWithUser } from './clerk/requestInterface.dto'
import { GetTicketDto } from './agreements/retrieveTicket'
@Controller()
export class AppController {
constructor(private prisma: PrismaService) {}
@Get()
async getUsers() {
const users = await this.prisma.user.findMany()
return {
data: users,
}
}
@Get('/users/:userId/ticket')
@UseGuards(ClerkAuthGuard)
async getTicket(@Req() req: RequestWithUser, @Param() params: GetTicketDto) {
const { userId } = params
if (req.user.id !== userId) {
// TODO: throw error (403 or 401 status code?)
return { data: { message: 'unauthorized' } }
}
const ticketUser = await this.prisma.ticketToUser.findUnique({
where: {
userId,
},
})
if (!ticketUser) {
// TODO: throw error (404 status code?)
return { data: null }
}
return { data: ticketUser }
}
}
// agreements/retrieveTickets.ts
import * as z from 'zod'
export const getTicketDto = z.object({
userId: z.string(),
})
export type GetTicketDto = z.infer<typeof getTicketDto>
o Id que vc está usando ai é o client, o id do user(presente no front end) vem nas seções do usuario, da uma olhada:
{
"id": "client_2O7jNpqHMuzFQvpjTHZnsXX8x0m",
"sessionIds": [
"sess_2O7jNq3zziuyTrkg8myZ2pLTDwd"
],
"sessions": [
{
"id": "sess_2O7jNq3zziuyTrkg8myZ2pLTDwd",
"clientId": "client_2O7jNpqHMuzFQvpjTHZnsXX8x0m",
"userId": "user_2O7jK6GKRv3exxSxts0RG05vaPd",
"status": "expired",
"lastActiveAt": 1680918943789,
"expireAt": 1680920276065,
"abandonAt": 1683510476063,
"createdAt": 1680918476065,
"updatedAt": 1680918943789
}
],
"signInId": null,
"signUpId": null,
"lastActiveSessionId": null,
"createdAt": 1680918476014,
"updatedAt": 1680918476086
}
@trolliama me adiciona no discord pra gente codar isso junto, ai já fazemos o crud de pegar, vincular e deletar o ticekt e o service do ticket, ai temos uma evolução juntos, o que acha? tag: Fountai#9077
ou me manda o link da sua fork, pra trabalharmos juntos na implementação!
Massa! Já enviei o pedido
Dei uma atualizada junto com o @eletroswing no controller da rota!
Para resolver a issue mais facilmente, foi pensado o modelo completo de crud (presente no seguinte fork.). O código final ficou assim(isolando a parte de buscar o ingresso):
//schema.prisma
model Tickets {
userId String @unique
ticketNumber String @unique
@@id([userId, ticketNumber])
}
//src/tickets/tickets.service
import { Injectable } from '@nestjs/common'
import { PrismaService } from 'src/database/prisma.service'
@Injectable()
export class TicketsService {
constructor(private prisma: PrismaService) {}
async getTicketByUserId(userId: string) {
return await this.prisma.tickets.findUnique({ where: { userId } })
}
}
//app.controller
@Get('/users/ticket')
@UseGuards(ClerkAuthGuard)
async getTicketByUserId(@Req() req: RequestWithUser, @Res() res: Response) {
const userId = req.user.sessions[0].userId
const ticketInDb = await this.ticketsService.getTicketByUserId(userId)
if (!ticketInDb) {
return res
.status(404)
.json({ data: null, error: 'Ticket não encontrado' })
}
if (ticketInDb.userId !== userId) {
res
.status(403)
.json({ data: null, error: 'O conteúdo pertence a outro usuário.' })
}
return {
data: ticketInDb,
}
}
Fala @trolliama, implementei essa parte de link nos últimos commits que fiz e ficou bem legal caso queira dar uma olhada! Obrigado! <3
Agora na v2 vai ter muito mais coisa pra implementar!
Eu sei que ainda falta o esquema da comunicação que será feita entre o aplicativo e o backend mas tomei a liberdade de ir testando algumas coisas. Gostaria de trabalhar nesta feature quando o esquema do contrato estiver completo :smile:
Fiz um esquema de como mais ou menos eu imagino que seria feito essa feature:
// app.controller.ts
// agreements/retrieveTickets.ts
//schema.prisma