refactor: rename owner to createdBy

This commit is contained in:
Mohamed Marrouchi 2025-01-15 15:59:30 +01:00
parent 90aad93356
commit bdf1763503
17 changed files with 80 additions and 79 deletions

View File

@ -137,16 +137,16 @@ describe('AttachmentController', () => {
name: attachmentFile.originalname, name: attachmentFile.originalname,
location: expect.stringMatching(new RegExp(`^/${name}`)), location: expect.stringMatching(new RegExp(`^/${name}`)),
context: 'block_attachment', context: 'block_attachment',
ownerType: 'User', createdByRef: 'User',
owner: '9'.repeat(24), createdBy: '9'.repeat(24),
}); });
expect(result).toEqualPayload( expect(result).toEqualPayload(
[ [
{ {
...attachment, ...attachment,
context: 'block_attachment', context: 'block_attachment',
ownerType: 'User', createdByRef: 'User',
owner: '9'.repeat(24), createdBy: '9'.repeat(24),
}, },
], ],
[...IGNORED_TEST_FIELDS, 'location', 'url'], [...IGNORED_TEST_FIELDS, 'location', 'url'],

View File

@ -150,8 +150,8 @@ export class AttachmentController extends BaseController<Attachment> {
size: file.size, size: file.size,
type: file.mimetype, type: file.mimetype,
context, context,
owner: userId, createdBy: userId,
ownerType: 'User', createdByRef: 'User',
}); });
attachments.push(attachment); attachments.push(attachment);
} }

View File

@ -25,9 +25,9 @@ import { IsObjectId } from '@/utils/validation-rules/is-object-id';
import { import {
AttachmentContext, AttachmentContext,
AttachmentOwnerType, AttachmentCreatedByRef,
TAttachmentContext, TAttachmentContext,
TAttachmentOwnerType, TAttachmentCreatedByRef,
} from '../types'; } from '../types';
export class AttachmentMetadataDto { export class AttachmentMetadataDto {
@ -81,12 +81,12 @@ export class AttachmentMetadataDto {
*/ */
@ApiPropertyOptional({ @ApiPropertyOptional({
description: 'Attachment Owner Type', description: 'Attachment Owner Type',
enum: Object.values(AttachmentOwnerType), enum: Object.values(AttachmentCreatedByRef),
}) })
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsIn(Object.values(AttachmentOwnerType)) @IsIn(Object.values(AttachmentCreatedByRef))
ownerType: TAttachmentOwnerType; createdByRef: TAttachmentCreatedByRef;
/** /**
* Attachment Owner : Subscriber or User ID * Attachment Owner : Subscriber or User ID
@ -98,7 +98,7 @@ export class AttachmentMetadataDto {
@IsString() @IsString()
@IsNotEmpty() @IsNotEmpty()
@IsObjectId({ message: 'Owner must be a valid ObjectId' }) @IsObjectId({ message: 'Owner must be a valid ObjectId' })
owner: string; createdBy: string;
} }
export class AttachmentCreateDto extends AttachmentMetadataDto { export class AttachmentCreateDto extends AttachmentMetadataDto {

View File

@ -20,8 +20,8 @@ export const attachment: Attachment = {
id: '65940d115178607da65c82b6', id: '65940d115178607da65c82b6',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
owner: '1', createdBy: '1',
ownerType: 'User', createdByRef: 'User',
}; };
export const attachmentFile: Express.Multer.File = { export const attachmentFile: Express.Multer.File = {
@ -50,8 +50,8 @@ export const attachments: Attachment[] = [
id: '65940d115178607da65c82b7', id: '65940d115178607da65c82b7',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
owner: '1', createdBy: '1',
ownerType: 'User', createdByRef: 'User',
}, },
{ {
name: 'Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png', name: 'Screenshot from 2022-03-18 08-58-15-af61e7f71281f9fd3f1ad7ad10107741c.png',
@ -64,7 +64,7 @@ export const attachments: Attachment[] = [
id: '65940d115178607da65c82b8', id: '65940d115178607da65c82b8',
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
owner: '1', createdBy: '1',
ownerType: 'User', createdByRef: 'User',
}, },
]; ];

View File

@ -25,9 +25,9 @@ import {
import { import {
AttachmentContext, AttachmentContext,
AttachmentOwnerType, AttachmentCreatedByRef,
TAttachmentContext, TAttachmentContext,
TAttachmentOwnerType, TAttachmentCreatedByRef,
} from '../types'; } from '../types';
import { MIME_REGEX } from '../utilities'; import { MIME_REGEX } from '../utilities';
@ -79,20 +79,20 @@ export class AttachmentStub extends BaseSchema {
channel?: Partial<Record<ChannelName, any>>; channel?: Partial<Record<ChannelName, any>>;
/** /**
* Object ID of the owner (depending on the owner type) * Object ID of the createdBy (depending on the createdBy type)
*/ */
@Prop({ @Prop({
type: MongooseSchema.Types.ObjectId, type: MongooseSchema.Types.ObjectId,
refPath: 'ownerType', refPath: 'createdByRef',
default: null, default: null,
}) })
owner: unknown; createdBy: unknown;
/** /**
* Type of the owner (depending on the owner type) * Type of the createdBy (depending on the createdBy type)
*/ */
@Prop({ type: String, enum: Object.values(AttachmentOwnerType) }) @Prop({ type: String, enum: Object.values(AttachmentCreatedByRef) })
ownerType: TAttachmentOwnerType; createdByRef: TAttachmentCreatedByRef;
/** /**
* Context of the attachment * Context of the attachment
@ -142,20 +142,20 @@ export class AttachmentStub extends BaseSchema {
@Schema({ timestamps: true }) @Schema({ timestamps: true })
export class Attachment extends AttachmentStub { export class Attachment extends AttachmentStub {
@Transform(({ obj }) => obj.owner?.toString() || null) @Transform(({ obj }) => obj.createdBy?.toString() || null)
owner: string | null; createdBy: string | null;
} }
@Schema({ timestamps: true }) @Schema({ timestamps: true })
export class UserAttachmentFull extends AttachmentStub { export class UserAttachmentFull extends AttachmentStub {
@Type(() => User) @Type(() => User)
owner: User | undefined; createdBy: User | undefined;
} }
@Schema({ timestamps: true }) @Schema({ timestamps: true })
export class SubscriberAttachmentFull extends AttachmentStub { export class SubscriberAttachmentFull extends AttachmentStub {
@Type(() => Subscriber) @Type(() => Subscriber)
owner: Subscriber | undefined; createdBy: Subscriber | undefined;
} }
export type AttachmentDocument = THydratedDocument<Attachment>; export type AttachmentDocument = THydratedDocument<Attachment>;
@ -182,4 +182,4 @@ export type AttachmentPopulate = keyof TFilterPopulateFields<
AttachmentStub AttachmentStub
>; >;
export const ATTACHMENT_POPULATE: AttachmentPopulate[] = ['owner']; export const ATTACHMENT_POPULATE: AttachmentPopulate[] = ['createdBy'];

View File

@ -9,15 +9,15 @@
import { Readable, Stream } from 'stream'; import { Readable, Stream } from 'stream';
/** /**
* Defines the types of owners for an attachment, * Defines the types of createdBys for an attachment,
* indicating whether the file belongs to a User or a Subscriber. * indicating whether the file belongs to a User or a Subscriber.
*/ */
export enum AttachmentOwnerType { export enum AttachmentCreatedByRef {
User = 'User', User = 'User',
Subscriber = 'Subscriber', Subscriber = 'Subscriber',
} }
export type TAttachmentOwnerType = `${AttachmentOwnerType}`; export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`;
/** /**
* Defines the various contexts in which an attachment can exist. * Defines the various contexts in which an attachment can exist.

View File

@ -259,8 +259,8 @@ export default abstract class ChannelHandler<
type, type,
size, size,
context: 'message_attachment', context: 'message_attachment',
ownerType: 'Subscriber', createdByRef: 'Subscriber',
owner: subscriber.id, createdBy: subscriber.id,
}); });
}), }),
); );

View File

@ -89,8 +89,8 @@ const attachment: Attachment = {
}, },
}, },
context: 'block_attachment', context: 'block_attachment',
ownerType: 'User', createdByRef: 'User',
owner: null, createdBy: null,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date(), updatedAt: new Date(),
}; };

View File

@ -277,8 +277,8 @@ export class ChatService {
size, size,
type, type,
context: 'subscriber_avatar', context: 'subscriber_avatar',
ownerType: 'Subscriber', createdByRef: 'Subscriber',
owner: subscriber.id, createdBy: subscriber.id,
}); });
if (avatar) { if (avatar) {

View File

@ -621,8 +621,8 @@ export default abstract class BaseWebChannelHandler<
size: Buffer.byteLength(data.file), size: Buffer.byteLength(data.file),
type: data.type, type: data.type,
context: 'message_attachment', context: 'message_attachment',
ownerType: 'Subscriber', createdByRef: 'Subscriber',
owner: req.session.web.profile?.id, createdBy: req.session.web.profile?.id,
}); });
} catch (err) { } catch (err) {
this.logger.error( this.logger.error(
@ -687,8 +687,8 @@ export default abstract class BaseWebChannelHandler<
size: file.size, size: file.size,
type: file.mimetype, type: file.mimetype,
context: 'message_attachment', context: 'message_attachment',
ownerType: 'Subscriber', createdByRef: 'Subscriber',
owner: req.session.web.profile?.id, createdBy: req.session.web.profile?.id,
}); });
} catch (err) { } catch (err) {
this.logger.error( this.logger.error(

View File

@ -15,7 +15,7 @@ import { v4 as uuidv4 } from 'uuid';
import attachmentSchema, { import attachmentSchema, {
Attachment, Attachment,
} from '@/attachment/schemas/attachment.schema'; } from '@/attachment/schemas/attachment.schema';
import { AttachmentContext, AttachmentOwnerType } from '@/attachment/types'; import { AttachmentContext, AttachmentCreatedByRef } from '@/attachment/types';
import blockSchema, { Block } from '@/chat/schemas/block.schema'; import blockSchema, { Block } from '@/chat/schemas/block.schema';
import messageSchema, { Message } from '@/chat/schemas/message.schema'; import messageSchema, { Message } from '@/chat/schemas/message.schema';
import subscriberSchema, { Subscriber } from '@/chat/schemas/subscriber.schema'; import subscriberSchema, { Subscriber } from '@/chat/schemas/subscriber.schema';
@ -80,8 +80,8 @@ const populateBlockAttachments = async ({ logger }: MigrationServices) => {
{ {
$set: { $set: {
context: AttachmentContext.BlockAttachment, context: AttachmentContext.BlockAttachment,
ownerType: AttachmentOwnerType.User, createdByRef: AttachmentCreatedByRef.User,
owner: user._id, createdBy: user._id,
}, },
}, },
); );
@ -102,7 +102,7 @@ const populateBlockAttachments = async ({ logger }: MigrationServices) => {
}; };
/** /**
* Updates setting attachment documents to populate new attributes (context, owner, ownerType) * Updates setting attachment documents to populate new attributes (context, createdBy, createdByRef)
* *
* @returns Resolves when the migration process is complete. * @returns Resolves when the migration process is complete.
*/ */
@ -130,8 +130,8 @@ const populateSettingAttachments = async ({ logger }: MigrationServices) => {
{ {
$set: { $set: {
context: AttachmentContext.SettingAttachment, context: AttachmentContext.SettingAttachment,
ownerType: AttachmentOwnerType.User, createdByRef: AttachmentCreatedByRef.User,
owner: user._id, createdBy: user._id,
}, },
}, },
); );
@ -146,7 +146,7 @@ const populateSettingAttachments = async ({ logger }: MigrationServices) => {
}; };
/** /**
* Updates user attachment documents to populate new attributes (context, owner, ownerType) * Updates user attachment documents to populate new attributes (context, createdBy, createdByRef)
* *
* @returns Resolves when the migration process is complete. * @returns Resolves when the migration process is complete.
*/ */
@ -168,8 +168,8 @@ const populateUserAvatars = async ({ logger }: MigrationServices) => {
{ {
$set: { $set: {
context: AttachmentContext.UserAvatar, context: AttachmentContext.UserAvatar,
ownerType: AttachmentOwnerType.User, createdByRef: AttachmentCreatedByRef.User,
owner: user._id, createdBy: user._id,
}, },
}, },
); );
@ -184,7 +184,7 @@ const populateUserAvatars = async ({ logger }: MigrationServices) => {
/** /**
* Updates subscriber documents with their corresponding avatar attachments, * Updates subscriber documents with their corresponding avatar attachments,
* populate new attributes (context, owner, ownerType) and moves avatar files to a new directory. * populate new attributes (context, createdBy, createdByRef) and moves avatar files to a new directory.
* *
* @returns Resolves when the migration process is complete. * @returns Resolves when the migration process is complete.
*/ */
@ -229,8 +229,8 @@ const populateSubscriberAvatars = async ({ logger }: MigrationServices) => {
{ {
$set: { $set: {
context: AttachmentContext.SubscriberAvatar, context: AttachmentContext.SubscriberAvatar,
ownerType: AttachmentOwnerType.Subscriber, createdByRef: AttachmentCreatedByRef.Subscriber,
owner: subscriber._id, createdBy: subscriber._id,
}, },
}, },
); );
@ -361,8 +361,8 @@ const undoPopulateAttachments = async ({ logger }: MigrationServices) => {
{ {
$unset: { $unset: {
context: '', context: '',
ownerType: '', createdByRef: '',
owner: '', createdBy: '',
}, },
}, },
); );
@ -640,8 +640,8 @@ const migrateAndPopulateAttachmentMessages = async ({
await attachmentService.updateOne( await attachmentService.updateOne(
msg.message.attachment.payload.attachment_id, msg.message.attachment.payload.attachment_id,
{ {
ownerType: msg.sender ? 'Subscriber' : 'User', createdByRef: msg.sender ? 'Subscriber' : 'User',
owner: msg.sender ? msg.sender : adminUser.id, createdBy: msg.sender ? msg.sender : adminUser.id,
context: 'message_attachment', context: 'message_attachment',
}, },
); );
@ -672,8 +672,8 @@ const migrateAndPopulateAttachmentMessages = async ({
size: fileBuffer.length, size: fileBuffer.length,
type: response.headers['content-type'], type: response.headers['content-type'],
channel: {}, channel: {},
owner: msg.sender ? msg.sender : adminUser.id, createdBy: msg.sender ? msg.sender : adminUser.id,
ownerType: msg.sender ? 'Subscriber' : 'User', createdByRef: msg.sender ? 'Subscriber' : 'User',
context: 'message_attachment', context: 'message_attachment',
}); });

View File

@ -295,8 +295,8 @@ export class ReadWriteUserController extends ReadOnlyUserController {
size: avatarFile.size, size: avatarFile.size,
type: avatarFile.mimetype, type: avatarFile.mimetype,
context: 'user_avatar', context: 'user_avatar',
ownerType: 'User', createdByRef: 'User',
owner: req.user.id, createdBy: req.user.id,
}) })
: undefined; : undefined;

View File

@ -1,9 +1,9 @@
/* /*
* Copyright © 2024 Hexastack. All rights reserved. * Copyright © 2025 Hexastack. All rights reserved.
* *
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
export type TRelation = 'role' | 'owner'; export type TRelation = 'role' | 'createdBy';

View File

@ -23,8 +23,8 @@ export const attachmentFixtures: AttachmentCreateDto[] = [
}, },
}, },
context: 'content_attachment', context: 'content_attachment',
ownerType: 'User', createdByRef: 'User',
owner: null, createdBy: null,
}, },
{ {
name: 'store2.jpg', name: 'store2.jpg',
@ -37,8 +37,8 @@ export const attachmentFixtures: AttachmentCreateDto[] = [
}, },
}, },
context: 'content_attachment', context: 'content_attachment',
ownerType: 'User', createdByRef: 'User',
owner: null, createdBy: null,
}, },
]; ];

View File

@ -17,12 +17,12 @@ import { IUser } from "./user.types";
* Defines the types of owners for an attachment, * Defines the types of owners for an attachment,
* indicating whether the file belongs to a User or a Subscriber. * indicating whether the file belongs to a User or a Subscriber.
*/ */
export enum AttachmentOwnerType { export enum AttachmentCreatedByRef {
User = "User", User = "User",
Subscriber = "Subscriber", Subscriber = "Subscriber",
} }
export type TAttachmentOwnerType = `${AttachmentOwnerType}`; export type TAttachmentCreatedByRef = `${AttachmentCreatedByRef}`;
/** /**
* Defines the various contexts in which an attachment can exist. * Defines the various contexts in which an attachment can exist.
@ -47,8 +47,8 @@ export interface IAttachmentAttributes {
url: string; url: string;
channel?: Record<string, any>; channel?: Record<string, any>;
context: TAttachmentContext; context: TAttachmentContext;
ownerType: TAttachmentOwnerType; createdByRef: TAttachmentCreatedByRef;
owner: string | null; createdBy: string | null;
} }
export interface IAttachmentStub export interface IAttachmentStub
@ -56,11 +56,11 @@ export interface IAttachmentStub
OmitPopulate<IAttachmentAttributes, EntityType.ATTACHMENT> {} OmitPopulate<IAttachmentAttributes, EntityType.ATTACHMENT> {}
export interface IAttachment extends IAttachmentStub, IFormat<Format.BASIC> { export interface IAttachment extends IAttachmentStub, IFormat<Format.BASIC> {
owner: string | null; createdBy: string | null;
} }
export interface ISubscriberAttachmentFull export interface ISubscriberAttachmentFull
extends IAttachmentStub, extends IAttachmentStub,
IFormat<Format.FULL> { IFormat<Format.FULL> {
owner: (ISubscriber | IUser)[]; createdBy: (ISubscriber | IUser)[];
} }

View File

@ -110,7 +110,7 @@ export const POPULATE_BY_TYPE = {
[EntityType.MENUTREE]: [], [EntityType.MENUTREE]: [],
[EntityType.LANGUAGE]: [], [EntityType.LANGUAGE]: [],
[EntityType.TRANSLATION]: [], [EntityType.TRANSLATION]: [],
[EntityType.ATTACHMENT]: ["owner"], [EntityType.ATTACHMENT]: ["createdBy"],
[EntityType.CUSTOM_BLOCK]: [], [EntityType.CUSTOM_BLOCK]: [],
[EntityType.CUSTOM_BLOCK_SETTINGS]: [], [EntityType.CUSTOM_BLOCK_SETTINGS]: [],
[EntityType.CHANNEL]: [], [EntityType.CHANNEL]: [],

View File

@ -1,17 +1,18 @@
/* /*
* Copyright © 2024 Hexastack. All rights reserved. * Copyright © 2025 Hexastack. All rights reserved.
* *
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms: * Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission. * 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/ */
import { EntityType, Format } from "@/services/types"; import { EntityType, Format } from "@/services/types";
import { IBaseSchema, IFormat, OmitPopulate } from "./base.types"; import { IBaseSchema, IFormat, OmitPopulate } from "./base.types";
import { IPermission } from "./permission.types"; import { IPermission } from "./permission.types";
export type TRelation = "role" | "owner"; export type TRelation = "role" | "createdBy";
export interface IModelAttributes { export interface IModelAttributes {
name: string; name: string;