Răsfoiți Sursa

Start implementing backend and frontend logic

arvid-e 9 luni în urmă
părinte
comite
271c1ee0b7

+ 70 - 0
apps/app/src/client/services/AdminAttachmentContainer.js

@@ -0,0 +1,70 @@
+import { isServer } from '@growi/core/dist/utils';
+import { Container } from 'unstated';
+
+import { apiv3Get, apiv3Put } from '../util/apiv3-client';
+
+export default class AdminAttachmentContainer extends Container {
+
+  constructor(appContainer) {
+    super();
+
+    if (isServer()) {
+      return;
+    }
+
+    this.appContainer = appContainer;
+
+
+    this.state = {
+      imagepng: true,
+      imagejpeg: true,
+      imagegif: true,
+      imagewebp: true,
+      imagebmp: true,
+      imagexicon: true,
+      applicationpdf: true,
+      videomp4: true,
+      audiompeg: true,
+      textplain: true,
+    };
+  }
+
+  async retrieveContentTypeSettings() {
+    const response = await apiv3Get('/content-type-settings/');
+    const { contentTypes } = response.data.contentTypes;
+
+    this.setState({
+      imagepng: contentTypes.imagepng,
+      imagejpeg: contentTypes.imagejpeg,
+      imagegif: contentTypes.imagegif,
+      imagewebp: contentTypes.imagewebp,
+      imagebmp: contentTypes.imagebmp,
+      imagexicon: contentTypes.imagexicon,
+      applicationpdf: contentTypes.applicationpdf,
+      videomp4: contentTypes.videomp4,
+      audiompeg: contentTypes.audiompeg,
+      textplain: contentTypes.textplain,
+    });
+  }
+
+  async setStrictContentDispositionSettings() {
+
+    await apiv3Put('/content-disposition-settings', {
+    });
+  }
+
+
+  async setModerateContentDispositionSettings() {
+
+    await apiv3Put('/content-disposition-settings', {
+    });
+  }
+
+
+  async setLaxContentDispositionSettings() {
+
+    await apiv3Put('/content-disposition-settings', {
+    });
+  }
+
+}

+ 0 - 162
apps/app/src/client/services/attachment.ts

@@ -1,162 +0,0 @@
-import express from 'express';
-import type { Request, Response } from 'express';
-import { body, validationResult } from 'express-validator';
-
-import { configManager } from '~/server/service/config-manager';
-import ApiResponse from '~/server/util/apiResponse';
-import loggerFactory from '~/utils/logger';
-
-const logger = loggerFactory('growi:routes:admin:attachments');
-
-export const PREDEFINED_INLINE_MIME_TYPES = [
-  'image/png',
-  'image/jpeg',
-  'image/gif',
-  'image/webp',
-  'image/bmp',
-  'image/x-icon',
-  'application/pdf',
-  'video/mp4',
-  'audio/mpeg',
-  'text/plain',
-] as const;
-
-const DANGEROUS_MIME_TYPES = new Set([
-  'text/html',
-  'application/javascript',
-  'application/x-javascript',
-  'image/svg+xml',
-  'application/x-shockwave-flash',
-]);
-
-// Assign the router factory function to a variable before exporting
-const adminAttachmentsRouterFactory = (crowi: any) => {
-  const router = express.Router();
-
-  /**
-   * @swagger
-   * /admin/attachments/inline-allowlist:
-   * get:
-   * tags: [Attachments, Admin]
-   * summary: Get inline display allowlist settings
-   * description: Retrieve the current inline display allowlist for attachment MIME types.
-   * responses:
-   * 200:
-   * description: Successfully retrieved settings.
-   * content:
-   * application/json:
-   * schema:
-   * properties:
-   * inlineAllowlistTypes:
-   * type: array
-   * items:
-   * type: string
-   * description: List of allowed MIME types for inline display.
-   * customInlineAllowlistTypes:
-   * type: string
-   * description: Comma-separated string of custom allowed MIME types.
-   * 500:
-   * description: Server error.
-   */
-  router.get('/inline-allowlist', (req: Request, res: Response) => {
-    try {
-      const inlineAllowlistTypes = configManager.getConfig('security:inlineAllowlistTypes') || [];
-      const customInlineAllowlistTypes = configManager.getConfig('security:customInlineAllowlistTypes') || '';
-      return res.json(ApiResponse.success({ inlineAllowlistTypes, customInlineAllowlistTypes }));
-    } catch (err) {
-      logger.error('Failed to retrieve inline allowlist settings', err);
-      return res.json(ApiResponse.error('Failed to retrieve settings.'));
-    }
-  });
-
-  /**
-   * @swagger
-   * /admin/attachments/inline-allowlist:
-   * put:
-   * tags: [Attachments, Admin]
-   * summary: Update inline display allowlist settings
-   * description: Update the inline display allowlist for attachment MIME types.
-   * requestBody:
-   * required: true
-   * content:
-   * application/json:
-   * schema:
-   * type: object
-   * properties:
-   * inlineAllowlistTypes:
-   * type: array
-   * items:
-   * type: string
-   * description: List of selected predefined MIME types.
-   * customInlineAllowlistTypes:
-   * type: string
-   * description: Comma-separated string of custom MIME types.
-   * responses:
-   * 200:
-   * description: Successfully updated settings.
-   * content:
-   * application/json:
-   * schema:
-   * properties:
-   * updatedConfig:
-   * type: object
-   * properties:
-   * inlineAllowlistTypes:
-   * type: array
-   * items:
-   * type: string
-   * customInlineAllowlistTypes:
-   * type: string
-   * 400:
-   * description: Invalid request body.
-   * 500:
-   * description: Server error.
-   */
-  router.put('/inline-allowlist', [
-    body('inlineAllowlistTypes').isArray().withMessage('inlineAllowlistTypes must be an array'),
-    body('inlineAllowlistTypes.*').isString().withMessage('inlineAllowlistTypes elements must be strings'),
-    body('customInlineAllowlistTypes').isString().withMessage('customInlineAllowlistTypes must be a string'),
-  ], async(req: Request, res: Response) => {
-    const errors = validationResult(req);
-    if (!errors.isEmpty()) {
-      return res.status(400).json(ApiResponse.error(errors.array().map(e => e.msg).join(', ')));
-    }
-
-    const { inlineAllowlistTypes, customInlineAllowlistTypes } = req.body;
-
-    const validPredefinedTypes = (Array.isArray(inlineAllowlistTypes) ? inlineAllowlistTypes : [])
-      .filter((type: string) => typeof type === 'string' && PREDEFINED_INLINE_MIME_TYPES.includes(type as (typeof PREDEFINED_INLINE_MIME_TYPES)[number]));
-
-    const sanitizedCustomTypesArray = (typeof customInlineAllowlistTypes === 'string' ? customInlineAllowlistTypes : '')
-      .split(',')
-      .map(type => type.trim())
-      .filter(type => type.length > 0 && !DANGEROUS_MIME_TYPES.has(type));
-
-    const combinedAllowlist = Array.from(new Set([
-      ...validPredefinedTypes,
-      ...sanitizedCustomTypesArray,
-    ]));
-
-    try {
-      await configManager.updateConfigs({
-        'security:inlineAllowlistTypes': combinedAllowlist,
-        'security:customInlineAllowlistTypes': sanitizedCustomTypesArray.join(','),
-      });
-
-      const updatedConfig = {
-        inlineAllowlistTypes: combinedAllowlist,
-        customInlineAllowlistTypes: sanitizedCustomTypesArray.join(','),
-      };
-
-      return res.json(ApiResponse.success({ updatedConfig }));
-    } catch (err) {
-      logger.error('Failed to update inline allowlist settings', err);
-      return res.json(ApiResponse.error('Failed to update settings.'));
-    }
-  });
-
-  return router;
-};
-
-// Export the variable as the default module export
-export default adminAttachmentsRouterFactory;

+ 48 - 0
apps/app/src/server/routes/apiv3/content-disposition-settings.js

@@ -0,0 +1,48 @@
+import { ErrorV3 } from '@growi/core/dist/models';
+
+import { SupportedAction } from '~/interfaces/activity';
+import { configManager } from '~/server/service/config-manager';
+import loggerFactory from '~/utils/logger';
+
+import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
+import { apiV3FormValidator } from '../../middlewares/apiv3-form-validator';
+
+
+const logger = loggerFactory('growi:routes:apiv3:markdown-setting');
+
+const express = require('express');
+
+const router = express.Router();
+
+const { body } = require('express-validator');
+
+
+module.exports = (crowi) => {
+  const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
+  const adminRequired = require('../../middlewares/admin-required')(crowi);
+  const addActivity = generateAddActivityMiddleware(crowi);
+  const activityEvent = crowi.event('activity');
+
+
+  router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
+    const contentDispositionSettings = {
+      // change to mime types
+      isEnabledLinebreaks: await crowi.configManager.getConfig('markdown:isEnabledLinebreaks'),
+      isEnabledLinebreaksInComments: await crowi.configManager.getConfig('markdown:isEnabledLinebreaksInComments'),
+      adminPreferredIndentSize: await crowi.configManager.getConfig('markdown:adminPreferredIndentSize'),
+      isIndentSizeForced: await crowi.configManager.getConfig('markdown:isIndentSizeForced'),
+      isEnabledXss: await crowi.configManager.getConfig('markdown:rehypeSanitize:isEnabledPrevention'),
+      xssOption: await crowi.configManager.getConfig('markdown:rehypeSanitize:option'),
+      tagWhitelist: await crowi.configManager.getConfig('markdown:rehypeSanitize:tagNames'),
+      attrWhitelist: await crowi.configManager.getConfig('markdown:rehypeSanitize:attributes'),
+    };
+
+    return res.apiv3({ contentDispositionSettings });
+  });
+
+  // add functions for adding and removing allowed mime types
+  // add function for setting predetermined allowed mime types in lists
+  // Recommended, Strict, Moderately strict, Lax, etc
+
+  return router;
+};

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

@@ -85,8 +85,6 @@ export const CONFIG_KEYS = [
   'security:trustProxyBool',
   'security:trustProxyBool',
   'security:trustProxyCsv',
   'security:trustProxyCsv',
   'security:trustProxyHops',
   'security:trustProxyHops',
-  'security:inlineAllowlistTypes',
-  'security:customInlineAllowlistTypes',
   'security:passport-local:isEnabled',
   'security:passport-local:isEnabled',
   'security:passport-local:isPasswordResetEnabled',
   'security:passport-local:isPasswordResetEnabled',
   'security:passport-local:isEmailAuthenticationEnabled',
   'security:passport-local:isEmailAuthenticationEnabled',
@@ -569,12 +567,6 @@ export const CONFIG_DEFINITIONS = {
     defaultValue: undefined,
     defaultValue: undefined,
     isSecret: true,
     isSecret: true,
   }),
   }),
-  'security:inlineAllowlistTypes': defineConfig<string[]>({
-    defaultValue: [],
-  }),
-  'security:customInlineAllowlistTypes': defineConfig<string>({
-    defaultValue: '',
-  }),
   'security:passport-local:isEnabled': defineConfig<boolean>({
   'security:passport-local:isEnabled': defineConfig<boolean>({
     envVarName: 'LOCAL_STRATEGY_ENABLED',
     envVarName: 'LOCAL_STRATEGY_ENABLED',
     defaultValue: true,
     defaultValue: true,