From c27f37a6e6af4bbeae772943ef1a10ea88469e13 Mon Sep 17 00:00:00 2001 From: Mohamed Marrouchi Date: Thu, 16 Jan 2025 10:14:50 +0100 Subject: [PATCH] feat: rename enum instead of string --- .../controllers/attachment.controller.spec.ts | 9 ++-- .../guards/attachment-ability.guard.spec.ts | 7 +-- .../guards/attachment-ability.guard.ts | 52 +++++++++---------- api/src/attachment/mocks/attachment.mock.ts | 7 +-- .../attachment/services/attachment.service.ts | 5 +- api/src/attachment/types/index.ts | 12 ++--- api/src/channel/lib/Handler.ts | 4 +- api/src/channel/lib/__test__/common.mock.ts | 3 +- api/src/chat/services/chat.service.ts | 3 +- .../channels/web/base-web-channel.ts | 5 +- .../1735836154221-v-2-2-0.migration.ts | 45 +++++++++++++--- api/src/user/controllers/user.controller.ts | 3 +- api/src/utils/test/fixtures/attachment.ts | 5 +- .../src/components/contents/ContentDialog.tsx | 3 +- .../contents/ContentImportDialog.tsx | 3 +- .../src/components/settings/SettingInput.tsx | 5 +- .../form/AttachmentMessageForm.tsx | 3 +- frontend/src/types/attachment.types.ts | 12 ++--- 18 files changed, 116 insertions(+), 70 deletions(-) diff --git a/api/src/attachment/controllers/attachment.controller.spec.ts b/api/src/attachment/controllers/attachment.controller.spec.ts index 12a902f3..34b19ef0 100644 --- a/api/src/attachment/controllers/attachment.controller.spec.ts +++ b/api/src/attachment/controllers/attachment.controller.spec.ts @@ -39,6 +39,7 @@ import { attachment, attachmentFile } from '../mocks/attachment.mock'; import { AttachmentRepository } from '../repositories/attachment.repository'; import { Attachment, AttachmentModel } from '../schemas/attachment.schema'; import { AttachmentService } from '../services/attachment.service'; +import { AttachmentResourceRef } from '../types'; import { AttachmentController } from './attachment.controller'; @@ -110,7 +111,7 @@ describe('AttachmentController', () => { file: [], }, {} as Request, - { resourceRef: 'block_attachment' }, + { resourceRef: AttachmentResourceRef.BlockAttachment }, ); await expect(promiseResult).rejects.toThrow( new BadRequestException('No file was selected'), @@ -128,7 +129,7 @@ describe('AttachmentController', () => { { session: { passport: { user: { id: '9'.repeat(24) } } }, } as unknown as Request, - { resourceRef: 'block_attachment' }, + { resourceRef: AttachmentResourceRef.BlockAttachment }, ); const [name] = attachmentFile.filename.split('.'); expect(attachmentService.create).toHaveBeenCalledWith({ @@ -136,7 +137,7 @@ describe('AttachmentController', () => { type: attachmentFile.mimetype, name: attachmentFile.originalname, location: expect.stringMatching(new RegExp(`^/${name}`)), - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, access: 'public', createdByRef: 'User', createdBy: '9'.repeat(24), @@ -145,7 +146,7 @@ describe('AttachmentController', () => { [ { ...attachment, - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, createdByRef: 'User', createdBy: '9'.repeat(24), }, diff --git a/api/src/attachment/guards/attachment-ability.guard.spec.ts b/api/src/attachment/guards/attachment-ability.guard.spec.ts index 75d0a4d5..395163ae 100644 --- a/api/src/attachment/guards/attachment-ability.guard.spec.ts +++ b/api/src/attachment/guards/attachment-ability.guard.spec.ts @@ -18,6 +18,7 @@ import { Action } from '@/user/types/action.type'; import { attachment } from '../mocks/attachment.mock'; import { Attachment } from '../schemas/attachment.schema'; import { AttachmentService } from '../services/attachment.service'; +import { AttachmentResourceRef } from '../types'; import { AttachmentGuard } from './attachment-ability.guard'; @@ -55,7 +56,7 @@ describe('AttachmentGuard', () => { describe('canActivate', () => { it('should allow GET requests with valid ref', async () => { const mockUser = { roles: ['admin-id'] } as any; - const mockRef = ['user_avatar']; + const mockRef = [AttachmentResourceRef.UserAvatar]; jest.spyOn(modelService, 'findOne').mockImplementation((criteria) => { return typeof criteria === 'string' || @@ -120,7 +121,7 @@ describe('AttachmentGuard', () => { ? Promise.reject('Invalid ID') : Promise.resolve({ id: '9'.repeat(24), - resourceRef: `user_avatar`, + resourceRef: AttachmentResourceRef.UserAvatar, } as Attachment); }); @@ -191,7 +192,7 @@ describe('AttachmentGuard', () => { const mockExecutionContext = { switchToHttp: jest.fn().mockReturnValue({ getRequest: jest.fn().mockReturnValue({ - query: { resourceRef: 'block_attachment' }, + query: { resourceRef: AttachmentResourceRef.BlockAttachment }, method: 'POST', user: mockUser, }), diff --git a/api/src/attachment/guards/attachment-ability.guard.ts b/api/src/attachment/guards/attachment-ability.guard.ts index cfa1a583..be5deea3 100644 --- a/api/src/attachment/guards/attachment-ability.guard.ts +++ b/api/src/attachment/guards/attachment-ability.guard.ts @@ -26,7 +26,7 @@ import { Action } from '@/user/types/action.type'; import { TModel } from '@/user/types/model.type'; import { AttachmentService } from '../services/attachment.service'; -import { TAttachmentResourceRef } from '../types'; +import { AttachmentResourceRef, TAttachmentResourceRef } from '../types'; import { isAttachmentResourceRef, isAttachmentResourceRefArray, @@ -46,46 +46,46 @@ export class AttachmentGuard implements CanActivate { > = { // Read attachments by ref [Action.READ]: { - setting_attachment: [ + [AttachmentResourceRef.SettingAttachment]: [ ['setting', Action.READ], ['attachment', Action.READ], ], - user_avatar: [['user', Action.READ]], - block_attachment: [ + [AttachmentResourceRef.UserAvatar]: [['user', Action.READ]], + [AttachmentResourceRef.BlockAttachment]: [ ['block', Action.READ], ['attachment', Action.READ], ], - content_attachment: [ + [AttachmentResourceRef.ContentAttachment]: [ ['content', Action.READ], ['attachment', Action.READ], ], - subscriber_avatar: [['subscriber', Action.READ]], - message_attachment: [ + [AttachmentResourceRef.SubscriberAvatar]: [['subscriber', Action.READ]], + [AttachmentResourceRef.MessageAttachment]: [ ['message', Action.READ], ['attachment', Action.READ], ], }, // Create attachments by ref [Action.CREATE]: { - setting_attachment: [ + [AttachmentResourceRef.SettingAttachment]: [ ['setting', Action.UPDATE], ['attachment', Action.CREATE], ], - user_avatar: [ + [AttachmentResourceRef.UserAvatar]: [ // Not authorized, done via /user/:id/edit endpoint ], - block_attachment: [ + [AttachmentResourceRef.BlockAttachment]: [ ['block', Action.UPDATE], ['attachment', Action.CREATE], ], - content_attachment: [ + [AttachmentResourceRef.ContentAttachment]: [ ['content', Action.UPDATE], ['attachment', Action.CREATE], ], - subscriber_avatar: [ + [AttachmentResourceRef.SubscriberAvatar]: [ // Not authorized, done programmatically by the channel ], - message_attachment: [ + [AttachmentResourceRef.MessageAttachment]: [ // Unless we're in case of a handover, done programmatically by the channel ['message', Action.CREATE], ['attachment', Action.CREATE], @@ -93,36 +93,36 @@ export class AttachmentGuard implements CanActivate { }, // Delete attachments by ref [Action.DELETE]: { - setting_attachment: [ + [AttachmentResourceRef.SettingAttachment]: [ ['setting', Action.UPDATE], ['attachment', Action.DELETE], ], - user_avatar: [ + [AttachmentResourceRef.UserAvatar]: [ // Not authorized ], - block_attachment: [ + [AttachmentResourceRef.BlockAttachment]: [ ['block', Action.UPDATE], ['attachment', Action.DELETE], ], - content_attachment: [ + [AttachmentResourceRef.ContentAttachment]: [ ['content', Action.UPDATE], ['attachment', Action.DELETE], ], - subscriber_avatar: [ + [AttachmentResourceRef.SubscriberAvatar]: [ // Not authorized, done programmatically by the channel ], - message_attachment: [ + [AttachmentResourceRef.MessageAttachment]: [ // Not authorized ], }, // Update attachments is not possible [Action.UPDATE]: { - setting_attachment: [], - user_avatar: [], - block_attachment: [], - content_attachment: [], - subscriber_avatar: [], - message_attachment: [], + [AttachmentResourceRef.SettingAttachment]: [], + [AttachmentResourceRef.UserAvatar]: [], + [AttachmentResourceRef.BlockAttachment]: [], + [AttachmentResourceRef.ContentAttachment]: [], + [AttachmentResourceRef.SubscriberAvatar]: [], + [AttachmentResourceRef.MessageAttachment]: [], }, }; @@ -163,7 +163,7 @@ export class AttachmentGuard implements CanActivate { * * @param action - The action on the attachment. * @param user - The current user. - * @param resourceRef - The resource ref of the attachment (e.g., user_avatar, setting_attachment). + * @param resourceRef - The resource ref of the attachment (e.g., [AttachmentResourceRef.UserAvatar], [AttachmentResourceRef.SettingAttachment]). * @returns A promise that resolves to `true` if the user has the required upload permission, otherwise `false`. */ private async isAuthorized( diff --git a/api/src/attachment/mocks/attachment.mock.ts b/api/src/attachment/mocks/attachment.mock.ts index fd54334f..cbc885b8 100644 --- a/api/src/attachment/mocks/attachment.mock.ts +++ b/api/src/attachment/mocks/attachment.mock.ts @@ -9,6 +9,7 @@ import { Stream } from 'node:stream'; import { Attachment } from '../schemas/attachment.schema'; +import { AttachmentResourceRef } from '../types'; export const attachment: Attachment = { name: 'Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', @@ -16,7 +17,7 @@ export const attachment: Attachment = { size: 343370, location: '/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, access: 'public', id: '65940d115178607da65c82b6', createdAt: new Date(), @@ -47,7 +48,7 @@ export const attachments: Attachment[] = [ location: '/app/src/attachment/uploads/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', channel: { ['some-channel']: {} }, - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, access: 'public', id: '65940d115178607da65c82b7', createdAt: new Date(), @@ -62,7 +63,7 @@ export const attachments: Attachment[] = [ location: '/app/src/attachment/uploads/Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png', channel: { ['some-channel']: {} }, - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, access: 'public', id: '65940d115178607da65c82b8', createdAt: new Date(), diff --git a/api/src/attachment/services/attachment.service.ts b/api/src/attachment/services/attachment.service.ts index c26dea8d..f4721b2b 100644 --- a/api/src/attachment/services/attachment.service.ts +++ b/api/src/attachment/services/attachment.service.ts @@ -30,7 +30,7 @@ import { BaseService } from '@/utils/generics/base-service'; import { AttachmentMetadataDto } from '../dto/attachment.dto'; import { AttachmentRepository } from '../repositories/attachment.repository'; import { Attachment } from '../schemas/attachment.schema'; -import { TAttachmentResourceRef } from '../types'; +import { AttachmentResourceRef, TAttachmentResourceRef } from '../types'; import { fileExists, generateUniqueFilename, @@ -164,7 +164,8 @@ export class AttachmentService extends BaseService { * @returns The root directory path */ getRootDirByResourceRef(ref: TAttachmentResourceRef) { - return ref === 'subscriber_avatar' || ref === 'user_avatar' + return ref === AttachmentResourceRef.SubscriberAvatar || + ref === AttachmentResourceRef.UserAvatar ? config.parameters.avatarDir : config.parameters.uploadDir; } diff --git a/api/src/attachment/types/index.ts b/api/src/attachment/types/index.ts index 267410bb..ae2ae728 100644 --- a/api/src/attachment/types/index.ts +++ b/api/src/attachment/types/index.ts @@ -24,12 +24,12 @@ export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`; * These resource references influence how the attachment is uploaded, stored, and accessed: */ export enum AttachmentResourceRef { - SettingAttachment = 'setting_attachment', // Attachments related to app settings, restricted to users with specific permissions. - UserAvatar = 'user_avatar', // Avatar files for users, only the current user can upload, accessible to those with appropriate permissions. - SubscriberAvatar = 'subscriber_avatar', // Avatar files for subscribers, uploaded programmatically, accessible to authorized users. - BlockAttachment = 'block_attachment', // Files sent by the bot, public or private based on the channel and user authentication. - ContentAttachment = 'content_attachment', // Files in the knowledge base, usually public but could vary based on specific needs. - MessageAttachment = 'message_attachment', // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; + SettingAttachment = 'Setting', // Attachments related to app settings, restricted to users with specific permissions. + UserAvatar = 'User', // Avatar files for users, only the current user can upload, accessible to those with appropriate permissions. + SubscriberAvatar = 'Subscriber', // Avatar files for subscribers, uploaded programmatically, accessible to authorized users. + BlockAttachment = 'Block', // Files sent by the bot, public or private based on the channel and user authentication. + ContentAttachment = 'Content', // Files in the knowledge base, usually public but could vary based on specific needs. + MessageAttachment = 'Message', // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; } export type TAttachmentResourceRef = `${AttachmentResourceRef}`; diff --git a/api/src/channel/lib/Handler.ts b/api/src/channel/lib/Handler.ts index f524d819..d1525758 100644 --- a/api/src/channel/lib/Handler.ts +++ b/api/src/channel/lib/Handler.ts @@ -22,7 +22,7 @@ import { v4 as uuidv4 } from 'uuid'; import { Attachment } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; -import { AttachmentFile } from '@/attachment/types'; +import { AttachmentFile, AttachmentResourceRef } from '@/attachment/types'; import { SubscriberCreateDto } from '@/chat/dto/subscriber.dto'; import { AttachmentRef } from '@/chat/schemas/types/attachment'; import { @@ -258,7 +258,7 @@ export default abstract class ChannelHandler< name: `${name ? `${name}-` : ''}${uuidv4()}.${mime.extension(type)}`, type, size, - resourceRef: 'message_attachment', + resourceRef: AttachmentResourceRef.MessageAttachment, access: 'private', createdByRef: 'Subscriber', createdBy: subscriber.id, diff --git a/api/src/channel/lib/__test__/common.mock.ts b/api/src/channel/lib/__test__/common.mock.ts index c23b6d06..0f6f04a8 100644 --- a/api/src/channel/lib/__test__/common.mock.ts +++ b/api/src/channel/lib/__test__/common.mock.ts @@ -7,6 +7,7 @@ */ import { Attachment } from '@/attachment/schemas/attachment.schema'; +import { AttachmentResourceRef } from '@/attachment/types'; import { ButtonType } from '@/chat/schemas/types/button'; import { FileType, @@ -88,7 +89,7 @@ const attachment: Attachment = { id: 'any-channel-attachment-id', }, }, - resourceRef: 'block_attachment', + resourceRef: AttachmentResourceRef.BlockAttachment, access: 'public', createdByRef: 'User', createdBy: null, diff --git a/api/src/chat/services/chat.service.ts b/api/src/chat/services/chat.service.ts index 25090cc5..78ef8866 100644 --- a/api/src/chat/services/chat.service.ts +++ b/api/src/chat/services/chat.service.ts @@ -12,6 +12,7 @@ import mime from 'mime'; import { v4 as uuidv4 } from 'uuid'; import { AttachmentService } from '@/attachment/services/attachment.service'; +import { AttachmentResourceRef } from '@/attachment/types'; import EventWrapper from '@/channel/lib/EventWrapper'; import { config } from '@/config'; import { HelperService } from '@/helper/helper.service'; @@ -280,7 +281,7 @@ export class ChatService { name: `avatar-${uuidv4()}.${extension}`, size, type, - resourceRef: 'subscriber_avatar', + resourceRef: AttachmentResourceRef.SubscriberAvatar, access: 'private', createdByRef: 'Subscriber', createdBy: subscriber.id, diff --git a/api/src/extensions/channels/web/base-web-channel.ts b/api/src/extensions/channels/web/base-web-channel.ts index eb70e8aa..454a2dd5 100644 --- a/api/src/extensions/channels/web/base-web-channel.ts +++ b/api/src/extensions/channels/web/base-web-channel.ts @@ -15,6 +15,7 @@ import { v4 as uuidv4 } from 'uuid'; import { Attachment } from '@/attachment/schemas/attachment.schema'; import { AttachmentService } from '@/attachment/services/attachment.service'; +import { AttachmentResourceRef } from '@/attachment/types'; import { ChannelService } from '@/channel/channel.service'; import ChannelHandler from '@/channel/lib/Handler'; import { ChannelName } from '@/channel/types'; @@ -625,7 +626,7 @@ export default abstract class BaseWebChannelHandler< name: data.name, size: Buffer.byteLength(data.file), type: data.type, - resourceRef: 'message_attachment', + resourceRef: AttachmentResourceRef.MessageAttachment, access: 'private', createdByRef: 'Subscriber', createdBy: req.session?.web?.profile?.id, @@ -692,7 +693,7 @@ export default abstract class BaseWebChannelHandler< name: file.originalname, size: file.size, type: file.mimetype, - resourceRef: 'message_attachment', + resourceRef: AttachmentResourceRef.MessageAttachment, access: 'private', createdByRef: 'Subscriber', createdBy: req.session.web.profile?.id, diff --git a/api/src/migration/migrations/1735836154221-v-2-2-0.migration.ts b/api/src/migration/migrations/1735836154221-v-2-2-0.migration.ts index e9c039e8..b94a68af 100644 --- a/api/src/migration/migrations/1735836154221-v-2-2-0.migration.ts +++ b/api/src/migration/migrations/1735836154221-v-2-2-0.migration.ts @@ -362,6 +362,8 @@ const undoPopulateAttachments = async ({ logger }: MigrationServices) => { AttachmentResourceRef.SettingAttachment, AttachmentResourceRef.UserAvatar, AttachmentResourceRef.SubscriberAvatar, + AttachmentResourceRef.ContentAttachment, + AttachmentResourceRef.MessageAttachment, ], }, }, @@ -376,11 +378,11 @@ const undoPopulateAttachments = async ({ logger }: MigrationServices) => { ); logger.log( - `Successfully reverted attributes for ${result.modifiedCount} attachments with ref 'setting_attachment'`, + `Successfully reverted attributes for ${result.modifiedCount} attachments with ref AttachmentResourceRef.SettingAttachment`, ); } catch (error) { logger.error( - `Failed to revert attributes for attachments with ref 'setting_attachment': ${error.message}`, + `Failed to revert attributes for attachments with ref AttachmentResourceRef.SettingAttachment: ${error.message}`, ); } }; @@ -552,7 +554,7 @@ const buildRenameAttributeCallback = }; /** - * Traverses an content document to search for any attachment object + * Traverses a content document to search for any attachment object * @param obj * @param callback * @returns @@ -584,7 +586,14 @@ const migrateAttachmentContents = async ( const updateField = action === MigrationAction.UP ? 'id' : 'attachment_id'; const unsetField = action === MigrationAction.UP ? 'attachment_id' : 'id'; const ContentModel = mongoose.model(Content.name, contentSchema); - // Find blocks where "message.attachment" exists + const AttachmentModel = mongoose.model( + Attachment.name, + attachmentSchema, + ); + + const adminUser = await getAdminUser(); + + // Process all contents const cursor = ContentModel.find({}).cursor(); for await (const content of cursor) { @@ -594,6 +603,30 @@ const migrateAttachmentContents = async ( buildRenameAttributeCallback(unsetField, updateField), ); + for (const key in content.dynamicFields) { + if ( + content.dynamicFields[key] && + typeof content.dynamicFields[key] === 'object' && + 'payload' in content.dynamicFields[key] && + 'id' in content.dynamicFields[key].payload && + content.dynamicFields[key].payload.id + ) { + await AttachmentModel.updateOne( + { + _id: content.dynamicFields[key].payload.id, + }, + { + $set: { + resourceRef: AttachmentResourceRef.ContentAttachment, + createdBy: adminUser.id, + createdByRef: 'User', + access: 'public', + }, + }, + ); + } + } + await ContentModel.replaceOne({ _id: content._id }, content); } catch (error) { logger.error(`Failed to update content ${content._id}: ${error.message}`); @@ -648,7 +681,7 @@ const migrateAndPopulateAttachmentMessages = async ({ await attachmentService.updateOne( msg.message.attachment.payload.attachment_id as string, { - resourceRef: 'message_attachment', + resourceRef: AttachmentResourceRef.MessageAttachment, access: 'private', createdByRef: msg.sender ? 'Subscriber' : 'User', createdBy: msg.sender ? msg.sender : adminUser.id, @@ -681,7 +714,7 @@ const migrateAndPopulateAttachmentMessages = async ({ size: fileBuffer.length, type: response.headers['content-type'], channel: {}, - resourceRef: 'message_attachment', + resourceRef: AttachmentResourceRef.MessageAttachment, access: msg.sender ? 'private' : 'public', createdBy: msg.sender ? msg.sender : adminUser.id, createdByRef: msg.sender ? 'Subscriber' : 'User', diff --git a/api/src/user/controllers/user.controller.ts b/api/src/user/controllers/user.controller.ts index 1af1674b..968855b8 100644 --- a/api/src/user/controllers/user.controller.ts +++ b/api/src/user/controllers/user.controller.ts @@ -31,6 +31,7 @@ import { Session as ExpressSession } from 'express-session'; import { diskStorage, memoryStorage } from 'multer'; import { AttachmentService } from '@/attachment/services/attachment.service'; +import { AttachmentResourceRef } from '@/attachment/types'; import { config } from '@/config'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; import { LoggerService } from '@/logger/logger.service'; @@ -294,7 +295,7 @@ export class ReadWriteUserController extends ReadOnlyUserController { name: avatarFile.originalname, size: avatarFile.size, type: avatarFile.mimetype, - resourceRef: 'user_avatar', + resourceRef: AttachmentResourceRef.UserAvatar, access: 'private', createdByRef: 'User', createdBy: req.user.id, diff --git a/api/src/utils/test/fixtures/attachment.ts b/api/src/utils/test/fixtures/attachment.ts index cece4802..73fda51c 100644 --- a/api/src/utils/test/fixtures/attachment.ts +++ b/api/src/utils/test/fixtures/attachment.ts @@ -10,6 +10,7 @@ import mongoose from 'mongoose'; import { AttachmentCreateDto } from '@/attachment/dto/attachment.dto'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; +import { AttachmentResourceRef } from '@/attachment/types'; export const attachmentFixtures: AttachmentCreateDto[] = [ { @@ -22,7 +23,7 @@ export const attachmentFixtures: AttachmentCreateDto[] = [ id: '1', }, }, - resourceRef: 'content_attachment', + resourceRef: AttachmentResourceRef.ContentAttachment, access: 'public', createdByRef: 'User', createdBy: '9'.repeat(24), @@ -37,7 +38,7 @@ export const attachmentFixtures: AttachmentCreateDto[] = [ id: '2', }, }, - resourceRef: 'content_attachment', + resourceRef: AttachmentResourceRef.ContentAttachment, access: 'public', createdByRef: 'User', createdBy: '9'.repeat(24), diff --git a/frontend/src/components/contents/ContentDialog.tsx b/frontend/src/components/contents/ContentDialog.tsx index 761e9eec..642f9d91 100644 --- a/frontend/src/components/contents/ContentDialog.tsx +++ b/frontend/src/components/contents/ContentDialog.tsx @@ -38,6 +38,7 @@ import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; import { useTranslate } from "@/hooks/useTranslate"; import { EntityType } from "@/services/types"; +import { AttachmentResourceRef } from "@/types/attachment.types"; import { ContentField, ContentFieldType, @@ -116,7 +117,7 @@ const ContentFieldInput: React.FC = ({ value={field.value?.payload?.id} accept={MIME_TYPES["images"].join(",")} format="full" - resourceRef="content_attachment" + resourceRef={AttachmentResourceRef.ContentAttachment} /> ); default: diff --git a/frontend/src/components/contents/ContentImportDialog.tsx b/frontend/src/components/contents/ContentImportDialog.tsx index ba1bece0..ddf613bb 100644 --- a/frontend/src/components/contents/ContentImportDialog.tsx +++ b/frontend/src/components/contents/ContentImportDialog.tsx @@ -20,6 +20,7 @@ import { useApiClient } from "@/hooks/useApiClient"; import { DialogControlProps } from "@/hooks/useDialog"; import { useToast } from "@/hooks/useToast"; import { useTranslate } from "@/hooks/useTranslate"; +import { AttachmentResourceRef } from "@/types/attachment.types"; import { IContentType } from "@/types/content-type.types"; export type ContentImportDialogProps = DialogControlProps<{ @@ -81,7 +82,7 @@ export const ContentImportDialog: FC = ({ }} label="" value={attachmentId} - resourceRef="content_attachment" + resourceRef={AttachmentResourceRef.ContentAttachment} /> diff --git a/frontend/src/components/settings/SettingInput.tsx b/frontend/src/components/settings/SettingInput.tsx index 174f3eea..889ce979 100644 --- a/frontend/src/components/settings/SettingInput.tsx +++ b/frontend/src/components/settings/SettingInput.tsx @@ -20,6 +20,7 @@ import MultipleInput from "@/app-components/inputs/MultipleInput"; import { PasswordInput } from "@/app-components/inputs/PasswordInput"; import { useTranslate } from "@/hooks/useTranslate"; import { EntityType, Format } from "@/services/types"; +import { AttachmentResourceRef } from "@/types/attachment.types"; import { IBlock } from "@/types/block.types"; import { IHelper } from "@/types/helper.types"; import { ISetting, SettingType } from "@/types/setting.types"; @@ -186,7 +187,7 @@ const SettingInput: React.FC = ({ accept={MIME_TYPES["images"].join(",")} format="full" size={128} - resourceRef="setting_attachment" + resourceRef={AttachmentResourceRef.SettingAttachment} /> ); @@ -199,7 +200,7 @@ const SettingInput: React.FC = ({ accept={MIME_TYPES["images"].join(",")} format="full" size={128} - resourceRef="setting_attachment" + resourceRef={AttachmentResourceRef.SettingAttachment} /> ); default: diff --git a/frontend/src/components/visual-editor/form/AttachmentMessageForm.tsx b/frontend/src/components/visual-editor/form/AttachmentMessageForm.tsx index a5b12b2e..13cb4877 100644 --- a/frontend/src/components/visual-editor/form/AttachmentMessageForm.tsx +++ b/frontend/src/components/visual-editor/form/AttachmentMessageForm.tsx @@ -13,6 +13,7 @@ import AttachmentInput from "@/app-components/attachment/AttachmentInput"; import { ContentItem } from "@/app-components/dialogs"; import AttachmentIcon from "@/app-components/svg/toolbar/AttachmentIcon"; import { useTranslate } from "@/hooks/useTranslate"; +import { AttachmentResourceRef } from "@/types/attachment.types"; import { IBlockAttributes } from "@/types/block.types"; import { FileType } from "@/types/message.types"; import { MIME_TYPES, getFileType } from "@/utils/attachment"; @@ -69,7 +70,7 @@ const AttachmentMessageForm = () => { }, }); }} - resourceRef="block_attachment" + resourceRef={AttachmentResourceRef.BlockAttachment} /> ); }} diff --git a/frontend/src/types/attachment.types.ts b/frontend/src/types/attachment.types.ts index 213ea268..d70ba7b8 100644 --- a/frontend/src/types/attachment.types.ts +++ b/frontend/src/types/attachment.types.ts @@ -29,12 +29,12 @@ export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`; * These references influence how the attachment is uploaded, stored, and accessed: */ export enum AttachmentResourceRef { - SettingAttachment = "setting_attachment", // Attachments related to app settings, restricted to users with specific permissions. - UserAvatar = "user_avatar", // Avatar files for users, only the current user can upload, accessible to those with appropriate permissions. - SubscriberAvatar = "subscriber_avatar", // Avatar files for subscribers, uploaded programmatically, accessible to authorized users. - BlockAttachment = "block_attachment", // Files sent by the bot, public or private based on the channel and user authentication. - ContentAttachment = "content_attachment", // Files in the knowledge base, usually public but could vary based on specific needs. - MessageAttachment = "message_attachment", // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; + SettingAttachment = "Setting", // Attachments related to app settings, restricted to users with specific permissions. + UserAvatar = "User", // Avatar files for users, only the current user can upload, accessible to those with appropriate permissions. + SubscriberAvatar = "Subscriber", // Avatar files for subscribers, uploaded programmatically, accessible to authorized users. + BlockAttachment = "Block", // Files sent by the bot, public or private based on the channel and user authentication. + ContentAttachment = "Content", // Files in the knowledge base, usually public but could vary based on specific needs. + MessageAttachment = "Message", // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; } export type TAttachmentResourceRef = `${AttachmentResourceRef}`;