@solidxai/core 0.1.13-beta.20 → 0.1.13-beta.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1181 -0
- package/CLAUDE.md +5 -6
- package/dist/constants/media-file-types.d.ts.map +1 -1
- package/dist/constants/media-file-types.js +1 -0
- package/dist/constants/media-file-types.js.map +1 -1
- package/dist/dtos/create-field-metadata.dto.d.ts +1 -0
- package/dist/dtos/create-field-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-field-metadata.dto.js +12 -1
- package/dist/dtos/create-field-metadata.dto.js.map +1 -1
- package/dist/entities/field-metadata.entity.d.ts +1 -0
- package/dist/entities/field-metadata.entity.d.ts.map +1 -1
- package/dist/entities/field-metadata.entity.js +5 -1
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.js +3 -2
- package/dist/helpers/field-crud-managers/LongTextFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +6 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +54 -27
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.js +3 -2
- package/dist/helpers/field-crud-managers/ShortTextFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.d.ts +3 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.d.ts.map +1 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.js +17 -0
- package/dist/helpers/field-crud-managers/textFieldCrudManagerUtils.js.map +1 -0
- package/dist/services/chatter-message.service.d.ts +1 -0
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +44 -12
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +1 -0
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +2 -0
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +1 -0
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +7 -0
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +4 -0
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +20 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +14 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +6 -0
- package/dist/solid-core.module.js.map +1 -1
- package/package.json +1 -1
- package/src/constants/media-file-types.ts +1 -0
- package/src/dtos/create-field-metadata.dto.ts +14 -1
- package/src/entities/field-metadata.entity.ts +3 -0
- package/src/helpers/field-crud-managers/LongTextFieldCrudManager.ts +3 -2
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +73 -34
- package/src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts +3 -2
- package/src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts +14 -0
- package/src/services/chatter-message.service.ts +56 -14
- package/src/services/crud.service.ts +1 -0
- package/src/services/field-metadata.service.ts +2 -0
- package/src/services/media.service.ts +1 -0
- package/src/services/module-metadata.service.ts +7 -0
- package/src/services/setting.service.ts +5 -0
- package/src/services/settings/default-settings-provider.service.ts +14 -0
- package/src/solid-core.module.ts +13 -0
- package/postman/mpin.postman_collection.json +0 -1045
|
@@ -61,34 +61,31 @@ class MediaFieldCrudManager {
|
|
|
61
61
|
return null;
|
|
62
62
|
}
|
|
63
63
|
const ext = (0, media_file_types_1.getLowercaseFileExtension)((0, media_file_types_1.getUploadedFileName)(file));
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
return
|
|
64
|
+
const extType = ext ? media_file_types_1.EXT_TO_MEDIA_TYPE[ext] : undefined;
|
|
65
|
+
if (!extType) {
|
|
66
|
+
return null;
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return 'video';
|
|
74
|
-
if (ext && media_file_types_1.EXT_TO_MEDIA_TYPE[ext]) {
|
|
75
|
-
return media_file_types_1.EXT_TO_MEDIA_TYPE[ext];
|
|
68
|
+
const mt = (file.mimetype || '').toLowerCase().trim();
|
|
69
|
+
const mimeType = MIME_TO_MEDIA_TYPE[mt]
|
|
70
|
+
?? (mt.startsWith('image/') ? 'image' : mt.startsWith('audio/') ? 'audio' : mt.startsWith('video/') ? 'video' : undefined);
|
|
71
|
+
if (mimeType && mimeType !== extType) {
|
|
72
|
+
return null;
|
|
76
73
|
}
|
|
77
|
-
return
|
|
74
|
+
return extType;
|
|
78
75
|
}
|
|
79
76
|
validate(dto, files) {
|
|
80
77
|
const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);
|
|
81
78
|
return this.applyValidations(fieldFiles);
|
|
82
79
|
}
|
|
83
80
|
applyValidations(fieldFiles) {
|
|
84
|
-
const
|
|
81
|
+
const dangerousFileErrors = this.validateDangerousFiles(fieldFiles);
|
|
85
82
|
switch (this.options.type) {
|
|
86
83
|
case SolidMediaType.mediaSingle:
|
|
87
|
-
return [...
|
|
84
|
+
return [...dangerousFileErrors, ...this.validateMediaSingle(fieldFiles)];
|
|
88
85
|
case SolidMediaType.mediaMultiple:
|
|
89
|
-
return [...
|
|
86
|
+
return [...dangerousFileErrors, ...this.validateMediaMultiple(fieldFiles)];
|
|
90
87
|
default:
|
|
91
|
-
return
|
|
88
|
+
return dangerousFileErrors;
|
|
92
89
|
}
|
|
93
90
|
}
|
|
94
91
|
validateDangerousFiles(fieldFiles) {
|
|
@@ -100,7 +97,15 @@ class MediaFieldCrudManager {
|
|
|
100
97
|
`${(0, media_file_types_1.getUploadedFileName)(fieldFile) || 'File'} is a potentially dangerous file type.`
|
|
101
98
|
}));
|
|
102
99
|
}
|
|
103
|
-
|
|
100
|
+
validateCommon(fieldFiles) {
|
|
101
|
+
return [
|
|
102
|
+
...this.validateRequired(fieldFiles),
|
|
103
|
+
...this.validateSize(fieldFiles),
|
|
104
|
+
...this.validateTypes(fieldFiles),
|
|
105
|
+
...this.validateAllowedExtensions(fieldFiles),
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
validateRequired(fieldFiles) {
|
|
104
109
|
const errors = [];
|
|
105
110
|
if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {
|
|
106
111
|
errors.push({
|
|
@@ -108,12 +113,10 @@ class MediaFieldCrudManager {
|
|
|
108
113
|
error: `${this.options.fieldName} is required`
|
|
109
114
|
});
|
|
110
115
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
}
|
|
116
|
+
return errors;
|
|
117
|
+
}
|
|
118
|
+
validateSize(fieldFiles) {
|
|
119
|
+
const errors = [];
|
|
117
120
|
if (this.options.mediaMaxSizeKb) {
|
|
118
121
|
for (let i = 0; i < fieldFiles.length; i++) {
|
|
119
122
|
const fieldFile = fieldFiles[i];
|
|
@@ -126,6 +129,10 @@ class MediaFieldCrudManager {
|
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
}
|
|
132
|
+
return errors;
|
|
133
|
+
}
|
|
134
|
+
validateTypes(fieldFiles) {
|
|
135
|
+
const errors = [];
|
|
129
136
|
if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {
|
|
130
137
|
const allowedFileTypes = this.options.mediaTypes;
|
|
131
138
|
for (let i = 0; i < fieldFiles.length; i++) {
|
|
@@ -143,16 +150,36 @@ class MediaFieldCrudManager {
|
|
|
143
150
|
}
|
|
144
151
|
return errors;
|
|
145
152
|
}
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
if (!
|
|
153
|
+
validateAllowedExtensions(fieldFiles) {
|
|
154
|
+
const allowed = this.options.mediaAllowedExtensions;
|
|
155
|
+
if (!allowed || allowed.length === 0) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const normalizedAllowed = new Set(allowed.map(ext => ext.toLowerCase().replace(/^\./, '')));
|
|
159
|
+
return fieldFiles
|
|
160
|
+
.filter(fieldFile => {
|
|
161
|
+
const ext = (0, media_file_types_1.getLowercaseFileExtension)((0, media_file_types_1.getUploadedFileName)(fieldFile));
|
|
162
|
+
return !ext || !normalizedAllowed.has(ext);
|
|
163
|
+
})
|
|
164
|
+
.map(fieldFile => ({
|
|
165
|
+
field: this.options.fieldName,
|
|
166
|
+
error: `${this.options.fieldName} file type not allowed. ` +
|
|
167
|
+
`Allowed extensions: ${[...normalizedAllowed].join(', ')}.`
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
validateMediaSingle(fieldFiles) {
|
|
171
|
+
const errors = this.validateCommon(fieldFiles);
|
|
172
|
+
if (fieldFiles.length > 1) {
|
|
149
173
|
errors.push({
|
|
150
174
|
field: this.options.fieldName,
|
|
151
|
-
error: `${this.options.fieldName}
|
|
175
|
+
error: `${this.options.fieldName} must be a single file`
|
|
152
176
|
});
|
|
153
177
|
}
|
|
154
178
|
return errors;
|
|
155
179
|
}
|
|
180
|
+
validateMediaMultiple(fieldFiles) {
|
|
181
|
+
return this.validateCommon(fieldFiles);
|
|
182
|
+
}
|
|
156
183
|
transformForCreate(dto) {
|
|
157
184
|
return dto;
|
|
158
185
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { EXT_TO_MEDIA_TYPE, getLowercaseFileExtension, getUploadedFileName, isDangerousMediaFile, MediaCategory } from \"src/constants/media-file-types\";\n\nexport enum SolidMediaType {\n mediaSingle = 'mediaSingle',\n mediaMultiple = 'mediaMultiple'\n}\n\nexport interface MediaFieldOptions {\n type: SolidMediaType;\n required: boolean | undefined | null;\n fieldName: string | undefined | null;\n mediaMaxSizeKb: number | undefined | null;\n mediaTypes: string[];\n isUpdate: boolean | undefined | null;\n}\n\ntype MediaType = MediaCategory;\n\nconst MIME_TO_MEDIA_TYPE: Record<string, MediaType> = {\n // Images\n 'image/png': 'image',\n 'image/jpeg': 'image',\n 'image/jpg': 'image',\n 'image/webp': 'image',\n 'image/gif': 'image',\n 'image/bmp': 'image',\n 'image/tiff': 'image',\n 'image/heic': 'image',\n 'image/heif': 'image',\n\n // Audio\n 'audio/mpeg': 'audio', // mp3\n 'audio/mp3': 'audio',\n 'audio/wav': 'audio',\n 'audio/x-wav': 'audio',\n 'audio/webm': 'audio',\n 'audio/ogg': 'audio',\n 'audio/aac': 'audio',\n 'audio/mp4': 'audio', // m4a often shows as audio/mp4\n 'audio/x-m4a': 'audio',\n 'audio/flac': 'audio',\n\n // Video\n 'video/mp4': 'video',\n 'video/mpeg': 'video',\n 'video/webm': 'video',\n 'video/ogg': 'video',\n 'video/quicktime': 'video', // mov\n 'video/x-msvideo': 'video', // avi\n 'video/x-matroska': 'video',// mkv\n 'video/3gpp': 'video',\n 'video/3gpp2': 'video',\n\n // Documents / files (treat as \"file\")\n 'application/pdf': 'pdf',\n 'text/plain': 'file',\n 'text/markdown': 'file',\n 'application/json': 'file',\n 'text/csv': 'file',\n\n // Office\n 'application/msword': 'file', // doc\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'file', // docx\n 'application/vnd.ms-excel': 'file', // xls\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'file', // xlsx\n 'application/vnd.ms-powerpoint': 'file', // ppt\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'file', // pptx,\n\n // Archives (optional)\n 'application/zip': 'file',\n 'application/x-zip-compressed': 'file',\n 'application/x-rar-compressed': 'file',\n 'application/x-7z-compressed': 'file',\n};\n\nexport class MediaFieldCrudManager implements FieldCrudManager {\n\n constructor(private readonly options: MediaFieldOptions) {\n }\n\n private resolveMediaType(file: Express.Multer.File): MediaType | null {\n // Belt-and-braces: dangerous files are already rejected outright by\n // validateDangerousFiles, but never let one resolve to a usable category.\n if (isDangerousMediaFile(file)) {\n return null;\n }\n\n const ext = getLowercaseFileExtension(getUploadedFileName(file));\n const mt = (file.mimetype || '').toLowerCase().trim();\n if (mt && MIME_TO_MEDIA_TYPE[mt]) {\n return MIME_TO_MEDIA_TYPE[mt];\n }\n\n // Some libs may send \"image/*\" etc. Treat broad families safely.\n if (mt.startsWith('image/')) return 'image';\n if (mt.startsWith('audio/')) return 'audio';\n if (mt.startsWith('video/')) return 'video';\n\n // Fallback to extension if provided (also covers generic/unrecognized\n // mimetypes such as application/octet-stream).\n if (ext && EXT_TO_MEDIA_TYPE[ext]) {\n return EXT_TO_MEDIA_TYPE[ext];\n }\n\n return null;\n }\n\n validate(dto: any, files: Array<Express.Multer.File>): ValidationError[] {\n const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);\n return this.applyValidations(fieldFiles);\n }\n\n private applyValidations(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n // Runs for every media field type and regardless of the admin-configured mediaTypes\n // allowlist - a dangerous upload is never acceptable, so this must not sit behind\n // the optional type checks below.\n const errors = this.validateDangerousFiles(fieldFiles);\n\n switch (this.options.type) {\n case SolidMediaType.mediaSingle:\n return [...errors, ...this.validateMediaSingle(fieldFiles)];\n case SolidMediaType.mediaMultiple:\n return [...errors, ...this.validateMediaMultiple(fieldFiles)];\n default:\n return errors;\n }\n }\n\n private validateDangerousFiles(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return fieldFiles\n .filter(fieldFile => isDangerousMediaFile(fieldFile))\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `${getUploadedFileName(fieldFile) || 'File'} is a potentially dangerous file type.`\n }));\n }\n\n private validateMediaSingle(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} is required`\n });\n }\n if (fieldFiles.length > 1) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} must be a single file`\n });\n }\n // validate size\n if (this.options.mediaMaxSizeKb) {\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n const fieldFileSizeInBytes = Math.ceil(fieldFile.size / 1024);\n if (fieldFileSizeInBytes > this.options.mediaMaxSizeKb) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} with size ${fieldFileSizeInBytes} KB exceeds max size limit of ${this.options.mediaMaxSizeKb} KB`\n });\n }\n }\n }\n // validate type\n if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {\n const allowedFileTypes = this.options.mediaTypes as MediaType[];\n\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n\n const resolvedType = this.resolveMediaType(fieldFile);\n if (!resolvedType || !allowedFileTypes.includes(resolvedType)) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `Allowed: ${allowedFileTypes.join(', ')}. ` +\n `Received mimetype: ${fieldFile.mimetype}${resolvedType ? ` (mapped to ${resolvedType})` : ''}`\n });\n }\n }\n }\n\n return errors;\n }\n\n private validateMediaMultiple(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} is required`\n });\n }\n return errors;\n }\n\n transformForCreate(dto: any): any {\n return dto;\n }\n\n // Validation to be applied\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MediaFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/MediaFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { EXT_TO_MEDIA_TYPE, getLowercaseFileExtension, getUploadedFileName, isDangerousMediaFile, MediaCategory } from \"src/constants/media-file-types\";\n\nexport enum SolidMediaType {\n mediaSingle = 'mediaSingle',\n mediaMultiple = 'mediaMultiple'\n}\n\nexport interface MediaFieldOptions {\n type: SolidMediaType;\n required: boolean | undefined | null;\n fieldName: string | undefined | null;\n mediaMaxSizeKb: number | undefined | null;\n mediaTypes: string[];\n mediaAllowedExtensions?: string[] | null;\n isUpdate: boolean | undefined | null;\n}\n\ntype MediaType = MediaCategory;\n\nconst MIME_TO_MEDIA_TYPE: Record<string, MediaType> = {\n // Images\n 'image/png': 'image',\n 'image/jpeg': 'image',\n 'image/jpg': 'image',\n 'image/webp': 'image',\n 'image/gif': 'image',\n 'image/bmp': 'image',\n 'image/tiff': 'image',\n 'image/heic': 'image',\n 'image/heif': 'image',\n\n // Audio\n 'audio/mpeg': 'audio', // mp3\n 'audio/mp3': 'audio',\n 'audio/wav': 'audio',\n 'audio/x-wav': 'audio',\n 'audio/webm': 'audio',\n 'audio/ogg': 'audio',\n 'audio/aac': 'audio',\n 'audio/mp4': 'audio', // m4a often shows as audio/mp4\n 'audio/x-m4a': 'audio',\n 'audio/flac': 'audio',\n\n // Video\n 'video/mp4': 'video',\n 'video/mpeg': 'video',\n 'video/webm': 'video',\n 'video/ogg': 'video',\n 'video/quicktime': 'video', // mov\n 'video/x-msvideo': 'video', // avi\n 'video/x-matroska': 'video',// mkv\n 'video/3gpp': 'video',\n 'video/3gpp2': 'video',\n\n // Documents / files (treat as \"file\")\n 'application/pdf': 'pdf',\n 'text/plain': 'file',\n 'text/markdown': 'file',\n 'application/json': 'file',\n 'text/csv': 'file',\n\n // Office\n 'application/msword': 'file', // doc\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'file', // docx\n 'application/vnd.ms-excel': 'file', // xls\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'file', // xlsx\n 'application/vnd.ms-powerpoint': 'file', // ppt\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'file', // pptx,\n\n // Archives (optional)\n 'application/zip': 'file',\n 'application/x-zip-compressed': 'file',\n 'application/x-rar-compressed': 'file',\n 'application/x-7z-compressed': 'file',\n};\n\nexport class MediaFieldCrudManager implements FieldCrudManager {\n\n constructor(private readonly options: MediaFieldOptions) {\n }\n\n private resolveMediaType(file: Express.Multer.File): MediaType | null {\n // Belt-and-braces: dangerous files are already rejected outright by\n // validateDangerousFiles, but never let one resolve to a usable category.\n if (isDangerousMediaFile(file)) {\n return null;\n }\n\n // Extension is authoritative: a declared mimetype is fully attacker-controlled and\n // proved insufficient on its own (a .msi uploaded as image/png previously resolved to\n // 'image', since the mimetype match short-circuited before the extension was ever\n // checked). The extension must independently resolve to a known-safe category before\n // anything is accepted - not merely \"not on the denylist\".\n const ext = getLowercaseFileExtension(getUploadedFileName(file));\n const extType = ext ? EXT_TO_MEDIA_TYPE[ext] : undefined;\n if (!extType) {\n return null;\n }\n\n // The mimetype may only confirm or veto what the extension already established, never\n // grant a category on its own. A mimetype that doesn't resolve to anything (e.g.\n // application/octet-stream) has no opinion and is treated as agreeing.\n const mt = (file.mimetype || '').toLowerCase().trim();\n const mimeType = MIME_TO_MEDIA_TYPE[mt]\n ?? (mt.startsWith('image/') ? 'image' : mt.startsWith('audio/') ? 'audio' : mt.startsWith('video/') ? 'video' : undefined);\n if (mimeType && mimeType !== extType) {\n return null;\n }\n\n return extType;\n }\n\n validate(dto: any, files: Array<Express.Multer.File>): ValidationError[] {\n const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);\n return this.applyValidations(fieldFiles);\n }\n\n private applyValidations(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n // A dangerous upload is never acceptable, regardless of admin config, so this is the\n // only check that sits outside validateCommon() and can't be skipped either way below.\n const dangerousFileErrors = this.validateDangerousFiles(fieldFiles);\n\n switch (this.options.type) {\n case SolidMediaType.mediaSingle:\n return [...dangerousFileErrors, ...this.validateMediaSingle(fieldFiles)];\n case SolidMediaType.mediaMultiple:\n return [...dangerousFileErrors, ...this.validateMediaMultiple(fieldFiles)];\n default:\n return dangerousFileErrors;\n }\n }\n\n private validateDangerousFiles(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return fieldFiles\n .filter(fieldFile => isDangerousMediaFile(fieldFile))\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `${getUploadedFileName(fieldFile) || 'File'} is a potentially dangerous file type.`\n }));\n }\n\n // Every optional, admin-configured, per-field check - no-ops when its setting is unset -\n // shared between mediaSingle and mediaMultiple so neither can drift out of sync with it.\n private validateCommon(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return [\n ...this.validateRequired(fieldFiles),\n ...this.validateSize(fieldFiles),\n ...this.validateTypes(fieldFiles),\n ...this.validateAllowedExtensions(fieldFiles),\n ];\n }\n\n private validateRequired(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} is required`\n });\n }\n return errors;\n }\n\n private validateSize(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (this.options.mediaMaxSizeKb) {\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n const fieldFileSizeInBytes = Math.ceil(fieldFile.size / 1024);\n if (fieldFileSizeInBytes > this.options.mediaMaxSizeKb) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} with size ${fieldFileSizeInBytes} KB exceeds max size limit of ${this.options.mediaMaxSizeKb} KB`\n });\n }\n }\n }\n return errors;\n }\n\n private validateTypes(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors: ValidationError[] = [];\n if (this.options.mediaTypes && this.options.mediaTypes.length > 0) {\n const allowedFileTypes = this.options.mediaTypes as MediaType[];\n\n for (let i = 0; i < fieldFiles.length; i++) {\n const fieldFile = fieldFiles[i];\n\n const resolvedType = this.resolveMediaType(fieldFile);\n if (!resolvedType || !allowedFileTypes.includes(resolvedType)) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `Allowed: ${allowedFileTypes.join(', ')}. ` +\n `Received mimetype: ${fieldFile.mimetype}${resolvedType ? ` (mapped to ${resolvedType})` : ''}`\n });\n }\n }\n }\n return errors;\n }\n\n private validateAllowedExtensions(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const allowed = this.options.mediaAllowedExtensions;\n if (!allowed || allowed.length === 0) {\n return [];\n }\n\n const normalizedAllowed = new Set(allowed.map(ext => ext.toLowerCase().replace(/^\\./, '')));\n return fieldFiles\n .filter(fieldFile => {\n const ext = getLowercaseFileExtension(getUploadedFileName(fieldFile));\n return !ext || !normalizedAllowed.has(ext);\n })\n .map(fieldFile => ({\n field: this.options.fieldName,\n error: `${this.options.fieldName} file type not allowed. ` +\n `Allowed extensions: ${[...normalizedAllowed].join(', ')}.`\n }));\n }\n\n private validateMediaSingle(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n const errors = this.validateCommon(fieldFiles);\n if (fieldFiles.length > 1) {\n errors.push({\n field: this.options.fieldName,\n error: `${this.options.fieldName} must be a single file`\n });\n }\n return errors;\n }\n\n private validateMediaMultiple(fieldFiles: Array<Express.Multer.File>): ValidationError[] {\n return this.validateCommon(fieldFiles);\n }\n\n transformForCreate(dto: any): any {\n return dto;\n }\n\n // Validation to be applied\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShortTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ShortTextFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGnE,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,yBAA0B,YAAW,gBAAgB;IAC9D,OAAO,CAAC,OAAO,CAAwB;gBAE3B,OAAO,EAAE,qBAAqB;IAI1C,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAG,MAAM,EAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,EAAE;IAMzE,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,sBAAsB;IAQ9B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;IAKjC,OAAO,CAAC,uBAAuB;IAG/B,OAAO,CAAC,uBAAuB;IAG/B,OAAO,CAAC,sBAAsB;IAG9B,OAAO,CAAC,yBAAyB;CAGpC"}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ShortTextFieldCrudManager = void 0;
|
|
4
4
|
const class_validator_1 = require("class-validator");
|
|
5
|
+
const textFieldCrudManagerUtils_1 = require("./textFieldCrudManagerUtils");
|
|
5
6
|
class ShortTextFieldCrudManager {
|
|
6
7
|
constructor(options) {
|
|
7
8
|
this.options = options;
|
|
8
9
|
}
|
|
9
10
|
validate(dto, _files) {
|
|
10
|
-
const fieldValue = dto[this.options.fieldName];
|
|
11
|
+
const fieldValue = (0, textFieldCrudManagerUtils_1.normalizeTextFieldValue)(dto[this.options.fieldName]);
|
|
11
12
|
return this.applyValidations(fieldValue);
|
|
12
13
|
}
|
|
13
14
|
applyValidations(fieldValue) {
|
|
@@ -26,7 +27,7 @@ class ShortTextFieldCrudManager {
|
|
|
26
27
|
return errors;
|
|
27
28
|
}
|
|
28
29
|
transformForCreate(dto) {
|
|
29
|
-
return dto;
|
|
30
|
+
return (0, textFieldCrudManagerUtils_1.normalizeTextFieldInDto)(dto, this.options.fieldName);
|
|
30
31
|
}
|
|
31
32
|
isApplyStringValidation() {
|
|
32
33
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShortTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAiF;
|
|
1
|
+
{"version":3,"file":"ShortTextFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ShortTextFieldCrudManager.ts"],"names":[],"mappings":";;;AAAA,qDAAiF;AAEjF,2EAA+F;AAS/F,MAAa,yBAAyB;IAGlC,YAAY,OAA8B;QACtC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED,QAAQ,CAAC,GAAQ,EAAG,MAAiC;QACjD,MAAM,UAAU,GAAQ,IAAA,mDAAuB,EAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7E,OAAO,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC7C,CAAC;IAGO,gBAAgB,CAAC,UAAe;QACpC,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,yBAAyB,EAAE,IAAI,IAAA,yBAAO,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,IAAI,CAAC,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAA,CAAC,CAAC,WAAW,CAAC;QAC7K,IAAI,IAAA,4BAAU,EAAC,UAAU,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,MAAM,CAAC;IAClB,CAAC;IAEO,sBAAsB,CAAC,UAAe;QAC1C,MAAM,MAAM,GAAsB,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAA,0BAAQ,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACvJ,IAAI,CAAC,uBAAuB,EAAE,IAAI,CAAC,IAAA,wBAAM,EAAC,UAAU,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAC/K,IAAI,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAA,yBAAO,EAAC,UAAU,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QACrM,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,kBAAkB,CAAC,GAAQ;QACvB,OAAO,IAAA,mDAAuB,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChE,CAAC;IAGO,uBAAuB;QAC3B,OAAO,IAAI,CAAC;IAChB,CAAC;IACO,uBAAuB;QAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IACO,sBAAsB;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACxI,CAAC;IACO,yBAAyB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IACjC,CAAC;CACJ;AA/CD,8DA+CC","sourcesContent":["import { isEmpty, isNotEmpty, isString, length, matches } from \"class-validator\";\nimport { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { normalizeTextFieldInDto, normalizeTextFieldValue } from \"./textFieldCrudManagerUtils\";\n\nexport interface ShortTextFieldOptions {\n length: number | undefined | null;\n regexPattern: string | undefined | null;\n required: boolean | undefined | null;\n fieldName: string;\n}\n\nexport class ShortTextFieldCrudManager implements FieldCrudManager {\n private options: ShortTextFieldOptions;\n\n constructor(options: ShortTextFieldOptions) {\n this.options = options;\n }\n\n validate(dto: any, _files:Array<Express.Multer.File>): ValidationError[] {\n const fieldValue: any = normalizeTextFieldValue(dto[this.options.fieldName]);\n return this.applyValidations(fieldValue);\n }\n\n\n private applyValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyRequiredValidation() && isEmpty(fieldValue) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required` }): \"no errors\";\n if (isNotEmpty(fieldValue)) {\n errors.push(...this.applyFormatValidations(fieldValue));\n }\n return errors;\n }\n\n private applyFormatValidations(fieldValue: any): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyStringValidation() && !isString(fieldValue) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : \"no errors\";\n this.isApplyLengthValidation() && !length(fieldValue, 1, this.options.length) ? errors.push({ field: this.options.fieldName, error: 'Field length is invalid' }) : \"no errors\"; //FIXME min length to be handled\n this.isApplyRegexValidation() && !matches(fieldValue, new RegExp(this.options.regexPattern)) ? errors.push({ field: this.options.fieldName, error: 'Field regex pattern is invalid' }) : \"no errors\";\n return errors;\n }\n\n transformForCreate(dto: any): any {\n return normalizeTextFieldInDto(dto, this.options.fieldName);\n }\n\n // Validation to be applied\n private isApplyStringValidation(): boolean {\n return true;\n }\n private isApplyLengthValidation(): boolean {\n return (this.options.length > 0);\n }\n private isApplyRegexValidation(): boolean {\n return this.options.regexPattern !== null && this.options.regexPattern !== undefined && this.options.regexPattern.trim().length > 0;\n }\n private isApplyRequiredValidation(): boolean {\n return this.options.required;\n }\n}"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textFieldCrudManagerUtils.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,GAAI,YAAY,GAAG,KAAG,GAEzD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,KAAK,GAAG,EAAE,YAAY,MAAM,GAAG,IAAI,KAAG,GAO7E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeTextFieldInDto = exports.normalizeTextFieldValue = void 0;
|
|
4
|
+
const class_validator_1 = require("class-validator");
|
|
5
|
+
const normalizeTextFieldValue = (fieldValue) => {
|
|
6
|
+
return (0, class_validator_1.isString)(fieldValue) ? fieldValue.trim() : fieldValue;
|
|
7
|
+
};
|
|
8
|
+
exports.normalizeTextFieldValue = normalizeTextFieldValue;
|
|
9
|
+
const normalizeTextFieldInDto = (dto, fieldName) => {
|
|
10
|
+
if (!fieldName || !Object.prototype.hasOwnProperty.call(dto, fieldName)) {
|
|
11
|
+
return dto;
|
|
12
|
+
}
|
|
13
|
+
dto[fieldName] = (0, exports.normalizeTextFieldValue)(dto[fieldName]);
|
|
14
|
+
return dto;
|
|
15
|
+
};
|
|
16
|
+
exports.normalizeTextFieldInDto = normalizeTextFieldInDto;
|
|
17
|
+
//# sourceMappingURL=textFieldCrudManagerUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textFieldCrudManagerUtils.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/textFieldCrudManagerUtils.ts"],"names":[],"mappings":";;;AAAA,qDAA2C;AAEpC,MAAM,uBAAuB,GAAG,CAAC,UAAe,EAAO,EAAE;IAC5D,OAAO,IAAA,0BAAQ,EAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AACjE,CAAC,CAAC;AAFW,QAAA,uBAAuB,2BAElC;AAEK,MAAM,uBAAuB,GAAG,CAAC,GAAQ,EAAE,SAAyB,EAAO,EAAE;IAChF,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;QACtE,OAAO,GAAG,CAAC;IACf,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,GAAG,IAAA,+BAAuB,EAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,OAAO,GAAG,CAAC;AACf,CAAC,CAAC;AAPW,QAAA,uBAAuB,2BAOlC","sourcesContent":["import { isString } from \"class-validator\";\n\nexport const normalizeTextFieldValue = (fieldValue: any): any => {\n return isString(fieldValue) ? fieldValue.trim() : fieldValue;\n};\n\nexport const normalizeTextFieldInDto = (dto: any, fieldName?: string | null): any => {\n if (!fieldName || !Object.prototype.hasOwnProperty.call(dto, fieldName)) {\n return dto;\n }\n\n dto[fieldName] = normalizeTextFieldValue(dto[fieldName]);\n return dto;\n};\n"]}
|
|
@@ -44,6 +44,7 @@ export declare class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
44
44
|
private parseMessageBodyMentions;
|
|
45
45
|
private renderMentionTokens;
|
|
46
46
|
private validateChatterMediaFiles;
|
|
47
|
+
private validateChatterAttachmentsForFields;
|
|
47
48
|
private publishChatterMentionNotifications;
|
|
48
49
|
getMentionableUsers(search?: string, limit?: number): Promise<Array<{
|
|
49
50
|
id: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatter-message.service.d.ts","sourceRoot":"","sources":["../../src/services/chatter-message.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAY,aAAa,EAAsB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"chatter-message.service.d.ts","sourceRoot":"","sources":["../../src/services/chatter-message.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ const strings_1 = require("@angular-devkit/core/src/utils/strings");
|
|
|
23
23
|
const chatter_message_constants_1 = require("../constants/chatter-message.constants");
|
|
24
24
|
const media_file_types_1 = require("../constants/media-file-types");
|
|
25
25
|
const error_messages_1 = require("../constants/error-messages");
|
|
26
|
+
const MediaFieldCrudManager_1 = require("../helpers/field-crud-managers/MediaFieldCrudManager");
|
|
26
27
|
const model_metadata_helper_service_1 = require("../helpers/model-metadata-helper.service");
|
|
27
28
|
const string_helper_1 = require("../helpers/string.helper");
|
|
28
29
|
const chatter_message_details_repository_1 = require("../repository/chatter-message-details.repository");
|
|
@@ -145,6 +146,26 @@ let ChatterMessageService = ChatterMessageService_1 = class ChatterMessageServic
|
|
|
145
146
|
throw new common_1.BadRequestException('Dangerous file types are not allowed in chatter attachments.');
|
|
146
147
|
}
|
|
147
148
|
}
|
|
149
|
+
validateChatterAttachmentsForFields(files, mediaFields, isUpdate) {
|
|
150
|
+
for (const mediaField of mediaFields) {
|
|
151
|
+
const media = files.filter(multerFile => multerFile.fieldname === mediaField.name);
|
|
152
|
+
if (media.length === 0)
|
|
153
|
+
continue;
|
|
154
|
+
const validator = new MediaFieldCrudManager_1.MediaFieldCrudManager({
|
|
155
|
+
type: mediaField.type,
|
|
156
|
+
required: mediaField.required,
|
|
157
|
+
fieldName: mediaField.name,
|
|
158
|
+
mediaMaxSizeKb: mediaField.mediaMaxSizeKb,
|
|
159
|
+
mediaTypes: mediaField.mediaTypes,
|
|
160
|
+
mediaAllowedExtensions: mediaField.mediaAllowedExtensions,
|
|
161
|
+
isUpdate,
|
|
162
|
+
});
|
|
163
|
+
const validationErrors = validator.validate({}, media);
|
|
164
|
+
if (validationErrors.length > 0) {
|
|
165
|
+
throw new common_1.BadRequestException(validationErrors.map(error => error.error).join(', '));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
148
169
|
async publishChatterMentionNotifications(message, model) {
|
|
149
170
|
if (message.messageType !== chatter_message_constants_1.CHATTER_MESSAGE_TYPE.CUSTOM || message.messageSubType !== chatter_message_constants_1.CHATTER_MESSAGE_SUBTYPE.NOTE) {
|
|
150
171
|
return;
|
|
@@ -251,6 +272,21 @@ let ChatterMessageService = ChatterMessageService_1 = class ChatterMessageServic
|
|
|
251
272
|
throw new common_1.BadRequestException('Message body cannot be empty.');
|
|
252
273
|
}
|
|
253
274
|
this.validateChatterMediaFiles(files);
|
|
275
|
+
let chatterModel = null;
|
|
276
|
+
let mediaFields = [];
|
|
277
|
+
if (removeAttachmentIds.length > 0 || hasNewFiles) {
|
|
278
|
+
chatterModel = await this.modelMetadataService.findOneBySingularName('chatterMessage', {
|
|
279
|
+
fields: {
|
|
280
|
+
model: true,
|
|
281
|
+
mediaStorageProvider: true,
|
|
282
|
+
},
|
|
283
|
+
module: true,
|
|
284
|
+
});
|
|
285
|
+
mediaFields = chatterModel.fields.filter(field => field.type === 'mediaSingle' || field.type === 'mediaMultiple');
|
|
286
|
+
if (hasNewFiles) {
|
|
287
|
+
this.validateChatterAttachmentsForFields(files, mediaFields, true);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
254
290
|
if (hasMessageBody) {
|
|
255
291
|
message.messageBody = trimmedMessageBody;
|
|
256
292
|
}
|
|
@@ -265,21 +301,13 @@ let ChatterMessageService = ChatterMessageService_1 = class ChatterMessageServic
|
|
|
265
301
|
message.updatedAt = new Date();
|
|
266
302
|
const savedMessage = await this.repo.save(message);
|
|
267
303
|
if (removeAttachmentIds.length > 0 || hasNewFiles) {
|
|
268
|
-
const model = await this.modelMetadataService.findOneBySingularName('chatterMessage', {
|
|
269
|
-
fields: {
|
|
270
|
-
model: true,
|
|
271
|
-
mediaStorageProvider: true,
|
|
272
|
-
},
|
|
273
|
-
module: true,
|
|
274
|
-
});
|
|
275
|
-
const mediaFields = model.fields.filter(field => field.type === 'mediaSingle' || field.type === 'mediaMultiple');
|
|
276
304
|
const attachmentFieldIds = mediaFields.map(field => field.id);
|
|
277
305
|
if (removeAttachmentIds.length > 0 && attachmentFieldIds.length > 0) {
|
|
278
306
|
const mediaToRemove = await this.mediaRepository.find({
|
|
279
307
|
where: {
|
|
280
308
|
id: (0, typeorm_2.In)(removeAttachmentIds),
|
|
281
309
|
entityId: savedMessage.id,
|
|
282
|
-
modelMetadata: { id:
|
|
310
|
+
modelMetadata: { id: chatterModel.id },
|
|
283
311
|
fieldMetadata: { id: (0, typeorm_2.In)(attachmentFieldIds) },
|
|
284
312
|
},
|
|
285
313
|
relations: {
|
|
@@ -331,16 +359,20 @@ let ChatterMessageService = ChatterMessageService_1 = class ChatterMessageServic
|
|
|
331
359
|
});
|
|
332
360
|
chatterMessage.modelDisplayName = model?.displayName ?? null;
|
|
333
361
|
this.stampMessageAuditFields(chatterMessage);
|
|
334
|
-
|
|
362
|
+
let mediaFields = [];
|
|
335
363
|
if (files && files.length > 0) {
|
|
336
|
-
const
|
|
364
|
+
const chatterModel = await this.modelMetadataService.findOneBySingularName('chatterMessage', {
|
|
337
365
|
fields: {
|
|
338
366
|
model: true,
|
|
339
367
|
mediaStorageProvider: true,
|
|
340
368
|
},
|
|
341
369
|
module: true,
|
|
342
370
|
});
|
|
343
|
-
|
|
371
|
+
mediaFields = chatterModel.fields.filter(field => field.type === 'mediaSingle' || field.type === 'mediaMultiple');
|
|
372
|
+
this.validateChatterAttachmentsForFields(files, mediaFields, false);
|
|
373
|
+
}
|
|
374
|
+
const savedMessage = await this.repo.save(chatterMessage);
|
|
375
|
+
if (files && files.length > 0) {
|
|
344
376
|
for (const mediaField of mediaFields) {
|
|
345
377
|
const media = files.filter(multerFile => multerFile.fieldname === mediaField.name);
|
|
346
378
|
if (media.length > 0) {
|