import { UseGuards, NotFoundException, UnauthorizedException, ForbiddenException, } from '@nestjs/common'; import { Args, Context, Mutation, Parent, ResolveField, Resolver, Subscription, } from '@nestjs/graphql'; import { GraphQLString, GraphQLInt } from 'graphql'; import { Request } from 'express'; import { GroupAuthGuard } from '../auth/group-auth.guard'; import { PrismaService } from '../prisma/prisma.service'; import { TokenCode } from './models/tokenCode.model'; import { AgentAuthGuard } from '../auth/agent-auth.guard'; import { pubSub } from '../pubSub.instance'; @Resolver(() => TokenCode) export class TokenCodeResolver { constructor(private prismaService: PrismaService) {} @Subscription(() => TokenCode, { filter: (payload, variables, state) => payload.newTokenCode.agent.slug === variables.agentSlug, }) async newTokenCode( @Args({ name: 'agentSlug', type: () => GraphQLString }) agentSlug: string, ) { if (!agentSlug) throw new UnauthorizedException(); const agent = await this.prismaService.agent.findFirst({ where: { slug: agentSlug, }, }); if (!agent) throw new ForbiddenException(); return pubSub.asyncIterator('newTokenCode'); } @Mutation(() => TokenCode) async tokenCode( @Args({ name: 'agentSlug', type: () => GraphQLString }) agentSlug: string, ) { if (!agentSlug) throw new UnauthorizedException(); const agent = await this.prismaService.agent.findFirst({ where: { slug: agentSlug, }, }); if (!agent) throw new ForbiddenException(); let tokenCode = agent.tokenCodeId && (await this.prismaService.tokenCode.findFirst({ where: { id: agent.tokenCodeId, }, })); if (!tokenCode) { tokenCode = await this.prismaService.tokenCode.create({ data: { value: 1, agent: { connect: { id: agent.id }, }, }, include: { agent: true, }, }); await pubSub.publish('newTokenCode', { newTokenCode: tokenCode, }); } return tokenCode; } @UseGuards(GroupAuthGuard) @Mutation(() => GraphQLInt) async redeemCode( @Args({ name: 'tokenCode', type: () => GraphQLString }) code: string, @Context() { req }: { req: Request }, ) { const tokenCode = await this.prismaService.tokenCode.findFirst({ where: { id: code }, include: { agent: true, }, }); if (!tokenCode) throw new NotFoundException(); const newTokenCode = await this.prismaService.tokenCode.create({ data: { value: 1, agent: { connect: { id: tokenCode.agent.id }, }, }, include: { agent: true, }, }); await pubSub.publish('newTokenCode', { newTokenCode: newTokenCode, }); await this.prismaService.tokenCode.delete({ where: { id: tokenCode.id }, }); req.group = await this.prismaService.group.update({ where: { id: req.group.id }, data: { tokens: { increment: tokenCode.value, }, }, }); await pubSub.publish('updateToken', { updateToken: req.group, }); return tokenCode.value; } @ResolveField('agent') agent(@Parent() token: TokenCode) { return this.prismaService.agent.findFirst({ where: { tokenCodeId: token.id, }, }); } }