Skip to content
Snippets Groups Projects
token-code.resolver.ts 4.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    	Args,
    	Context,
    	Mutation,
    	Query,
    	Resolver,
    	Subscription,
    
    } from '@nestjs/graphql';
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    import { TokenCodeModel } from './models/token-code.model';
    
    import { PrismaService } from '../prisma/prisma.service';
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    import { Request } from 'express';
    
    import { Inject, NotFoundException, UseGuards } from '@nestjs/common';
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    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';
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    import { PubSub } from 'graphql-subscriptions';
    import { TokenCodeInputModel } from './models/token-code-input.model';
    
    @Resolver(() => TokenCodeModel)
    
    export class TokenCodeResolver {
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    	constructor(
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    		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;
    		},
    	})
    
    xcf-t's avatar
    xcf-t committed
    	onTokenCodeUpdate() {
    		return this.pubSub.asyncIterator('onTokenCodeUpdate');
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    	}
    
    	@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 [];
    
    
    Adrian Paschkowski's avatar
    Adrian Paschkowski committed
    		if ((req.agent.flags & AgentFlags.ADMIN) === AgentFlags.ADMIN)
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    			return await this.prisma.tokenCode.findMany({
    				include: {
    					agent: true,
    				},
    			});
    
    Adrian Paschkowski's avatar
    Adrian Paschkowski committed
    		else
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    			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)
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    	@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;
    
    Adrian Paschkowski's avatar
    V2  
    Adrian Paschkowski committed
    
    	/*@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,
    			},
    		});
    	}*/