update something can update

This commit is contained in:
2024-11-08 17:27:09 +07:00
parent 7eabba1868
commit d7c7f8a782
10 changed files with 93 additions and 19 deletions

View File

@@ -47,8 +47,18 @@ export class CenterSchema extends PothosSchema {
adminNote: t.relation('adminNote', { adminNote: t.relation('adminNote', {
description: 'The admin note of the center.', description: 'The admin note of the center.',
}), }),
logoUrl: t.exposeString('logoUrl', { logoUrl: t.string({
nullable: true,
description: 'The URL of the center logo.', description: 'The URL of the center logo.',
resolve: async (center) => {
// get file id from logoUrl
const logoFileId = center.logoUrl?.split('/').pop()?.split('?')[0]
return await this.minioService.updatePresignUrl(
logoFileId ?? '',
'files',
center.logoUrl ?? undefined,
)
},
}), }),
logoFile: t.relation('logoFile', { logoFile: t.relation('logoFile', {
description: 'The file associated with the center logo.', description: 'The file associated with the center logo.',

View File

@@ -37,7 +37,6 @@ export class GraphqlService {
// redis context cache // redis context cache
const cachedUser = await this.redis.getUser(sessionId) const cachedUser = await this.redis.getUser(sessionId)
if (cachedUser) { if (cachedUser) {
Logger.log(`Cache hit for sessionId: ${sessionId}`)
return cachedUser return cachedUser
} }
// check if the token is valid // check if the token is valid

View File

@@ -1,4 +1,4 @@
import { Inject, Injectable } from '@nestjs/common' import { Inject, Injectable, Logger } from '@nestjs/common'
import { import {
Pothos, Pothos,
PothosRef, PothosRef,
@@ -148,6 +148,8 @@ export class MessageSchema extends PothosSchema {
'sender', 'sender',
'sentAt', 'sentAt',
'context', 'context',
'recipient',
'recipientId',
]), ]),
description: 'The message to send.', description: 'The message to send.',
required: true, required: true,
@@ -167,14 +169,19 @@ export class MessageSchema extends PothosSchema {
if (!args.input.sender) { if (!args.input.sender) {
throw new Error('Cannot get sender from context') throw new Error('Cannot get sender from context')
} }
// check if content is empty
if (!args.input.content || args.input.content.trim() === '') {
throw new Error('Content cannot be empty')
}
args.input.context = messageContext args.input.context = messageContext
// check if content is longer than 1024 characters
if (args.input.content.length > 1024) {
throw new Error('Content cannot be longer than 1024 characters')
}
const message = await this.prisma.message.create({ const message = await this.prisma.message.create({
...query, ...query,
data: args.input, data: args.input,
}) })
if (ctx.isSubscription) {
throw new Error('Not allowed')
}
ctx.http.pubSub.publish(`MESSAGE_SENT_${message.chatRoomId}`, message) ctx.http.pubSub.publish(`MESSAGE_SENT_${message.chatRoomId}`, message)
return message return message
}, },

View File

@@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'
import { FileUpload } from 'graphql-upload/processRequest.js' import { FileUpload } from 'graphql-upload/processRequest.js'
import { Client } from 'minio' import { Client } from 'minio'
import { MINIO_CONNECTION } from 'nestjs-minio' import { MINIO_CONNECTION } from 'nestjs-minio'
import { DateTimeUtils } from 'src/common/utils/datetime.utils'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
@Injectable() @Injectable()
export class MinioService { export class MinioService {
@@ -12,7 +13,7 @@ export class MinioService {
) {} ) {}
async uploadFile(file: FileUpload, category: string) { async uploadFile(file: FileUpload, category: string) {
// sonar ignore next // @ts-nocheck
const { mimetype, createReadStream, filename: actualFileName } = await file const { mimetype, createReadStream, filename: actualFileName } = await file
const filename = this.fileName() const filename = this.fileName()
const Name = `${category}/${filename}` const Name = `${category}/${filename}`
@@ -30,12 +31,18 @@ export class MinioService {
return { result, filename, mimetype, actualFileName } return { result, filename, mimetype, actualFileName }
} }
async getFileUrl(id: string, category: string) { async getFileUrl(id: string, category: string, presignUrl?: string) {
if (!id) { if (!id) {
return null return null
} }
let url = null let url = null
// check if presignUrl is provided and not expired else get new presignUrl
if (
presignUrl &&
!DateTimeUtils.isExpired(presignUrl.split('&X-Amz-Date=')[1])
) {
url = presignUrl
} else {
try { try {
url = await this.minioClient.presignedUrl( url = await this.minioClient.presignedUrl(
'GET', 'GET',
@@ -46,10 +53,35 @@ export class MinioService {
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
}
console.log(url) console.log(url)
return url return url
} }
async updatePresignUrl(id: string, category: string, presignUrl?: string) {
// check if presignUrl is expired else get new presignUrl
const date = presignUrl?.split('&X-Amz-Date=')[1].split('&')[0]
if (presignUrl && !DateTimeUtils.isExpired(date ?? '')) {
return presignUrl
}
// if presignUrl is not provided, get new presignUrl
if (!presignUrl) {
return await this.minioClient.presignedUrl(
'GET',
this.configService.get('BUCKET_NAME') ?? 'epess',
`${category}/${id}`,
60 * 60 * 24 * 7,
)
}
// if presignUrl is expired, renew it and return
return await this.minioClient.presignedUrl(
'GET',
this.configService.get('BUCKET_NAME') ?? 'epess',
`${category}/${id}`,
60 * 60 * 24 * 7,
)
}
async deleteFile(id: string, category: string) { async deleteFile(id: string, category: string) {
return await this.minioClient.removeObject( return await this.minioClient.removeObject(
this.configService.get('BUCKET_NAME') ?? 'epess', this.configService.get('BUCKET_NAME') ?? 'epess',

View File

@@ -14,7 +14,7 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
super({ super({
log: [ log: [
{ {
emit: 'stdout', emit: 'event',
level: 'query', level: 'query',
}, },
{ {

View File

@@ -59,10 +59,24 @@ export class ServiceSchema extends PothosSchema {
description: 'The image file for the service.', description: 'The image file for the service.',
}), }),
imageFileId: t.exposeID('imageFileId', { imageFileId: t.exposeID('imageFileId', {
nullable: true,
description: 'The ID of the image file for the service.', description: 'The ID of the image file for the service.',
}), }),
imageFileUrl: t.exposeString('imageFileUrl', { imageFileUrl: t.string({
nullable: true,
description: 'The URL of the image file for the service.', description: 'The URL of the image file for the service.',
resolve: async (service) => {
// get file id from imageFileUrl
const imageFileId = service.imageFileUrl
?.split('/')
.pop()
?.split('?')[0]
return await this.minioService.updatePresignUrl(
imageFileId ?? '',
'files',
service.imageFileUrl ?? undefined,
)
},
}), }),
status: t.expose('status', { status: t.expose('status', {
type: ServiceStatus, type: ServiceStatus,

View File

@@ -41,8 +41,16 @@ export class UploadedFileSchema extends PothosSchema {
nullable: true, nullable: true,
description: 'The type of the file.', description: 'The type of the file.',
}), }),
fileUrl: t.exposeString('fileUrl', { fileUrl: t.string({
nullable: true,
description: 'The URL of the file.', description: 'The URL of the file.',
resolve: async (file) => {
return await this.minioService.updatePresignUrl(
file.id,
'files',
file.fileUrl,
)
},
}), }),
uploadedAt: t.expose('uploadedAt', { uploadedAt: t.expose('uploadedAt', {
type: 'DateTime', type: 'DateTime',

View File

@@ -48,6 +48,10 @@ export class DateTimeUtils {
} }
} }
static isExpired(expires: string): boolean {
return DateTime.fromISO(expires) < DateTime.now()
}
static isOverlap( static isOverlap(
startA: DateTime, startA: DateTime,
endA: DateTime, endA: DateTime,

File diff suppressed because one or more lines are too long