import { Args, Mutation, Resolver } from '@nestjs/graphql'; import { PrismaService } from '../prisma/prisma.service'; import { AgentModel } from './models/agent.model'; import { NotFoundException, UseGuards } from '@nestjs/common'; import { AuthGuard } from '../auth/auth.guard'; import { AdminGuard } from '../auth/admin.guard'; import { AgentInputModel } from './models/agent-input.model'; import { GroupModel } from './models/group.model'; import { GroupInputModel } from './models/group-input.model'; import { TokenCodeModel } from './models/token-code.model'; import { TokenCodeInputModel } from './models/token-code-input.model'; import { EntryModel } from './models/entry.model'; import { EntryService } from '../utils/entry.service'; import { PubSub } from 'graphql-subscriptions'; import { GraphQLString } from 'graphql/type'; @Resolver() export class AdminResolver { constructor( private readonly pubSub: PubSub, private readonly prisma: PrismaService, private readonly entryService: EntryService, ) {} @Mutation(() => AgentModel) @UseGuards(AuthGuard, AdminGuard) async createAgent( @Args('data') data: AgentInputModel, ): Promise<AgentModel> { const agent = await this.prisma.agent.create({ data: { ...data, tokenCodes: { create: { value: 1 }, }, }, }); await this.pubSub.publish('onAgentUpdate', agent); return agent; } @Mutation(() => AgentModel) @UseGuards(AuthGuard, AdminGuard) async updateAgent( @Args('id') id: string, @Args('data') data: AgentInputModel, ): Promise<AgentModel> { const agent = await this.prisma.agent.update({ where: { id }, data, }); await this.pubSub.publish('onAgentUpdate', agent); return agent; } @Mutation(() => AgentModel) @UseGuards(AuthGuard, AdminGuard) async deleteAgent(@Args('id') id: string): Promise<AgentModel> { const agent = await this.prisma.agent.delete({ where: { id }, }); await this.pubSub.publish('onAgentUpdate', { id: agent.id, deleted: true, }); return agent; } @Mutation(() => GroupModel) @UseGuards(AuthGuard, AdminGuard) async createGroup( @Args('data') data: GroupInputModel, ): Promise<GroupModel> { const group = await this.prisma.group.create({ data, }); await this.pubSub.publish('onGroupUpdate', group); return group; } @Mutation(() => GroupModel) @UseGuards(AuthGuard, AdminGuard) async updateGroup( @Args('id') id: string, @Args('data') data: GroupInputModel, ): Promise<GroupModel> { const group = await this.prisma.group.update({ where: { id }, data, }); await this.pubSub.publish('onGroupUpdate', group); return group; } @Mutation(() => GroupModel) @UseGuards(AuthGuard, AdminGuard) async deleteGroup(@Args('id') id: string): Promise<GroupModel> { const group = await this.prisma.group.delete({ where: { id }, }); await this.pubSub.publish('onGroupUpdate', { id: group.id, deleted: true, }); return group; } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AdminGuard) async createTokenCode( @Args('agentId') agentId: string, @Args('data') data: TokenCodeInputModel, ): Promise<TokenCodeModel> { return await this.prisma.$transaction(async (prisma) => { const codes = await prisma.tokenCode.findMany({ where: { agentId }, }); await prisma.tokenCode.deleteMany({ where: { agentId }, }); for (const code of codes) { await this.pubSub.publish('onTokenCodeUpdate', { id: code.id, deleted: true, }); } const code = prisma.tokenCode.create({ data: { ...data, agent: { connect: { id: agentId }, }, }, }); await this.pubSub.publish('onTokenCodeUpdate', code); return code; }); } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AdminGuard) async updateTokenCode( @Args('tokenCode') tokenCode: string, @Args('data') data: TokenCodeInputModel, ): Promise<TokenCodeModel> { return await this.prisma.tokenCode.update({ where: { id: tokenCode }, data, }); } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AdminGuard) async deleteTokenCode( @Args('tokenCode') tokenCode: string, ): Promise<TokenCodeModel> { return await this.prisma.$transaction(async (prisma) => { const toDelete = await prisma.tokenCode.findFirst({ where: { id: tokenCode }, }); if (!toDelete) throw new NotFoundException(); const agentCount = await prisma.tokenCode.count({ where: { agentId: toDelete.agentId }, }); await this.pubSub.publish('onTokenCodeUpdate', { id: toDelete.id, deleted: true, }); if (agentCount <= 1) { await prisma.tokenCode.create({ data: { value: 1, agent: { connect: { id: toDelete.agentId }, }, }, }); } const deleted = await prisma.tokenCode.delete({ where: { id: tokenCode }, }); await this.pubSub.publish('onTokenCodeUpdate', { id: deleted.id, deleted: true, }); return deleted; }); } @Mutation(() => TokenCodeModel) @UseGuards(AuthGuard, AdminGuard) deleteEntry(@Args('id') id: string): Promise<EntryModel> { return this.prisma.entry .delete({ where: { id }, }) .then(async (entry) => { await this.pubSub.publish('onEntryUpdate', entry); return this.entryService.unlockedEntry(entry); }); } @Mutation(() => GraphQLString, { nullable: true }) @UseGuards(AuthGuard, AdminGuard) async broadcastCommand(@Args('command') command: string) { await this.pubSub.publish('onCommand', command); } }