import { Args, Context, Mutation, Query, Resolver, Subscription, } from '@nestjs/graphql'; import { TokenCodeModel } from './models/token-code.model'; import { PrismaService } from '../prisma/prisma.service'; import { Request } from 'express'; import { Inject, NotFoundException, UseGuards } from '@nestjs/common'; import { AuthGuard } from '../auth/auth.guard'; import { AgentGuard } from '../auth/agent.guard'; import { GroupGuard } from '../auth/group.guard'; import { TokenCode } from '@prisma/client'; import { AgentFlags } from './models/agent.model'; import { PubSub } from 'graphql-subscriptions'; import { TokenCodeInputModel } from './models/token-code-input.model'; @Resolver(() => TokenCodeModel) export class TokenCodeResolver { constructor( @Inject('PUBSUB') private readonly pubSub: PubSub, private readonly prisma: PrismaService, ) {} @Subscription(() => TokenCodeModel, { filter: (payload: TokenCode, variables, { req }: { req: Request }) => { return req.agent && req.agent.id === payload.agentId; }, }) @UseGuards(AuthGuard) onTokenCodeUpdate(@Context('pubsub') pubSub: PubSub) { return pubSub.asyncIterator('onTokenCodeUpdate'); } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AgentGuard) async invalidateTokenCode( @Args('tokenCode') tokenCode: string, @Context() { req }: { req: Request }, ) { return await this.prisma.$transaction(async (prisma) => { const token = await prisma.tokenCode.findFirst({ where: { id: tokenCode }, }); if (!token) throw new NotFoundException(); const newToken = await prisma.tokenCode.create({ data: { agent: { connect: { id: req.agent.id }, }, }, include: { agent: true }, }); const oldToken = await prisma.tokenCode.delete({ where: { id: tokenCode }, include: { agent: true }, }); await this.pubSub.publish('onTokenCodeUpdate', newToken); await this.pubSub.publish('onTokenCodeUpdate', { id: oldToken.id, deleted: true, }); return newToken; }); } @Query(() => [TokenCodeModel]) @UseGuards(AuthGuard) async getTokenCodes( @Context() { req }: { req: Request }, ): Promise<TokenCodeModel[]> { if (!req.agent) return []; if ((req.agent.flags & AgentFlags.ADMIN) === AgentFlags.ADMIN) return await this.prisma.tokenCode.findMany({ include: { agent: true, }, }); else return await this.prisma.tokenCode.findMany({ where: { agentId: req.agent.id }, include: { agent: { select: { id: true, bio: true, name: true, slug: false, flags: true, avatar: true, }, }, }, }); } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, GroupGuard) async redeemTokenCode( @Args('tokenCode') tokenCode: string, @Context() { req }: { req: Request }, ): Promise<TokenCodeModel> { return this.prisma.$transaction(async (prisma) => { const token = await prisma.tokenCode.findFirst({ where: { id: tokenCode }, include: { agent: { select: { id: true, bio: true, name: true, slug: false, flags: true, avatar: true, }, }, }, }); if (!token) throw new NotFoundException(); const deleted = await prisma.tokenCode.delete({ where: { id: tokenCode }, }); const { tokenCodes } = await prisma.agent.update({ where: { id: token.agentId }, data: { tokenCodes: { create: { value: 1 }, }, }, include: { tokenCodes: true }, }); const group = await prisma.group.update({ where: { id: req.group.id }, data: { tokens: { increment: token.value }, }, }); await this.pubSub.publish('onTokenCodeUpdate', { id: deleted.id, deleted: true, }); await this.pubSub.publish('onGroupUpdate', group); await this.pubSub.publish('onTokenCodeUpdate', tokenCodes[0]); return token; }); } /*@Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AgentGuard) async updateTokenCode( @Args('id') id: string, @Args('data') data: TokenCodeInputModel, @Context() { req }: { req: Request }, ): Promise<TokenCode> { const count = await this.prisma.tokenCode.count({ where: { id, agentId: req.agent.id }, }); if (count === 0) throw new NotFoundException(); const tokenCode = await this.prisma.tokenCode.update({ where: { id, }, data, include: { agent: { select: { id: true, bio: true, name: true, slug: false, flags: true, avatar: true, }, }, }, }); await this.pubSub.publish('onTokenCodeUpdate', tokenCode); return tokenCode; }*/ /*@ResolveField('agent') async agent(@Parent() parent: TokenCodeModel): Promise<AgentModel> { return this.prisma.agent.findFirst({ where: { tokenCodes: { some: { id: parent.id }, }, }, select: { id: true, bio: true, name: true, slug: false, flags: true, avatar: true, }, }); }*/ }