Просмотр исходного кода

Save attachment MIME types in its own list and update using the same endpoint

arvid-e 6 месяцев назад
Родитель
Сommit
b47777cb7e

+ 32 - 6
apps/app/src/server/routes/apiv3/content-disposition-settings.ts

@@ -16,10 +16,14 @@ module.exports = (crowi) => {
   const addActivity = generateAddActivityMiddleware();
   const addActivity = generateAddActivityMiddleware();
   const activityEvent = crowi.event('activity');
   const activityEvent = crowi.event('activity');
 
 
-  interface UpdateMimeTypesPayload {
+  interface UpdateInlineMimeTypesPayload {
   newInlineMimeTypes: string[];
   newInlineMimeTypes: string[];
   }
   }
 
 
+  interface UpdateAttachmentMimeTypesPayload {
+  newAttachmentMimeTypes: string[];
+  }
+
   /**
   /**
  * @swagger
  * @swagger
  *
  *
@@ -55,19 +59,41 @@ module.exports = (crowi) => {
     async(req, res) => {
     async(req, res) => {
 
 
       try {
       try {
-        const { newInlineMimeTypes } = req.body as UpdateMimeTypesPayload;
-        const inlineMimeTypes = Array.from(new Set(newInlineMimeTypes));
-        await configManager.updateConfigs({ 'attachments:contentDisposition:inlineMimeTypes': { inlineMimeTypes } });
+        const { newInlineMimeTypes } = req.body as UpdateInlineMimeTypesPayload;
+        const { newAttachmentMimeTypes } = req.body as UpdateAttachmentMimeTypesPayload;
+
+        // Ensure no MIME type is in both lists.
+        const inlineSet = new Set(newInlineMimeTypes);
+        const attachmentSet = new Set(newAttachmentMimeTypes);
+        const intersection = [...inlineSet].filter(mimeType => attachmentSet.has(mimeType));
+
+        if (intersection.length > 0) {
+          const msg = `MIME types cannot be in both inline and attachment lists: ${intersection.join(', ')}`;
+          return res.apiv3Err(new ErrorV3(msg, 'invalid-payload'));
+        }
+
+        await configManager.updateConfigs({
+          'attachments:contentDisposition:inlineMimeTypes': {
+            inlineMimeTypes: Array.from(inlineSet),
+          },
+          'attachments:contentDisposition:attachmentMimeTypes': {
+            attachmentMimeTypes: Array.from(attachmentSet),
+          },
+        });
 
 
         const parameters = {
         const parameters = {
           action: SupportedAction.ACTION_ADMIN_ATTACHMENT_DISPOSITION_UPDATE,
           action: SupportedAction.ACTION_ADMIN_ATTACHMENT_DISPOSITION_UPDATE,
-          currentDispositionSettings: inlineMimeTypes,
+          currentDispositionSettings: {
+            inlineMimeTypes: Array.from(inlineSet),
+            attachmentMimeTypes: Array.from(attachmentSet),
+          },
         };
         };
         activityEvent.emit('update', res.locals.activity._id, parameters);
         activityEvent.emit('update', res.locals.activity._id, parameters);
 
 
         return res.apiv3({
         return res.apiv3({
           currentDispositionSettings: {
           currentDispositionSettings: {
-            inlineMimeTypes,
+            inlineMimeTypes: Array.from(inlineSet),
+            attachmentMimeTypes: Array.from(attachmentSet),
           },
           },
         });
         });
       }
       }

+ 7 - 0
apps/app/src/server/service/config-manager/config-definition.ts

@@ -80,6 +80,8 @@ export const CONFIG_KEYS = [
 
 
   // Content-Disposition settings for MIME types
   // Content-Disposition settings for MIME types
   'attachments:contentDisposition:inlineMimeTypes',
   'attachments:contentDisposition:inlineMimeTypes',
+  'attachments:contentDisposition:attachmentMimeTypes',
+
 
 
   // Security Settings
   // Security Settings
   'security:wikiMode',
   'security:wikiMode',
@@ -548,6 +550,11 @@ export const CONFIG_DEFINITIONS = {
     },
     },
   }),
   }),
 
 
+  'attachments:contentDisposition:attachmentMimeTypes': defineConfig<{ attachmentMimeTypes: string[]; }>({
+    defaultValue: {
+      attachmentMimeTypes: [],
+    },
+  }),
 
 
   // Security Settings
   // Security Settings
   'security:wikiMode': defineConfig<string | undefined>({
   'security:wikiMode': defineConfig<string | undefined>({

+ 13 - 5
apps/app/src/server/service/file-uploader/utils/headers.ts

@@ -35,13 +35,22 @@ export class ContentHeaders implements IContentHeaders {
 
 
     let finalDispositionValue: string;
     let finalDispositionValue: string;
 
 
-    const currentInlineMimeTypes = configManager.getConfig('attachments:contentDisposition:inlineMimeTypes');
-    const test = currentInlineMimeTypes.inlineMimeTypes;
+    const currentConfig = configManager.getConfig('attachments:contentDisposition:inlineMimeTypes');
+    const adminInlineMimeTypes = currentConfig.inlineMimeTypes;
 
 
-    if (test.includes(mimeType)) {
+    const currentAttachmentMimeTypes = configManager.getConfig('attachments:contentDisposition:attachmentMimeTypes');
+    const adminAttachmentMimeTypes = currentAttachmentMimeTypes.attachmentMimeTypes;
+
+
+    // 1. Check for explicit admin override to 'inline'
+    if (adminInlineMimeTypes.includes(mimeType)) {
       finalDispositionValue = 'inline';
       finalDispositionValue = 'inline';
     }
     }
-
+    // 2. Check for explicit admin override to 'attachment'
+    else if (adminAttachmentMimeTypes.includes(mimeType)) {
+      finalDispositionValue = 'attachment';
+    }
+    // 3. If no override, fall back to the default setting
     else {
     else {
       const defaultSetting = defaultContentDispositionSettings[mimeType];
       const defaultSetting = defaultContentDispositionSettings[mimeType];
 
 
@@ -51,7 +60,6 @@ export class ContentHeaders implements IContentHeaders {
       else {
       else {
         finalDispositionValue = 'attachment';
         finalDispositionValue = 'attachment';
       }
       }
-    }
 
 
 
 
     this.contentDisposition = {
     this.contentDisposition = {