From d242c39e2e2209615a281c13d0c243add6c31579 Mon Sep 17 00:00:00 2001 From: An Vu Date: Tue, 10 Dec 2024 13:05:15 +0700 Subject: [PATCH] commit expose quizAttempt --- src/User/user.schema.ts | 185 +++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 95 deletions(-) diff --git a/src/User/user.schema.ts b/src/User/user.schema.ts index 1b3f0db..f867aa0 100644 --- a/src/User/user.schema.ts +++ b/src/User/user.schema.ts @@ -1,14 +1,14 @@ -import { clerkClient } from '@clerk/express' -import { Inject, Injectable, Logger } from '@nestjs/common' -import { Message, Role } from '@prisma/client' -import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos' -import { ChatroomSchema } from '../ChatRoom/chatroom.schema' -import { Builder, SchemaContext } from '../Graphql/graphql.builder' -import { MailService } from '../Mail/mail.service' -import { MessageSchema } from '../Message/message.schema' -import { PrismaService } from '../Prisma/prisma.service' -import { PubSubEvent } from '../common/pubsub/pubsub-event' -import { DateTimeUtils } from '../common/utils/datetime.utils' +import { clerkClient } from '@clerk/express'; +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { Message, Role } from '@prisma/client'; +import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'; +import { ChatroomSchema } from '../ChatRoom/chatroom.schema'; +import { Builder, SchemaContext } from '../Graphql/graphql.builder'; +import { MailService } from '../Mail/mail.service'; +import { MessageSchema } from '../Message/message.schema'; +import { PrismaService } from '../Prisma/prisma.service'; +import { PubSubEvent } from '../common/pubsub/pubsub-event'; +import { DateTimeUtils } from '../common/utils/datetime.utils'; @Injectable() export class UserSchema extends PothosSchema { constructor( @@ -16,9 +16,9 @@ export class UserSchema extends PothosSchema { private readonly prisma: PrismaService, private readonly mailService: MailService, private readonly messageSchema: MessageSchema, - private readonly chatRoomSchema: ChatroomSchema, + private readonly chatRoomSchema: ChatroomSchema ) { - super() + super(); } // Types section @@ -109,8 +109,11 @@ export class UserSchema extends PothosSchema { banned: t.exposeBoolean('banned', { description: 'The banned status of the user.', }), + quizAttempt: t.relation('QuizAttempt', { + description: 'The quiz attempt of the user', + }), }), - }) + }); } @PothosRef() @@ -134,7 +137,7 @@ export class UserSchema extends PothosSchema { description: 'The last message of the chat room.', }), }), - }) + }); } // Query section @@ -147,8 +150,8 @@ export class UserSchema extends PothosSchema { sessionId: t.arg({ type: 'String', required: true }), }, resolve: async (_, { sessionId }) => { - const session = await clerkClient.sessions.getSession(sessionId) - return JSON.parse(JSON.stringify(session)) + const session = await clerkClient.sessions.getSession(sessionId); + return JSON.parse(JSON.stringify(session)); }, }), newSession: t.field({ @@ -163,8 +166,8 @@ export class UserSchema extends PothosSchema { const session = await clerkClient.signInTokens.createSignInToken({ userId, expiresInSeconds: 60 * 60 * 24, - }) - return session.id + }); + return session.id; }, }), me: t.prismaField({ @@ -172,9 +175,9 @@ export class UserSchema extends PothosSchema { type: this.user(), resolve: async (_query, _root, _args, ctx) => { if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } - return ctx.http.me + return ctx.http.me; }, }), @@ -186,11 +189,11 @@ export class UserSchema extends PothosSchema { }, resolve: async (_parent, args, ctx) => { if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } - const me = ctx.http.me + const me = ctx.http.me; if (!me) { - throw new Error('User not found') + throw new Error('User not found'); } // get chat rooms that the user is a part of @@ -202,7 +205,7 @@ export class UserSchema extends PothosSchema { lastActivity: 'desc', }, take: args.take ?? 10, - }) + }); // get the last message for each chat room const lastMessages = await Promise.all( @@ -214,28 +217,28 @@ export class UserSchema extends PothosSchema { orderBy: { sentAt: 'desc', }, - }) + }); if (!lastMessage) { - return null + return null; } const sender = lastMessage.senderId ? await this.prisma.user.findUnique({ where: { id: lastMessage.senderId }, }) - : undefined + : undefined; return { chatRoom: chatRoom, lastActivity: lastMessage.sentAt, sender: sender, message: lastMessage, - } - }), - ) + }; + }) + ); - return lastMessages.filter((msg) => msg !== null) + return lastMessages.filter((msg) => msg !== null); }, }), @@ -250,7 +253,7 @@ export class UserSchema extends PothosSchema { skip: args.skip ?? undefined, orderBy: args.orderBy ?? undefined, where: args.filter ?? undefined, - }) + }); }, }), @@ -262,11 +265,11 @@ export class UserSchema extends PothosSchema { const user = await this.prisma.user.findUnique({ ...query, where: args.where, - }) + }); if (!user) { - throw new Error('User not found') + throw new Error('User not found'); } - return user + return user; }, }), userBySession: t.prismaField({ @@ -277,17 +280,17 @@ export class UserSchema extends PothosSchema { }, resolve: async (query, _root, args) => { // check if the token is valid - const session = await clerkClient.sessions.getSession(args.sessionId) - Logger.log(session, 'Session') + const session = await clerkClient.sessions.getSession(args.sessionId); + Logger.log(session, 'Session'); return await this.prisma.user.findFirstOrThrow({ ...query, where: { id: session.userId, }, - }) + }); }, }), - })) + })); // Mutation section this.builder.mutationFields((t) => ({ @@ -309,7 +312,7 @@ export class UserSchema extends PothosSchema { ...query, where: args.where, data: args.input, - }) + }); }, }), @@ -359,32 +362,32 @@ export class UserSchema extends PothosSchema { }, resolve: async (_query, args, ctx, _info) => { if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } - const id = ctx.http.me?.id + const id = ctx.http.me?.id; if (!id) { - throw new Error('User not found') + throw new Error('User not found'); } if (args.imageBlob) { - const { mimetype, createReadStream } = await args.imageBlob + const { mimetype, createReadStream } = await args.imageBlob; if (mimetype && createReadStream) { - const stream = createReadStream() - const chunks: Uint8Array[] = [] + const stream = createReadStream(); + const chunks: Uint8Array[] = []; for await (const chunk of stream) { - chunks.push(chunk) + chunks.push(chunk); } - const buffer = Buffer.concat(chunks) + const buffer = Buffer.concat(chunks); const { id: userId, imageUrl } = await clerkClient.users.updateUserProfileImage(id, { file: new Blob([buffer]), - }) + }); await this.prisma.user.update({ where: { id: userId }, data: { avatarUrl: imageUrl, }, - }) + }); } } @@ -392,7 +395,7 @@ export class UserSchema extends PothosSchema { const clerkUser = await clerkClient.users.updateUser(id, { firstName: args.firstName as string, lastName: args.lastName as string, - }) + }); // update bank account number and bank bin to database if (args.input?.bankAccountNumber) { await this.prisma.user.update({ @@ -400,7 +403,7 @@ export class UserSchema extends PothosSchema { data: { bankAccountNumber: args.input.bankAccountNumber, }, - }) + }); } if (args.input?.bankBin) { @@ -409,7 +412,7 @@ export class UserSchema extends PothosSchema { data: { bankBin: args.input.bankBin, }, - }) + }); } if (args.firstName || args.lastName) { @@ -418,13 +421,13 @@ export class UserSchema extends PothosSchema { data: { name: `${args.firstName || ''} ${args.lastName || ''}`.trim(), }, - }) + }); } // invalidate cache - await ctx.http.invalidateCache() + await ctx.http.invalidateCache(); return await this.prisma.user.findUniqueOrThrow({ where: { id: clerkUser.id }, - }) + }); }, }), @@ -436,35 +439,30 @@ export class UserSchema extends PothosSchema { resolve: async (_parent, args, ctx) => { // check context if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } // check context is admin if (ctx.http.me?.role !== Role.ADMIN) { - throw new Error(`Only admin can invite moderator`) + throw new Error(`Only admin can invite moderator`); } return this.prisma.$transaction(async (tx) => { - let user + let user; // perform update role try { user = await tx.user.update({ where: { email: args.email }, data: { role: 'MODERATOR' }, - }) + }); } catch (_error) { - throw new Error(`User ${args.email} not found`) + throw new Error(`User ${args.email} not found`); } // send email - await this.mailService.sendTemplateEmail( - [args.email], - 'Thông báo chọn lựa quản trị viên cho người điều hành', - 'ModeratorInvitation', - { - USER_NAME: user.name, - }, - ) - return 'Invited' - }) + await this.mailService.sendTemplateEmail([args.email], 'Thông báo chọn lựa quản trị viên cho người điều hành', 'ModeratorInvitation', { + USER_NAME: user.name, + }); + return 'Invited'; + }); }, }), // send test notification @@ -479,11 +477,11 @@ export class UserSchema extends PothosSchema { }, resolve: async (_, args, ctx) => { if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } - const me = ctx.http.me + const me = ctx.http.me; if (!me) { - throw new Error('User not found') + throw new Error('User not found'); } // create message const message = await this.prisma.message.create({ @@ -497,10 +495,10 @@ export class UserSchema extends PothosSchema { context: args.input.context ?? undefined, metadata: args.input.metadata ?? undefined, }, - }) + }); // publish message - await ctx.http.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`, message) - return message + await ctx.http.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`, message); + return message; }, }), banUser: t.field({ @@ -510,38 +508,38 @@ export class UserSchema extends PothosSchema { }, resolve: async (_parent, args, ctx) => { if (ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } if (ctx.http.me?.role !== Role.ADMIN && ctx.http.me?.role !== Role.MODERATOR) { - throw new Error(`Only admin or moderator can ban user`) + throw new Error(`Only admin or moderator can ban user`); } if (args.userId === ctx.http.me?.id) { - throw new Error(`Cannot ban yourself`) + throw new Error(`Cannot ban yourself`); } // get banning user info const banningUser = await this.prisma.user.findUnique({ where: { id: args.userId }, - }) + }); if (!banningUser) { - throw new Error(`User ${args.userId} not found`) + throw new Error(`User ${args.userId} not found`); } // if banning user is moderator or admin, throw error if (banningUser.role === Role.MODERATOR || banningUser.role === Role.ADMIN) { - throw new Error(`Cannot ban moderator or admin`) + throw new Error(`Cannot ban moderator or admin`); } // ban user from clerk - await clerkClient.users.banUser(args.userId) + await clerkClient.users.banUser(args.userId); // invalidate cache - await ctx.http.invalidateCache() + await ctx.http.invalidateCache(); // update user banned status await this.prisma.user.update({ where: { id: args.userId }, data: { banned: true }, - }) - return 'Banned' + }); + return 'Banned'; }, }), - })) + })); // Subscription section this.builder.subscriptionFields((t) => ({ @@ -549,16 +547,13 @@ export class UserSchema extends PothosSchema { type: this.messageSchema.message(), subscribe: async (_, _args, ctx) => { if (!ctx.isSubscription) { - throw new Error('Not allowed') + throw new Error('Not allowed'); } - return ctx.websocket.pubSub.asyncIterator([ - `${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`, - `${PubSubEvent.NOTIFICATION}.${ctx.websocket.me?.id}`, - ]) as unknown as AsyncIterable + return ctx.websocket.pubSub.asyncIterator([`${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`, `${PubSubEvent.NOTIFICATION}.${ctx.websocket.me?.id}`]) as unknown as AsyncIterable; }, resolve: async (payload: Message) => payload, }), - })) + })); } }