-
Adrian Paschkowski authoredAdrian Paschkowski authored
entry.resolver.ts 2.88 KiB
import {
Args,
Context,
Mutation,
Parent,
Query,
ResolveField,
Resolver,
Subscription,
} from '@nestjs/graphql';
import { EntryModel } from './models/entry.model';
import { PrismaService } from '../prisma/prisma.service';
import {
BadRequestException,
Inject,
InternalServerErrorException,
NotFoundException,
UseGuards,
} from '@nestjs/common';
import { AuthGuard } from '../auth/auth.guard';
import { Request } from 'express';
import { EntryService } from '../utils/entry.service';
import { AgentModel } from './models/agent.model';
import { GroupGuard } from '../auth/group.guard';
import { PubSub } from 'graphql-subscriptions';
import { Entry, Group } from '@prisma/client';
@Resolver(() => EntryModel)
export class EntryResolver {
constructor(
@Inject('PUBSUB')
private readonly pubSub: PubSub,
private readonly prisma: PrismaService,
private readonly entryService: EntryService,
) {}
@Subscription(() => EntryModel, {
filter: (
payload: { onEntryUpdate: Entry & { by?: Group } },
variables,
{ req },
) => {
if (req.group && payload.onEntryUpdate.by)
return req.group.id === payload.onEntryUpdate.by.id;
return true;
},
})
@UseGuards(AuthGuard)
onEntryUpdate() {
return this.pubSub.asyncIterator('onEntryUpdate');
}
@Mutation(() => EntryModel)
@UseGuards(AuthGuard, GroupGuard)
unlockEntry(
@Args('id') id: string,
@Context() { req }: { req: Request },
): Promise<EntryModel> {
return this.prisma.$transaction(async (prisma) => {
const entry = await prisma.entry.findFirst({
where: {
id,
unlockedBy: {
none: { id: req.group.id },
},
},
});
if (!entry) throw new NotFoundException();
if (req.group.tokens < entry.cost)
throw new BadRequestException('Not enough tokens');
const group = await prisma.group.update({
where: { id: req.group.id },
data: {
tokens: { decrement: entry.cost },
unlocks: {
connect: { id: entry.id },
},
},
});
if (!group)
throw new InternalServerErrorException('Group not found');
await this.pubSub.publish('onEntryUpdate', {
onEntryUpdate: {
...entry,
by: group,
},
});
await this.pubSub.publish('onGroupUpdate', {
onGroupUpdate: group,
});
return this.entryService.unlockedEntry(entry);
});
}
@Query(() => [EntryModel])
@UseGuards(AuthGuard)
async getEntries(@Context() { req }: { req: Request }) {
if (req.agent)
return this.prisma.entry
.findMany()
.then((entries) =>
entries.map(this.entryService.unlockedEntry),
);
return await this.entryService.getAccessibleEntries(req.group.id);
}
@ResolveField('agent')
async agent(@Parent() parent: EntryModel): Promise<AgentModel> {
return this.prisma.agent.findFirst({
where: {
entries: {
some: { id: parent.id },
},
},
select: {
id: true,
name: true,
slug: false,
flags: true,
},
});
}
}