refactor: standardize code formatting and improve readability in User schema

- Reformatted import statements and method calls to use consistent line endings and spacing, enhancing code clarity.
- Updated error handling messages to maintain uniformity across the schema.
- Improved overall readability by ensuring consistent use of semicolons and line breaks, making the code easier to navigate and maintain.
This commit is contained in:
2024-12-10 16:37:10 +07:00
parent d242c39e2e
commit 4435bc0804

View File

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