Bladeren bron

Removed eslint-disable-next-line max-len

Shun Miyazawa 10 maanden geleden
bovenliggende
commit
a86a02081a

+ 3 - 2
apps/app/src/features/openai/server/routes/ai-assistant.ts

@@ -29,8 +29,9 @@ export const createAiAssistantFactory: CreateAssistantFactory = (crowi) => {
   const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
 
   return [
-    // eslint-disable-next-line max-len
-    accessTokenParser([SCOPE.WRITE.FEATURES.AI_ASSISTANT], { acceptLegacy: true }), loginRequiredStrictly, certifyAiService, upsertAiAssistantValidator, apiV3FormValidator,
+    accessTokenParser(
+      [SCOPE.WRITE.FEATURES.AI_ASSISTANT], { acceptLegacy: true },
+    ), loginRequiredStrictly, certifyAiService, upsertAiAssistantValidator, apiV3FormValidator,
     async(req: Req, res: ApiV3Response) => {
       const openaiService = getOpenaiService();
       if (openaiService == null) {

+ 2 - 2
apps/app/src/features/openai/server/routes/set-default-ai-assistant.ts

@@ -39,8 +39,8 @@ export const setDefaultAiAssistantFactory: setDefaultAiAssistantFactory = (crowi
   ];
 
   return [
-    // eslint-disable-next-line max-len
-    accessTokenParser([SCOPE.WRITE.FEATURES.AI_ASSISTANT], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, certifyAiService, validator, apiV3FormValidator,
+    accessTokenParser([SCOPE.WRITE.FEATURES.AI_ASSISTANT], { acceptLegacy: true }),
+    loginRequiredStrictly, adminRequired, certifyAiService, validator, apiV3FormValidator,
     async(req: Req, res: ApiV3Response) => {
       const openaiService = getOpenaiService();
       if (openaiService == null) {

+ 19 - 18
apps/app/src/features/questionnaire/server/routes/apiv3/questionnaire.ts

@@ -86,21 +86,22 @@ module.exports = (crowi: Crowi): Router => {
    *                   items:
    *                     type: object
    */
-  // eslint-disable-next-line max-len
-  router.get('/orders', accessTokenParser([SCOPE.READ.FEATURES.QUESTIONNAIRE], { acceptLegacy: true }), loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const growiInfo = await growiInfoService.getGrowiInfo(true);
-    const userInfo = crowi.questionnaireService.getUserInfo(req.user ?? null, getSiteUrlHashed(growiInfo.appSiteUrl));
+  router.get('/orders',
+    accessTokenParser([SCOPE.READ.FEATURES.QUESTIONNAIRE], { acceptLegacy: true }),
+    loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const growiInfo = await growiInfoService.getGrowiInfo(true);
+      const userInfo = crowi.questionnaireService.getUserInfo(req.user ?? null, getSiteUrlHashed(growiInfo.appSiteUrl));
 
-    try {
-      const questionnaireOrders = await crowi.questionnaireService!.getQuestionnaireOrdersToShow(userInfo, growiInfo, req.user?._id ?? null);
+      try {
+        const questionnaireOrders = await crowi.questionnaireService!.getQuestionnaireOrdersToShow(userInfo, growiInfo, req.user?._id ?? null);
 
-      return res.apiv3({ questionnaireOrders });
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+        return res.apiv3({ questionnaireOrders });
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(err, 500);
+      }
+    });
 
   /**
    * @swagger
@@ -124,11 +125,11 @@ module.exports = (crowi: Crowi): Router => {
    *                 isEnabled:
    *                   type: boolean
    */
-  // eslint-disable-next-line max-len
-  router.get('/is-enabled', accessTokenParser([SCOPE.READ.FEATURES.QUESTIONNAIRE], { acceptLegacy: true }), loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const isEnabled = configManager.getConfig('questionnaire:isQuestionnaireEnabled');
-    return res.apiv3({ isEnabled });
-  });
+  router.get('/is-enabled',
+    accessTokenParser([SCOPE.READ.FEATURES.QUESTIONNAIRE], { acceptLegacy: true }), loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const isEnabled = configManager.getConfig('questionnaire:isQuestionnaireEnabled');
+      return res.apiv3({ isEnabled });
+    });
 
 
   /**

+ 80 - 79
apps/app/src/server/routes/apiv3/activity.ts

@@ -212,99 +212,100 @@ module.exports = (crowi: Crowi): Router => {
    *             schema:
    *               $ref: '#/components/schemas/ActivityResponse'
    */
-  // eslint-disable-next-line max-len
-  router.get('/', accessTokenParser([SCOPE.READ.ADMIN.AUDIT_LOG], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, validator.list, apiV3FormValidator, async(req: Request, res: ApiV3Response) => {
-    const auditLogEnabled = configManager.getConfig('app:auditLogEnabled');
-    if (!auditLogEnabled) {
-      const msg = 'AuditLog is not enabled';
-      logger.error(msg);
-      return res.apiv3Err(msg, 405);
-    }
+  router.get('/',
+    accessTokenParser([SCOPE.READ.ADMIN.AUDIT_LOG], { acceptLegacy: true }),
+    loginRequiredStrictly, adminRequired, validator.list, apiV3FormValidator, async(req: Request, res: ApiV3Response) => {
+      const auditLogEnabled = configManager.getConfig('app:auditLogEnabled');
+      if (!auditLogEnabled) {
+        const msg = 'AuditLog is not enabled';
+        logger.error(msg);
+        return res.apiv3Err(msg, 405);
+      }
 
-    const limit = req.query.limit || configManager.getConfig('customize:showPageLimitationS');
-    const offset = req.query.offset || 1;
+      const limit = req.query.limit || configManager.getConfig('customize:showPageLimitationS');
+      const offset = req.query.offset || 1;
 
-    const query = {};
+      const query = {};
 
-    try {
-      const parsedSearchFilter = JSON.parse(req.query.searchFilter as string) as ISearchFilter;
+      try {
+        const parsedSearchFilter = JSON.parse(req.query.searchFilter as string) as ISearchFilter;
 
-      // add username to query
-      const canContainUsernameFilterToQuery = (
-        parsedSearchFilter.usernames != null
+        // add username to query
+        const canContainUsernameFilterToQuery = (
+          parsedSearchFilter.usernames != null
         && parsedSearchFilter.usernames.length > 0
         && parsedSearchFilter.usernames.every(u => typeof u === 'string')
-      );
-      if (canContainUsernameFilterToQuery) {
-        Object.assign(query, { 'snapshot.username': parsedSearchFilter.usernames });
-      }
+        );
+        if (canContainUsernameFilterToQuery) {
+          Object.assign(query, { 'snapshot.username': parsedSearchFilter.usernames });
+        }
 
-      // add action to query
-      if (parsedSearchFilter.actions != null) {
-        const availableActions = crowi.activityService.getAvailableActions(false);
-        const searchableActions = parsedSearchFilter.actions.filter(action => availableActions.includes(action));
-        Object.assign(query, { action: searchableActions });
-      }
+        // add action to query
+        if (parsedSearchFilter.actions != null) {
+          const availableActions = crowi.activityService.getAvailableActions(false);
+          const searchableActions = parsedSearchFilter.actions.filter(action => availableActions.includes(action));
+          Object.assign(query, { action: searchableActions });
+        }
 
-      // add date to query
-      const startDate = parseISO(parsedSearchFilter?.dates?.startDate || '');
-      const endDate = parseISO(parsedSearchFilter?.dates?.endDate || '');
-      if (isValid(startDate) && isValid(endDate)) {
-        Object.assign(query, {
-          createdAt: {
-            $gte: startDate,
-            // + 23 hours 59 minutes
-            $lt: addMinutes(endDate, 1439),
-          },
-        });
+        // add date to query
+        const startDate = parseISO(parsedSearchFilter?.dates?.startDate || '');
+        const endDate = parseISO(parsedSearchFilter?.dates?.endDate || '');
+        if (isValid(startDate) && isValid(endDate)) {
+          Object.assign(query, {
+            createdAt: {
+              $gte: startDate,
+              // + 23 hours 59 minutes
+              $lt: addMinutes(endDate, 1439),
+            },
+          });
+        }
+        else if (isValid(startDate) && !isValid(endDate)) {
+          Object.assign(query, {
+            createdAt: {
+              $gte: startDate,
+              // + 23 hours 59 minutes
+              $lt: addMinutes(startDate, 1439),
+            },
+          });
+        }
       }
-      else if (isValid(startDate) && !isValid(endDate)) {
-        Object.assign(query, {
-          createdAt: {
-            $gte: startDate,
-            // + 23 hours 59 minutes
-            $lt: addMinutes(startDate, 1439),
-          },
-        });
+      catch (err) {
+        logger.error('Invalid value', err);
+        return res.apiv3Err(err, 400);
       }
-    }
-    catch (err) {
-      logger.error('Invalid value', err);
-      return res.apiv3Err(err, 400);
-    }
 
-    try {
-      const paginateResult = await Activity.paginate(
-        query,
-        {
-          lean: true,
-          limit,
-          offset,
-          sort: { createdAt: -1 },
-          populate: 'user',
-        },
-      );
+      try {
+        const paginateResult = await Activity.paginate(
+          query,
+          {
+            lean: true,
+            limit,
+            offset,
+            sort: { createdAt: -1 },
+            populate: 'user',
+          },
+        );
 
-      const serializedDocs = paginateResult.docs.map((doc: IActivity) => {
-        const { user, ...rest } = doc;
-        return {
-          user: serializeUserSecurely(user),
-          ...rest,
-        };
-      });
+        const serializedDocs = paginateResult.docs.map((doc: IActivity) => {
+          const { user, ...rest } = doc;
+          return {
+            user: serializeUserSecurely(user),
+            ...rest,
+          };
+        });
 
-      const serializedPaginationResult = {
-        ...paginateResult,
-        docs: serializedDocs,
-      };
+        const serializedPaginationResult = {
+          ...paginateResult,
+          docs: serializedDocs,
+        };
 
-      return res.apiv3({ serializedPaginationResult });
-    }
-    catch (err) {
-      logger.error('Failed to get paginated activity', err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+        return res.apiv3({ serializedPaginationResult });
+      }
+      catch (err) {
+        logger.error('Failed to get paginated activity', err);
+        return res.apiv3Err(err, 500);
+      }
+    });
 
   return router;
 };

+ 136 - 133
apps/app/src/server/routes/apiv3/app-settings.js

@@ -899,87 +899,88 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/FileUploadSettingParams'
    */
-  //  eslint-disable-next-line max-len
-  router.put('/file-upload-setting', accessTokenParser([SCOPE.WRITE.ADMIN.APP]), loginRequiredStrictly, adminRequired, addActivity, validator.fileUploadSetting, apiV3FormValidator, async(req, res) => {
-    const { fileUploadType } = req.body;
+  router.put('/file-upload-setting',
+    accessTokenParser([SCOPE.WRITE.ADMIN.APP]), loginRequiredStrictly, adminRequired,
+    addActivity, validator.fileUploadSetting, apiV3FormValidator, async(req, res) => {
+      const { fileUploadType } = req.body;
 
-    const requestParams = {
-      'app:fileUploadType': fileUploadType,
-    };
+      const requestParams = {
+        'app:fileUploadType': fileUploadType,
+      };
 
-    if (fileUploadType === 'gcs') {
-      requestParams['gcs:apiKeyJsonPath'] = req.body.gcsApiKeyJsonPath;
-      requestParams['gcs:bucket'] = req.body.gcsBucket;
-      requestParams['gcs:uploadNamespace'] = req.body.gcsUploadNamespace;
-      requestParams['gcs:referenceFileWithRelayMode'] = req.body.gcsReferenceFileWithRelayMode;
-    }
+      if (fileUploadType === 'gcs') {
+        requestParams['gcs:apiKeyJsonPath'] = req.body.gcsApiKeyJsonPath;
+        requestParams['gcs:bucket'] = req.body.gcsBucket;
+        requestParams['gcs:uploadNamespace'] = req.body.gcsUploadNamespace;
+        requestParams['gcs:referenceFileWithRelayMode'] = req.body.gcsReferenceFileWithRelayMode;
+      }
 
-    if (fileUploadType === 'aws') {
-      requestParams['aws:s3Region'] = req.body.s3Region;
-      requestParams['aws:s3CustomEndpoint'] = req.body.s3CustomEndpoint;
-      requestParams['aws:s3Bucket'] = req.body.s3Bucket;
-      requestParams['aws:s3AccessKeyId'] = req.body.s3AccessKeyId;
-      requestParams['aws:referenceFileWithRelayMode'] = req.body.s3ReferenceFileWithRelayMode;
-    }
+      if (fileUploadType === 'aws') {
+        requestParams['aws:s3Region'] = req.body.s3Region;
+        requestParams['aws:s3CustomEndpoint'] = req.body.s3CustomEndpoint;
+        requestParams['aws:s3Bucket'] = req.body.s3Bucket;
+        requestParams['aws:s3AccessKeyId'] = req.body.s3AccessKeyId;
+        requestParams['aws:referenceFileWithRelayMode'] = req.body.s3ReferenceFileWithRelayMode;
+      }
 
-    if (fileUploadType === 'azure') {
-      requestParams['azure:tenantId'] = req.body.azureTenantId;
-      requestParams['azure:clientId'] = req.body.azureClientId;
-      requestParams['azure:clientSecret'] = req.body.azureClientSecret;
-      requestParams['azure:storageAccountName'] = req.body.azureStorageAccountName;
-      requestParams['azure:storageContainerName'] = req.body.azureStorageContainerName;
-      requestParams['azure:referenceFileWithRelayMode'] = req.body.azureReferenceFileWithRelayMode;
-    }
+      if (fileUploadType === 'azure') {
+        requestParams['azure:tenantId'] = req.body.azureTenantId;
+        requestParams['azure:clientId'] = req.body.azureClientId;
+        requestParams['azure:clientSecret'] = req.body.azureClientSecret;
+        requestParams['azure:storageAccountName'] = req.body.azureStorageAccountName;
+        requestParams['azure:storageContainerName'] = req.body.azureStorageContainerName;
+        requestParams['azure:referenceFileWithRelayMode'] = req.body.azureReferenceFileWithRelayMode;
+      }
 
-    try {
-      await configManager.updateConfigs(requestParams, { skipPubsub: true });
+      try {
+        await configManager.updateConfigs(requestParams, { skipPubsub: true });
 
-      const s3SecretAccessKey = req.body.s3SecretAccessKey;
-      if (fileUploadType === 'aws' && s3SecretAccessKey != null && s3SecretAccessKey.trim() !== '') {
-        await configManager.updateConfigs({ 'aws:s3SecretAccessKey': s3SecretAccessKey }, { skipPubsub: true });
-      }
+        const s3SecretAccessKey = req.body.s3SecretAccessKey;
+        if (fileUploadType === 'aws' && s3SecretAccessKey != null && s3SecretAccessKey.trim() !== '') {
+          await configManager.updateConfigs({ 'aws:s3SecretAccessKey': s3SecretAccessKey }, { skipPubsub: true });
+        }
 
-      await crowi.setUpFileUpload(true);
-      crowi.fileUploaderSwitchService.publishUpdatedMessage();
+        await crowi.setUpFileUpload(true);
+        crowi.fileUploaderSwitchService.publishUpdatedMessage();
 
-      const responseParams = {
-        fileUploadType: configManager.getConfig('app:fileUploadType'),
-      };
+        const responseParams = {
+          fileUploadType: configManager.getConfig('app:fileUploadType'),
+        };
 
-      if (fileUploadType === 'gcs') {
-        responseParams.gcsApiKeyJsonPath = configManager.getConfig('gcs:apiKeyJsonPath');
-        responseParams.gcsBucket = configManager.getConfig('gcs:bucket');
-        responseParams.gcsUploadNamespace = configManager.getConfig('gcs:uploadNamespace');
-        responseParams.gcsReferenceFileWithRelayMode = configManager.getConfig('gcs:referenceFileWithRelayMode ');
-      }
+        if (fileUploadType === 'gcs') {
+          responseParams.gcsApiKeyJsonPath = configManager.getConfig('gcs:apiKeyJsonPath');
+          responseParams.gcsBucket = configManager.getConfig('gcs:bucket');
+          responseParams.gcsUploadNamespace = configManager.getConfig('gcs:uploadNamespace');
+          responseParams.gcsReferenceFileWithRelayMode = configManager.getConfig('gcs:referenceFileWithRelayMode ');
+        }
 
-      if (fileUploadType === 'aws') {
-        responseParams.s3Region = configManager.getConfig('aws:s3Region');
-        responseParams.s3CustomEndpoint = configManager.getConfig('aws:s3CustomEndpoint');
-        responseParams.s3Bucket = configManager.getConfig('aws:s3Bucket');
-        responseParams.s3AccessKeyId = configManager.getConfig('aws:s3AccessKeyId');
-        responseParams.s3ReferenceFileWithRelayMode = configManager.getConfig('aws:referenceFileWithRelayMode');
-      }
+        if (fileUploadType === 'aws') {
+          responseParams.s3Region = configManager.getConfig('aws:s3Region');
+          responseParams.s3CustomEndpoint = configManager.getConfig('aws:s3CustomEndpoint');
+          responseParams.s3Bucket = configManager.getConfig('aws:s3Bucket');
+          responseParams.s3AccessKeyId = configManager.getConfig('aws:s3AccessKeyId');
+          responseParams.s3ReferenceFileWithRelayMode = configManager.getConfig('aws:referenceFileWithRelayMode');
+        }
 
-      if (fileUploadType === 'azure') {
-        responseParams.azureTenantId = configManager.getConfig('azure:tenantId');
-        responseParams.azureClientId = configManager.getConfig('azure:clientId');
-        responseParams.azureClientSecret = configManager.getConfig('azure:clientSecret');
-        responseParams.azureStorageAccountName = configManager.getConfig('azure:storageAccountName');
-        responseParams.azureStorageContainerName = configManager.getConfig('azure:storageContainerName');
-        responseParams.azureReferenceFileWithRelayMode = configManager.getConfig('azure:referenceFileWithRelayMode');
+        if (fileUploadType === 'azure') {
+          responseParams.azureTenantId = configManager.getConfig('azure:tenantId');
+          responseParams.azureClientId = configManager.getConfig('azure:clientId');
+          responseParams.azureClientSecret = configManager.getConfig('azure:clientSecret');
+          responseParams.azureStorageAccountName = configManager.getConfig('azure:storageAccountName');
+          responseParams.azureStorageContainerName = configManager.getConfig('azure:storageContainerName');
+          responseParams.azureReferenceFileWithRelayMode = configManager.getConfig('azure:referenceFileWithRelayMode');
+        }
+        const parameters = { action: SupportedAction.ACTION_ADMIN_FILE_UPLOAD_CONFIG_UPDATE };
+        activityEvent.emit('update', res.locals.activity._id, parameters);
+        return res.apiv3({ responseParams });
+      }
+      catch (err) {
+        const msg = 'Error occurred in updating fileUploadType';
+        logger.error('Error', err);
+        return res.apiv3Err(new ErrorV3(msg, 'update-fileUploadType-failed'));
       }
-      const parameters = { action: SupportedAction.ACTION_ADMIN_FILE_UPLOAD_CONFIG_UPDATE };
-      activityEvent.emit('update', res.locals.activity._id, parameters);
-      return res.apiv3({ responseParams });
-    }
-    catch (err) {
-      const msg = 'Error occurred in updating fileUploadType';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-fileUploadType-failed'));
-    }
 
-  });
+    });
 
   /**
    * @swagger
@@ -1010,34 +1011,35 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/QuestionnaireSettingParams'
    */
-  // eslint-disable-next-line max-len
-  router.put('/questionnaire-settings', accessTokenParser([SCOPE.WRITE.ADMIN.APP]), loginRequiredStrictly, adminRequired, addActivity, validator.questionnaireSettings, apiV3FormValidator, async(req, res) => {
-    const { isQuestionnaireEnabled, isAppSiteUrlHashed } = req.body;
+  router.put('/questionnaire-settings',
+    accessTokenParser([SCOPE.WRITE.ADMIN.APP]), loginRequiredStrictly, adminRequired, addActivity,
+    validator.questionnaireSettings, apiV3FormValidator, async(req, res) => {
+      const { isQuestionnaireEnabled, isAppSiteUrlHashed } = req.body;
 
-    const requestParams = {
-      'questionnaire:isQuestionnaireEnabled': isQuestionnaireEnabled,
-      'questionnaire:isAppSiteUrlHashed': isAppSiteUrlHashed,
-    };
+      const requestParams = {
+        'questionnaire:isQuestionnaireEnabled': isQuestionnaireEnabled,
+        'questionnaire:isAppSiteUrlHashed': isAppSiteUrlHashed,
+      };
 
-    try {
-      await configManager.updateConfigs(requestParams, { skipPubsub: true });
+      try {
+        await configManager.updateConfigs(requestParams, { skipPubsub: true });
 
-      const responseParams = {
-        isQuestionnaireEnabled: configManager.getConfig('questionnaire:isQuestionnaireEnabled'),
-        isAppSiteUrlHashed: configManager.getConfig('questionnaire:isAppSiteUrlHashed'),
-      };
+        const responseParams = {
+          isQuestionnaireEnabled: configManager.getConfig('questionnaire:isQuestionnaireEnabled'),
+          isAppSiteUrlHashed: configManager.getConfig('questionnaire:isAppSiteUrlHashed'),
+        };
 
-      const parameters = { action: SupportedAction.ACTION_ADMIN_QUESTIONNAIRE_SETTINGS_UPDATE };
-      activityEvent.emit('update', res.locals.activity._id, parameters);
-      return res.apiv3({ responseParams });
-    }
-    catch (err) {
-      const msg = 'Error occurred in updating questionnaire settings';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'update-questionnaire-settings-failed'));
-    }
+        const parameters = { action: SupportedAction.ACTION_ADMIN_QUESTIONNAIRE_SETTINGS_UPDATE };
+        activityEvent.emit('update', res.locals.activity._id, parameters);
+        return res.apiv3({ responseParams });
+      }
+      catch (err) {
+        const msg = 'Error occurred in updating questionnaire settings';
+        logger.error('Error', err);
+        return res.apiv3Err(new ErrorV3(msg, 'update-questionnaire-settings-failed'));
+      }
 
-  });
+    });
 
   router.put('/page-bulk-export-settings',
     accessTokenParser([SCOPE.WRITE.ADMIN.APP]), loginRequiredStrictly, adminRequired, addActivity, validator.pageBulkExportSettings, apiV3FormValidator,
@@ -1092,27 +1094,27 @@ module.exports = (crowi) => {
    *                      description: is V5 compatible, or not
    *                      example: true
    */
-  // eslint-disable-next-line max-len
-  router.post('/v5-schema-migration', accessTokenParser([SCOPE.WRITE.ADMIN.APP], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, async(req, res) => {
-    const isMaintenanceMode = crowi.appService.isMaintenanceMode();
-    if (!isMaintenanceMode) {
-      return res.apiv3Err(new ErrorV3('GROWI is not maintenance mode. To import data, please activate the maintenance mode first.', 'not_maintenance_mode'));
-    }
+  router.post('/v5-schema-migration',
+    accessTokenParser([SCOPE.WRITE.ADMIN.APP], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, async(req, res) => {
+      const isMaintenanceMode = crowi.appService.isMaintenanceMode();
+      if (!isMaintenanceMode) {
+        return res.apiv3Err(new ErrorV3('GROWI is not maintenance mode. To import data, please activate the maintenance mode first.', 'not_maintenance_mode'));
+      }
 
-    const isV5Compatible = configManager.getConfig('app:isV5Compatible');
+      const isV5Compatible = configManager.getConfig('app:isV5Compatible');
 
-    try {
-      if (!isV5Compatible) {
+      try {
+        if (!isV5Compatible) {
         // This method throws and emit socketIo event when error occurs
-        crowi.pageService.normalizeAllPublicPages();
+          crowi.pageService.normalizeAllPublicPages();
+        }
+      }
+      catch (err) {
+        return res.apiv3Err(new ErrorV3(`Failed to migrate pages: ${err.message}`), 500);
       }
-    }
-    catch (err) {
-      return res.apiv3Err(new ErrorV3(`Failed to migrate pages: ${err.message}`), 500);
-    }
 
-    return res.apiv3({ isV5Compatible });
-  });
+      return res.apiv3({ isV5Compatible });
+    });
 
   /**
    * @swagger
@@ -1148,36 +1150,37 @@ module.exports = (crowi) => {
    *                      description: true if maintenance mode is enabled
    *                      example: true
    */
-  // eslint-disable-next-line max-len
-  router.post('/maintenance-mode', accessTokenParser([SCOPE.WRITE.ADMIN.APP], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, addActivity, validator.maintenanceMode, apiV3FormValidator, async(req, res) => {
-    const { flag } = req.body;
-    const parameters = {};
-    try {
-      if (flag) {
-        await crowi.appService.startMaintenanceMode();
-        Object.assign(parameters, { action: SupportedAction.ACTION_ADMIN_MAINTENANCEMODE_ENABLED });
-      }
-      else {
-        await crowi.appService.endMaintenanceMode();
-        Object.assign(parameters, { action: SupportedAction.ACTION_ADMIN_MAINTENANCEMODE_DISABLED });
-      }
-    }
-    catch (err) {
-      logger.error(err);
-      if (flag) {
-        res.apiv3Err(new ErrorV3('Failed to start maintenance mode', 'failed_to_start_maintenance_mode'), 500);
+  router.post('/maintenance-mode',
+    accessTokenParser([SCOPE.WRITE.ADMIN.APP], { acceptLegacy: true }),
+    loginRequiredStrictly, adminRequired, addActivity, validator.maintenanceMode, apiV3FormValidator, async(req, res) => {
+      const { flag } = req.body;
+      const parameters = {};
+      try {
+        if (flag) {
+          await crowi.appService.startMaintenanceMode();
+          Object.assign(parameters, { action: SupportedAction.ACTION_ADMIN_MAINTENANCEMODE_ENABLED });
+        }
+        else {
+          await crowi.appService.endMaintenanceMode();
+          Object.assign(parameters, { action: SupportedAction.ACTION_ADMIN_MAINTENANCEMODE_DISABLED });
+        }
       }
-      else {
-        res.apiv3Err(new ErrorV3('Failed to end maintenance mode', 'failed_to_end_maintenance_mode'), 500);
+      catch (err) {
+        logger.error(err);
+        if (flag) {
+          res.apiv3Err(new ErrorV3('Failed to start maintenance mode', 'failed_to_start_maintenance_mode'), 500);
+        }
+        else {
+          res.apiv3Err(new ErrorV3('Failed to end maintenance mode', 'failed_to_end_maintenance_mode'), 500);
+        }
       }
-    }
 
-    if ('action' in parameters) {
-      activityEvent.emit('update', res.locals.activity._id, parameters);
-    }
+      if ('action' in parameters) {
+        activityEvent.emit('update', res.locals.activity._id, parameters);
+      }
 
-    res.apiv3({ flag });
-  });
+      res.apiv3({ flag });
+    });
 
   return router;
 };

+ 4 - 4
apps/app/src/server/routes/apiv3/attachment.js

@@ -199,8 +199,8 @@ module.exports = (crowi) => {
    *                  type: object
    *                  $ref: '#/components/schemas/AttachmentPaginateResult'
    */
-  // eslint-disable-next-line max-len
-  router.get('/list', accessTokenParser([SCOPE.READ.FEATURES.ATTACHMENT], { acceptLegacy: true }), loginRequired, validator.retrieveAttachments, apiV3FormValidator,
+  router.get('/list',
+    accessTokenParser([SCOPE.READ.FEATURES.ATTACHMENT], { acceptLegacy: true }), loginRequired, validator.retrieveAttachments, apiV3FormValidator,
     async(req, res) => {
 
       const limit = req.query.limit || await crowi.configManager.getConfig('customize:showPageLimitationS') || 10;
@@ -275,8 +275,8 @@ module.exports = (crowi) => {
    *          500:
    *            $ref: '#/components/responses/500'
    */
-  // eslint-disable-next-line max-len
-  router.get('/limit', accessTokenParser([SCOPE.READ.FEATURES.ATTACHMENT], { acceptLegacy: true }), loginRequiredStrictly, validator.retrieveFileLimit, apiV3FormValidator,
+  router.get('/limit',
+    accessTokenParser([SCOPE.READ.FEATURES.ATTACHMENT], { acceptLegacy: true }), loginRequiredStrictly, validator.retrieveFileLimit, apiV3FormValidator,
     async(req, res) => {
       const { fileUploadService } = crowi;
       const fileSize = Number(req.query.fileSize);

+ 49 - 46
apps/app/src/server/routes/apiv3/bookmark-folder.ts

@@ -1,4 +1,3 @@
-/* eslint-disable max-len */
 import { ErrorV3 } from '@growi/core/dist/models';
 import { body } from 'express-validator';
 import type { Types } from 'mongoose';
@@ -159,27 +158,28 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/BookmarkFolder'
    */
-  // eslint-disable-next-line max-len
-  router.post('/', accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmarkFolder, apiV3FormValidator, async(req, res) => {
-    const owner = req.user?._id;
-    const { name, parent } = req.body;
-    const params = {
-      name, owner, parent,
-    };
+  router.post('/',
+    accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }),
+    loginRequiredStrictly, validator.bookmarkFolder, apiV3FormValidator, async(req, res) => {
+      const owner = req.user?._id;
+      const { name, parent } = req.body;
+      const params = {
+        name, owner, parent,
+      };
 
-    try {
-      const bookmarkFolder = await BookmarkFolder.createByParameters(params);
-      logger.debug('bookmark folder created', bookmarkFolder);
-      return res.apiv3({ bookmarkFolder });
-    }
-    catch (err) {
-      logger.error(err);
-      if (err instanceof InvalidParentBookmarkFolderError) {
-        return res.apiv3Err(new ErrorV3(err.message, 'failed_to_create_bookmark_folder'));
+      try {
+        const bookmarkFolder = await BookmarkFolder.createByParameters(params);
+        logger.debug('bookmark folder created', bookmarkFolder);
+        return res.apiv3({ bookmarkFolder });
       }
-      return res.apiv3Err(err, 500);
-    }
-  });
+      catch (err) {
+        logger.error(err);
+        if (err instanceof InvalidParentBookmarkFolderError) {
+          return res.apiv3Err(new ErrorV3(err.message, 'failed_to_create_bookmark_folder'));
+        }
+        return res.apiv3Err(err, 500);
+      }
+    });
 
   /**
    * @swagger
@@ -359,19 +359,20 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/BookmarkFolder'
    */
-  router.put('/', accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmarkFolder, async(req, res) => {
-    const {
-      bookmarkFolderId, name, parent, childFolder,
-    } = req.body;
-    try {
-      const bookmarkFolder = await BookmarkFolder.updateBookmarkFolder(bookmarkFolderId, name, parent, childFolder);
-      return res.apiv3({ bookmarkFolder });
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+  router.put('/',
+    accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmarkFolder, async(req, res) => {
+      const {
+        bookmarkFolderId, name, parent, childFolder,
+      } = req.body;
+      try {
+        const bookmarkFolder = await BookmarkFolder.updateBookmarkFolder(bookmarkFolderId, name, parent, childFolder);
+        return res.apiv3({ bookmarkFolder });
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(err, 500);
+      }
+    });
 
   /**
    * @swagger
@@ -409,7 +410,8 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/BookmarkFolder'
    */
-  router.post('/add-bookmark-to-folder', accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmarkPage, apiV3FormValidator,
+  router.post('/add-bookmark-to-folder',
+    accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmarkPage, apiV3FormValidator,
     async(req, res) => {
       const userId = req.user?._id;
       const { pageId, folderId } = req.body;
@@ -460,17 +462,18 @@ module.exports = (crowi) => {
    *                      type: object
    *                      $ref: '#/components/schemas/BookmarkFolder'
    */
-  router.put('/update-bookmark', accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmark, async(req, res) => {
-    const { pageId, status } = req.body;
-    const userId = req.user?._id;
-    try {
-      const bookmarkFolder = await BookmarkFolder.updateBookmark(pageId, status, userId);
-      return res.apiv3({ bookmarkFolder });
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+  router.put('/update-bookmark',
+    accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, validator.bookmark, async(req, res) => {
+      const { pageId, status } = req.body;
+      const userId = req.user?._id;
+      try {
+        const bookmarkFolder = await BookmarkFolder.updateBookmark(pageId, status, userId);
+        return res.apiv3({ bookmarkFolder });
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(err, 500);
+      }
+    });
   return router;
 };

+ 71 - 70
apps/app/src/server/routes/apiv3/bookmarks.js

@@ -126,44 +126,44 @@ module.exports = (crowi) => {
    *                schema:
    *                  $ref: '#/components/schemas/BookmarkInfo'
    */
-  // eslint-disable-next-line max-len
-  router.get('/info', accessTokenParser([SCOPE.READ.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequired, validator.bookmarkInfo, apiV3FormValidator, async(req, res) => {
-    const { user } = req;
-    const { pageId } = req.query;
-
-    const responsesParams = {};
-
-    try {
-      const bookmarks = await Bookmark.find({ page: pageId }).populate('user');
-      let users = [];
-      if (bookmarks.length > 0) {
-        users = bookmarks.map(bookmark => serializeUserSecurely(bookmark.user));
+  router.get('/info',
+    accessTokenParser([SCOPE.READ.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequired, validator.bookmarkInfo, apiV3FormValidator, async(req, res) => {
+      const { user } = req;
+      const { pageId } = req.query;
+
+      const responsesParams = {};
+
+      try {
+        const bookmarks = await Bookmark.find({ page: pageId }).populate('user');
+        let users = [];
+        if (bookmarks.length > 0) {
+          users = bookmarks.map(bookmark => serializeUserSecurely(bookmark.user));
+        }
+        responsesParams.sumOfBookmarks = bookmarks.length;
+        responsesParams.bookmarkedUsers = users;
+        responsesParams.pageId = pageId;
+      }
+      catch (err) {
+        logger.error('get-bookmark-document-failed', err);
+        return res.apiv3Err(err, 500);
+      }
+
+      // guest user only get bookmark count
+      if (user == null) {
+        return res.apiv3(responsesParams);
+      }
+
+      try {
+        const bookmark = await Bookmark.findByPageIdAndUserId(pageId, user._id);
+        responsesParams.isBookmarked = (bookmark != null);
+        return res.apiv3(responsesParams);
+      }
+      catch (err) {
+        logger.error('get-bookmark-state-failed', err);
+        return res.apiv3Err(err, 500);
       }
-      responsesParams.sumOfBookmarks = bookmarks.length;
-      responsesParams.bookmarkedUsers = users;
-      responsesParams.pageId = pageId;
-    }
-    catch (err) {
-      logger.error('get-bookmark-document-failed', err);
-      return res.apiv3Err(err, 500);
-    }
-
-    // guest user only get bookmark count
-    if (user == null) {
-      return res.apiv3(responsesParams);
-    }
-
-    try {
-      const bookmark = await Bookmark.findByPageIdAndUserId(pageId, user._id);
-      responsesParams.isBookmarked = (bookmark != null);
-      return res.apiv3(responsesParams);
-    }
-    catch (err) {
-      logger.error('get-bookmark-state-failed', err);
-      return res.apiv3Err(err, 500);
-    }
-
-  });
+
+    });
 
   // select page from bookmark where userid = userid
   /**
@@ -194,37 +194,38 @@ module.exports = (crowi) => {
     param('userId').isMongoId().withMessage('userId is required'),
   ];
 
-  // eslint-disable-next-line max-len
-  router.get('/:userId', accessTokenParser([SCOPE.READ.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequired, validator.userBookmarkList, apiV3FormValidator, async(req, res) => {
-    const { userId } = req.params;
-
-    if (userId == null) {
-      return res.apiv3Err('User id is not found or forbidden', 400);
-    }
-    try {
-      const bookmarkIdsInFolders = await BookmarkFolder.distinct('bookmarks', { owner: userId });
-      const userRootBookmarks = await Bookmark.find({
-        _id: { $nin: bookmarkIdsInFolders },
-        user: userId,
-      }).populate({
-        path: 'page',
-        model: 'Page',
-        populate: {
-          path: 'lastUpdateUser',
-          model: 'User',
-        },
-      }).exec();
-
-      // serialize Bookmark
-      const serializedUserRootBookmarks = userRootBookmarks.map(bookmark => serializeBookmarkSecurely(bookmark));
-
-      return res.apiv3({ userRootBookmarks: serializedUserRootBookmarks });
-    }
-    catch (err) {
-      logger.error('get-bookmark-failed', err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+  router.get('/:userId',
+    accessTokenParser([SCOPE.READ.FEATURES.BOOKMARK], { acceptLegacy: true }),
+    loginRequired, validator.userBookmarkList, apiV3FormValidator, async(req, res) => {
+      const { userId } = req.params;
+
+      if (userId == null) {
+        return res.apiv3Err('User id is not found or forbidden', 400);
+      }
+      try {
+        const bookmarkIdsInFolders = await BookmarkFolder.distinct('bookmarks', { owner: userId });
+        const userRootBookmarks = await Bookmark.find({
+          _id: { $nin: bookmarkIdsInFolders },
+          user: userId,
+        }).populate({
+          path: 'page',
+          model: 'Page',
+          populate: {
+            path: 'lastUpdateUser',
+            model: 'User',
+          },
+        }).exec();
+
+        // serialize Bookmark
+        const serializedUserRootBookmarks = userRootBookmarks.map(bookmark => serializeBookmarkSecurely(bookmark));
+
+        return res.apiv3({ userRootBookmarks: serializedUserRootBookmarks });
+      }
+      catch (err) {
+        logger.error('get-bookmark-failed', err);
+        return res.apiv3Err(err, 500);
+      }
+    });
 
 
   /**
@@ -252,8 +253,8 @@ module.exports = (crowi) => {
    *                    bookmark:
    *                      $ref: '#/components/schemas/Bookmark'
    */
-  // eslint-disable-next-line max-len
-  router.put('/', accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.bookmarks, apiV3FormValidator,
+  router.put('/',
+    accessTokenParser([SCOPE.WRITE.FEATURES.BOOKMARK], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.bookmarks, apiV3FormValidator,
     async(req, res) => {
       const { pageId, bool } = req.body;
       const userId = req.user?._id;

+ 56 - 56
apps/app/src/server/routes/apiv3/g2g-transfer.ts

@@ -198,7 +198,6 @@ module.exports = (crowi: Crowi): Router => {
    *                          type: number
    *                          description: The size of the file
    */
-  // eslint-disable-next-line max-len
   receiveRouter.get('/files', validateTransferKey, async(req: Request, res: ApiV3Response) => {
     const files = await crowi.fileUploadService.listFiles();
     return res.apiv3({ files });
@@ -249,7 +248,6 @@ module.exports = (crowi: Crowi): Router => {
    *                    type: string
    *                    description: The message of the result
    */
-  // eslint-disable-next-line max-len
   receiveRouter.post('/', validateTransferKey, uploads.single('transferDataZipFile'), async(req: Request & { file: any; }, res: ApiV3Response) => {
     const { file } = req;
     const {
@@ -466,31 +464,32 @@ module.exports = (crowi: Crowi): Router => {
    *                    type: string
    *                    description: The transfer key
    */
-  // eslint-disable-next-line max-len
-  receiveRouter.post('/generate-key', accessTokenParser([SCOPE.WRITE.ADMIN.EXPORET_DATA], { acceptLegacy: true }), adminRequiredIfInstalled, appSiteUrlRequiredIfNotInstalled, async(req: Request, res: ApiV3Response) => {
-    const appSiteUrl = req.body.appSiteUrl ?? configManager.getConfig('app:siteUrl');
+  receiveRouter.post('/generate-key',
+    accessTokenParser([SCOPE.WRITE.ADMIN.EXPORET_DATA], { acceptLegacy: true }),
+    adminRequiredIfInstalled, appSiteUrlRequiredIfNotInstalled, async(req: Request, res: ApiV3Response) => {
+      const appSiteUrl = req.body.appSiteUrl ?? configManager.getConfig('app:siteUrl');
 
-    let appSiteUrlOrigin: string;
-    try {
-      appSiteUrlOrigin = new URL(appSiteUrl).origin;
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(new ErrorV3('appSiteUrl may be wrong', 'failed_to_generate_key_string'));
-    }
+      let appSiteUrlOrigin: string;
+      try {
+        appSiteUrlOrigin = new URL(appSiteUrl).origin;
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(new ErrorV3('appSiteUrl may be wrong', 'failed_to_generate_key_string'));
+      }
 
-    // Save TransferKey document
-    let transferKeyString: string;
-    try {
-      transferKeyString = await g2gTransferReceiverService.createTransferKey(appSiteUrlOrigin);
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(new ErrorV3('Error occurred while generating transfer key.', 'failed_to_generate_key'));
-    }
+      // Save TransferKey document
+      let transferKeyString: string;
+      try {
+        transferKeyString = await g2gTransferReceiverService.createTransferKey(appSiteUrlOrigin);
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(new ErrorV3('Error occurred while generating transfer key.', 'failed_to_generate_key'));
+      }
 
-    return res.apiv3({ transferKey: transferKeyString });
-  });
+      return res.apiv3({ transferKey: transferKeyString });
+    });
 
   /**
    * @swagger
@@ -532,43 +531,44 @@ module.exports = (crowi: Crowi): Router => {
    *                    type: string
    *                    description: The message of the result
    */
-  // eslint-disable-next-line max-len
-  pushRouter.post('/transfer', accessTokenParser([SCOPE.WRITE.ADMIN.EXPORET_DATA], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, validator.transfer, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const { transferKey, collections, optionsMap } = req.body;
+  pushRouter.post('/transfer',
+    accessTokenParser([SCOPE.WRITE.ADMIN.EXPORET_DATA], { acceptLegacy: true }),
+    loginRequiredStrictly, adminRequired, validator.transfer, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const { transferKey, collections, optionsMap } = req.body;
 
-    // Parse transfer key
-    let tk: TransferKey;
-    try {
-      tk = TransferKey.parse(transferKey);
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(new ErrorV3('Transfer key is invalid', 'transfer_key_invalid'), 400);
-    }
+      // Parse transfer key
+      let tk: TransferKey;
+      try {
+        tk = TransferKey.parse(transferKey);
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(new ErrorV3('Transfer key is invalid', 'transfer_key_invalid'), 400);
+      }
 
-    // get growi info
-    let destGROWIInfo: IDataGROWIInfo;
-    try {
-      destGROWIInfo = await g2gTransferPusherService.askGROWIInfo(tk);
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err(new ErrorV3('Error occurred while asking GROWI info.', 'failed_to_ask_growi_info'));
-    }
+      // get growi info
+      let destGROWIInfo: IDataGROWIInfo;
+      try {
+        destGROWIInfo = await g2gTransferPusherService.askGROWIInfo(tk);
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(new ErrorV3('Error occurred while asking GROWI info.', 'failed_to_ask_growi_info'));
+      }
 
-    // Check if can transfer
-    const transferability = await g2gTransferPusherService.getTransferability(destGROWIInfo);
-    if (!transferability.canTransfer) {
-      return res.apiv3Err(new ErrorV3(transferability.reason, 'growi_incompatible_to_transfer'));
-    }
+      // Check if can transfer
+      const transferability = await g2gTransferPusherService.getTransferability(destGROWIInfo);
+      if (!transferability.canTransfer) {
+        return res.apiv3Err(new ErrorV3(transferability.reason, 'growi_incompatible_to_transfer'));
+      }
 
-    // Start transfer
-    // DO NOT "await". Let it run in the background.
-    // Errors should be emitted through websocket.
-    g2gTransferPusherService.startTransfer(tk, req.user, collections, optionsMap, destGROWIInfo);
+      // Start transfer
+      // DO NOT "await". Let it run in the background.
+      // Errors should be emitted through websocket.
+      g2gTransferPusherService.startTransfer(tk, req.user, collections, optionsMap, destGROWIInfo);
 
-    return res.apiv3({ message: 'Successfully requested auto transfer.' });
-  });
+      return res.apiv3({ message: 'Successfully requested auto transfer.' });
+    });
 
   // Merge receiveRouter and pushRouter
   router.use(receiveRouter, pushRouter);

+ 2 - 2
apps/app/src/server/routes/apiv3/import.js

@@ -409,8 +409,8 @@ export default function route(crowi) {
    *              schema:
    *                $ref: '#/components/schemas/FileImportResponse'
    */
-  // eslint-disable-next-line max-len
-  router.post('/upload', accessTokenParser([SCOPE.WRITE.ADMIN.IMPORT_DATA], { acceptLegacy: true }), loginRequired, adminRequired, uploads.single('file'), addActivity,
+  router.post('/upload',
+    accessTokenParser([SCOPE.WRITE.ADMIN.IMPORT_DATA], { acceptLegacy: true }), loginRequired, adminRequired, uploads.single('file'), addActivity,
     async(req, res) => {
       const { file } = req;
       const zipFile = importService.getFile(file.filename);

+ 2 - 2
apps/app/src/server/routes/apiv3/in-app-notification.ts

@@ -293,8 +293,8 @@ module.exports = (crowi) => {
    *        200:
    *          description: All notifications opened successfully
    */
-  // eslint-disable-next-line max-len
-  router.put('/all-statuses-open', accessTokenParser([SCOPE.WRITE.USER_SETTINGS.IN_APP_NOTIFICATION], { acceptLegacy: true }), loginRequiredStrictly, addActivity,
+  router.put('/all-statuses-open',
+    accessTokenParser([SCOPE.WRITE.USER_SETTINGS.IN_APP_NOTIFICATION], { acceptLegacy: true }), loginRequiredStrictly, addActivity,
     async(req: CrowiRequest, res: ApiV3Response) => {
     // user must be set by loginRequiredStrictly
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion

+ 111 - 108
apps/app/src/server/routes/apiv3/page-listing.ts

@@ -89,20 +89,20 @@ const routerFactory = (crowi: Crowi): Router => {
    *                 rootPage:
    *                   $ref: '#/components/schemas/Page'
    */
-  // eslint-disable-next-line max-len
-  router.get('/root', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const Page = mongoose.model<IPage, PageModel>('Page');
+  router.get('/root',
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const Page = mongoose.model<IPage, PageModel>('Page');
 
-    let rootPage;
-    try {
-      rootPage = await Page.findByPathAndViewer('/', req.user, null, true);
-    }
-    catch (err) {
-      return res.apiv3Err(new ErrorV3('rootPage not found'));
-    }
+      let rootPage;
+      try {
+        rootPage = await Page.findByPathAndViewer('/', req.user, null, true);
+      }
+      catch (err) {
+        return res.apiv3Err(new ErrorV3('rootPage not found'));
+      }
 
-    return res.apiv3({ rootPage });
-  });
+      return res.apiv3({ rootPage });
+    });
 
   /**
    * @swagger
@@ -154,21 +154,22 @@ const routerFactory = (crowi: Crowi): Router => {
    *                         nullable: true
    *                         description: Revision ID (nullable)
    */
-  // eslint-disable-next-line max-len
-  router.get('/ancestors-children', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, ...validator.pagePathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response): Promise<any> => {
-    const { path } = req.query;
-
-    const pageService = crowi.pageService;
-    try {
-      const ancestorsChildren = await pageService.findAncestorsChildrenByPathAndViewer(path as string, req.user);
-      return res.apiv3({ ancestorsChildren });
-    }
-    catch (err) {
-      logger.error('Failed to get ancestorsChildren.', err);
-      return res.apiv3Err(new ErrorV3('Failed to get ancestorsChildren.'));
-    }
-
-  });
+  router.get('/ancestors-children',
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    loginRequired, ...validator.pagePathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response): Promise<any> => {
+      const { path } = req.query;
+
+      const pageService = crowi.pageService;
+      try {
+        const ancestorsChildren = await pageService.findAncestorsChildrenByPathAndViewer(path as string, req.user);
+        return res.apiv3({ ancestorsChildren });
+      }
+      catch (err) {
+        logger.error('Failed to get ancestorsChildren.', err);
+        return res.apiv3Err(new ErrorV3('Failed to get ancestorsChildren.'));
+      }
+
+    });
 
   /**
    * @swagger
@@ -206,26 +207,27 @@ const routerFactory = (crowi: Crowi): Router => {
   /*
    * In most cases, using id should be prioritized
    */
-  // eslint-disable-next-line max-len
-  router.get('/children', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.pageIdOrPathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const { id, path } = req.query;
+  router.get('/children',
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    loginRequired, validator.pageIdOrPathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const { id, path } = req.query;
 
-    const pageService = crowi.pageService;
+      const pageService = crowi.pageService;
 
-    const hideRestrictedByOwner = await configManager.getConfig('security:list-policy:hideRestrictedByOwner');
-    const hideRestrictedByGroup = await configManager.getConfig('security:list-policy:hideRestrictedByGroup');
+      const hideRestrictedByOwner = await configManager.getConfig('security:list-policy:hideRestrictedByOwner');
+      const hideRestrictedByGroup = await configManager.getConfig('security:list-policy:hideRestrictedByGroup');
 
-    try {
-      const pages = await pageService.findChildrenByParentPathOrIdAndViewer(
+      try {
+        const pages = await pageService.findChildrenByParentPathOrIdAndViewer(
         (id || path) as string, req.user, undefined, !hideRestrictedByOwner, !hideRestrictedByGroup,
-      );
-      return res.apiv3({ children: pages });
-    }
-    catch (err) {
-      logger.error('Error occurred while finding children.', err);
-      return res.apiv3Err(new ErrorV3('Error occurred while finding children.'));
-    }
-  });
+        );
+        return res.apiv3({ children: pages });
+      }
+      catch (err) {
+        logger.error('Error occurred while finding children.', err);
+        return res.apiv3Err(new ErrorV3('Error occurred while finding children.'));
+      }
+    });
 
   /**
    * @swagger
@@ -301,79 +303,80 @@ const routerFactory = (crowi: Crowi): Router => {
    *                       sumOfSeenUsers:
    *                         type: integer
    */
-  // eslint-disable-next-line max-len
-  router.get('/info', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.pageIdsOrPathRequired, validator.infoParams, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const {
-      pageIds, path, attachBookmarkCount: attachBookmarkCountParam, attachShortBody: attachShortBodyParam,
-    } = req.query;
-
-    const attachBookmarkCount: boolean = attachBookmarkCountParam === 'true';
-    const attachShortBody: boolean = attachShortBodyParam === 'true';
-
-    const Page = mongoose.model<HydratedDocument<PageDocument>, PageModel>('Page');
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    const Bookmark = mongoose.model<any, any>('Bookmark');
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const pageService = crowi.pageService;
-    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-    const pageGrantService: IPageGrantService = crowi.pageGrantService!;
-
-    try {
-      const pages = pageIds != null
-        ? await Page.findByIdsAndViewer(pageIds as string[], req.user, null, true)
-        : await Page.findByPathAndViewer(path as string, req.user, null, false, true);
-
-      const foundIds = pages.map(page => page._id);
-
-      let shortBodiesMap;
-      if (attachShortBody) {
-        shortBodiesMap = await pageService.shortBodiesMapByPageIds(foundIds, req.user);
-      }
+  router.get('/info',
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    loginRequired, validator.pageIdsOrPathRequired, validator.infoParams, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const {
+        pageIds, path, attachBookmarkCount: attachBookmarkCountParam, attachShortBody: attachShortBodyParam,
+      } = req.query;
 
-      let bookmarkCountMap;
-      if (attachBookmarkCount) {
-        bookmarkCountMap = await Bookmark.getPageIdToCountMap(foundIds) as Record<string, number>;
-      }
+      const attachBookmarkCount: boolean = attachBookmarkCountParam === 'true';
+      const attachShortBody: boolean = attachShortBodyParam === 'true';
 
-      const idToPageInfoMap: Record<string, IPageInfo | IPageInfoForListing> = {};
+      const Page = mongoose.model<HydratedDocument<PageDocument>, PageModel>('Page');
+      // eslint-disable-next-line @typescript-eslint/no-explicit-any
+      const Bookmark = mongoose.model<any, any>('Bookmark');
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      const pageService = crowi.pageService;
+      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+      const pageGrantService: IPageGrantService = crowi.pageGrantService!;
 
-      const isGuestUser = req.user == null;
+      try {
+        const pages = pageIds != null
+          ? await Page.findByIdsAndViewer(pageIds as string[], req.user, null, true)
+          : await Page.findByPathAndViewer(path as string, req.user, null, false, true);
 
-      const userRelatedGroups = await pageGrantService.getUserRelatedGroups(req.user);
+        const foundIds = pages.map(page => page._id);
 
-      for (const page of pages) {
+        let shortBodiesMap;
+        if (attachShortBody) {
+          shortBodiesMap = await pageService.shortBodiesMapByPageIds(foundIds, req.user);
+        }
+
+        let bookmarkCountMap;
+        if (attachBookmarkCount) {
+          bookmarkCountMap = await Bookmark.getPageIdToCountMap(foundIds) as Record<string, number>;
+        }
+
+        const idToPageInfoMap: Record<string, IPageInfo | IPageInfoForListing> = {};
+
+        const isGuestUser = req.user == null;
+
+        const userRelatedGroups = await pageGrantService.getUserRelatedGroups(req.user);
+
+        for (const page of pages) {
         // construct isIPageInfoForListing
-        const basicPageInfo = pageService.constructBasicPageInfo(page, isGuestUser);
-
-        // TODO: use pageService.getCreatorIdForCanDelete to get creatorId (https://redmine.weseek.co.jp/issues/140574)
-        const canDeleteCompletely = pageService.canDeleteCompletely(
-          page,
-          page.creator == null ? null : getIdForRef(page.creator),
-          req.user,
-          false,
-          userRelatedGroups,
-        ); // use normal delete config
-
-        const pageInfo = (!isIPageInfoForEntity(basicPageInfo))
-          ? basicPageInfo
+          const basicPageInfo = pageService.constructBasicPageInfo(page, isGuestUser);
+
+          // TODO: use pageService.getCreatorIdForCanDelete to get creatorId (https://redmine.weseek.co.jp/issues/140574)
+          const canDeleteCompletely = pageService.canDeleteCompletely(
+            page,
+            page.creator == null ? null : getIdForRef(page.creator),
+            req.user,
+            false,
+            userRelatedGroups,
+          ); // use normal delete config
+
+          const pageInfo = (!isIPageInfoForEntity(basicPageInfo))
+            ? basicPageInfo
           // create IPageInfoForListing
-          : {
-            ...basicPageInfo,
-            isAbleToDeleteCompletely: canDeleteCompletely,
-            bookmarkCount: bookmarkCountMap != null ? bookmarkCountMap[page._id.toString()] : undefined,
-            revisionShortBody: shortBodiesMap != null ? shortBodiesMap[page._id.toString()] : undefined,
-          } as IPageInfoForListing;
-
-        idToPageInfoMap[page._id.toString()] = pageInfo;
-      }
+            : {
+              ...basicPageInfo,
+              isAbleToDeleteCompletely: canDeleteCompletely,
+              bookmarkCount: bookmarkCountMap != null ? bookmarkCountMap[page._id.toString()] : undefined,
+              revisionShortBody: shortBodiesMap != null ? shortBodiesMap[page._id.toString()] : undefined,
+            } as IPageInfoForListing;
+
+          idToPageInfoMap[page._id.toString()] = pageInfo;
+        }
 
-      return res.apiv3(idToPageInfoMap);
-    }
-    catch (err) {
-      logger.error('Error occurred while fetching page informations.', err);
-      return res.apiv3Err(new ErrorV3('Error occurred while fetching page informations.'));
-    }
-  });
+        return res.apiv3(idToPageInfoMap);
+      }
+      catch (err) {
+        logger.error('Error occurred while fetching page informations.', err);
+        return res.apiv3Err(new ErrorV3('Error occurred while fetching page informations.'));
+      }
+    });
 
   return router;
 };

+ 47 - 46
apps/app/src/server/routes/apiv3/page/index.ts

@@ -213,62 +213,63 @@ module.exports = (crowi) => {
    *                schema:
    *                  $ref: '#/components/schemas/Page'
    */
-  // eslint-disable-next-line max-len
-  router.get('/', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), certifySharedPage, loginRequired, validator.getPage, apiV3FormValidator, async(req, res) => {
-    const { user, isSharedPage } = req;
-    const {
-      pageId, path, findAll, revisionId, shareLinkId, includeEmpty,
-    } = req.query;
+  router.get('/',
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    certifySharedPage, loginRequired, validator.getPage, apiV3FormValidator, async(req, res) => {
+      const { user, isSharedPage } = req;
+      const {
+        pageId, path, findAll, revisionId, shareLinkId, includeEmpty,
+      } = req.query;
 
-    const isValid = (shareLinkId != null && pageId != null && path == null) || (shareLinkId == null && (pageId != null || path != null));
-    if (!isValid) {
-      return res.apiv3Err(new Error('Either parameter of (pageId or path) or (pageId and shareLinkId) is required.'), 400);
-    }
+      const isValid = (shareLinkId != null && pageId != null && path == null) || (shareLinkId == null && (pageId != null || path != null));
+      if (!isValid) {
+        return res.apiv3Err(new Error('Either parameter of (pageId or path) or (pageId and shareLinkId) is required.'), 400);
+      }
 
-    let page;
-    let pages;
-    try {
-      if (isSharedPage) {
-        const shareLink = await ShareLink.findOne({ _id: shareLinkId });
-        if (shareLink == null) {
-          throw new Error('ShareLink is not found');
+      let page;
+      let pages;
+      try {
+        if (isSharedPage) {
+          const shareLink = await ShareLink.findOne({ _id: shareLinkId });
+          if (shareLink == null) {
+            throw new Error('ShareLink is not found');
+          }
+          page = await Page.findOne({ _id: getIdForRef(shareLink.relatedPage) });
+        }
+        else if (pageId != null) { // prioritized
+          page = await Page.findByIdAndViewer(pageId, user);
+        }
+        else if (!findAll) {
+          page = await Page.findByPathAndViewer(path, user, null, true, false);
+        }
+        else {
+          pages = await Page.findByPathAndViewer(path, user, null, false, includeEmpty);
         }
-        page = await Page.findOne({ _id: getIdForRef(shareLink.relatedPage) });
-      }
-      else if (pageId != null) { // prioritized
-        page = await Page.findByIdAndViewer(pageId, user);
-      }
-      else if (!findAll) {
-        page = await Page.findByPathAndViewer(path, user, null, true, false);
       }
-      else {
-        pages = await Page.findByPathAndViewer(path, user, null, false, includeEmpty);
+      catch (err) {
+        logger.error('get-page-failed', err);
+        return res.apiv3Err(err, 500);
       }
-    }
-    catch (err) {
-      logger.error('get-page-failed', err);
-      return res.apiv3Err(err, 500);
-    }
 
-    if (page == null && (pages == null || pages.length === 0)) {
-      return res.apiv3Err('Page is not found', 404);
-    }
+      if (page == null && (pages == null || pages.length === 0)) {
+        return res.apiv3Err('Page is not found', 404);
+      }
 
-    if (page != null) {
-      try {
-        page.initLatestRevisionField(revisionId);
+      if (page != null) {
+        try {
+          page.initLatestRevisionField(revisionId);
 
-        // populate
-        page = await page.populateDataToShowRevision();
-      }
-      catch (err) {
-        logger.error('populate-page-failed', err);
-        return res.apiv3Err(err, 500);
+          // populate
+          page = await page.populateDataToShowRevision();
+        }
+        catch (err) {
+          logger.error('populate-page-failed', err);
+          return res.apiv3Err(err, 500);
+        }
       }
-    }
 
-    return res.apiv3({ page, pages });
-  });
+      return res.apiv3({ page, pages });
+    });
 
   router.get('/page-paths-with-descendant-count', getPagePathsWithDescendantCountFactory(crowi));
 

+ 86 - 88
apps/app/src/server/routes/apiv3/pages/index.js

@@ -157,70 +157,70 @@ module.exports = (crowi) => {
    *          200:
    *            description: Return pages recently updated
    */
-  // eslint-disable-next-line max-len
-  router.get('/recent', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.recent, apiV3FormValidator, async(req, res) => {
-    const limit = parseInt(req.query.limit) || 20;
-    const offset = parseInt(req.query.offset) || 0;
-    const includeWipPage = req.query.includeWipPage === 'true'; // Need validation using express-validator
+  router.get('/recent', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    loginRequired, validator.recent, apiV3FormValidator, async(req, res) => {
+      const limit = parseInt(req.query.limit) || 20;
+      const offset = parseInt(req.query.offset) || 0;
+      const includeWipPage = req.query.includeWipPage === 'true'; // Need validation using express-validator
 
-    const hideRestrictedByOwner = configManager.getConfig('security:list-policy:hideRestrictedByOwner');
-    const hideRestrictedByGroup = configManager.getConfig('security:list-policy:hideRestrictedByGroup');
+      const hideRestrictedByOwner = configManager.getConfig('security:list-policy:hideRestrictedByOwner');
+      const hideRestrictedByGroup = configManager.getConfig('security:list-policy:hideRestrictedByGroup');
 
-    /**
+      /**
     * @type {import('~/server/models/page').FindRecentUpdatedPagesOption}
     */
-    const queryOptions = {
-      offset,
-      limit,
-      includeWipPage,
-      includeTrashed: false,
-      isRegExpEscapedFromPath: true,
-      sort: 'updatedAt',
-      desc: -1,
-      hideRestrictedByOwner,
-      hideRestrictedByGroup,
-    };
-
-    try {
-      const result = await Page.findRecentUpdatedPages('/', req.user, queryOptions);
-      if (result.pages.length > limit) {
-        result.pages.pop();
-      }
+      const queryOptions = {
+        offset,
+        limit,
+        includeWipPage,
+        includeTrashed: false,
+        isRegExpEscapedFromPath: true,
+        sort: 'updatedAt',
+        desc: -1,
+        hideRestrictedByOwner,
+        hideRestrictedByGroup,
+      };
 
-      result.pages.forEach((page) => {
-        if (page.lastUpdateUser != null && page.lastUpdateUser instanceof User) {
-          page.lastUpdateUser = serializeUserSecurely(page.lastUpdateUser);
-        }
-      });
-
-      const ids = result.pages.map((page) => { return page._id });
-      const relations = await PageTagRelation.find({ relatedPage: { $in: ids } }).populate('relatedTag');
-
-      // { pageId: [{ tag }, ...] }
-      const relationsMap = new Map();
-      // increment relationsMap
-      relations.forEach((relation) => {
-        const pageId = relation.relatedPage.toString();
-        if (!relationsMap.has(pageId)) {
-          relationsMap.set(pageId, []);
-        }
-        if (relation.relatedTag != null) {
-          relationsMap.get(pageId).push(relation.relatedTag);
+      try {
+        const result = await Page.findRecentUpdatedPages('/', req.user, queryOptions);
+        if (result.pages.length > limit) {
+          result.pages.pop();
         }
-      });
-      // add tags to each page
-      result.pages.forEach((page) => {
-        const pageId = page._id.toString();
-        page.tags = relationsMap.has(pageId) ? relationsMap.get(pageId) : [];
-      });
 
-      return res.apiv3(result);
-    }
-    catch (err) {
-      logger.error('Failed to get recent pages', err);
-      return res.apiv3Err(new ErrorV3('Failed to get recent pages', 'unknown'), 500);
-    }
-  });
+        result.pages.forEach((page) => {
+          if (page.lastUpdateUser != null && page.lastUpdateUser instanceof User) {
+            page.lastUpdateUser = serializeUserSecurely(page.lastUpdateUser);
+          }
+        });
+
+        const ids = result.pages.map((page) => { return page._id });
+        const relations = await PageTagRelation.find({ relatedPage: { $in: ids } }).populate('relatedTag');
+
+        // { pageId: [{ tag }, ...] }
+        const relationsMap = new Map();
+        // increment relationsMap
+        relations.forEach((relation) => {
+          const pageId = relation.relatedPage.toString();
+          if (!relationsMap.has(pageId)) {
+            relationsMap.set(pageId, []);
+          }
+          if (relation.relatedTag != null) {
+            relationsMap.get(pageId).push(relation.relatedTag);
+          }
+        });
+        // add tags to each page
+        result.pages.forEach((page) => {
+          const pageId = page._id.toString();
+          page.tags = relationsMap.has(pageId) ? relationsMap.get(pageId) : [];
+        });
+
+        return res.apiv3(result);
+      }
+      catch (err) {
+        logger.error('Failed to get recent pages', err);
+        return res.apiv3Err(new ErrorV3('Failed to get recent pages', 'unknown'), 500);
+      }
+    });
 
   /**
    * @swagger
@@ -553,41 +553,41 @@ module.exports = (crowi) => {
     *                              lastUpdateUser:
     *                                $ref: '#/components/schemas/User'
     */
-  // eslint-disable-next-line max-len
-  router.get('/list', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.list, apiV3FormValidator, async(req, res) => {
+  router.get('/list', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
+    loginRequired, validator.list, apiV3FormValidator, async(req, res) => {
 
-    const path = normalizePath(req.query.path ?? '/');
-    const limit = parseInt(req.query.limit ?? configManager.getConfig('customize:showPageLimitationS'));
-    const page = req.query.page || 1;
-    const offset = (page - 1) * limit;
-    let includeTrashed = false;
+      const path = normalizePath(req.query.path ?? '/');
+      const limit = parseInt(req.query.limit ?? configManager.getConfig('customize:showPageLimitationS'));
+      const page = req.query.page || 1;
+      const offset = (page - 1) * limit;
+      let includeTrashed = false;
 
-    if (isTrashPage(path)) {
-      includeTrashed = true;
-    }
+      if (isTrashPage(path)) {
+        includeTrashed = true;
+      }
 
-    const queryOptions = {
-      offset,
-      limit,
-      includeTrashed,
-    };
+      const queryOptions = {
+        offset,
+        limit,
+        includeTrashed,
+      };
 
-    try {
-      const result = await Page.findListWithDescendants(path, req.user, queryOptions);
+      try {
+        const result = await Page.findListWithDescendants(path, req.user, queryOptions);
 
-      result.pages.forEach((page) => {
-        if (page.lastUpdateUser != null && page.lastUpdateUser instanceof User) {
-          page.lastUpdateUser = serializeUserSecurely(page.lastUpdateUser);
-        }
-      });
+        result.pages.forEach((page) => {
+          if (page.lastUpdateUser != null && page.lastUpdateUser instanceof User) {
+            page.lastUpdateUser = serializeUserSecurely(page.lastUpdateUser);
+          }
+        });
 
-      return res.apiv3(result);
-    }
-    catch (err) {
-      logger.error('Failed to get Descendants Pages', err);
-      return res.apiv3Err(err, 500);
-    }
-  });
+        return res.apiv3(result);
+      }
+      catch (err) {
+        logger.error('Failed to get Descendants Pages', err);
+        return res.apiv3Err(err, 500);
+      }
+    });
 
   /**
    * @swagger
@@ -887,7 +887,6 @@ module.exports = (crowi) => {
    *                  type: object
    *                  description: Empty object
    */
-  // eslint-disable-next-line max-len
   router.post(
     '/convert-pages-by-path',
     accessTokenParser([SCOPE.WRITE.FEATURES.PAGE], { acceptLegacy: true }),
@@ -948,7 +947,6 @@ module.exports = (crowi) => {
    *                  type: object
    *                  description: Empty object
   */
-  // eslint-disable-next-line max-len
   router.post(
     '/legacy-pages-migration',
     accessTokenParser([SCOPE.WRITE.FEATURES.PAGE], { acceptLegacy: true }),

+ 51 - 50
apps/app/src/server/routes/apiv3/personal-setting/index.js

@@ -238,8 +238,8 @@ module.exports = (crowi) => {
    *                      type: object
    *                      description: personal params
    */
-  // eslint-disable-next-line max-len
-  router.put('/', accessTokenParser([SCOPE.WRITE.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.personal, apiV3FormValidator,
+  router.put('/',
+    accessTokenParser([SCOPE.WRITE.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.personal, apiV3FormValidator,
     async(req, res) => {
 
       try {
@@ -339,20 +339,20 @@ module.exports = (crowi) => {
    *                      type: object
    *                      description: array of external accounts
    */
-  // eslint-disable-next-line max-len
-  router.get('/external-accounts', accessTokenParser([SCOPE.READ.USER_SETTINGS.EXTERNAL_ACCOUNT], { acceptLegacy: true }), loginRequiredStrictly, async(req, res) => {
-    const userData = req.user;
+  router.get('/external-accounts',
+    accessTokenParser([SCOPE.READ.USER_SETTINGS.EXTERNAL_ACCOUNT], { acceptLegacy: true }), loginRequiredStrictly, async(req, res) => {
+      const userData = req.user;
 
-    try {
-      const externalAccounts = await ExternalAccount.find({ user: userData });
-      return res.apiv3({ externalAccounts });
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err('get-external-accounts-failed');
-    }
+      try {
+        const externalAccounts = await ExternalAccount.find({ user: userData });
+        return res.apiv3({ externalAccounts });
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err('get-external-accounts-failed');
+      }
 
-  });
+    });
 
   /**
    * @swagger
@@ -385,8 +385,8 @@ module.exports = (crowi) => {
    *                      type: object
    *                      description: user data updated
    */
-  // eslint-disable-next-line max-len
-  router.put('/password', accessTokenParser([SCOPE.WRITE.USER_SETTINGS.PASSWORD], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.password, apiV3FormValidator,
+  router.put('/password',
+    accessTokenParser([SCOPE.WRITE.USER_SETTINGS.PASSWORD], { acceptLegacy: true }), loginRequiredStrictly, addActivity, validator.password, apiV3FormValidator,
     async(req, res) => {
       const { body, user } = req;
       const { oldPassword, newPassword } = body;
@@ -617,8 +617,8 @@ module.exports = (crowi) => {
    *                      type: object
    *                      description: Ldap account disassociate to me
    */
-  // eslint-disable-next-line max-len
-  router.put('/disassociate-ldap', accessTokenParser([SCOPE.WRITE.USER_SETTINGS.EXTERNAL_ACCOUNT]), loginRequiredStrictly, addActivity, validator.disassociateLdap, apiV3FormValidator,
+  router.put('/disassociate-ldap',
+    accessTokenParser([SCOPE.WRITE.USER_SETTINGS.EXTERNAL_ACCOUNT]), loginRequiredStrictly, addActivity, validator.disassociateLdap, apiV3FormValidator,
     async(req, res) => {
       const { user, body } = req;
       const { providerType, accountId } = body;
@@ -773,29 +773,30 @@ module.exports = (crowi) => {
    *                schema:
    *                 type: object
    */
-  // eslint-disable-next-line max-len
-  router.put('/in-app-notification-settings', accessTokenParser([SCOPE.WRITE.USER_SETTINGS.IN_APP_NOTIFICATION]), loginRequiredStrictly, addActivity, validator.inAppNotificationSettings, apiV3FormValidator, async(req, res) => {
-    const query = { userId: req.user.id };
-    const subscribeRules = req.body.subscribeRules;
+  router.put('/in-app-notification-settings',
+    accessTokenParser([SCOPE.WRITE.USER_SETTINGS.IN_APP_NOTIFICATION]),
+    loginRequiredStrictly, addActivity, validator.inAppNotificationSettings, apiV3FormValidator, async(req, res) => {
+      const query = { userId: req.user.id };
+      const subscribeRules = req.body.subscribeRules;
 
-    if (subscribeRules == null) {
-      return res.apiv3Err('no-rules-found');
-    }
+      if (subscribeRules == null) {
+        return res.apiv3Err('no-rules-found');
+      }
 
-    const options = { upsert: true, new: true, runValidators: true };
-    try {
-      const response = await InAppNotificationSettings.findOneAndUpdate(query, { $set: { subscribeRules } }, options);
+      const options = { upsert: true, new: true, runValidators: true };
+      try {
+        const response = await InAppNotificationSettings.findOneAndUpdate(query, { $set: { subscribeRules } }, options);
 
-      const parameters = { action: SupportedAction.ACTION_USER_IN_APP_NOTIFICATION_SETTINGS_UPDATE };
-      activityEvent.emit('update', res.locals.activity._id, parameters);
+        const parameters = { action: SupportedAction.ACTION_USER_IN_APP_NOTIFICATION_SETTINGS_UPDATE };
+        activityEvent.emit('update', res.locals.activity._id, parameters);
 
-      return res.apiv3(response);
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err('updating-in-app-notification-settings-failed');
-    }
-  });
+        return res.apiv3(response);
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err('updating-in-app-notification-settings-failed');
+      }
+    });
 
   /**
    * @swagger
@@ -857,20 +858,20 @@ module.exports = (crowi) => {
    *                   isQuestionnaireEnabled:
    *                     type: boolean
    */
-  // eslint-disable-next-line max-len
-  router.put('/questionnaire-settings', accessTokenParser([SCOPE.WRITE.FEATURES.QUESTIONNAIRE]), loginRequiredStrictly, validator.questionnaireSettings, apiV3FormValidator, async(req, res) => {
-    const { isQuestionnaireEnabled } = req.body;
-    const { user } = req;
-    try {
-      await user.updateIsQuestionnaireEnabled(isQuestionnaireEnabled);
+  router.put('/questionnaire-settings',
+    accessTokenParser([SCOPE.WRITE.FEATURES.QUESTIONNAIRE]), loginRequiredStrictly, validator.questionnaireSettings, apiV3FormValidator, async(req, res) => {
+      const { isQuestionnaireEnabled } = req.body;
+      const { user } = req;
+      try {
+        await user.updateIsQuestionnaireEnabled(isQuestionnaireEnabled);
 
-      return res.apiv3({ message: 'Successfully updated questionnaire settings.', isQuestionnaireEnabled });
-    }
-    catch (err) {
-      logger.error(err);
-      return res.apiv3Err({ error: 'Failed to update questionnaire settings.' });
-    }
-  });
+        return res.apiv3({ message: 'Successfully updated questionnaire settings.', isQuestionnaireEnabled });
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err({ error: 'Failed to update questionnaire settings.' });
+      }
+    });
 
 
   return router;

+ 4 - 4
apps/app/src/server/routes/apiv3/revisions.js

@@ -135,8 +135,8 @@ module.exports = (crowi) => {
    *                    type: number
    *                    description: offset of the revisions
    */
-  // eslint-disable-next-line max-len
-  router.get('/list', certifySharedPage, accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.retrieveRevisions, apiV3FormValidator,
+  router.get('/list',
+    certifySharedPage, accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.retrieveRevisions, apiV3FormValidator,
     async(req, res) => {
       const pageId = req.query.pageId;
       const limit = req.query.limit || await crowi.configManager.getConfig('customize:showPageLimitationS') || 10;
@@ -236,8 +236,8 @@ module.exports = (crowi) => {
    *                    revision:
    *                      $ref: '#/components/schemas/Revision'
    */
-  // eslint-disable-next-line max-len
-  router.get('/:id', certifySharedPage, accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.retrieveRevisionById, apiV3FormValidator,
+  router.get('/:id',
+    certifySharedPage, accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, validator.retrieveRevisionById, apiV3FormValidator,
     async(req, res) => {
       const revisionId = req.params.id;
       const pageId = req.query.pageId;

+ 31 - 31
apps/app/src/server/routes/apiv3/search.js

@@ -126,22 +126,22 @@ module.exports = (crowi) => {
    *                    description: Status of indices
    *                    $ref: '#/components/schemas/Indices'
    */
-  // eslint-disable-next-line max-len
-  router.get('/indices', noCache(), accessTokenParser([SCOPE.READ.ADMIN.FULL_TEXT_SEARCH], { acceptLegacy: true }), loginRequired, adminRequired, async(req, res) => {
-    const { searchService } = crowi;
-
-    if (!searchService.isConfigured) {
-      return res.apiv3Err(new ErrorV3('SearchService is not configured', 'search-service-unconfigured'), 503);
-    }
-
-    try {
-      const info = await searchService.getInfoForAdmin();
-      return res.status(200).send({ info });
-    }
-    catch (err) {
-      return res.apiv3Err(err, 503);
-    }
-  });
+  router.get('/indices',
+    noCache(), accessTokenParser([SCOPE.READ.ADMIN.FULL_TEXT_SEARCH], { acceptLegacy: true }), loginRequired, adminRequired, async(req, res) => {
+      const { searchService } = crowi;
+
+      if (!searchService.isConfigured) {
+        return res.apiv3Err(new ErrorV3('SearchService is not configured', 'search-service-unconfigured'), 503);
+      }
+
+      try {
+        const info = await searchService.getInfoForAdmin();
+        return res.status(200).send({ info });
+      }
+      catch (err) {
+        return res.apiv3Err(err, 503);
+      }
+    });
 
   /**
    * @swagger
@@ -155,25 +155,25 @@ module.exports = (crowi) => {
    *        200:
    *          description: Successfully connected
    */
-  // eslint-disable-next-line max-len
-  router.post('/connection', accessTokenParser([SCOPE.WRITE.ADMIN.FULL_TEXT_SEARCH], { acceptLegacy: true }), loginRequired, adminRequired, addActivity, async(req, res) => {
-    const { searchService } = crowi;
+  router.post('/connection',
+    accessTokenParser([SCOPE.WRITE.ADMIN.FULL_TEXT_SEARCH], { acceptLegacy: true }), loginRequired, adminRequired, addActivity, async(req, res) => {
+      const { searchService } = crowi;
 
-    if (!searchService.isConfigured) {
-      return res.apiv3Err(new ErrorV3('SearchService is not configured', 'search-service-unconfigured'));
-    }
+      if (!searchService.isConfigured) {
+        return res.apiv3Err(new ErrorV3('SearchService is not configured', 'search-service-unconfigured'));
+      }
 
-    try {
-      await searchService.reconnectClient();
+      try {
+        await searchService.reconnectClient();
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SEARCH_CONNECTION });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SEARCH_CONNECTION });
 
-      return res.status(200).send();
-    }
-    catch (err) {
-      return res.apiv3Err(err, 503);
-    }
-  });
+        return res.status(200).send();
+      }
+      catch (err) {
+        return res.apiv3Err(err, 503);
+      }
+    });
 
   const validatorForPutIndices = [
     body('operation').isString().isIn(['rebuild', 'normalize']),

+ 125 - 120
apps/app/src/server/routes/apiv3/slack-integration-settings.js

@@ -334,25 +334,26 @@ module.exports = (crowi) => {
    *           200:
    *             description: Succeeded to put botType setting.
    */
-  // eslint-disable-next-line max-len
-  router.put('/bot-type', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, addActivity, validator.botType, apiV3FormValidator, async(req, res) => {
-    const { currentBotType } = req.body;
+  router.put('/bot-type',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION], { acceptLegacy: true }),
+    loginRequiredStrictly, adminRequired, addActivity, validator.botType, apiV3FormValidator, async(req, res) => {
+      const { currentBotType } = req.body;
 
-    if (currentBotType == null) {
-      return res.apiv3Err(new ErrorV3('The param \'currentBotType\' must be specified.', 'update-CustomBotSetting-failed'), 400);
-    }
+      if (currentBotType == null) {
+        return res.apiv3Err(new ErrorV3('The param \'currentBotType\' must be specified.', 'update-CustomBotSetting-failed'), 400);
+      }
 
-    try {
-      await handleBotTypeChanging(req, res, currentBotType);
+      try {
+        await handleBotTypeChanging(req, res, currentBotType);
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_BOT_TYPE_UPDATE });
-    }
-    catch (error) {
-      const msg = 'Error occured in updating Custom bot setting';
-      logger.error('Error', error);
-      return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
-    }
-  });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_BOT_TYPE_UPDATE });
+      }
+      catch (error) {
+        const msg = 'Error occured in updating Custom bot setting';
+        logger.error('Error', error);
+        return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
+      }
+    });
 
   /**
    * @swagger
@@ -372,8 +373,8 @@ module.exports = (crowi) => {
    *           200:
    *             description: Succeeded to delete botType setting.
    */
-  // eslint-disable-next-line max-len
-  router.delete('/bot-type', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, addActivity, apiV3FormValidator,
+  router.delete('/bot-type',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION], { acceptLegacy: true }), loginRequiredStrictly, adminRequired, addActivity, apiV3FormValidator,
     async(req, res) => {
       try {
         await handleBotTypeChanging(req, res, null);
@@ -467,34 +468,35 @@ module.exports = (crowi) => {
    *           200:
    *             description: Succeeded to put CustomBotWithoutProxy permissions.
    */
-  // eslint-disable-next-line max-len
-  router.put('/without-proxy/update-permissions', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]), loginRequiredStrictly, adminRequired, addActivity, validator.updatePermissionsWithoutProxy, async(req, res) => {
-    const currentBotType = crowi.configManager.getConfig('slackbot:currentBotType');
-    if (currentBotType !== SlackbotType.CUSTOM_WITHOUT_PROXY) {
-      const msg = 'Not CustomBotWithoutProxy';
-      return res.apiv3Err(new ErrorV3(msg, 'not-customBotWithoutProxy'), 400);
-    }
+  router.put('/without-proxy/update-permissions',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]),
+    loginRequiredStrictly, adminRequired, addActivity, validator.updatePermissionsWithoutProxy, async(req, res) => {
+      const currentBotType = crowi.configManager.getConfig('slackbot:currentBotType');
+      if (currentBotType !== SlackbotType.CUSTOM_WITHOUT_PROXY) {
+        const msg = 'Not CustomBotWithoutProxy';
+        return res.apiv3Err(new ErrorV3(msg, 'not-customBotWithoutProxy'), 400);
+      }
 
-    // TODO: look here 78978
-    const { commandPermission, eventActionsPermission } = req.body;
-    const params = {
-      'slackbot:withoutProxy:commandPermission': commandPermission,
-      'slackbot:withoutProxy:eventActionsPermission': eventActionsPermission,
-    };
-    try {
-      await updateSlackBotSettings(params);
-      crowi.slackIntegrationService.publishUpdatedMessage();
+      // TODO: look here 78978
+      const { commandPermission, eventActionsPermission } = req.body;
+      const params = {
+        'slackbot:withoutProxy:commandPermission': commandPermission,
+        'slackbot:withoutProxy:eventActionsPermission': eventActionsPermission,
+      };
+      try {
+        await updateSlackBotSettings(params);
+        crowi.slackIntegrationService.publishUpdatedMessage();
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_WITHOUT_PROXY_PERMISSION_UPDATE });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_WITHOUT_PROXY_PERMISSION_UPDATE });
 
-      return res.apiv3();
-    }
-    catch (error) {
-      const msg = 'Error occured in updating command permission settigns';
-      logger.error('Error', error);
-      return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
-    }
-  });
+        return res.apiv3();
+      }
+      catch (error) {
+        const msg = 'Error occured in updating command permission settigns';
+        logger.error('Error', error);
+        return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
+      }
+    });
 
 
   /**
@@ -690,39 +692,40 @@ module.exports = (crowi) => {
    *          200:
    *            description: Succeeded to make it primary
    */
-  // eslint-disable-next-line max-len
-  router.put('/slack-app-integrations/:id/make-primary', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]), loginRequiredStrictly, adminRequired, addActivity, validator.makePrimary, apiV3FormValidator, async(req, res) => {
+  router.put('/slack-app-integrations/:id/make-primary',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]),
+    loginRequiredStrictly, adminRequired, addActivity, validator.makePrimary, apiV3FormValidator, async(req, res) => {
 
-    const { id } = req.params;
+      const { id } = req.params;
 
-    try {
-      await SlackAppIntegration.bulkWrite([
+      try {
+        await SlackAppIntegration.bulkWrite([
         // unset isPrimary for others
-        {
-          updateMany: {
-            filter: { _id: { $ne: id } },
-            update: { $unset: { isPrimary: '' } },
+          {
+            updateMany: {
+              filter: { _id: { $ne: id } },
+              update: { $unset: { isPrimary: '' } },
+            },
           },
-        },
-        // set primary
-        {
-          updateOne: {
-            filter: { _id: id },
-            update: { isPrimary: true },
+          // set primary
+          {
+            updateOne: {
+              filter: { _id: id },
+              update: { isPrimary: true },
+            },
           },
-        },
-      ]);
+        ]);
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_MAKE_APP_PRIMARY });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_MAKE_APP_PRIMARY });
 
-      return res.apiv3();
-    }
-    catch (error) {
-      const msg = 'Error occurred during making SlackAppIntegration primary';
-      logger.error('Error', error);
-      return res.apiv3Err(new ErrorV3(msg, 'making-primary-failed'), 500);
-    }
-  });
+        return res.apiv3();
+      }
+      catch (error) {
+        const msg = 'Error occurred during making SlackAppIntegration primary';
+        logger.error('Error', error);
+        return res.apiv3Err(new ErrorV3(msg, 'making-primary-failed'), 500);
+      }
+    });
 
   /**
    * @swagger
@@ -749,25 +752,26 @@ module.exports = (crowi) => {
    *                schema:
    *                  type: object
    */
-  // eslint-disable-next-line max-len
-  router.put('/slack-app-integrations/:id/regenerate-tokens', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]), loginRequiredStrictly, adminRequired, addActivity, validator.regenerateTokens, apiV3FormValidator, async(req, res) => {
+  router.put('/slack-app-integrations/:id/regenerate-tokens',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]),
+    loginRequiredStrictly, adminRequired, addActivity, validator.regenerateTokens, apiV3FormValidator, async(req, res) => {
 
-    const { id } = req.params;
+      const { id } = req.params;
 
-    try {
-      const { tokenGtoP, tokenPtoG } = await SlackAppIntegration.generateUniqueAccessTokens();
-      const slackAppTokens = await SlackAppIntegration.findByIdAndUpdate(id, { tokenGtoP, tokenPtoG });
+      try {
+        const { tokenGtoP, tokenPtoG } = await SlackAppIntegration.generateUniqueAccessTokens();
+        const slackAppTokens = await SlackAppIntegration.findByIdAndUpdate(id, { tokenGtoP, tokenPtoG });
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_ACCESS_TOKEN_REGENERATE });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_ACCESS_TOKEN_REGENERATE });
 
-      return res.apiv3(slackAppTokens, 200);
-    }
-    catch (error) {
-      const msg = 'Error occurred during regenerating slack app tokens';
-      logger.error('Error', error);
-      return res.apiv3Err(new ErrorV3(msg, 'regenerating-slackAppTokens-failed'), 500);
-    }
-  });
+        return res.apiv3(slackAppTokens, 200);
+      }
+      catch (error) {
+        const msg = 'Error occurred during regenerating slack app tokens';
+        logger.error('Error', error);
+        return res.apiv3Err(new ErrorV3(msg, 'regenerating-slackAppTokens-failed'), 500);
+      }
+    });
 
   /**
    * @swagger
@@ -806,51 +810,52 @@ module.exports = (crowi) => {
    *                schema:
    *                  type: object
    */
-  // eslint-disable-next-line max-len
-  router.put('/slack-app-integrations/:id/permissions', accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]), loginRequiredStrictly, adminRequired, addActivity, validator.updatePermissionsWithProxy, apiV3FormValidator, async(req, res) => {
+  router.put('/slack-app-integrations/:id/permissions',
+    accessTokenParser([SCOPE.WRITE.ADMIN.SLACK_INTEGRATION]),
+    loginRequiredStrictly, adminRequired, addActivity, validator.updatePermissionsWithProxy, apiV3FormValidator, async(req, res) => {
     // TODO: look here 78975
-    const { permissionsForBroadcastUseCommands, permissionsForSingleUseCommands, permissionsForSlackEventActions } = req.body;
-    const { id } = req.params;
+      const { permissionsForBroadcastUseCommands, permissionsForSingleUseCommands, permissionsForSlackEventActions } = req.body;
+      const { id } = req.params;
 
-    const updatePermissionsForBroadcastUseCommands = new Map(Object.entries(permissionsForBroadcastUseCommands));
-    const updatePermissionsForSingleUseCommands = new Map(Object.entries(permissionsForSingleUseCommands));
-    const newPermissionsForSlackEventActions = new Map(Object.entries(permissionsForSlackEventActions));
+      const updatePermissionsForBroadcastUseCommands = new Map(Object.entries(permissionsForBroadcastUseCommands));
+      const updatePermissionsForSingleUseCommands = new Map(Object.entries(permissionsForSingleUseCommands));
+      const newPermissionsForSlackEventActions = new Map(Object.entries(permissionsForSlackEventActions));
 
 
-    try {
-      const slackAppIntegration = await SlackAppIntegration.findByIdAndUpdate(
-        id,
-        {
-          permissionsForBroadcastUseCommands: updatePermissionsForBroadcastUseCommands,
-          permissionsForSingleUseCommands: updatePermissionsForSingleUseCommands,
-          permissionsForSlackEventActions: newPermissionsForSlackEventActions,
-        },
-        { new: true },
-      );
-
-      const proxyUri = crowi.slackIntegrationService.proxyUriForCurrentType;
-      if (proxyUri != null) {
-        await requestToProxyServer(
-          slackAppIntegration.tokenGtoP,
-          'put',
-          '/g2s/supported-commands',
+      try {
+        const slackAppIntegration = await SlackAppIntegration.findByIdAndUpdate(
+          id,
           {
-            permissionsForBroadcastUseCommands: slackAppIntegration.permissionsForBroadcastUseCommands,
-            permissionsForSingleUseCommands: slackAppIntegration.permissionsForSingleUseCommands,
+            permissionsForBroadcastUseCommands: updatePermissionsForBroadcastUseCommands,
+            permissionsForSingleUseCommands: updatePermissionsForSingleUseCommands,
+            permissionsForSlackEventActions: newPermissionsForSlackEventActions,
           },
+          { new: true },
         );
-      }
 
-      activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_PERMISSION_UPDATE });
+        const proxyUri = crowi.slackIntegrationService.proxyUriForCurrentType;
+        if (proxyUri != null) {
+          await requestToProxyServer(
+            slackAppIntegration.tokenGtoP,
+            'put',
+            '/g2s/supported-commands',
+            {
+              permissionsForBroadcastUseCommands: slackAppIntegration.permissionsForBroadcastUseCommands,
+              permissionsForSingleUseCommands: slackAppIntegration.permissionsForSingleUseCommands,
+            },
+          );
+        }
 
-      return res.apiv3({});
-    }
-    catch (error) {
-      const msg = `Error occured in updating settings. Cause: ${error.message}`;
-      logger.error('Error', error);
-      return res.apiv3Err(new ErrorV3(msg, 'update-permissions-failed'), 500);
-    }
-  });
+        activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_SLACK_PERMISSION_UPDATE });
+
+        return res.apiv3({});
+      }
+      catch (error) {
+        const msg = `Error occured in updating settings. Cause: ${error.message}`;
+        logger.error('Error', error);
+        return res.apiv3Err(new ErrorV3(msg, 'update-permissions-failed'), 500);
+      }
+    });
 
   /**
    * @swagger

+ 112 - 112
apps/app/src/server/routes/apiv3/users.js

@@ -287,90 +287,90 @@ module.exports = (crowi) => {
    *                      $ref: '#/components/schemas/PaginateResult'
    */
 
-  // eslint-disable-next-line max-len
-  router.get('/', accessTokenParser([SCOPE.READ.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequired, validator.statusList, apiV3FormValidator, async(req, res) => {
-
-    const page = parseInt(req.query.page) || 1;
+  router.get('/',
+    accessTokenParser([SCOPE.READ.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequired, validator.statusList, apiV3FormValidator, async(req, res) => {
+
+      const page = parseInt(req.query.page) || 1;
+
+      // status
+      const forceIncludeAttributes = Array.isArray(req.query.forceIncludeAttributes)
+        ? req.query.forceIncludeAttributes
+        : [];
+      const selectedStatusList = Array.isArray(req.query.selectedStatusList)
+        ? req.query.selectedStatusList
+        : ['active'];
+
+      const statusNoList = (selectedStatusList.includes('all')) ? Object.values(statusNo) : selectedStatusList.map(element => statusNo[element]);
+
+      // Search from input
+      const searchText = req.query.searchText || '';
+      const searchWord = new RegExp(escapeStringRegexp(searchText));
+      // Sort
+      const { sort, sortOrder } = req.query;
+      const sortOutput = {
+        [sort]: (sortOrder === 'desc') ? -1 : 1,
+      };
+
+      //  For more information about the external specification of the User API, see here (https://dev.growi.org/5fd7466a31d89500488248e3)
+
+      const orConditions = [
+        { name: { $in: searchWord } },
+        { username: { $in: searchWord } },
+      ];
+
+      const query = {
+        $and: [
+          { status: { $in: statusNoList } },
+          {
+            $or: orConditions,
+          },
+        ],
+      };
 
-    // status
-    const forceIncludeAttributes = Array.isArray(req.query.forceIncludeAttributes)
-      ? req.query.forceIncludeAttributes
-      : [];
-    const selectedStatusList = Array.isArray(req.query.selectedStatusList)
-      ? req.query.selectedStatusList
-      : ['active'];
-
-    const statusNoList = (selectedStatusList.includes('all')) ? Object.values(statusNo) : selectedStatusList.map(element => statusNo[element]);
-
-    // Search from input
-    const searchText = req.query.searchText || '';
-    const searchWord = new RegExp(escapeStringRegexp(searchText));
-    // Sort
-    const { sort, sortOrder } = req.query;
-    const sortOutput = {
-      [sort]: (sortOrder === 'desc') ? -1 : 1,
-    };
-
-    //  For more information about the external specification of the User API, see here (https://dev.growi.org/5fd7466a31d89500488248e3)
-
-    const orConditions = [
-      { name: { $in: searchWord } },
-      { username: { $in: searchWord } },
-    ];
-
-    const query = {
-      $and: [
-        { status: { $in: statusNoList } },
-        {
-          $or: orConditions,
-        },
-      ],
-    };
+      try {
+        if (req.user != null) {
+          orConditions.push(
+            {
+              $and: [
+                { isEmailPublished: true },
+                { email: { $in: searchWord } },
+              ],
+            },
+          );
+        }
+        if (forceIncludeAttributes.includes('email')) {
+          orConditions.push({ email: { $in: searchWord } });
+        }
 
-    try {
-      if (req.user != null) {
-        orConditions.push(
+        const paginateResult = await User.paginate(
+          query,
           {
-            $and: [
-              { isEmailPublished: true },
-              { email: { $in: searchWord } },
-            ],
+            sort: sortOutput,
+            page,
+            limit: PAGE_ITEMS,
           },
         );
-      }
-      if (forceIncludeAttributes.includes('email')) {
-        orConditions.push({ email: { $in: searchWord } });
-      }
 
-      const paginateResult = await User.paginate(
-        query,
-        {
-          sort: sortOutput,
-          page,
-          limit: PAGE_ITEMS,
-        },
-      );
+        paginateResult.docs = paginateResult.docs.map((doc) => {
 
-      paginateResult.docs = paginateResult.docs.map((doc) => {
+          // return email only when specified by query
+          const { email } = doc;
+          const user = serializeUserSecurely(doc);
+          if (forceIncludeAttributes.includes('email')) {
+            user.email = email;
+          }
 
-        // return email only when specified by query
-        const { email } = doc;
-        const user = serializeUserSecurely(doc);
-        if (forceIncludeAttributes.includes('email')) {
-          user.email = email;
-        }
-
-        return user;
-      });
+          return user;
+        });
 
-      return res.apiv3({ paginateResult });
-    }
-    catch (err) {
-      const msg = 'Error occurred in fetching user group list';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'user-group-list-fetch-failed'), 500);
-    }
-  });
+        return res.apiv3({ paginateResult });
+      }
+      catch (err) {
+        const msg = 'Error occurred in fetching user group list';
+        logger.error('Error', err);
+        return res.apiv3Err(new ErrorV3(msg, 'user-group-list-fetch-failed'), 500);
+      }
+    });
 
   /**
    * @swagger
@@ -1354,49 +1354,49 @@ module.exports = (crowi) => {
     *                        items:
     *                          type: string
     */
-  // eslint-disable-next-line max-len
-  router.get('/usernames', accessTokenParser([SCOPE.READ.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequired, validator.usernames, apiV3FormValidator, async(req, res) => {
-    const q = req.query.q;
-    const offset = +req.query.offset || 0;
-    const limit = +req.query.limit || 10;
+  router.get('/usernames',
+    accessTokenParser([SCOPE.READ.USER_SETTINGS.INFO], { acceptLegacy: true }), loginRequired, validator.usernames, apiV3FormValidator, async(req, res) => {
+      const q = req.query.q;
+      const offset = +req.query.offset || 0;
+      const limit = +req.query.limit || 10;
 
-    try {
-      const options = JSON.parse(req.query.options || '{}');
-      const data = {};
+      try {
+        const options = JSON.parse(req.query.options || '{}');
+        const data = {};
 
-      if (options.isIncludeActiveUser == null || options.isIncludeActiveUser) {
-        const activeUserData = await User.findUserByUsernameRegexWithTotalCount(q, [User.STATUS_ACTIVE], { offset, limit });
-        const activeUsernames = activeUserData.users.map(user => user.username);
-        Object.assign(data, { activeUser: { usernames: activeUsernames, totalCount: activeUserData.totalCount } });
-      }
+        if (options.isIncludeActiveUser == null || options.isIncludeActiveUser) {
+          const activeUserData = await User.findUserByUsernameRegexWithTotalCount(q, [User.STATUS_ACTIVE], { offset, limit });
+          const activeUsernames = activeUserData.users.map(user => user.username);
+          Object.assign(data, { activeUser: { usernames: activeUsernames, totalCount: activeUserData.totalCount } });
+        }
 
-      if (options.isIncludeInactiveUser) {
-        const inactiveUserStates = [User.STATUS_REGISTERED, User.STATUS_SUSPENDED, User.STATUS_INVITED];
-        const inactiveUserData = await User.findUserByUsernameRegexWithTotalCount(q, inactiveUserStates, { offset, limit });
-        const inactiveUsernames = inactiveUserData.users.map(user => user.username);
-        Object.assign(data, { inactiveUser: { usernames: inactiveUsernames, totalCount: inactiveUserData.totalCount } });
-      }
+        if (options.isIncludeInactiveUser) {
+          const inactiveUserStates = [User.STATUS_REGISTERED, User.STATUS_SUSPENDED, User.STATUS_INVITED];
+          const inactiveUserData = await User.findUserByUsernameRegexWithTotalCount(q, inactiveUserStates, { offset, limit });
+          const inactiveUsernames = inactiveUserData.users.map(user => user.username);
+          Object.assign(data, { inactiveUser: { usernames: inactiveUsernames, totalCount: inactiveUserData.totalCount } });
+        }
 
-      if (options.isIncludeActivitySnapshotUser && req.user.admin) {
-        const activitySnapshotUserData = await Activity.findSnapshotUsernamesByUsernameRegexWithTotalCount(q, { offset, limit });
-        Object.assign(data, { activitySnapshotUser: activitySnapshotUserData });
-      }
+        if (options.isIncludeActivitySnapshotUser && req.user.admin) {
+          const activitySnapshotUserData = await Activity.findSnapshotUsernamesByUsernameRegexWithTotalCount(q, { offset, limit });
+          Object.assign(data, { activitySnapshotUser: activitySnapshotUserData });
+        }
 
-      // eslint-disable-next-line max-len
-      const canIncludeMixedUsernames = (options.isIncludeMixedUsernames && req.user.admin) || (options.isIncludeMixedUsernames && !options.isIncludeActivitySnapshotUser);
-      if (canIncludeMixedUsernames) {
-        const allUsernames = [...data.activeUser?.usernames || [], ...data.inactiveUser?.usernames || [], ...data?.activitySnapshotUser?.usernames || []];
-        const distinctUsernames = Array.from(new Set(allUsernames));
-        Object.assign(data, { mixedUsernames: distinctUsernames });
-      }
+        // eslint-disable-next-line max-len
+        const canIncludeMixedUsernames = (options.isIncludeMixedUsernames && req.user.admin) || (options.isIncludeMixedUsernames && !options.isIncludeActivitySnapshotUser);
+        if (canIncludeMixedUsernames) {
+          const allUsernames = [...data.activeUser?.usernames || [], ...data.inactiveUser?.usernames || [], ...data?.activitySnapshotUser?.usernames || []];
+          const distinctUsernames = Array.from(new Set(allUsernames));
+          Object.assign(data, { mixedUsernames: distinctUsernames });
+        }
 
-      return res.apiv3(data);
-    }
-    catch (err) {
-      logger.error('Failed to get usernames', err);
-      return res.apiv3Err(err);
-    }
-  });
+        return res.apiv3(data);
+      }
+      catch (err) {
+        logger.error('Failed to get usernames', err);
+        return res.apiv3Err(err);
+      }
+    });
 
   return router;
 };