Skip to content
Snippets Groups Projects
admin.resolver.ts 5.67 KiB
Newer Older
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { PrismaService } from '../prisma/prisma.service';
import { AgentModel } from './models/agent.model';
import { Inject, NotFoundException, UseGuards } from '@nestjs/common';
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
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(
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
		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('id') id: string,
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
		@Args('data') data: TokenCodeInputModel,
	): Promise<TokenCodeModel> {
		const count = await this.prisma.tokenCode.count({
			where: { id },
		});

		if (count === 0) throw new NotFoundException();

		const tokenCode = await this.prisma.tokenCode.update({
			where: {
				id,
			},
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
			data,
			include: {
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
		});

		await this.pubSub.publish('onTokenCodeUpdate', tokenCode);

		return tokenCode;
Adrian Paschkowski's avatar
V2
Adrian Paschkowski committed
	}

	@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);
	}
}