refactor: use enums

This commit is contained in:
Mohamed Marrouchi 2025-01-16 17:41:30 +01:00
parent 4fac5d4fc9
commit 359049ff3d
22 changed files with 124 additions and 90 deletions

View File

@ -39,7 +39,11 @@ import { attachment, attachmentFile } from '../mocks/attachment.mock';
import { AttachmentRepository } from '../repositories/attachment.repository'; import { AttachmentRepository } from '../repositories/attachment.repository';
import { Attachment, AttachmentModel } from '../schemas/attachment.schema'; import { Attachment, AttachmentModel } from '../schemas/attachment.schema';
import { AttachmentService } from '../services/attachment.service'; import { AttachmentService } from '../services/attachment.service';
import { AttachmentResourceRef } from '../types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '../types';
import { AttachmentController } from './attachment.controller'; import { AttachmentController } from './attachment.controller';
@ -138,8 +142,8 @@ describe('AttachmentController', () => {
name: attachmentFile.originalname, name: attachmentFile.originalname,
location: expect.stringMatching(new RegExp(`^/${name}`)), location: expect.stringMatching(new RegExp(`^/${name}`)),
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
access: 'public', access: AttachmentAccess.Public,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: '9'.repeat(24), createdBy: '9'.repeat(24),
}); });
expect(result).toEqualPayload( expect(result).toEqualPayload(
@ -147,7 +151,7 @@ describe('AttachmentController', () => {
{ {
...attachment, ...attachment,
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: '9'.repeat(24), createdBy: '9'.repeat(24),
}, },
], ],

View File

@ -46,6 +46,7 @@ import {
import { AttachmentGuard } from '../guards/attachment-ability.guard'; import { AttachmentGuard } from '../guards/attachment-ability.guard';
import { Attachment } from '../schemas/attachment.schema'; import { Attachment } from '../schemas/attachment.schema';
import { AttachmentService } from '../services/attachment.service'; import { AttachmentService } from '../services/attachment.service';
import { AttachmentAccess, AttachmentCreatedByRef } from '../types';
@UseInterceptors(CsrfInterceptor) @UseInterceptors(CsrfInterceptor)
@Controller('attachment') @Controller('attachment')
@ -131,7 +132,10 @@ export class AttachmentController extends BaseController<Attachment> {
@UploadedFiles() files: { file: Express.Multer.File[] }, @UploadedFiles() files: { file: Express.Multer.File[] },
@Req() req: Request, @Req() req: Request,
@Query() @Query()
{ resourceRef, access = 'public' }: AttachmentContextParamDto, {
resourceRef,
access = AttachmentAccess.Public,
}: AttachmentContextParamDto,
): Promise<Attachment[]> { ): Promise<Attachment[]> {
if (!files || !Array.isArray(files?.file) || files.file.length === 0) { if (!files || !Array.isArray(files?.file) || files.file.length === 0) {
throw new BadRequestException('No file was selected'); throw new BadRequestException('No file was selected');
@ -153,7 +157,7 @@ export class AttachmentController extends BaseController<Attachment> {
resourceRef, resourceRef,
access, access,
createdBy: userId, createdBy: userId,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
}); });
if (attachment) { if (attachment) {

View File

@ -27,9 +27,6 @@ import {
AttachmentAccess, AttachmentAccess,
AttachmentCreatedByRef, AttachmentCreatedByRef,
AttachmentResourceRef, AttachmentResourceRef,
TAttachmentAccess,
TAttachmentCreatedByRef,
TAttachmentResourceRef,
} from '../types'; } from '../types';
export class AttachmentMetadataDto { export class AttachmentMetadataDto {
@ -76,7 +73,7 @@ export class AttachmentMetadataDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsIn(Object.values(AttachmentResourceRef)) @IsIn(Object.values(AttachmentResourceRef))
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
/** /**
* Attachment Owner Type * Attachment Owner Type
@ -88,7 +85,7 @@ export class AttachmentMetadataDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsIn(Object.values(AttachmentCreatedByRef)) @IsIn(Object.values(AttachmentCreatedByRef))
createdByRef: TAttachmentCreatedByRef; createdByRef: AttachmentCreatedByRef;
/** /**
* Attachment Access * Attachment Access
@ -100,7 +97,7 @@ export class AttachmentMetadataDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsIn(Object.values(AttachmentAccess)) @IsIn(Object.values(AttachmentAccess))
access: TAttachmentAccess; access: AttachmentAccess;
/** /**
* Attachment Owner : Subscriber or User ID * Attachment Owner : Subscriber or User ID
@ -147,7 +144,7 @@ export class AttachmentContextParamDto {
@IsString() @IsString()
@IsIn(Object.values(AttachmentResourceRef)) @IsIn(Object.values(AttachmentResourceRef))
@IsNotEmpty() @IsNotEmpty()
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
@ApiPropertyOptional({ @ApiPropertyOptional({
description: 'Attachment Access', description: 'Attachment Access',
@ -156,5 +153,5 @@ export class AttachmentContextParamDto {
@IsString() @IsString()
@IsIn(Object.values(AttachmentAccess)) @IsIn(Object.values(AttachmentAccess))
@IsOptional() @IsOptional()
access?: TAttachmentAccess; access?: AttachmentAccess;
} }

View File

@ -26,7 +26,7 @@ import { Action } from '@/user/types/action.type';
import { TModel } from '@/user/types/model.type'; import { TModel } from '@/user/types/model.type';
import { AttachmentService } from '../services/attachment.service'; import { AttachmentService } from '../services/attachment.service';
import { AttachmentResourceRef, TAttachmentResourceRef } from '../types'; import { AttachmentResourceRef } from '../types';
import { import {
isAttachmentResourceRef, isAttachmentResourceRef,
isAttachmentResourceRefArray, isAttachmentResourceRefArray,
@ -42,7 +42,7 @@ export class AttachmentGuard implements CanActivate {
private permissionMap: Record< private permissionMap: Record<
Action, Action,
Record<TAttachmentResourceRef, [TModel, Action][]> Record<AttachmentResourceRef, [TModel, Action][]>
> = { > = {
// Read attachments by ref // Read attachments by ref
[Action.READ]: { [Action.READ]: {
@ -169,7 +169,7 @@ export class AttachmentGuard implements CanActivate {
private async isAuthorized( private async isAuthorized(
action: Action, action: Action,
user: Express.User & User, user: Express.User & User,
resourceRef: TAttachmentResourceRef, resourceRef: AttachmentResourceRef,
): Promise<boolean> { ): Promise<boolean> {
if (!action) { if (!action) {
throw new TypeError('Invalid action'); throw new TypeError('Invalid action');

View File

@ -9,7 +9,11 @@
import { Stream } from 'node:stream'; import { Stream } from 'node:stream';
import { Attachment } from '../schemas/attachment.schema'; import { Attachment } from '../schemas/attachment.schema';
import { AttachmentResourceRef } from '../types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '../types';
export const attachment: Attachment = { export const attachment: Attachment = {
name: 'Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', name: 'Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png',
@ -18,12 +22,12 @@ export const attachment: Attachment = {
location: location:
'/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', '/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png',
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
access: 'public', access: AttachmentAccess.Public,
id: '65940d115178607da65c82b6', id: '65940d115178607da65c82b6',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
createdBy: '1', createdBy: '1',
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
}; };
export const attachmentFile: Express.Multer.File = { export const attachmentFile: Express.Multer.File = {
@ -49,12 +53,12 @@ export const attachments: Attachment[] = [
'/app/src/attachment/uploads/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png', '/app/src/attachment/uploads/Screenshot from 2022-03-11 08-41-27-2a9799a8b6109c88fd9a7a690c1101934c.png',
channel: { ['some-channel']: {} }, channel: { ['some-channel']: {} },
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
access: 'public', access: AttachmentAccess.Public,
id: '65940d115178607da65c82b7', id: '65940d115178607da65c82b7',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
createdBy: '1', createdBy: '1',
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
}, },
{ {
name: 'Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png', name: 'Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png',
@ -64,11 +68,11 @@ export const attachments: Attachment[] = [
'/app/src/attachment/uploads/Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png', '/app/src/attachment/uploads/Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png',
channel: { ['some-channel']: {} }, channel: { ['some-channel']: {} },
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
access: 'public', access: AttachmentAccess.Public,
id: '65940d115178607da65c82b8', id: '65940d115178607da65c82b8',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
createdBy: '1', createdBy: '1',
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
}, },
]; ];

View File

@ -27,9 +27,6 @@ import {
AttachmentAccess, AttachmentAccess,
AttachmentCreatedByRef, AttachmentCreatedByRef,
AttachmentResourceRef, AttachmentResourceRef,
TAttachmentAccess,
TAttachmentCreatedByRef,
TAttachmentResourceRef,
} from '../types'; } from '../types';
import { MIME_REGEX } from '../utilities'; import { MIME_REGEX } from '../utilities';
@ -94,19 +91,19 @@ export class AttachmentStub extends BaseSchema {
* Type of the createdBy (depending on the createdBy type) * Type of the createdBy (depending on the createdBy type)
*/ */
@Prop({ type: String, enum: Object.values(AttachmentCreatedByRef) }) @Prop({ type: String, enum: Object.values(AttachmentCreatedByRef) })
createdByRef: TAttachmentCreatedByRef; createdByRef: AttachmentCreatedByRef;
/** /**
* Resource reference of the attachment * Resource reference of the attachment
*/ */
@Prop({ type: String, enum: Object.values(AttachmentResourceRef) }) @Prop({ type: String, enum: Object.values(AttachmentResourceRef) })
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
/** /**
* Access level of the attachment * Access level of the attachment
*/ */
@Prop({ type: String, enum: Object.values(AttachmentAccess) }) @Prop({ type: String, enum: Object.values(AttachmentAccess) })
access: TAttachmentAccess; access: AttachmentAccess;
/** /**
* Optional property representing the URL of the attachment. * Optional property representing the URL of the attachment.

View File

@ -30,7 +30,7 @@ import { BaseService } from '@/utils/generics/base-service';
import { AttachmentMetadataDto } from '../dto/attachment.dto'; import { AttachmentMetadataDto } from '../dto/attachment.dto';
import { AttachmentRepository } from '../repositories/attachment.repository'; import { AttachmentRepository } from '../repositories/attachment.repository';
import { Attachment } from '../schemas/attachment.schema'; import { Attachment } from '../schemas/attachment.schema';
import { AttachmentResourceRef, TAttachmentResourceRef } from '../types'; import { AttachmentResourceRef } from '../types';
import { import {
fileExists, fileExists,
generateUniqueFilename, generateUniqueFilename,
@ -163,7 +163,7 @@ export class AttachmentService extends BaseService<Attachment> {
* @param ref The attachment resource reference * @param ref The attachment resource reference
* @returns The root directory path * @returns The root directory path
*/ */
getRootDirByResourceRef(ref: TAttachmentResourceRef) { getRootDirByResourceRef(ref: AttachmentResourceRef) {
return ref === AttachmentResourceRef.SubscriberAvatar || return ref === AttachmentResourceRef.SubscriberAvatar ||
ref === AttachmentResourceRef.UserAvatar ref === AttachmentResourceRef.UserAvatar
? config.parameters.avatarDir ? config.parameters.avatarDir

View File

@ -17,8 +17,6 @@ export enum AttachmentCreatedByRef {
Subscriber = 'Subscriber', Subscriber = 'Subscriber',
} }
export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`;
/** /**
* Defines the various resource references in which an attachment can exist. * Defines the various resource references in which an attachment can exist.
* These resource references influence how the attachment is uploaded, stored, and accessed: * These resource references influence how the attachment is uploaded, stored, and accessed:
@ -32,15 +30,11 @@ export enum AttachmentResourceRef {
MessageAttachment = 'Message', // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; MessageAttachment = 'Message', // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.;
} }
export type TAttachmentResourceRef = `${AttachmentResourceRef}`;
export enum AttachmentAccess { export enum AttachmentAccess {
Public = 'public', Public = 'public',
Private = 'private', Private = 'private',
} }
export type TAttachmentAccess = `${AttachmentAccess}`;
export class AttachmentFile { export class AttachmentFile {
/** /**
* File original file name * File original file name

View File

@ -15,7 +15,7 @@ import { v4 as uuidv4 } from 'uuid';
import { config } from '@/config'; import { config } from '@/config';
import { AttachmentResourceRef, TAttachmentResourceRef } from '../types'; import { AttachmentResourceRef } from '../types';
export const MIME_REGEX = /^[a-z-]+\/[0-9a-z\-.]+$/gm; export const MIME_REGEX = /^[a-z-]+\/[0-9a-z\-.]+$/gm;
@ -84,13 +84,13 @@ export const generateUniqueFilename = (originalname: string) => {
/** /**
* Checks if the given ref is of type TAttachmentResourceRef. * Checks if the given ref is of type TAttachmentResourceRef.
* *
* @param ref - The ref to check. * @param resourceRef - The ref to check.
* @returns True if the ref is of type TAttachmentResourceRef, otherwise false. * @returns True if the ref is of type TAttachmentResourceRef, otherwise false.
*/ */
export const isAttachmentResourceRef = ( export const isAttachmentResourceRef = (
ref: any, resourceRef: any,
): ref is TAttachmentResourceRef => { ): resourceRef is AttachmentResourceRef => {
return Object.values(AttachmentResourceRef).includes(ref); return Object.values(AttachmentResourceRef).includes(resourceRef);
}; };
AttachmentResourceRef; AttachmentResourceRef;
@ -102,7 +102,7 @@ AttachmentResourceRef;
*/ */
export const isAttachmentResourceRefArray = ( export const isAttachmentResourceRefArray = (
refList: any, refList: any,
): refList is TAttachmentResourceRef[] => { ): refList is AttachmentResourceRef[] => {
return ( return (
Array.isArray(refList) && Array.isArray(refList) &&
refList.length > 0 && refList.length > 0 &&

View File

@ -23,7 +23,12 @@ import { v4 as uuidv4 } from 'uuid';
import { Attachment } from '@/attachment/schemas/attachment.schema'; import { Attachment } from '@/attachment/schemas/attachment.schema';
import { AttachmentService } from '@/attachment/services/attachment.service'; import { AttachmentService } from '@/attachment/services/attachment.service';
import { AttachmentFile, AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentFile,
AttachmentResourceRef,
} from '@/attachment/types';
import { SubscriberCreateDto } from '@/chat/dto/subscriber.dto'; import { SubscriberCreateDto } from '@/chat/dto/subscriber.dto';
import { AttachmentRef } from '@/chat/schemas/types/attachment'; import { AttachmentRef } from '@/chat/schemas/types/attachment';
import { import {
@ -260,8 +265,8 @@ export default abstract class ChannelHandler<
type, type,
size, size,
resourceRef: AttachmentResourceRef.MessageAttachment, resourceRef: AttachmentResourceRef.MessageAttachment,
access: 'private', access: AttachmentAccess.Private,
createdByRef: 'Subscriber', createdByRef: AttachmentCreatedByRef.Subscriber,
createdBy: subscriber.id, createdBy: subscriber.id,
}); });
}), }),
@ -327,7 +332,7 @@ export default abstract class ChannelHandler<
* @return True, if requester is authorized to download the attachment * @return True, if requester is authorized to download the attachment
*/ */
public async hasDownloadAccess(attachment: Attachment, _req: Request) { public async hasDownloadAccess(attachment: Attachment, _req: Request) {
return attachment.access === 'public'; return attachment.access === AttachmentAccess.Public;
} }
/** /**

View File

@ -7,7 +7,11 @@
*/ */
import { Attachment } from '@/attachment/schemas/attachment.schema'; import { Attachment } from '@/attachment/schemas/attachment.schema';
import { AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '@/attachment/types';
import { ButtonType } from '@/chat/schemas/types/button'; import { ButtonType } from '@/chat/schemas/types/button';
import { import {
FileType, FileType,
@ -90,8 +94,8 @@ const attachment: Attachment = {
}, },
}, },
resourceRef: AttachmentResourceRef.BlockAttachment, resourceRef: AttachmentResourceRef.BlockAttachment,
access: 'public', access: AttachmentAccess.Public,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: null, createdBy: null,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),

View File

@ -12,7 +12,11 @@ import mime from 'mime';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { AttachmentService } from '@/attachment/services/attachment.service'; import { AttachmentService } from '@/attachment/services/attachment.service';
import { AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '@/attachment/types';
import EventWrapper from '@/channel/lib/EventWrapper'; import EventWrapper from '@/channel/lib/EventWrapper';
import { config } from '@/config'; import { config } from '@/config';
import { HelperService } from '@/helper/helper.service'; import { HelperService } from '@/helper/helper.service';
@ -282,8 +286,8 @@ export class ChatService {
size, size,
type, type,
resourceRef: AttachmentResourceRef.SubscriberAvatar, resourceRef: AttachmentResourceRef.SubscriberAvatar,
access: 'private', access: AttachmentAccess.Private,
createdByRef: 'Subscriber', createdByRef: AttachmentCreatedByRef.Subscriber,
createdBy: subscriber.id, createdBy: subscriber.id,
}); });

View File

@ -15,7 +15,11 @@ import { v4 as uuidv4 } from 'uuid';
import { Attachment } from '@/attachment/schemas/attachment.schema'; import { Attachment } from '@/attachment/schemas/attachment.schema';
import { AttachmentService } from '@/attachment/services/attachment.service'; import { AttachmentService } from '@/attachment/services/attachment.service';
import { AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '@/attachment/types';
import { ChannelService } from '@/channel/channel.service'; import { ChannelService } from '@/channel/channel.service';
import ChannelHandler from '@/channel/lib/Handler'; import ChannelHandler from '@/channel/lib/Handler';
import { ChannelName } from '@/channel/types'; import { ChannelName } from '@/channel/types';
@ -627,8 +631,8 @@ export default abstract class BaseWebChannelHandler<
size: Buffer.byteLength(data.file), size: Buffer.byteLength(data.file),
type: data.type, type: data.type,
resourceRef: AttachmentResourceRef.MessageAttachment, resourceRef: AttachmentResourceRef.MessageAttachment,
access: 'private', access: AttachmentAccess.Private,
createdByRef: 'Subscriber', createdByRef: AttachmentCreatedByRef.Subscriber,
createdBy: req.session?.web?.profile?.id, createdBy: req.session?.web?.profile?.id,
}); });
} catch (err) { } catch (err) {
@ -694,8 +698,8 @@ export default abstract class BaseWebChannelHandler<
size: file.size, size: file.size,
type: file.mimetype, type: file.mimetype,
resourceRef: AttachmentResourceRef.MessageAttachment, resourceRef: AttachmentResourceRef.MessageAttachment,
access: 'private', access: AttachmentAccess.Private,
createdByRef: 'Subscriber', createdByRef: AttachmentCreatedByRef.Subscriber,
createdBy: req.session.web.profile?.id, createdBy: req.session.web.profile?.id,
}); });
} catch (err) { } catch (err) {
@ -1355,7 +1359,7 @@ export default abstract class BaseWebChannelHandler<
*/ */
public async hasDownloadAccess(attachment: Attachment, req: Request) { public async hasDownloadAccess(attachment: Attachment, req: Request) {
const subscriberId = req.session?.web?.profile?.id as string; const subscriberId = req.session?.web?.profile?.id as string;
if (attachment.access === 'public') { if (attachment.access === AttachmentAccess.Public) {
return true; return true;
} else if (!subscriberId) { } else if (!subscriberId) {
this.logger.warn( this.logger.warn(
@ -1363,7 +1367,7 @@ export default abstract class BaseWebChannelHandler<
); );
return false; return false;
} else if ( } else if (
attachment.createdByRef === 'Subscriber' && attachment.createdByRef === AttachmentCreatedByRef.Subscriber &&
subscriberId === attachment.createdBy subscriberId === attachment.createdBy
) { ) {
// Either subscriber wants to access the attachment he sent // Either subscriber wants to access the attachment he sent

View File

@ -16,6 +16,7 @@ import attachmentSchema, {
Attachment, Attachment,
} from '@/attachment/schemas/attachment.schema'; } from '@/attachment/schemas/attachment.schema';
import { import {
AttachmentAccess,
AttachmentCreatedByRef, AttachmentCreatedByRef,
AttachmentResourceRef, AttachmentResourceRef,
} from '@/attachment/types'; } from '@/attachment/types';
@ -619,8 +620,8 @@ const migrateAttachmentContents = async (
$set: { $set: {
resourceRef: AttachmentResourceRef.ContentAttachment, resourceRef: AttachmentResourceRef.ContentAttachment,
createdBy: adminUser.id, createdBy: adminUser.id,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
access: 'public', access: AttachmentAccess.Public,
}, },
}, },
); );
@ -682,8 +683,10 @@ const migrateAndPopulateAttachmentMessages = async ({
msg.message.attachment.payload.attachment_id as string, msg.message.attachment.payload.attachment_id as string,
{ {
resourceRef: AttachmentResourceRef.MessageAttachment, resourceRef: AttachmentResourceRef.MessageAttachment,
access: 'private', access: AttachmentAccess.Private,
createdByRef: msg.sender ? 'Subscriber' : 'User', createdByRef: msg.sender
? AttachmentCreatedByRef.Subscriber
: AttachmentCreatedByRef.User,
createdBy: msg.sender ? msg.sender : adminUser.id, createdBy: msg.sender ? msg.sender : adminUser.id,
}, },
); );
@ -715,9 +718,13 @@ const migrateAndPopulateAttachmentMessages = async ({
type: response.headers['content-type'], type: response.headers['content-type'],
channel: {}, channel: {},
resourceRef: AttachmentResourceRef.MessageAttachment, resourceRef: AttachmentResourceRef.MessageAttachment,
access: msg.sender ? 'private' : 'public', access: msg.sender
? AttachmentAccess.Private
: AttachmentAccess.Public,
createdBy: msg.sender ? msg.sender : adminUser.id, createdBy: msg.sender ? msg.sender : adminUser.id,
createdByRef: msg.sender ? 'Subscriber' : 'User', createdByRef: msg.sender
? AttachmentCreatedByRef.Subscriber
: AttachmentCreatedByRef.User,
}); });
if (attachment) { if (attachment) {

View File

@ -31,7 +31,11 @@ import { Session as ExpressSession } from 'express-session';
import { diskStorage, memoryStorage } from 'multer'; import { diskStorage, memoryStorage } from 'multer';
import { AttachmentService } from '@/attachment/services/attachment.service'; import { AttachmentService } from '@/attachment/services/attachment.service';
import { AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '@/attachment/types';
import { config } from '@/config'; import { config } from '@/config';
import { CsrfInterceptor } from '@/interceptors/csrf.interceptor'; import { CsrfInterceptor } from '@/interceptors/csrf.interceptor';
import { LoggerService } from '@/logger/logger.service'; import { LoggerService } from '@/logger/logger.service';
@ -296,8 +300,8 @@ export class ReadWriteUserController extends ReadOnlyUserController {
size: avatarFile.size, size: avatarFile.size,
type: avatarFile.mimetype, type: avatarFile.mimetype,
resourceRef: AttachmentResourceRef.UserAvatar, resourceRef: AttachmentResourceRef.UserAvatar,
access: 'private', access: AttachmentAccess.Private,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: req.user.id, createdBy: req.user.id,
}) })
: undefined; : undefined;

View File

@ -10,7 +10,11 @@ import mongoose from 'mongoose';
import { AttachmentCreateDto } from '@/attachment/dto/attachment.dto'; import { AttachmentCreateDto } from '@/attachment/dto/attachment.dto';
import { AttachmentModel } from '@/attachment/schemas/attachment.schema'; import { AttachmentModel } from '@/attachment/schemas/attachment.schema';
import { AttachmentResourceRef } from '@/attachment/types'; import {
AttachmentAccess,
AttachmentCreatedByRef,
AttachmentResourceRef,
} from '@/attachment/types';
export const attachmentFixtures: AttachmentCreateDto[] = [ export const attachmentFixtures: AttachmentCreateDto[] = [
{ {
@ -24,8 +28,8 @@ export const attachmentFixtures: AttachmentCreateDto[] = [
}, },
}, },
resourceRef: AttachmentResourceRef.ContentAttachment, resourceRef: AttachmentResourceRef.ContentAttachment,
access: 'public', access: AttachmentAccess.Public,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: '9'.repeat(24), createdBy: '9'.repeat(24),
}, },
{ {
@ -39,8 +43,8 @@ export const attachmentFixtures: AttachmentCreateDto[] = [
}, },
}, },
resourceRef: AttachmentResourceRef.ContentAttachment, resourceRef: AttachmentResourceRef.ContentAttachment,
access: 'public', access: AttachmentAccess.Public,
createdByRef: 'User', createdByRef: AttachmentCreatedByRef.User,
createdBy: '9'.repeat(24), createdBy: '9'.repeat(24),
}, },
]; ];

View File

@ -13,7 +13,7 @@ import { forwardRef } from "react";
import { useGet } from "@/hooks/crud/useGet"; import { useGet } from "@/hooks/crud/useGet";
import { useHasPermission } from "@/hooks/useHasPermission"; import { useHasPermission } from "@/hooks/useHasPermission";
import { EntityType } from "@/services/types"; import { EntityType } from "@/services/types";
import { IAttachment, TAttachmentResourceRef } from "@/types/attachment.types"; import { AttachmentResourceRef, IAttachment } from "@/types/attachment.types";
import { PermissionAction } from "@/types/permission.types"; import { PermissionAction } from "@/types/permission.types";
import AttachmentThumbnail from "./AttachmentThumbnail"; import AttachmentThumbnail from "./AttachmentThumbnail";
@ -29,7 +29,7 @@ type AttachmentThumbnailProps = {
onChange?: (id: string | null, mimeType: string | null) => void; onChange?: (id: string | null, mimeType: string | null) => void;
error?: boolean; error?: boolean;
helperText?: string; helperText?: string;
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
}; };
const AttachmentInput = forwardRef<HTMLDivElement, AttachmentThumbnailProps>( const AttachmentInput = forwardRef<HTMLDivElement, AttachmentThumbnailProps>(

View File

@ -17,7 +17,7 @@ import { getDisplayDialogs, useDialog } from "@/hooks/useDialog";
import { useToast } from "@/hooks/useToast"; import { useToast } from "@/hooks/useToast";
import { useTranslate } from "@/hooks/useTranslate"; import { useTranslate } from "@/hooks/useTranslate";
import { EntityType } from "@/services/types"; import { EntityType } from "@/services/types";
import { IAttachment, TAttachmentResourceRef } from "@/types/attachment.types"; import { AttachmentResourceRef, IAttachment } from "@/types/attachment.types";
import { AttachmentDialog } from "./AttachmentDialog"; import { AttachmentDialog } from "./AttachmentDialog";
import AttachmentThumbnail from "./AttachmentThumbnail"; import AttachmentThumbnail from "./AttachmentThumbnail";
@ -68,7 +68,7 @@ export type FileUploadProps = {
enableMediaLibrary?: boolean; enableMediaLibrary?: boolean;
onChange?: (data?: IAttachment | null) => void; onChange?: (data?: IAttachment | null) => void;
onUploadComplete?: () => void; onUploadComplete?: () => void;
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
}; };
const AttachmentUploader: FC<FileUploadProps> = ({ const AttachmentUploader: FC<FileUploadProps> = ({

View File

@ -12,7 +12,7 @@ import { forwardRef, useState } from "react";
import { useHasPermission } from "@/hooks/useHasPermission"; import { useHasPermission } from "@/hooks/useHasPermission";
import { EntityType } from "@/services/types"; import { EntityType } from "@/services/types";
import { IAttachment, TAttachmentResourceRef } from "@/types/attachment.types"; import { AttachmentResourceRef, IAttachment } from "@/types/attachment.types";
import { PermissionAction } from "@/types/permission.types"; import { PermissionAction } from "@/types/permission.types";
import AttachmentThumbnail from "./AttachmentThumbnail"; import AttachmentThumbnail from "./AttachmentThumbnail";
@ -28,7 +28,7 @@ type MultipleAttachmentInputProps = {
onChange?: (ids: string[]) => void; onChange?: (ids: string[]) => void;
error?: boolean; error?: boolean;
helperText?: string; helperText?: string;
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
}; };
const MultipleAttachmentInput = forwardRef< const MultipleAttachmentInput = forwardRef<

View File

@ -9,7 +9,7 @@
import { useMutation, useQueryClient } from "react-query"; import { useMutation, useQueryClient } from "react-query";
import { QueryType, TMutationOptions } from "@/services/types"; import { QueryType, TMutationOptions } from "@/services/types";
import { TAttachmentResourceRef } from "@/types/attachment.types"; import { AttachmentResourceRef } from "@/types/attachment.types";
import { IBaseSchema, IDynamicProps, TType } from "@/types/base.types"; import { IBaseSchema, IDynamicProps, TType } from "@/types/base.types";
import { useEntityApiClient } from "../useApiClient"; import { useEntityApiClient } from "../useApiClient";
@ -27,7 +27,7 @@ export const useUpload = <
TMutationOptions< TMutationOptions<
TBasic, TBasic,
Error, Error,
{ file: File; resourceRef: TAttachmentResourceRef }, { file: File; resourceRef: AttachmentResourceRef },
TBasic TBasic
>, >,
"mutationFn" | "mutationKey" "mutationFn" | "mutationKey"

View File

@ -9,7 +9,7 @@
import { AxiosInstance, AxiosResponse } from "axios"; import { AxiosInstance, AxiosResponse } from "axios";
import { TAttachmentResourceRef } from "@/types/attachment.types"; import { AttachmentResourceRef } from "@/types/attachment.types";
import { ILoginAttributes } from "@/types/auth/login.types"; import { ILoginAttributes } from "@/types/auth/login.types";
import { IUserPermissions } from "@/types/auth/permission.types"; import { IUserPermissions } from "@/types/auth/permission.types";
import { StatsType } from "@/types/bot-stat.types"; import { StatsType } from "@/types/bot-stat.types";
@ -302,7 +302,7 @@ export class EntityApiClient<TAttr, TBasic, TFull> extends ApiClient {
return data; return data;
} }
async upload(file: File, resourceRef?: TAttachmentResourceRef) { async upload(file: File, resourceRef?: AttachmentResourceRef) {
const { _csrf } = await this.getCsrf(); const { _csrf } = await this.getCsrf();
const formData = new FormData(); const formData = new FormData();

View File

@ -22,8 +22,6 @@ export enum AttachmentCreatedByRef {
Subscriber = "Subscriber", Subscriber = "Subscriber",
} }
export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`;
/** /**
* Defines the various resource references in which an attachment can exist. * Defines the various resource references in which an attachment can exist.
* These references influence how the attachment is uploaded, stored, and accessed: * These references influence how the attachment is uploaded, stored, and accessed:
@ -37,7 +35,10 @@ export enum AttachmentResourceRef {
MessageAttachment = "Message", // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.; MessageAttachment = "Message", // Files sent or received via messages, uploaded programmatically, accessible to users with inbox permissions.;
} }
export type TAttachmentResourceRef = `${AttachmentResourceRef}`; export enum AttachmentAccess {
Public = "public",
Private = "private",
}
export interface IAttachmentAttributes { export interface IAttachmentAttributes {
name: string; name: string;
@ -46,8 +47,9 @@ export interface IAttachmentAttributes {
location: string; location: string;
url: string; url: string;
channel?: Record<string, any>; channel?: Record<string, any>;
resourceRef: TAttachmentResourceRef; resourceRef: AttachmentResourceRef;
createdByRef: TAttachmentCreatedByRef; access: AttachmentAccess;
createdByRef: AttachmentCreatedByRef;
createdBy: string | null; createdBy: string | null;
} }