chore: combine context
This commit is contained in:
@@ -171,19 +171,16 @@ export class AnalyticSchema extends PothosSchema {
|
||||
type: this.customerAnalytic(),
|
||||
description: 'Retrieve a single customer analytic.',
|
||||
resolve: async (_parent, _args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.CUSTOMER) {
|
||||
if (ctx.me.role !== Role.CUSTOMER) {
|
||||
throw new Error('Only customers can access this data')
|
||||
}
|
||||
// calculate analytic
|
||||
const activeServiceCount = await this.prisma.order.count({
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
status: OrderStatus.PAID,
|
||||
schedule: {
|
||||
dates: {
|
||||
@@ -198,12 +195,12 @@ export class AnalyticSchema extends PothosSchema {
|
||||
})
|
||||
const totalServiceCount = await this.prisma.order.count({
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
const totalSpent = await this.prisma.order.aggregate({
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
status: OrderStatus.PAID,
|
||||
},
|
||||
_sum: {
|
||||
@@ -211,7 +208,7 @@ export class AnalyticSchema extends PothosSchema {
|
||||
},
|
||||
})
|
||||
return {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
activeServiceCount: activeServiceCount,
|
||||
totalServiceCount: totalServiceCount,
|
||||
totalSpent: totalSpent._sum.total,
|
||||
@@ -223,18 +220,15 @@ export class AnalyticSchema extends PothosSchema {
|
||||
type: this.mentorAnalytic(),
|
||||
description: 'Retrieve a single mentor analytic.',
|
||||
resolve: async (_parent, _args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.CENTER_MENTOR) {
|
||||
if (ctx.me.role !== Role.CENTER_MENTOR) {
|
||||
throw new Error('Only center mentors can access this data')
|
||||
}
|
||||
// calculate analytic
|
||||
return {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
}
|
||||
},
|
||||
}),
|
||||
@@ -242,19 +236,16 @@ export class AnalyticSchema extends PothosSchema {
|
||||
type: this.centerAnalytic(),
|
||||
description: 'Retrieve a single center analytic.',
|
||||
resolve: async (_parent, _args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.CENTER_OWNER) {
|
||||
if (ctx.me.role !== Role.CENTER_OWNER) {
|
||||
throw new Error('Only center owners can access this data')
|
||||
}
|
||||
// get center by owner id
|
||||
const center = await this.prisma.center.findUnique({
|
||||
where: {
|
||||
centerOwnerId: ctx.http.me.id,
|
||||
centerOwnerId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
if (!center) {
|
||||
@@ -266,7 +257,7 @@ export class AnalyticSchema extends PothosSchema {
|
||||
const activeMentorCount = await this.prisma.user.count({
|
||||
where: {
|
||||
center: {
|
||||
centerOwnerId: ctx.http.me.id,
|
||||
centerOwnerId: ctx.me.id,
|
||||
},
|
||||
banned: false,
|
||||
},
|
||||
@@ -340,13 +331,10 @@ export class AnalyticSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Retrieve a single platform analytic.',
|
||||
resolve: async (_parent, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.ADMIN && ctx.http.me.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.ADMIN && ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Only admins and moderators can access this data')
|
||||
}
|
||||
// calculate analytic for services sorted by args.serviceSortBy and args.timeframes
|
||||
|
||||
@@ -154,16 +154,13 @@ export class CenterSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed in subscription')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.CUSTOMER) {
|
||||
if (ctx.me?.role !== Role.CUSTOMER) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
// check if user has already created a center
|
||||
const existingCenter = await this.prisma.center.findFirst({
|
||||
where: {
|
||||
centerOwnerId: ctx.http.me?.id,
|
||||
centerOwnerId: ctx.me?.id,
|
||||
},
|
||||
})
|
||||
if (existingCenter) {
|
||||
@@ -239,10 +236,7 @@ export class CenterSchema extends PothosSchema {
|
||||
},
|
||||
resolve: async (query, _root, args, ctx) => {
|
||||
return await this.prisma.$transaction(async (prisma) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed in subscription')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.ADMIN && ctx.http.me?.role !== Role.MODERATOR) {
|
||||
if (ctx.me?.role !== Role.ADMIN && ctx.me?.role !== Role.MODERATOR) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const center = await prisma.center.findUnique({
|
||||
|
||||
@@ -139,11 +139,11 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx) => {
|
||||
return this.prisma.$transaction(async (prisma) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// get centerId by user id from context
|
||||
const userId = ctx.http.me?.id
|
||||
const userId = ctx.me.id
|
||||
if (!userId) {
|
||||
throw new Error('User ID is required')
|
||||
}
|
||||
@@ -205,8 +205,8 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
adminNote: t.arg({ type: 'String', required: false }),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return this.prisma.$transaction(async (prisma) => {
|
||||
// get mentor info
|
||||
@@ -255,7 +255,7 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
data: {
|
||||
content: args.adminNote ?? '',
|
||||
mentorId: mentor.id,
|
||||
notedByUserId: ctx.http.me?.id ?? '',
|
||||
notedByUserId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
// update user role
|
||||
@@ -310,7 +310,7 @@ export class CenterMentorSchema extends PothosSchema {
|
||||
adminNote: {
|
||||
create: {
|
||||
content: args.adminNote ?? '',
|
||||
notedByUserId: ctx.http.me?.id ?? '',
|
||||
notedByUserId: ctx.me.id,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,88 +1,123 @@
|
||||
import { Inject, Injectable } from '@nestjs/common'
|
||||
import { ChatRoomType } from '@prisma/client'
|
||||
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||
import { Builder } from '../Graphql/graphql.builder'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { ChatRoomType } from "@prisma/client";
|
||||
import {
|
||||
Pothos,
|
||||
PothosRef,
|
||||
PothosSchema,
|
||||
SchemaBuilderToken,
|
||||
} from "@smatch-corp/nestjs-pothos";
|
||||
import { Builder } from "../Graphql/graphql.builder";
|
||||
import { PrismaService } from "../Prisma/prisma.service";
|
||||
|
||||
@Injectable()
|
||||
export class ChatroomSchema extends PothosSchema {
|
||||
constructor(
|
||||
@Inject(SchemaBuilderToken) private readonly builder: Builder,
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly prisma: PrismaService
|
||||
) {
|
||||
super()
|
||||
super();
|
||||
}
|
||||
|
||||
@PothosRef()
|
||||
chatRoom() {
|
||||
return this.builder.prismaObject('ChatRoom', {
|
||||
description: 'A chat room in the system.',
|
||||
return this.builder.prismaObject("ChatRoom", {
|
||||
description: "A chat room in the system.",
|
||||
fields: (t) => ({
|
||||
id: t.exposeID('id', {
|
||||
description: 'The ID of the chat room.',
|
||||
id: t.exposeID("id", {
|
||||
description: "The ID of the chat room.",
|
||||
}),
|
||||
type: t.expose('type', {
|
||||
type: t.expose("type", {
|
||||
type: ChatRoomType,
|
||||
description: 'The type of the chat room.',
|
||||
description: "The type of the chat room.",
|
||||
}),
|
||||
customerId: t.exposeID('customerId', {
|
||||
description: 'The ID of the customer.',
|
||||
customerId: t.exposeID("customerId", {
|
||||
description: "The ID of the customer.",
|
||||
}),
|
||||
centerId: t.exposeID('centerId', {
|
||||
description: 'The ID of the center.',
|
||||
centerId: t.exposeID("centerId", {
|
||||
description: "The ID of the center.",
|
||||
}),
|
||||
mentorId: t.exposeID('mentorId', {
|
||||
description: 'The ID of the mentor.',
|
||||
mentorId: t.exposeID("mentorId", {
|
||||
description: "The ID of the mentor.",
|
||||
}),
|
||||
createdAt: t.expose('createdAt', {
|
||||
type: 'DateTime',
|
||||
description: 'The date and time the chat room was created.',
|
||||
createdAt: t.expose("createdAt", {
|
||||
type: "DateTime",
|
||||
description: "The date and time the chat room was created.",
|
||||
}),
|
||||
message: t.relation('message', {
|
||||
description: 'The messages in the chat room.',
|
||||
message: t.relation("message", {
|
||||
description: "The messages in the chat room.",
|
||||
}),
|
||||
customer: t.relation('customer', {
|
||||
description: 'The customer.',
|
||||
customer: t.relation("customer", {
|
||||
description: "The customer.",
|
||||
}),
|
||||
center: t.relation('center', {
|
||||
description: 'The center.',
|
||||
center: t.relation("center", {
|
||||
description: "The center.",
|
||||
}),
|
||||
mentor: t.relation('mentor', {
|
||||
description: 'The mentor.',
|
||||
mentor: t.relation("mentor", {
|
||||
description: "The mentor.",
|
||||
}),
|
||||
collaborationSession: t.relation('CollaborationSession', {
|
||||
description: 'The collaboration session.',
|
||||
collaborationSession: t.relation("CollaborationSession", {
|
||||
description: "The collaboration session.",
|
||||
}),
|
||||
lastActivity: t.expose('lastActivity', {
|
||||
type: 'DateTime',
|
||||
description: 'The last activity date and time.',
|
||||
lastActivity: t.expose("lastActivity", {
|
||||
type: "DateTime",
|
||||
description: "The last activity date and time.",
|
||||
}),
|
||||
order: t.relation('Order', {
|
||||
description: 'The order.',
|
||||
order: t.relation("Order", {
|
||||
description: "The order.",
|
||||
}),
|
||||
}),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// @PothosRef()
|
||||
// chatUser() {
|
||||
// return this.builder.simpleObject("ChatUser", {
|
||||
// description: "A user in a chat room.",
|
||||
// fields: (t) => ({
|
||||
// user: t.field({
|
||||
// type: this.userSchema.user(),
|
||||
// description: "The user.",
|
||||
// }),
|
||||
// chatRoom: t.field({
|
||||
// type: this.chatRoom(),
|
||||
// description: "The chat room.",
|
||||
// }),
|
||||
// lastMessage: t.field({
|
||||
// type: this.messageSchema.message(),
|
||||
// description: "The last message.",
|
||||
// }),
|
||||
// lastMessageAt: t.field({
|
||||
// type: "DateTime",
|
||||
// description: "The date and time of the last message.",
|
||||
// }),
|
||||
// unreadCount: t.field({
|
||||
// type: "Int",
|
||||
// description: "The number of unread messages.",
|
||||
// }),
|
||||
// }),
|
||||
// });
|
||||
// }
|
||||
|
||||
@Pothos()
|
||||
init(): void {
|
||||
this.builder.queryFields((t) => ({
|
||||
chatRoom: t.prismaField({
|
||||
type: this.chatRoom(),
|
||||
description: 'Retrieve a single chat room by its unique identifier.',
|
||||
args: this.builder.generator.findUniqueArgs('ChatRoom'),
|
||||
description: "Retrieve a single chat room by its unique identifier.",
|
||||
args: this.builder.generator.findUniqueArgs("ChatRoom"),
|
||||
resolve: async (query, _root, args, _ctx, _info) => {
|
||||
return await this.prisma.chatRoom.findUnique({
|
||||
...query,
|
||||
where: args.where,
|
||||
})
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
chatRooms: t.prismaField({
|
||||
type: [this.chatRoom()],
|
||||
description: 'Retrieve a list of chat rooms with optional filtering, ordering, and pagination.',
|
||||
args: this.builder.generator.findManyArgs('ChatRoom'),
|
||||
description:
|
||||
"Retrieve a list of chat rooms with optional filtering, ordering, and pagination.",
|
||||
args: this.builder.generator.findManyArgs("ChatRoom"),
|
||||
resolve: async (query, _root, args, _ctx, _info) => {
|
||||
return await this.prisma.chatRoom.findMany({
|
||||
...query,
|
||||
@@ -90,9 +125,30 @@ export class ChatroomSchema extends PothosSchema {
|
||||
take: args.take ?? undefined,
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
where: args.filter ?? undefined,
|
||||
})
|
||||
});
|
||||
},
|
||||
}),
|
||||
}))
|
||||
// chatUsers: t.prismaField({
|
||||
// type: [this.chatUser()],
|
||||
// args: {
|
||||
// chatRoomId: t.arg({
|
||||
// type: "ID",
|
||||
// description: "The ID of the chat room.",
|
||||
// }),
|
||||
// },
|
||||
// description: "Retrieve a list of chat users.",
|
||||
// args: this.builder.generator.findManyArgs("ChatUser"),
|
||||
// resolve: async (query, _root, args, ctx, _info) => {
|
||||
// if (ctx.isSubscription) {
|
||||
// throw new Error("Not allowed");
|
||||
// }
|
||||
// if (!ctx.user) {
|
||||
// throw new Error("Unauthorized");
|
||||
// }
|
||||
// // TODO: get chat users for the chat room
|
||||
// return [];
|
||||
// },
|
||||
// }),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Retrieve a single collaboration session by its unique identifier.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
const scheduleDate = await this.prisma.scheduleDate.findUnique({
|
||||
@@ -94,9 +91,9 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
},
|
||||
})
|
||||
/* ---------- use case 1 : customer get collaboration session by id --------- */
|
||||
if (ctx.http.me?.role === Role.CUSTOMER && collaborationSession) {
|
||||
if (ctx.me?.role === Role.CUSTOMER && collaborationSession) {
|
||||
// check if user is participant
|
||||
if (!collaborationSession.collaboratorsIds.includes(ctx.http.me.id)) {
|
||||
if (!collaborationSession.collaboratorsIds.includes(ctx.me.id)) {
|
||||
throw new Error('User not allowed')
|
||||
}
|
||||
// update schedule date status
|
||||
@@ -111,14 +108,14 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
return collaborationSession
|
||||
}
|
||||
/* ---------- use case 2 : center mentor get collaboration session by schedule date id --------- */
|
||||
if (ctx.http.me.role !== Role.CENTER_MENTOR && ctx.http.me.role !== Role.CENTER_OWNER) {
|
||||
if (ctx.me.role !== Role.CENTER_MENTOR && ctx.me.role !== Role.CENTER_OWNER) {
|
||||
if (!collaborationSession) {
|
||||
throw new Error('Mentor does not created collaboration session yet')
|
||||
}
|
||||
throw new Error('User not allowed')
|
||||
}
|
||||
// check if user is participant
|
||||
if (!scheduleDate.participantIds.includes(ctx.http.me.id)) {
|
||||
if (!scheduleDate.participantIds.includes(ctx.me.id)) {
|
||||
throw new Error('User not allowed')
|
||||
}
|
||||
// check if order is exist in schedule date
|
||||
@@ -218,16 +215,13 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
liveKitToken: t.field({
|
||||
type: 'String',
|
||||
resolve: async (_, _args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me?.id) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// check if participantId is in meetingRoomCollaborators
|
||||
const meetingRoomCollaborator = await this.prisma.meetingRoomCollaborator.findFirst({
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
if (!meetingRoomCollaborator) {
|
||||
@@ -241,7 +235,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
if (!meetingRoom) {
|
||||
throw new Error('Meeting room not found')
|
||||
}
|
||||
const token = await this.liveKitService.createToken(ctx.http.me, meetingRoom.id)
|
||||
const token = await this.liveKitService.createToken(ctx.me, meetingRoom.id)
|
||||
return token
|
||||
},
|
||||
}),
|
||||
@@ -263,10 +257,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Update the active document ID for a collaboration session.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
// check permission
|
||||
@@ -281,7 +272,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
if (!collaborationSession) {
|
||||
throw new Error('Collaboration session not found')
|
||||
}
|
||||
if (!collaborationSession.scheduleDate.participantIds.includes(ctx.http.me.id)) {
|
||||
if (!collaborationSession.scheduleDate.participantIds.includes(ctx.me.id)) {
|
||||
throw new Error('User not allowed')
|
||||
}
|
||||
const updatedCollaborationSession = await this.prisma.collaborationSession.update({
|
||||
@@ -292,7 +283,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
activeDocumentId: args.activeDocumentId,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`collaborationSessionUpdated:${collaborationSession.id}`, updatedCollaborationSession)
|
||||
ctx.pubSub.publish(`collaborationSessionUpdated:${collaborationSession.id}`, updatedCollaborationSession)
|
||||
Logger.log(`Collaboration session updated: ${updatedCollaborationSession.id}`, 'updateActiveDocumentId')
|
||||
return updatedCollaborationSession
|
||||
},
|
||||
@@ -310,10 +301,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
subscribe: async (_parent, args, ctx) => {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.websocket.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
const collaborationSession = await this.prisma.collaborationSession.findUnique({
|
||||
@@ -324,7 +312,7 @@ export class CollaborationSessionSchema extends PothosSchema {
|
||||
if (!collaborationSession) {
|
||||
throw new Error('Collaboration session not found')
|
||||
}
|
||||
return ctx.websocket.pubSub.asyncIterator([
|
||||
return ctx.pubSub.asyncIterator([
|
||||
`collaborationSessionUpdated:${collaborationSession.id}`,
|
||||
]) as unknown as AsyncIterable<CollaborationSession>
|
||||
},
|
||||
|
||||
@@ -206,10 +206,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
type: [this.document()],
|
||||
args: this.builder.generator.findManyArgs("Document"),
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me?.id) {
|
||||
throw new Error("User not found");
|
||||
}
|
||||
return await this.prisma.document.findMany({
|
||||
@@ -217,8 +214,8 @@ export class DocumentSchema extends PothosSchema {
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
where: {
|
||||
OR: [
|
||||
{ ownerId: ctx.http.me.id },
|
||||
{ collaborators: { some: { userId: ctx.http.me.id } } },
|
||||
{ ownerId: ctx.me.id },
|
||||
{ collaborators: { some: { userId: ctx.me.id } } },
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -252,10 +249,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
type: this.document(),
|
||||
args: {},
|
||||
resolve: async (query, _args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const userId = ctx.http?.me?.id;
|
||||
const userId = ctx.me?.id;
|
||||
if (!userId) {
|
||||
throw new Error("User not found");
|
||||
}
|
||||
@@ -271,33 +265,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
},
|
||||
}),
|
||||
|
||||
testCheckGrammar: t.field({
|
||||
type: "Boolean",
|
||||
args: {
|
||||
documentId: t.arg({ type: "String", required: true }),
|
||||
pageId: t.arg({ type: "Int", required: true }),
|
||||
promptType: t.arg({
|
||||
type: this.builder.enumType("PromptType", {
|
||||
values: [
|
||||
"CHECK_GRAMMAR",
|
||||
"REWRITE_TEXT",
|
||||
"SUMMARIZE",
|
||||
"TRANSLATE",
|
||||
"EXPAND_CONTENT",
|
||||
] as const,
|
||||
}),
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, args, _ctx: SchemaContext) => {
|
||||
await this.documentService.checkGrammarForPage(
|
||||
args.documentId,
|
||||
args.pageId,
|
||||
args.promptType as PromptType
|
||||
);
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
|
||||
// exportDocument: t.field({
|
||||
// type: this.DocumentExportObject(),
|
||||
@@ -344,10 +311,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
pageIndex: t.arg({ type: "Int", required: true }),
|
||||
},
|
||||
resolve: async (_, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me?.id) {
|
||||
throw new Error("User not found");
|
||||
}
|
||||
if (!args.documentId) {
|
||||
@@ -371,7 +335,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
pageIndex: args.pageIndex,
|
||||
delta,
|
||||
totalPage,
|
||||
senderId: ctx.http?.me?.id,
|
||||
senderId: ctx.me?.id,
|
||||
eventType: DocumentEvent.CLIENT_REQUEST_SYNC,
|
||||
};
|
||||
},
|
||||
@@ -398,10 +362,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const userId = ctx.http?.me?.id;
|
||||
const userId = ctx.me?.id;
|
||||
if (!userId) {
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
@@ -430,13 +391,10 @@ export class DocumentSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const {
|
||||
http: { pubSub },
|
||||
pubSub,
|
||||
} = ctx;
|
||||
const senderId = ctx.http?.me?.id;
|
||||
const senderId = ctx.me?.id;
|
||||
if (!senderId) {
|
||||
throw new Error("User not found");
|
||||
}
|
||||
@@ -466,10 +424,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
data: t.arg({ type: this.documentDeltaInput(), required: true }),
|
||||
},
|
||||
resolve: async (_, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const senderId = ctx.http?.me?.id;
|
||||
const senderId = ctx.me?.id;
|
||||
if (!args.data.documentId) {
|
||||
throw new Error("Document id not found");
|
||||
}
|
||||
@@ -522,10 +477,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me?.id) {
|
||||
throw new Error("Unauthorized");
|
||||
}
|
||||
// check if user is owner or collaborator
|
||||
@@ -541,9 +493,9 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (
|
||||
!document.isPublic &&
|
||||
!document.collaborators.some(
|
||||
(c) => c.userId === ctx.http?.me?.id && c.writable
|
||||
(c) => c.userId === ctx.me?.id && c.writable
|
||||
) &&
|
||||
document.ownerId !== ctx.http?.me?.id
|
||||
document.ownerId !== ctx.me?.id
|
||||
) {
|
||||
throw new Error("User is not owner or collaborator of document");
|
||||
}
|
||||
@@ -563,9 +515,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
writable: t.arg({ type: "Boolean", required: true }),
|
||||
},
|
||||
resolve: async (_, __, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
// check if ctx user is owner of document
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id: args.documentId },
|
||||
@@ -573,7 +522,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (!document) {
|
||||
throw new Error("Document not found");
|
||||
}
|
||||
if (document.ownerId !== ctx.http?.me?.id) {
|
||||
if (document.ownerId !== ctx.me?.id) {
|
||||
throw new Error("User is not owner of document");
|
||||
}
|
||||
return await this.prisma.documentCollaborator.create({
|
||||
@@ -593,9 +542,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
userId: t.arg({ type: "String", required: true }),
|
||||
},
|
||||
resolve: async (_, __, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
// check if ctx user is owner of document
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id: args.documentId },
|
||||
@@ -603,7 +549,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (!document) {
|
||||
throw new Error("Document not found");
|
||||
}
|
||||
if (document.ownerId !== ctx.http?.me?.id) {
|
||||
if (document.ownerId !== ctx.me?.id) {
|
||||
throw new Error("User is not owner of document");
|
||||
}
|
||||
return await this.prisma.documentCollaborator.delete({
|
||||
@@ -625,9 +571,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
writable: t.arg({ type: "Boolean", required: true }),
|
||||
},
|
||||
resolve: async (_, __, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
// check if ctx user is owner of document
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id: args.documentId },
|
||||
@@ -635,7 +578,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
if (!document) {
|
||||
throw new Error("Document not found");
|
||||
}
|
||||
if (document.ownerId !== ctx.http?.me?.id) {
|
||||
if (document.ownerId !== ctx.me?.id) {
|
||||
throw new Error("User is not owner of document");
|
||||
}
|
||||
return await this.prisma.documentCollaborator.update({
|
||||
@@ -656,9 +599,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
imageId: t.arg({ type: "String", required: true }),
|
||||
},
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const document = await this.prisma.document.findUnique({
|
||||
where: { id: args.documentId },
|
||||
include: {
|
||||
@@ -669,9 +609,9 @@ export class DocumentSchema extends PothosSchema {
|
||||
throw new Error("Document not found");
|
||||
}
|
||||
if (
|
||||
document.ownerId !== ctx.http?.me?.id &&
|
||||
document.ownerId !== ctx.me?.id &&
|
||||
!document.collaborators.some(
|
||||
(c) => c.userId === ctx.http?.me?.id && (c.writable || c.readable)
|
||||
(c) => c.userId === ctx.me?.id && (c.writable || c.readable)
|
||||
)
|
||||
) {
|
||||
throw new Error("User is not owner or collaborator of document");
|
||||
@@ -702,9 +642,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
subscribe: async (_, args, ctx: SchemaContext) => {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const documentId = args.documentId;
|
||||
// check user permission
|
||||
const document = await this.prisma.document.findUnique({
|
||||
@@ -718,17 +655,17 @@ export class DocumentSchema extends PothosSchema {
|
||||
}
|
||||
if (!document.isPublic) {
|
||||
if (
|
||||
document.ownerId !== ctx.websocket?.me?.id &&
|
||||
document.ownerId !== ctx.me?.id &&
|
||||
!document.collaborators.some(
|
||||
(c) =>
|
||||
c.userId === ctx.websocket?.me?.id &&
|
||||
c.userId === ctx.me?.id &&
|
||||
(c.writable || c.readable)
|
||||
)
|
||||
) {
|
||||
throw new Error("User is not owner or collaborator of document");
|
||||
}
|
||||
}
|
||||
return ctx.websocket.pubSub.asyncIterator([
|
||||
return ctx.pubSub.asyncIterator([
|
||||
`${DocumentEvent.CHANGED}.${documentId}`,
|
||||
`${DocumentEvent.DELETED}.${documentId}`,
|
||||
`${DocumentEvent.SAVED}.${documentId}`,
|
||||
@@ -739,11 +676,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
`${DocumentEvent.CURSOR_MOVED}.${documentId}`,
|
||||
]) as unknown as AsyncIterable<DocumentDelta>;
|
||||
},
|
||||
resolve: async (payload: DocumentDelta, _args, ctx: SchemaContext) => {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
|
||||
resolve: async (payload: DocumentDelta, _args, _ctx: SchemaContext) => {
|
||||
// If there's an explicit sync request, pass it through immediately
|
||||
if (payload.requestSync) {
|
||||
return payload;
|
||||
@@ -797,9 +730,6 @@ export class DocumentSchema extends PothosSchema {
|
||||
pageIndex: number,
|
||||
ctx: SchemaContext
|
||||
): Promise<void> {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
try {
|
||||
const syncKey = `document:sync:${documentId}:${pageIndex}`;
|
||||
const currentTime = DateTimeUtils.now().toMillis().toString();
|
||||
@@ -823,7 +753,7 @@ export class DocumentSchema extends PothosSchema {
|
||||
}
|
||||
|
||||
// Optionally publish AI suggestion if needed
|
||||
ctx.websocket.pubSub.publish(
|
||||
ctx.pubSub.publish(
|
||||
`${DocumentEvent.AI_SUGGESTION}.${documentId}`,
|
||||
{
|
||||
documentId,
|
||||
|
||||
@@ -1,93 +1,84 @@
|
||||
import { Injectable, Logger } from '@nestjs/common'
|
||||
import SchemaBuilder from '@pothos/core'
|
||||
import AuthzPlugin from '@pothos/plugin-authz'
|
||||
import ErrorsPlugin from '@pothos/plugin-errors'
|
||||
import PrismaPlugin, { PothosPrismaDatamodel, PrismaClient } from '@pothos/plugin-prisma'
|
||||
import PrismaUtils from '@pothos/plugin-prisma-utils'
|
||||
import RelayPlugin from '@pothos/plugin-relay'
|
||||
import SimpleObjectPlugin from '@pothos/plugin-simple-objects'
|
||||
import SmartSubscriptionPlugin, { subscribeOptionsFromIterator } from '@pothos/plugin-smart-subscriptions'
|
||||
import ZodPlugin from '@pothos/plugin-zod'
|
||||
import { User } from '@prisma/client'
|
||||
import { JsonValue } from '@prisma/client/runtime/library'
|
||||
import { Request, Response } from 'express'
|
||||
import { Kind, ValueNode } from 'graphql'
|
||||
import { RedisPubSub } from 'graphql-redis-subscriptions'
|
||||
import { JSONObjectResolver } from 'graphql-scalars'
|
||||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import SchemaBuilder from "@pothos/core";
|
||||
import AuthzPlugin from "@pothos/plugin-authz";
|
||||
import ErrorsPlugin from "@pothos/plugin-errors";
|
||||
import PrismaPlugin, {
|
||||
PothosPrismaDatamodel,
|
||||
PrismaClient,
|
||||
} from "@pothos/plugin-prisma";
|
||||
import PrismaUtils from "@pothos/plugin-prisma-utils";
|
||||
import RelayPlugin from "@pothos/plugin-relay";
|
||||
import SimpleObjectPlugin from "@pothos/plugin-simple-objects";
|
||||
import SmartSubscriptionPlugin, {
|
||||
subscribeOptionsFromIterator,
|
||||
} from "@pothos/plugin-smart-subscriptions";
|
||||
import ZodPlugin from "@pothos/plugin-zod";
|
||||
import { User } from "@prisma/client";
|
||||
import { JsonValue } from "@prisma/client/runtime/library";
|
||||
import { Request, Response } from "express";
|
||||
import { Kind, ValueNode } from "graphql";
|
||||
import { RedisPubSub } from "graphql-redis-subscriptions";
|
||||
import { JSONObjectResolver } from "graphql-scalars";
|
||||
// @ts-expect-error
|
||||
import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs'
|
||||
import GraphQLUpload from "graphql-upload/GraphQLUpload.mjs";
|
||||
// @ts-expect-error
|
||||
import type { FileUpload } from 'graphql-upload/processRequest.mjs'
|
||||
import { DateTime } from 'luxon'
|
||||
import Delta from 'quill-delta'
|
||||
import { DateTimeUtils } from '../common/utils/datetime.utils'
|
||||
import type PrismaTypes from '../types/pothos.generated'
|
||||
import { getDatamodel } from '../types/pothos.generated'
|
||||
import { PrismaCrudGenerator } from './graphql.generator'
|
||||
|
||||
export type SchemaContext =
|
||||
| {
|
||||
isSubscription: true
|
||||
websocket: {
|
||||
req: Request
|
||||
pubSub: RedisPubSub
|
||||
sessionId: string
|
||||
me: User
|
||||
generator: PrismaCrudGenerator<BuilderTypes>
|
||||
}
|
||||
}
|
||||
| {
|
||||
isSubscription: false
|
||||
http: {
|
||||
req: Request
|
||||
res: Response
|
||||
me: User | null
|
||||
pubSub: RedisPubSub
|
||||
invalidateCache: () => Promise<void>
|
||||
generator: PrismaCrudGenerator<BuilderTypes>
|
||||
}
|
||||
}
|
||||
import type { FileUpload } from "graphql-upload/processRequest.mjs";
|
||||
import { DateTime } from "luxon";
|
||||
import Delta from "quill-delta";
|
||||
import { DateTimeUtils } from "../common/utils/datetime.utils";
|
||||
import type PrismaTypes from "../types/pothos.generated";
|
||||
import { getDatamodel } from "../types/pothos.generated";
|
||||
import { PrismaCrudGenerator } from "./graphql.generator";
|
||||
|
||||
export type SchemaContext = {
|
||||
req: Request;
|
||||
pubSub: RedisPubSub;
|
||||
sessionId: string;
|
||||
me: User;
|
||||
generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
res: Response;
|
||||
invalidateCache: () => Promise<void>;
|
||||
};
|
||||
// extend prisma types to contain string type
|
||||
export interface SchemaBuilderOption {
|
||||
Context: SchemaContext
|
||||
PrismaTypes: PrismaTypes
|
||||
DataModel: PothosPrismaDatamodel
|
||||
Context: SchemaContext;
|
||||
PrismaTypes: PrismaTypes;
|
||||
DataModel: PothosPrismaDatamodel;
|
||||
Connection: {
|
||||
totalCount: number | (() => number | Promise<number>)
|
||||
}
|
||||
totalCount: number | (() => number | Promise<number>);
|
||||
};
|
||||
// AuthZRule: keyof typeof rules;
|
||||
Scalars: {
|
||||
DateTime: {
|
||||
Input: string | DateTime | Date
|
||||
Output: string | DateTime | Date
|
||||
}
|
||||
Input: string | DateTime | Date;
|
||||
Output: string | DateTime | Date;
|
||||
};
|
||||
Json: {
|
||||
Input: JsonValue
|
||||
Output: JsonValue
|
||||
}
|
||||
Input: JsonValue;
|
||||
Output: JsonValue;
|
||||
};
|
||||
Upload: {
|
||||
Input: FileUpload
|
||||
Output: FileUpload
|
||||
}
|
||||
Input: FileUpload;
|
||||
Output: FileUpload;
|
||||
};
|
||||
Int: {
|
||||
Input: number
|
||||
Output: number | bigint | string
|
||||
}
|
||||
Input: number;
|
||||
Output: number | bigint | string;
|
||||
};
|
||||
Delta: {
|
||||
Input: Delta
|
||||
Output: Delta
|
||||
}
|
||||
Input: Delta;
|
||||
Output: Delta;
|
||||
};
|
||||
JsonList: {
|
||||
Input: JsonValue[]
|
||||
Output: JsonValue[]
|
||||
}
|
||||
}
|
||||
Input: JsonValue[];
|
||||
Output: JsonValue[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
public generator: PrismaCrudGenerator<BuilderTypes>
|
||||
public generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
|
||||
constructor(private readonly prisma: PrismaClient) {
|
||||
super({
|
||||
@@ -104,17 +95,15 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
smartSubscriptions: {
|
||||
debounceDelay: 1000,
|
||||
...subscribeOptionsFromIterator((name, context) => {
|
||||
return context.isSubscription
|
||||
? context.websocket.pubSub.asyncIterator(name)
|
||||
: context.http.pubSub.asyncIterator(name)
|
||||
return context.pubSub.asyncIterator(name);
|
||||
}),
|
||||
},
|
||||
zod: {
|
||||
// optionally customize how errors are formatted
|
||||
validationError: (zodError, _args, _context, _info) => {
|
||||
// the default behavior is to just throw the zod error directly
|
||||
Logger.error(zodError.message, 'Zod Error')
|
||||
return zodError
|
||||
Logger.error(zodError.message, "Zod Error");
|
||||
return zodError;
|
||||
},
|
||||
},
|
||||
relay: {},
|
||||
@@ -123,65 +112,70 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
exposeDescriptions: true,
|
||||
filterConnectionTotalCount: true,
|
||||
onUnusedQuery: (info) => {
|
||||
Logger.log(`Unused query: ${info.fieldName}`, 'GraphQL')
|
||||
Logger.log(`Unused query: ${info.fieldName}`, "GraphQL");
|
||||
},
|
||||
dmmf: getDatamodel(),
|
||||
},
|
||||
errors: {
|
||||
defaultTypes: [],
|
||||
},
|
||||
})
|
||||
this.generator = new PrismaCrudGenerator<BuilderTypes>(this)
|
||||
this.scalarType('DateTime', {
|
||||
});
|
||||
this.generator = new PrismaCrudGenerator<BuilderTypes>(this);
|
||||
this.scalarType("DateTime", {
|
||||
serialize: (value) => {
|
||||
if (typeof value === 'string') {
|
||||
return value
|
||||
if (typeof value === "string") {
|
||||
return value;
|
||||
}
|
||||
if (typeof value === 'object' && value !== null && 'toISO' in value) {
|
||||
return value
|
||||
if (typeof value === "object" && value !== null && "toISO" in value) {
|
||||
return value;
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return DateTimeUtils.toIsoString(DateTimeUtils.fromDate(value))
|
||||
return DateTimeUtils.toIsoString(DateTimeUtils.fromDate(value));
|
||||
}
|
||||
throw new Error('Invalid DateTime')
|
||||
throw new Error("Invalid DateTime");
|
||||
},
|
||||
parseValue: (value) => {
|
||||
if (typeof value === 'string') {
|
||||
return DateTimeUtils.fromIsoString(value)
|
||||
if (typeof value === "string") {
|
||||
return DateTimeUtils.fromIsoString(value);
|
||||
}
|
||||
throw new Error('Invalid DateTime')
|
||||
throw new Error("Invalid DateTime");
|
||||
},
|
||||
parseLiteral: (ast) => {
|
||||
if (ast.kind === Kind.STRING) {
|
||||
return DateTimeUtils.fromIsoString(ast.value)
|
||||
return DateTimeUtils.fromIsoString(ast.value);
|
||||
}
|
||||
throw new Error('Invalid DateTime')
|
||||
throw new Error("Invalid DateTime");
|
||||
},
|
||||
})
|
||||
this.scalarType('Delta', {
|
||||
});
|
||||
this.scalarType("Delta", {
|
||||
serialize: (value) => JSON.stringify(value),
|
||||
parseValue: (value: unknown) => JSON.parse(value as string) as Delta,
|
||||
parseLiteral: (ast: ValueNode) => ast as unknown as Delta,
|
||||
})
|
||||
});
|
||||
|
||||
this.scalarType('JsonList', {
|
||||
this.scalarType("JsonList", {
|
||||
serialize: (value) => JSON.stringify(value),
|
||||
parseValue: (value: unknown) => JSON.parse(value as string) as JsonValue[],
|
||||
parseValue: (value: unknown) =>
|
||||
JSON.parse(value as string) as JsonValue[],
|
||||
parseLiteral: (ast: ValueNode) => ast as unknown as JsonValue[],
|
||||
})
|
||||
});
|
||||
|
||||
this.addScalarType('Json', JSONObjectResolver)
|
||||
this.addScalarType('Upload', GraphQLUpload)
|
||||
this.addScalarType("Json", JSONObjectResolver);
|
||||
this.addScalarType("Upload", GraphQLUpload);
|
||||
|
||||
this.queryType({})
|
||||
this.mutationType({})
|
||||
this.subscriptionType({})
|
||||
this.globalConnectionField('totalCount', (t) =>
|
||||
this.queryType({});
|
||||
this.mutationType({});
|
||||
this.subscriptionType({});
|
||||
this.globalConnectionField("totalCount", (t) =>
|
||||
t.int({
|
||||
nullable: true,
|
||||
resolve: (parent) => (typeof parent.totalCount === 'function' ? parent.totalCount() : parent.totalCount),
|
||||
}),
|
||||
)
|
||||
resolve: (parent) =>
|
||||
typeof parent.totalCount === "function"
|
||||
? parent.totalCount()
|
||||
: parent.totalCount,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
export type BuilderTypes = PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>
|
||||
export type BuilderTypes =
|
||||
PothosSchemaTypes.ExtendDefaultTypes<SchemaBuilderOption>;
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
import { Global, Logger, Module } from '@nestjs/common'
|
||||
import { Global, Logger, Module } from "@nestjs/common";
|
||||
|
||||
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default'
|
||||
import { ApolloDriverConfig } from '@nestjs/apollo'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
import { GraphQLModule } from '@nestjs/graphql'
|
||||
import { initContextCache } from '@pothos/core'
|
||||
import { PothosModule } from '@smatch-corp/nestjs-pothos'
|
||||
import { PothosApolloDriver } from '@smatch-corp/nestjs-pothos-apollo-driver'
|
||||
import { Request } from 'express'
|
||||
import { RedisPubSub } from 'graphql-redis-subscriptions'
|
||||
import { CloseCode, Context, WebSocket } from 'graphql-ws'
|
||||
import { PersonalMilestoneModule } from 'src/PersonalMilestone/personalmilestone.module'
|
||||
import { AdminNoteModule } from '../AdminNote/adminnote.module'
|
||||
import { AnalyticModule } from '../Analytic/analytic.module'
|
||||
import { AppConfigModule } from '../AppConfig/appconfig.module'
|
||||
import { CategoryModule } from '../Category/category.module'
|
||||
import { CenterModule } from '../Center/center.module'
|
||||
import { CenterMentorModule } from '../CenterMentor/centermentor.module'
|
||||
import { ChatroomModule } from '../ChatRoom/chatroom.module'
|
||||
import { CollaborationSessionModule } from '../CollaborationSession/collaborationsession.module'
|
||||
import { DocumentModule } from '../Document/document.module'
|
||||
import { ManagedServiceModule } from '../ManagedService/managedservice.module'
|
||||
import { MeetingRoomModule } from '../MeetingRoom/meetingroom.module'
|
||||
import { MessageModule } from '../Message/message.module'
|
||||
import { OrderModule } from '../Order/order.module'
|
||||
import { PaymentModule } from '../Payment/payment.module'
|
||||
import { PrismaModule } from '../Prisma/prisma.module'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { PubSubModule } from '../PubSub/pubsub.module'
|
||||
import { PubSubService } from '../PubSub/pubsub.service'
|
||||
import { QuizModule } from '../Quiz/quiz.module'
|
||||
import { RedisModule } from '../Redis/redis.module'
|
||||
import { RedisService } from '../Redis/redis.service'
|
||||
import { RefundTicketModule } from '../RefundTicket/refundticket.module'
|
||||
import { ResumeModule } from '../Resume/resume.module'
|
||||
import { ScheduleModule } from '../Schedule/schedule.module'
|
||||
import { ServiceModule } from '../Service/service.module'
|
||||
import { ServiceAndCategoryModule } from '../ServiceAndCategory/serviceandcategory.module'
|
||||
import { ServiceFeedbackModule } from '../ServiceFeedback/servicefeedback.module'
|
||||
import { UploadedFileModule } from '../UploadedFile/uploadedfile.module'
|
||||
import { UserModule } from '../User/user.module'
|
||||
import { WorkshopModule } from '../Workshop/workshop.module'
|
||||
import { WorkshopMeetingRoomModule } from '../WorkshopMeetingRoom/workshopmeetingroom.module'
|
||||
import { WorkshopOrganizationModule } from '../WorkshopOrganization/workshoporganization.module'
|
||||
import { WorkshopSubscriptionModule } from '../WorkshopSubscription/workshopsubscription.module'
|
||||
import { CommonModule } from '../common/common.module'
|
||||
import { Builder } from './graphql.builder'
|
||||
import { PrismaCrudGenerator } from './graphql.generator'
|
||||
import { GraphqlService } from './graphql.service'
|
||||
import { ApolloServerPluginLandingPageLocalDefault } from "@apollo/server/plugin/landingPage/default";
|
||||
import { ApolloDriverConfig } from "@nestjs/apollo";
|
||||
import { ConfigModule } from "@nestjs/config";
|
||||
import { GraphQLModule } from "@nestjs/graphql";
|
||||
import { initContextCache } from "@pothos/core";
|
||||
import { PothosModule } from "@smatch-corp/nestjs-pothos";
|
||||
import { PothosApolloDriver } from "@smatch-corp/nestjs-pothos-apollo-driver";
|
||||
import { Request } from "express";
|
||||
import { RedisPubSub } from "graphql-redis-subscriptions";
|
||||
import { CloseCode, Context, WebSocket } from "graphql-ws";
|
||||
import { PersonalMilestoneModule } from "src/PersonalMilestone/personalmilestone.module";
|
||||
import { AdminNoteModule } from "../AdminNote/adminnote.module";
|
||||
import { AnalyticModule } from "../Analytic/analytic.module";
|
||||
import { AppConfigModule } from "../AppConfig/appconfig.module";
|
||||
import { CategoryModule } from "../Category/category.module";
|
||||
import { CenterModule } from "../Center/center.module";
|
||||
import { CenterMentorModule } from "../CenterMentor/centermentor.module";
|
||||
import { ChatroomModule } from "../ChatRoom/chatroom.module";
|
||||
import { CollaborationSessionModule } from "../CollaborationSession/collaborationsession.module";
|
||||
import { DocumentModule } from "../Document/document.module";
|
||||
import { ManagedServiceModule } from "../ManagedService/managedservice.module";
|
||||
import { MeetingRoomModule } from "../MeetingRoom/meetingroom.module";
|
||||
import { MessageModule } from "../Message/message.module";
|
||||
import { OrderModule } from "../Order/order.module";
|
||||
import { PaymentModule } from "../Payment/payment.module";
|
||||
import { PrismaModule } from "../Prisma/prisma.module";
|
||||
import { PrismaService } from "../Prisma/prisma.service";
|
||||
import { PubSubModule } from "../PubSub/pubsub.module";
|
||||
import { PubSubService } from "../PubSub/pubsub.service";
|
||||
import { QuizModule } from "../Quiz/quiz.module";
|
||||
import { RedisModule } from "../Redis/redis.module";
|
||||
import { RedisService } from "../Redis/redis.service";
|
||||
import { RefundTicketModule } from "../RefundTicket/refundticket.module";
|
||||
import { ResumeModule } from "../Resume/resume.module";
|
||||
import { ScheduleModule } from "../Schedule/schedule.module";
|
||||
import { ServiceModule } from "../Service/service.module";
|
||||
import { ServiceAndCategoryModule } from "../ServiceAndCategory/serviceandcategory.module";
|
||||
import { ServiceFeedbackModule } from "../ServiceFeedback/servicefeedback.module";
|
||||
import { UploadedFileModule } from "../UploadedFile/uploadedfile.module";
|
||||
import { UserModule } from "../User/user.module";
|
||||
import { WorkshopModule } from "../Workshop/workshop.module";
|
||||
import { WorkshopMeetingRoomModule } from "../WorkshopMeetingRoom/workshopmeetingroom.module";
|
||||
import { WorkshopOrganizationModule } from "../WorkshopOrganization/workshoporganization.module";
|
||||
import { WorkshopSubscriptionModule } from "../WorkshopSubscription/workshopsubscription.module";
|
||||
import { CommonModule } from "../common/common.module";
|
||||
import { Builder } from "./graphql.builder";
|
||||
import { PrismaCrudGenerator } from "./graphql.generator";
|
||||
import { GraphqlService } from "./graphql.service";
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -94,36 +94,48 @@ import { GraphqlService } from './graphql.service'
|
||||
}),
|
||||
GraphQLModule.forRootAsync<ApolloDriverConfig>({
|
||||
driver: PothosApolloDriver,
|
||||
inject: [GraphqlService, 'PUB_SUB_REDIS'],
|
||||
useFactory: async (graphqlService: GraphqlService, pubsub: RedisPubSub) => ({
|
||||
path: process.env.API_PATH + '/graphql',
|
||||
inject: [GraphqlService, "PUB_SUB_REDIS"],
|
||||
useFactory: async (
|
||||
graphqlService: GraphqlService,
|
||||
pubsub: RedisPubSub
|
||||
) => ({
|
||||
path: process.env.API_PATH + "/graphql",
|
||||
debug: true,
|
||||
playground: false,
|
||||
allowBatchedHttpRequests: true,
|
||||
includeStacktraceInErrorResponses: false,
|
||||
introspection: process.env.NODE_ENV === 'development' || false,
|
||||
introspection: process.env.NODE_ENV === "development" || false,
|
||||
logger: {
|
||||
debug: (...args) => Logger.debug(...args, 'GraphqlModule'),
|
||||
info: (...args) => Logger.log(...args, 'GraphqlModule'),
|
||||
warn: (...args) => Logger.warn(...args, 'GraphqlModule'),
|
||||
error: (...args) => Logger.error(...args, 'GraphqlModule'),
|
||||
debug: (...args) => Logger.debug(...args, "GraphqlModule"),
|
||||
info: (...args) => Logger.log(...args, "GraphqlModule"),
|
||||
warn: (...args) => Logger.warn(...args, "GraphqlModule"),
|
||||
error: (...args) => Logger.error(...args, "GraphqlModule"),
|
||||
},
|
||||
plugins: [ApolloServerPluginLandingPageLocalDefault()],
|
||||
installSubscriptionHandlers: true,
|
||||
subscriptions: {
|
||||
'graphql-ws': {
|
||||
"graphql-ws": {
|
||||
onSubscribe(ctx, message) {
|
||||
console.log('onSubscribe', ctx, message)
|
||||
console.log("onSubscribe", ctx, message);
|
||||
},
|
||||
onConnect: (ctx: Context<Record<string, unknown>>) => {
|
||||
if (!ctx.connectionParams) {
|
||||
Logger.log('No connectionParams provided', 'GraphqlModule')
|
||||
Logger.log("No connectionParams provided", "GraphqlModule");
|
||||
}
|
||||
if (!ctx.connectionParams?.["x-session-id"]) {
|
||||
Logger.log("No sessionId provided", "GraphqlModule");
|
||||
}
|
||||
if (!ctx.extra) {
|
||||
Logger.log('No extra provided', 'GraphqlModule')
|
||||
Logger.log("No extra provided", "GraphqlModule");
|
||||
}
|
||||
// @ts-expect-error: Request is not typed
|
||||
ctx.extra.request.headers['x-session-id'] = ctx.connectionParams['x-session-id']
|
||||
const sessionId: string = ctx.connectionParams?.[
|
||||
"x-session-id"
|
||||
] as string;
|
||||
if (!sessionId) {
|
||||
Logger.log("No sessionId provided", "GraphqlModule");
|
||||
}
|
||||
// @ts-expect-error: extra is not typed
|
||||
ctx.extra.request.headers["x-session-id"] = sessionId;
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -132,37 +144,34 @@ import { GraphqlService } from './graphql.service'
|
||||
subscriptions,
|
||||
extra,
|
||||
}: {
|
||||
req?: Request
|
||||
subscriptions?: Record<string, never>
|
||||
extra?: Record<string, never>
|
||||
req?: Request;
|
||||
subscriptions?: Record<string, never>;
|
||||
extra?: Record<string, never>;
|
||||
}) => {
|
||||
initContextCache()
|
||||
initContextCache();
|
||||
if (subscriptions) {
|
||||
// @ts-expect-error: TODO
|
||||
if (!extra?.request?.headers['x-session-id']) {
|
||||
throw new Error('No sessionId provided')
|
||||
if (!extra?.request?.headers["x-session-id"]) {
|
||||
throw new Error("No sessionId provided");
|
||||
}
|
||||
return {
|
||||
isSubscription: true,
|
||||
websocket: {
|
||||
req: extra?.request,
|
||||
pubSub: pubsub,
|
||||
me: await graphqlService.acquireContextFromSessionId(
|
||||
// @ts-expect-error: TODO
|
||||
extra.request.headers['x-session-id'],
|
||||
),
|
||||
},
|
||||
}
|
||||
req: extra?.request,
|
||||
pubSub: pubsub,
|
||||
me: await graphqlService.acquireContextFromSessionId(
|
||||
// @ts-expect-error: TODO
|
||||
extra.request.headers["x-session-id"]
|
||||
),
|
||||
};
|
||||
}
|
||||
return {
|
||||
isSubscription: false,
|
||||
http: {
|
||||
req,
|
||||
me: req ? await graphqlService.acquireContext(req) : null,
|
||||
pubSub: pubsub,
|
||||
invalidateCache: () => graphqlService.invalidateCache(req?.headers['x-session-id'] as string),
|
||||
},
|
||||
}
|
||||
req,
|
||||
me: req ? await graphqlService.acquireContext(req) : null,
|
||||
pubSub: pubsub,
|
||||
invalidateCache: () =>
|
||||
graphqlService.invalidateCache(
|
||||
req?.headers["x-session-id"] as string
|
||||
),
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
@@ -171,8 +180,9 @@ import { GraphqlService } from './graphql.service'
|
||||
RedisService,
|
||||
{
|
||||
provide: GraphqlService,
|
||||
useFactory: (prisma: PrismaService, redis: RedisService) => new GraphqlService(prisma, redis),
|
||||
inject: [PrismaService, 'REDIS_CLIENT'],
|
||||
useFactory: (prisma: PrismaService, redis: RedisService) =>
|
||||
new GraphqlService(prisma, redis),
|
||||
inject: [PrismaService, "REDIS_CLIENT"],
|
||||
},
|
||||
{
|
||||
provide: Builder,
|
||||
|
||||
@@ -75,10 +75,7 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
resolve: async (_query, _parent, args, _ctx: SchemaContext) => {
|
||||
const collaborationSession = await this.prisma.collaborationSession.findUnique({
|
||||
where: {
|
||||
scheduleDateId: args.scheduleDateId,
|
||||
@@ -112,10 +109,7 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
const meetingRoom = await this.prisma.meetingRoom.findUnique({
|
||||
@@ -131,11 +125,11 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
if (!collaborationSession) {
|
||||
throw new Error('Collaboration session not found')
|
||||
}
|
||||
if (!collaborationSession.collaboratorsIds.includes(ctx.http.me.id)) {
|
||||
if (!collaborationSession.collaboratorsIds.includes(ctx.me.id)) {
|
||||
throw new Error('User is not collaborator')
|
||||
}
|
||||
// create new token
|
||||
const token = await this.livekitService.createToken(ctx.http.me, meetingRoom.id)
|
||||
const token = await this.livekitService.createToken(ctx.me, meetingRoom.id)
|
||||
return {
|
||||
id: meetingRoom.id,
|
||||
token,
|
||||
@@ -151,13 +145,10 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
const token = await this.livekitService.createToken(ctx.http.me, args.scheduleId)
|
||||
const token = await this.livekitService.createToken(ctx.me, args.scheduleId)
|
||||
return {
|
||||
id: args.scheduleId,
|
||||
token,
|
||||
@@ -181,10 +172,7 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
return await this.prisma.meetingRoom.create({
|
||||
@@ -207,10 +195,7 @@ export class MeetingRoomSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _parent, args, ctx: SchemaContext) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
return await this.prisma.meetingRoom.update({
|
||||
|
||||
@@ -20,7 +20,7 @@ import { DateTimeUtils } from "../common/utils/datetime.utils";
|
||||
export class MessageSchema extends PothosSchema {
|
||||
constructor(
|
||||
@Inject(SchemaBuilderToken) private readonly builder: Builder,
|
||||
private readonly prisma: PrismaService
|
||||
private readonly prisma: PrismaService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -92,9 +92,6 @@ export class MessageSchema extends PothosSchema {
|
||||
"Retrieve a list of messages with optional filtering, ordering, and pagination.",
|
||||
args: this.builder.generator.findManyArgs("Message"),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
if (args.filter?.context && typeof args.filter.context === "object") {
|
||||
// if args.context is NOTIFICATION or SYSTEM, filter by recipientId
|
||||
if (
|
||||
@@ -105,7 +102,7 @@ export class MessageSchema extends PothosSchema {
|
||||
?.toString()
|
||||
.includes(MessageContextType.SYSTEM)
|
||||
) {
|
||||
args.filter.recipientId = ctx.http.me?.id;
|
||||
args.filter.recipientId = ctx.me?.id;
|
||||
}
|
||||
}
|
||||
return await this.prisma.message.findMany({
|
||||
@@ -151,14 +148,11 @@ export class MessageSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
const messageContext = MessageContextType.CHAT;
|
||||
// get the sender from the context and add it to the input
|
||||
args.input.sender = {
|
||||
connect: {
|
||||
id: ctx.http.me?.id,
|
||||
id: ctx.me?.id,
|
||||
},
|
||||
};
|
||||
if (!args.input.sender) {
|
||||
@@ -206,13 +200,13 @@ export class MessageSchema extends PothosSchema {
|
||||
});
|
||||
return message;
|
||||
});
|
||||
ctx.http.pubSub.publish(
|
||||
ctx.pubSub.publish(
|
||||
`${PubSubEvent.MESSAGE_SENT}.${message.chatRoomId}`,
|
||||
message
|
||||
);
|
||||
// publish to new message subscribers
|
||||
userIds.forEach((userId: string) => {
|
||||
ctx.http.pubSub.publish(
|
||||
ctx.pubSub.publish(
|
||||
`${PubSubEvent.NEW_MESSAGE}.${userId}`,
|
||||
message
|
||||
);
|
||||
@@ -233,10 +227,7 @@ export class MessageSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
subscribe: (_, args, ctx: SchemaContext) => {
|
||||
if (!ctx.isSubscription) {
|
||||
throw new Error("Not allowed");
|
||||
}
|
||||
return ctx.websocket.pubSub.asyncIterator([
|
||||
return ctx.pubSub.asyncIterator([
|
||||
`${PubSubEvent.MESSAGE_SENT}.${args.chatRoomId}`,
|
||||
]) as unknown as AsyncIterable<Message>;
|
||||
},
|
||||
|
||||
@@ -154,10 +154,7 @@ export class OrderSchema extends PothosSchema {
|
||||
description: 'Retrieve a list of completed orders',
|
||||
args: this.builder.generator.findManyArgs('Order'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Orders cannot be retrieved in subscription context')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// return orders where user is the one who made the order and status is PAID and schedule.dates is in the past
|
||||
@@ -167,7 +164,7 @@ export class OrderSchema extends PothosSchema {
|
||||
AND: [
|
||||
...(args.filter ? [args.filter] : []),
|
||||
{
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
status: OrderStatus.PAID,
|
||||
schedule: {
|
||||
OR: [
|
||||
@@ -202,14 +199,11 @@ export class OrderSchema extends PothosSchema {
|
||||
description: 'Retrieve a list of completed orders for moderator',
|
||||
args: this.builder.generator.findManyArgs('Order'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Orders cannot be retrieved in subscription context')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// only for role moderator
|
||||
if (ctx.http.me.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// return completed order list where schedule status is COMPLETED
|
||||
@@ -239,13 +233,10 @@ export class OrderSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Retrieve a list of completed orders details',
|
||||
resolve: async (_query, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Orders cannot be retrieved in subscription context')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// get order details
|
||||
@@ -367,10 +358,7 @@ export class OrderSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (!args.data.service.connect?.id) {
|
||||
@@ -388,7 +376,7 @@ export class OrderSchema extends PothosSchema {
|
||||
where: {
|
||||
AND: [
|
||||
{
|
||||
customerId: ctx.http.me?.id,
|
||||
customerId: ctx.me?.id,
|
||||
},
|
||||
{
|
||||
managedService: {
|
||||
@@ -419,7 +407,7 @@ export class OrderSchema extends PothosSchema {
|
||||
data: {
|
||||
status: OrderStatus.PENDING,
|
||||
total: service.price,
|
||||
userId: ctx.http.me?.id ?? '',
|
||||
userId: ctx.me?.id ?? '',
|
||||
serviceId: service.id,
|
||||
scheduleId: args.data.schedule.connect?.id ?? '',
|
||||
commission: service.commission ?? 0.0,
|
||||
@@ -460,8 +448,8 @@ export class OrderSchema extends PothosSchema {
|
||||
orderCode: paymentCode,
|
||||
amount: service.price,
|
||||
description: _name,
|
||||
buyerName: ctx.http.me?.name ?? '',
|
||||
buyerEmail: ctx.http.me?.email ?? '',
|
||||
buyerName: ctx.me?.name ?? '',
|
||||
buyerEmail: ctx.me?.email ?? '',
|
||||
returnUrl: `${process.env.PAYOS_RETURN_URL}`.replace('<serviceId>', service.id),
|
||||
cancelUrl: `${process.env.PAYOS_RETURN_URL}`.replace('<serviceId>', service.id),
|
||||
expiredAt: DateTimeUtils.now().plus({ minutes: 15 }).toUnixInteger(),
|
||||
@@ -519,13 +507,10 @@ export class OrderSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
return await this.prisma.order.update({
|
||||
|
||||
@@ -65,10 +65,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
args: this.builder.generator.findUniqueArgs('PersonalMilestone'),
|
||||
description: 'Retrieve a single personal milestone by its unique identifier.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
return this.prisma.personalMilestone.findUnique({
|
||||
@@ -81,10 +78,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
args: this.builder.generator.findManyArgs('PersonalMilestone'),
|
||||
description: 'Retrieve multiple personal milestones.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
return this.prisma.personalMilestone.findMany({
|
||||
@@ -119,13 +113,10 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Create multiple personal milestones.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
const userId = ctx.http.me.id
|
||||
const userId = ctx.me.id
|
||||
const result = await this.prisma.personalMilestone.createManyAndReturn({
|
||||
data: args.data.map((data) => ({
|
||||
...data,
|
||||
@@ -158,13 +149,10 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Update a personal milestone.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
const userId = ctx.http.me.id
|
||||
const userId = ctx.me.id
|
||||
return this.prisma.personalMilestone.update({
|
||||
where: {
|
||||
...args.where,
|
||||
@@ -185,10 +173,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Delete a personal milestone.',
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Cannot get your info')
|
||||
}
|
||||
// check if the user is mentor of the schedule where the personal milestone belongs to
|
||||
@@ -202,7 +187,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
|
||||
const managedService = await this.prisma.managedService.findUnique({
|
||||
where: { id: schedule.managedServiceId },
|
||||
})
|
||||
if (managedService?.mentorId !== ctx.http.me.id) {
|
||||
if (managedService?.mentorId !== ctx.me.id) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,10 +145,7 @@ export class QuizSchema extends PothosSchema {
|
||||
type: this.quiz(),
|
||||
args: this.builder.generator.findUniqueArgs('Quiz'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
return await this.prisma.quiz.findUnique({ ...query, where: { id: args.where.id } })
|
||||
@@ -167,17 +164,14 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// use case 1: customer
|
||||
if (ctx.http.me.role === Role.CUSTOMER) {
|
||||
if (ctx.me.role === Role.CUSTOMER) {
|
||||
// using pseudo random to get amount of quizzes based on userid as seed
|
||||
const random = getRandomWithSeed(
|
||||
parseInt(crypto.createHash('sha256').update(ctx.http.me.id).digest('hex'), 16),
|
||||
parseInt(crypto.createHash('sha256').update(ctx.me.id).digest('hex'), 16),
|
||||
)
|
||||
if (!args.scheduleId) {
|
||||
throw new Error('Schedule ID is required')
|
||||
@@ -192,7 +186,7 @@ export class QuizSchema extends PothosSchema {
|
||||
if (!schedule) {
|
||||
throw new Error('Schedule not found')
|
||||
}
|
||||
if (schedule.customerId !== ctx.http.me.id) {
|
||||
if (schedule.customerId !== ctx.me.id) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// get centerMentorId from schedule
|
||||
@@ -211,7 +205,7 @@ export class QuizSchema extends PothosSchema {
|
||||
// check if user has already taken the quiz
|
||||
const quizAttempt = await this.prisma.quizAttempt.findFirst({
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
quizId: quizzes[0]?.id,
|
||||
},
|
||||
})
|
||||
@@ -226,9 +220,9 @@ export class QuizSchema extends PothosSchema {
|
||||
}
|
||||
|
||||
// use case 2: center mentor or center owner
|
||||
if (ctx.http.me.role === Role.CENTER_MENTOR || ctx.http.me.role === Role.CENTER_OWNER) {
|
||||
if (ctx.me.role === Role.CENTER_MENTOR || ctx.me.role === Role.CENTER_OWNER) {
|
||||
const centerMentor = await this.prisma.centerMentor.findUnique({
|
||||
where: { mentorId: ctx.http.me.id },
|
||||
where: { mentorId: ctx.me.id },
|
||||
})
|
||||
if (!centerMentor) {
|
||||
throw new Error('Center mentor not found')
|
||||
@@ -252,10 +246,7 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (!args.id) {
|
||||
@@ -272,10 +263,10 @@ export class QuizSchema extends PothosSchema {
|
||||
}
|
||||
// check if user is the owner of the quiz attempt
|
||||
if (
|
||||
result.userId !== ctx.http.me.id &&
|
||||
ctx.http.me.role !== Role.CENTER_OWNER &&
|
||||
ctx.http.me.role !== Role.CENTER_MENTOR &&
|
||||
ctx.http.me.role !== Role.CUSTOMER
|
||||
result.userId !== ctx.me.id &&
|
||||
ctx.me.role !== Role.CENTER_OWNER &&
|
||||
ctx.me.role !== Role.CENTER_MENTOR &&
|
||||
ctx.me.role !== Role.CUSTOMER
|
||||
) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
@@ -299,16 +290,13 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// use case 1: center mentor or center owner
|
||||
if (ctx.http.me.role === Role.CENTER_MENTOR || ctx.http.me.role === Role.CENTER_OWNER) {
|
||||
if (ctx.me.role === Role.CENTER_MENTOR || ctx.me.role === Role.CENTER_OWNER) {
|
||||
const centerMentor = await this.prisma.centerMentor.findUnique({
|
||||
where: { mentorId: ctx.http.me.id },
|
||||
where: { mentorId: ctx.me.id },
|
||||
})
|
||||
if (!centerMentor) {
|
||||
throw new Error('Center mentor not found')
|
||||
@@ -331,11 +319,11 @@ export class QuizSchema extends PothosSchema {
|
||||
})
|
||||
}
|
||||
// use case 2: customer
|
||||
if (ctx.http.me.role === Role.CUSTOMER) {
|
||||
if (ctx.me.role === Role.CUSTOMER) {
|
||||
return await this.prisma.quizAttempt.findMany({
|
||||
...query,
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
...(args.quizId ? [{ quizId: args.quizId }] : []),
|
||||
},
|
||||
orderBy: {
|
||||
@@ -356,10 +344,7 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (!args.data) {
|
||||
@@ -370,7 +355,7 @@ export class QuizSchema extends PothosSchema {
|
||||
}
|
||||
args.data.centerMentor = {
|
||||
connect: {
|
||||
mentorId: ctx.http.me.id,
|
||||
mentorId: ctx.me.id,
|
||||
},
|
||||
}
|
||||
return await this.prisma.quiz.create({
|
||||
@@ -394,10 +379,7 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
return await this.prisma.quiz.update({
|
||||
@@ -422,10 +404,7 @@ export class QuizSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (!args.data) {
|
||||
@@ -450,7 +429,7 @@ export class QuizSchema extends PothosSchema {
|
||||
data: {
|
||||
...args.data,
|
||||
quiz: { connect: { id: args.data.quiz.connect.id } },
|
||||
user: { connect: { id: ctx.http.me.id } },
|
||||
user: { connect: { id: ctx.me.id } },
|
||||
},
|
||||
})
|
||||
// update schedule status to WAITING_INTERVIEW
|
||||
|
||||
@@ -91,10 +91,10 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
id: t.arg({ type: 'String', required: true }),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Only moderators can retrieve refund tickets')
|
||||
}
|
||||
return await this.prisma.refundTicket.findUnique({ ...query, where: { id: args.id } })
|
||||
@@ -132,24 +132,21 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// Check if the user is a customer or a center mentor
|
||||
if (
|
||||
ctx.http.me?.role !== Role.CUSTOMER &&
|
||||
ctx.http.me?.role !== Role.CENTER_MENTOR &&
|
||||
ctx.http.me?.role !== Role.CENTER_OWNER
|
||||
ctx.me?.role !== Role.CUSTOMER &&
|
||||
ctx.me?.role !== Role.CENTER_MENTOR &&
|
||||
ctx.me?.role !== Role.CENTER_OWNER
|
||||
) {
|
||||
throw new Error('Only customers and center mentors can request refund')
|
||||
}
|
||||
|
||||
// Check bank details for non-center mentors
|
||||
if (ctx.http.me?.role !== Role.CENTER_MENTOR) {
|
||||
if (!ctx.http.me?.bankBin || !ctx.http.me?.bankAccountNumber) {
|
||||
if (ctx.me?.role !== Role.CENTER_MENTOR) {
|
||||
if (!ctx.me?.bankBin || !ctx.me?.bankAccountNumber) {
|
||||
throw new Error('Bank bin and bank account number are required, please update your profile first')
|
||||
}
|
||||
}
|
||||
@@ -188,7 +185,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
let refundAmount = 0
|
||||
|
||||
// Special handling for center mentors - full refund always allowed
|
||||
if (ctx.http.me?.role === Role.CENTER_MENTOR) {
|
||||
if (ctx.me?.role === Role.CENTER_MENTOR) {
|
||||
refundAmount = order.total
|
||||
} else {
|
||||
// Existing refund logic for customers
|
||||
@@ -204,12 +201,12 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
}
|
||||
|
||||
// Prepare bank details
|
||||
let bankBin = ctx.http.me?.bankBin
|
||||
let bankAccountNumber = ctx.http.me?.bankAccountNumber
|
||||
let bankBin = ctx.me?.bankBin
|
||||
let bankAccountNumber = ctx.me?.bankAccountNumber
|
||||
let bankName = ''
|
||||
|
||||
// For center mentors, use a default or system bank account
|
||||
if (ctx.http.me?.role === Role.CENTER_MENTOR) {
|
||||
if (ctx.me?.role === Role.CENTER_MENTOR) {
|
||||
// You might want to replace this with a specific system bank account
|
||||
bankBin = 'SYSTEM_MENTOR_REFUND'
|
||||
bankAccountNumber = 'SYSTEM_MENTOR_ACCOUNT'
|
||||
@@ -234,7 +231,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
bankBin: bankBin,
|
||||
bankAccountNumber: bankAccountNumber,
|
||||
bankName: bankName,
|
||||
requesterId: ctx.http.me.id,
|
||||
requesterId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
// notify all Moderator
|
||||
@@ -244,15 +241,15 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
for (const moderator of moderators) {
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me.id,
|
||||
recipientId: moderator.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Có yêu cầu hoàn tiền mới từ ${ctx.http.me?.name}`,
|
||||
content: `Có yêu cầu hoàn tiền mới từ ${ctx.me.name}`,
|
||||
sentAt: DateTimeUtils.nowAsJSDate(),
|
||||
context: MessageContextType.NOTIFICATION,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
}
|
||||
return refundTicket
|
||||
},
|
||||
@@ -275,10 +272,10 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Subscription is not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Only moderators can process refund tickets')
|
||||
}
|
||||
// if action is REJECT, reason is required
|
||||
@@ -291,7 +288,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
data: {
|
||||
status: args.action === 'APPROVE' ? RefundTicketStatus.APPROVED : RefundTicketStatus.REJECTED,
|
||||
rejectedReason: args.action === 'REJECT' ? args.reason : undefined,
|
||||
moderatorId: ctx.http.me.id,
|
||||
moderatorId: ctx.me.id,
|
||||
},
|
||||
include: {
|
||||
order: true,
|
||||
@@ -332,7 +329,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
}
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me.id,
|
||||
senderId: ctx.me.id,
|
||||
recipientId: requester.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Yêu cầu hoàn tiền của bạn đã được ${args.action === 'APPROVE' ? 'chấp thuận' : 'từ chối'}`,
|
||||
@@ -340,7 +337,7 @@ export class RefundTicketSchema extends PothosSchema {
|
||||
context: MessageContextType.NOTIFICATION,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${requester.id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${requester.id}`, message)
|
||||
return refundTicket
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -108,13 +108,13 @@ export class ResumeSchema extends PothosSchema {
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
try {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
const resumes = await this.prisma.resume.findMany({
|
||||
...query,
|
||||
where: {
|
||||
userId: ctx.http.me?.id ?? '',
|
||||
userId: ctx.me.id,
|
||||
status: args.status ?? undefined,
|
||||
},
|
||||
})
|
||||
@@ -205,10 +205,10 @@ export class ResumeSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.CUSTOMER && ctx.http.me?.role !== Role.CENTER_OWNER) {
|
||||
if (ctx.me.role !== Role.CUSTOMER && ctx.me.role !== Role.CENTER_OWNER) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const { resumeFile } = args
|
||||
@@ -251,15 +251,15 @@ export class ResumeSchema extends PothosSchema {
|
||||
for (const moderator of moderators) {
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me?.id ?? '',
|
||||
recipientId: moderator.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Có yêu cầu hồ sơ mới từ ${ctx.http.me?.name}`,
|
||||
content: `Có yêu cầu hồ sơ mới từ ${ctx.me?.name}`,
|
||||
sentAt: DateTimeUtils.nowAsJSDate(),
|
||||
context: MessageContextType.NOTIFICATION,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
}
|
||||
return resume
|
||||
}
|
||||
@@ -278,15 +278,15 @@ export class ResumeSchema extends PothosSchema {
|
||||
for (const moderator of moderators) {
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me?.id ?? '',
|
||||
recipientId: moderator.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Có yêu cầu hồ sơ mới từ ${ctx.http.me?.name}`,
|
||||
content: `Có yêu cầu hồ sơ mới từ ${ctx.me?.name}`,
|
||||
sentAt: DateTimeUtils.nowAsJSDate(),
|
||||
context: MessageContextType.NOTIFICATION,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${moderator.id}`, message)
|
||||
}
|
||||
return resume
|
||||
},
|
||||
@@ -310,10 +310,10 @@ export class ResumeSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.MODERATOR) {
|
||||
if (ctx.me.role !== Role.MODERATOR) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const { resumeId, status, adminNote } = args
|
||||
@@ -348,7 +348,7 @@ export class ResumeSchema extends PothosSchema {
|
||||
_adminNote = await tx.adminNote.create({
|
||||
data: {
|
||||
content: adminNote,
|
||||
notedByUserId: ctx.http.me?.id ?? '',
|
||||
notedByUserId: ctx.me?.id ?? '',
|
||||
resumeId,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -225,10 +225,7 @@ export class ScheduleSchema extends PothosSchema {
|
||||
description: 'Retrieve a single schedule by its unique identifier.',
|
||||
args: this.builder.generator.findUniqueArgs('Schedule'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Cannot retrieve schedule in subscription')
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// only return schedule belong to center
|
||||
@@ -236,7 +233,7 @@ export class ScheduleSchema extends PothosSchema {
|
||||
const center = await this.prisma.center.findFirst({
|
||||
where: {
|
||||
AND: [
|
||||
{ OR: [{ centerOwnerId: ctx.http.me.id }, { centerMentors: { some: { mentorId: ctx.http.me.id } } }] },
|
||||
{ OR: [{ centerOwnerId: ctx.me.id }, { centerMentors: { some: { mentorId: ctx.me.id } } }] },
|
||||
{ centerStatus: CenterStatus.APPROVED },
|
||||
],
|
||||
},
|
||||
@@ -260,14 +257,11 @@ export class ScheduleSchema extends PothosSchema {
|
||||
args: this.builder.generator.findManyArgs('Schedule'),
|
||||
description: 'Retrieve a list of schedules with optional filtering, ordering, and pagination.',
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Cannot retrieve schedules in subscription')
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// use case 1: customer query schedules where customer is participant
|
||||
if (ctx.http.me.role === Role.CUSTOMER) {
|
||||
if (ctx.me.role === Role.CUSTOMER) {
|
||||
const schedules = await this.prisma.schedule.findMany({
|
||||
...query,
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
@@ -278,12 +272,12 @@ export class ScheduleSchema extends PothosSchema {
|
||||
return schedules
|
||||
}
|
||||
// use case 2: center mentor or center owner query schedules where center mentor or center owner is mentor
|
||||
if (ctx.http.me.role === Role.CENTER_MENTOR) {
|
||||
if (ctx.me.role === Role.CENTER_MENTOR) {
|
||||
const center = await this.prisma.center.findFirst({
|
||||
where: {
|
||||
centerMentors: {
|
||||
some: {
|
||||
mentorId: ctx.http.me.id,
|
||||
mentorId: ctx.me.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -299,7 +293,7 @@ export class ScheduleSchema extends PothosSchema {
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
where: {
|
||||
AND: [
|
||||
{ managedService: { service: { centerId: center.id }, mentorId: ctx.http.me.id } },
|
||||
{ managedService: { service: { centerId: center.id }, mentorId: ctx.me.id } },
|
||||
...(args.filter ? [args.filter] : []),
|
||||
],
|
||||
},
|
||||
@@ -307,9 +301,9 @@ export class ScheduleSchema extends PothosSchema {
|
||||
return schedules
|
||||
}
|
||||
// use case 3: Center owner query all schedules belong to center
|
||||
if (ctx.http.me.role === Role.CENTER_OWNER) {
|
||||
if (ctx.me.role === Role.CENTER_OWNER) {
|
||||
const center = await this.prisma.center.findFirst({
|
||||
where: { centerOwnerId: ctx.http.me.id },
|
||||
where: { centerOwnerId: ctx.me.id },
|
||||
})
|
||||
if (!center) {
|
||||
throw new Error('Center not found')
|
||||
@@ -333,10 +327,7 @@ export class ScheduleSchema extends PothosSchema {
|
||||
description: 'Retrieve a list of schedule dates.',
|
||||
args: this.builder.generator.findManyArgs('ScheduleDate'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Cannot retrieve schedule dates in subscription')
|
||||
}
|
||||
if (!ctx.http?.me?.id) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return await this.prisma.scheduleDate.findMany({
|
||||
@@ -345,7 +336,7 @@ export class ScheduleSchema extends PothosSchema {
|
||||
take: args.take ?? undefined,
|
||||
orderBy: args.orderBy ?? undefined,
|
||||
where: {
|
||||
AND: [{ participantIds: { has: ctx.http.me.id } }, ...(args.filter ? [args.filter] : [])],
|
||||
AND: [{ participantIds: { has: ctx.me.id } }, ...(args.filter ? [args.filter] : [])],
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -404,8 +395,8 @@ d72a864e-2f41-45ab-9c9b-bf0512a31883,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-1
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Cannot create schedule in subscription')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
Logger.log('args.schedule', args.schedule)
|
||||
// reject schedule if start date is today or in the past
|
||||
|
||||
@@ -118,16 +118,13 @@ export class ServiceSchema extends PothosSchema {
|
||||
description: 'Whether the user has already provided feedback for the service.',
|
||||
nullable: true,
|
||||
resolve: async (service, _args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
return null
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
return false
|
||||
}
|
||||
const serviceFeedbacks = await this.prisma.serviceFeedback.findMany({
|
||||
where: {
|
||||
serviceId: service.id,
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
return serviceFeedbacks.length > 0
|
||||
@@ -164,18 +161,15 @@ export class ServiceSchema extends PothosSchema {
|
||||
|
||||
args: this.builder.generator.findManyArgs('Service'),
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
// check role if user is mentor or center owner
|
||||
const role = ctx.http.me?.role
|
||||
const role = ctx.me?.role
|
||||
if (role !== Role.CENTER_MENTOR && role !== Role.CENTER_OWNER) {
|
||||
throw new Error('Not allowed')
|
||||
throw new Error('User not found')
|
||||
}
|
||||
if (role === Role.CENTER_MENTOR) {
|
||||
// load only service belong to center of current user
|
||||
const managedServices = await this.prisma.managedService.findMany({
|
||||
where: { mentorId: ctx.http.me?.id ?? '' },
|
||||
where: { mentorId: ctx.me.id },
|
||||
})
|
||||
if (!managedServices) {
|
||||
throw new Error('Managed services not found')
|
||||
@@ -188,7 +182,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
// if role is center owner, load all services belong to center of current user
|
||||
if (role === Role.CENTER_OWNER) {
|
||||
const center = await this.prisma.center.findUnique({
|
||||
where: { centerOwnerId: ctx.http.me?.id ?? '' },
|
||||
where: { centerOwnerId: ctx.me.id },
|
||||
})
|
||||
if (!center) {
|
||||
throw new Error('Center not found')
|
||||
@@ -239,11 +233,11 @@ export class ServiceSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// replace userId with current user id
|
||||
args.input.user = { connect: { id: ctx.http.me?.id ?? '' } }
|
||||
args.input.user = { connect: { id: ctx.me.id } }
|
||||
const service = await this.prisma.service.create({
|
||||
...query,
|
||||
data: args.input,
|
||||
@@ -279,7 +273,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
})
|
||||
const messages = await this.prisma.message.createManyAndReturn({
|
||||
data: moderatorIds.map((moderator) => ({
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me.id,
|
||||
recipientId: moderator.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Có một dịch vụ mới với tên ${service.name} được đăng tải bởi ${center.name}`,
|
||||
@@ -288,7 +282,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
})),
|
||||
})
|
||||
messages.forEach((message) => {
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${message.recipientId}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${message.recipientId}`, message)
|
||||
})
|
||||
return service
|
||||
},
|
||||
@@ -355,8 +349,8 @@ export class ServiceSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return await this.prisma.$transaction(async (prisma) => {
|
||||
// check if service is already approved or rejected
|
||||
@@ -382,7 +376,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
adminNote: {
|
||||
create: {
|
||||
content: args.adminNote ?? '',
|
||||
notedByUserId: ctx.http.me?.id ?? '',
|
||||
notedByUserId: ctx.me.id,
|
||||
},
|
||||
},
|
||||
commission: commission ?? 0,
|
||||
@@ -427,7 +421,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
// add message to database
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me.id,
|
||||
recipientId: id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Dịch vụ ${service.name} của bạn đã được chấp thuận`,
|
||||
@@ -438,7 +432,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${id}`, message)
|
||||
})
|
||||
} else {
|
||||
await this.mailService.sendTemplateEmail(emails, 'Thông báo về trạng thái dịch vụ', 'ServiceRejected', {
|
||||
@@ -455,7 +449,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
// add message to database
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me.id,
|
||||
recipientId: id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Dịch vụ ${service.name} của bạn đã bị từ chối`,
|
||||
@@ -466,7 +460,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
},
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${id}`, message)
|
||||
})
|
||||
}
|
||||
return updatedService
|
||||
|
||||
@@ -90,21 +90,18 @@ export class ServiceFeedbackSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Create a new service feedback.',
|
||||
resolve: async (_, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http?.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
// allow only when user is CUSTOMER and order is completed
|
||||
if (ctx.http?.me?.role !== Role.CUSTOMER) {
|
||||
if (ctx.me.role !== Role.CUSTOMER) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
Logger.log(`args: ${JSON.stringify(args)}`)
|
||||
const order = await this.prisma.order.findFirst({
|
||||
where: {
|
||||
id: args.orderId,
|
||||
userId: ctx.http?.me?.id,
|
||||
userId: ctx.me.id,
|
||||
status: OrderStatus.PAID,
|
||||
schedule: {
|
||||
dates: {
|
||||
@@ -118,7 +115,7 @@ export class ServiceFeedbackSchema extends PothosSchema {
|
||||
if (!order) {
|
||||
throw new Error('Order not found')
|
||||
}
|
||||
if (order.userId !== ctx.http?.me?.id) {
|
||||
if (order.userId !== ctx.me.id) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
if (order.status !== OrderStatus.PAID) {
|
||||
@@ -134,7 +131,7 @@ export class ServiceFeedbackSchema extends PothosSchema {
|
||||
}
|
||||
return await this.prisma.serviceFeedback.create({
|
||||
data: {
|
||||
userId: ctx.http?.me?.id,
|
||||
userId: ctx.me.id,
|
||||
serviceId: order.serviceId,
|
||||
rating: args.rating,
|
||||
comments: args.comments,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { ChatroomModule } from '../ChatRoom/chatroom.module'
|
||||
import { MessageModule } from '../Message/message.module'
|
||||
import { ChatroomSchema } from 'src/ChatRoom/chatroom.schema'
|
||||
import { MessageSchema } from 'src/Message/message.schema'
|
||||
import { UserSchema } from './user.schema'
|
||||
|
||||
@Module({
|
||||
imports: [MessageModule, ChatroomModule],
|
||||
providers: [UserSchema],
|
||||
providers: [UserSchema, ChatroomSchema, MessageSchema],
|
||||
exports: [UserSchema],
|
||||
})
|
||||
export class UserModule {}
|
||||
|
||||
|
||||
@@ -170,10 +170,10 @@ export class UserSchema extends PothosSchema {
|
||||
description: 'Retrieve the current user in context.',
|
||||
type: this.user(),
|
||||
resolve: async (_query, _root, _args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return ctx.http.me
|
||||
return ctx.me
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -184,18 +184,13 @@ export class UserSchema extends PothosSchema {
|
||||
take: t.arg({ type: 'Int', required: false }),
|
||||
},
|
||||
resolve: async (_parent, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const me = ctx.http.me
|
||||
if (!me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
|
||||
// get chat rooms that the user is a part of
|
||||
const chatRooms = await this.prisma.chatRoom.findMany({
|
||||
where: {
|
||||
OR: [{ customerId: me.id }, { mentorId: me.id }],
|
||||
OR: [{ customerId: ctx.me.id }, { mentorId: ctx.me.id }],
|
||||
},
|
||||
orderBy: {
|
||||
lastActivity: 'desc',
|
||||
@@ -357,10 +352,10 @@ export class UserSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
const id = ctx.http.me?.id
|
||||
const id = ctx.me.id
|
||||
if (!id) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
@@ -420,7 +415,7 @@ export class UserSchema extends PothosSchema {
|
||||
})
|
||||
}
|
||||
// invalidate cache
|
||||
await ctx.http.invalidateCache()
|
||||
await ctx.invalidateCache()
|
||||
return await this.prisma.user.findUniqueOrThrow({
|
||||
where: { id: clerkUser.id },
|
||||
})
|
||||
@@ -434,12 +429,12 @@ export class UserSchema extends PothosSchema {
|
||||
},
|
||||
resolve: async (_parent, args, ctx) => {
|
||||
// check context
|
||||
if (ctx.isSubscription) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
// check context is admin
|
||||
|
||||
if (ctx.http.me?.role !== Role.ADMIN) {
|
||||
if (ctx.me?.role !== Role.ADMIN) {
|
||||
throw new Error(`Only admin can invite moderator`)
|
||||
}
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
@@ -477,11 +472,7 @@ export class UserSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const me = ctx.http.me
|
||||
if (!me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// create message
|
||||
@@ -489,7 +480,7 @@ export class UserSchema extends PothosSchema {
|
||||
data: {
|
||||
type: args.input.type,
|
||||
content: args.input.content,
|
||||
senderId: me.id,
|
||||
senderId: ctx.me.id,
|
||||
recipientId: args.input.recipient?.connect?.id ?? null,
|
||||
chatRoomId: args.input.chatRoom?.connect?.id ?? null,
|
||||
sentAt: DateTimeUtils.nowAsJSDate(),
|
||||
@@ -498,7 +489,7 @@ export class UserSchema extends PothosSchema {
|
||||
},
|
||||
})
|
||||
// publish message
|
||||
await ctx.http.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`, message)
|
||||
await ctx.pubSub.publish(`${PubSubEvent.NEW_MESSAGE}.${message.recipientId}`, message)
|
||||
return message
|
||||
},
|
||||
}),
|
||||
@@ -508,13 +499,10 @@ export class UserSchema extends PothosSchema {
|
||||
userId: t.arg({ type: 'String', required: true }),
|
||||
},
|
||||
resolve: async (_parent, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.ADMIN && ctx.http.me?.role !== Role.MODERATOR) {
|
||||
if (ctx.me?.role !== Role.ADMIN && ctx.me?.role !== Role.MODERATOR) {
|
||||
throw new Error(`Only admin or moderator can ban user`)
|
||||
}
|
||||
if (args.userId === ctx.http.me?.id) {
|
||||
if (args.userId === ctx.me?.id) {
|
||||
throw new Error(`Cannot ban yourself`)
|
||||
}
|
||||
// get banning user info
|
||||
@@ -531,7 +519,7 @@ export class UserSchema extends PothosSchema {
|
||||
// ban user from clerk
|
||||
await clerkClient.users.banUser(args.userId)
|
||||
// invalidate cache
|
||||
await ctx.http.invalidateCache()
|
||||
await ctx.invalidateCache()
|
||||
// update user banned status
|
||||
await this.prisma.user.update({
|
||||
where: { id: args.userId },
|
||||
@@ -547,13 +535,13 @@ export class UserSchema extends PothosSchema {
|
||||
userScopedMessage: t.field({
|
||||
type: this.messageSchema.message(),
|
||||
subscribe: async (_, _args, ctx) => {
|
||||
if (!ctx.isSubscription) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
|
||||
return ctx.websocket.pubSub.asyncIterator([
|
||||
`${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`,
|
||||
`${PubSubEvent.NOTIFICATION}.${ctx.websocket.me?.id}`,
|
||||
return ctx.pubSub.asyncIterator([
|
||||
`${PubSubEvent.NEW_MESSAGE}.${ctx.me?.id}`,
|
||||
`${PubSubEvent.NOTIFICATION}.${ctx.me?.id}`,
|
||||
]) as unknown as AsyncIterable<Message>
|
||||
},
|
||||
resolve: async (payload: Message) => payload,
|
||||
|
||||
@@ -136,13 +136,10 @@ export class WorkshopSchema extends PothosSchema {
|
||||
},
|
||||
description: 'Create a new workshop.',
|
||||
resolve: async (query, _root, args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Workshops cannot be created in subscription context')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User is not authenticated to create a workshop')
|
||||
}
|
||||
if (ctx.http.me.role !== Role.CENTER_OWNER) {
|
||||
if (ctx.me.role !== Role.CENTER_OWNER) {
|
||||
throw new Error('Only center owners can create workshops')
|
||||
}
|
||||
if (!args.input.service.connect) {
|
||||
@@ -186,7 +183,7 @@ export class WorkshopSchema extends PothosSchema {
|
||||
for (const customer of customers) {
|
||||
const message = await this.prisma.message.create({
|
||||
data: {
|
||||
senderId: ctx.http.me?.id ?? '',
|
||||
senderId: ctx.me?.id ?? '',
|
||||
recipientId: customer.id,
|
||||
type: MessageType.TEXT,
|
||||
content: `Workshop ${workshop.title} đã được lên lịch do ${service.center.name} tổ chức. Nhanh tay đăng kí ngay!`,
|
||||
@@ -194,7 +191,7 @@ export class WorkshopSchema extends PothosSchema {
|
||||
context: MessageContextType.NOTIFICATION,
|
||||
},
|
||||
})
|
||||
ctx.http.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${customer.id}`, message)
|
||||
ctx.pubSub.publish(`${PubSubEvent.NOTIFICATION}.${customer.id}`, message)
|
||||
}
|
||||
return workshop
|
||||
},
|
||||
|
||||
@@ -72,10 +72,7 @@ export class WorkshopMeetingRoomSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
if (!ctx.http?.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
const meetingRoom = await this.prisma.workshopMeetingRoom.findUnique({
|
||||
@@ -96,7 +93,7 @@ export class WorkshopMeetingRoomSchema extends PothosSchema {
|
||||
const serverUrl = this.livekitService.getServerUrl()
|
||||
return {
|
||||
id: meetingRoom.id,
|
||||
token: await this.livekitService.createToken(ctx.http?.me, meetingRoom.id),
|
||||
token: await this.livekitService.createToken(ctx.me, meetingRoom.id),
|
||||
serverUrl,
|
||||
chatRoomId: chatRoom?.id,
|
||||
}
|
||||
|
||||
@@ -58,10 +58,7 @@ export class WorkshopSubscriptionSchema extends PothosSchema {
|
||||
type: [this.workshopSubscription()],
|
||||
args: this.builder.generator.findManyArgs('WorkshopSubscription'),
|
||||
description: 'Retrieve a list of workshop subscriptions with optional filtering, ordering, and pagination.',
|
||||
resolve: async (query, _root, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Workshops cannot be retrieved in subscription context')
|
||||
}
|
||||
resolve: async (query, _root, args, _ctx) => {
|
||||
return await this.prisma.workshopSubscription.findMany({
|
||||
...query,
|
||||
skip: args.skip ?? undefined,
|
||||
@@ -75,16 +72,13 @@ export class WorkshopSubscriptionSchema extends PothosSchema {
|
||||
type: [this.workshopSubscription()],
|
||||
description: 'Retrieve a list of workshops that the current user is subscribed to.',
|
||||
resolve: async (query, _root, _args, ctx, _info) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Workshops cannot be retrieved in subscription context')
|
||||
}
|
||||
if (!ctx.http.me) {
|
||||
if (!ctx.me) {
|
||||
throw new Error('User is not authenticated')
|
||||
}
|
||||
return await this.prisma.workshopSubscription.findMany({
|
||||
...query,
|
||||
where: {
|
||||
userId: ctx.http.me.id,
|
||||
userId: ctx.me.id,
|
||||
},
|
||||
})
|
||||
},
|
||||
@@ -100,10 +94,7 @@ export class WorkshopSubscriptionSchema extends PothosSchema {
|
||||
}),
|
||||
},
|
||||
resolve: async (_query, _root, args, ctx) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed in subscription')
|
||||
}
|
||||
const userId = ctx.http.me?.id
|
||||
const userId = ctx.me?.id
|
||||
// retrieve the workshop
|
||||
const workshop = await this.prisma.workshop.findUnique({
|
||||
where: { id: args.workshopId },
|
||||
|
||||
Reference in New Issue
Block a user