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

Merge pull request #10048 from weseek/imprv/166911-add-scopes-to-endpoints-where-accesstokenparser-has-no-scopes-configured

imprv: Add scopes to endpoints where AccessTokenParser has no scopes configured
Yuki Takei 10 месяцев назад
Родитель
Сommit
8ba71ab810
78 измененных файлов с 145 добавлено и 134 удалено
  1. 4 2
      apps/app/public/static/locales/en_US/commons.json
  2. 4 2
      apps/app/public/static/locales/fr_FR/commons.json
  3. 4 2
      apps/app/public/static/locales/ja_JP/commons.json
  4. 4 2
      apps/app/public/static/locales/zh_CN/commons.json
  5. 1 1
      apps/app/src/client/components/Me/AccessTokenForm.tsx
  6. 1 1
      apps/app/src/client/components/Me/AccessTokenScopeList.tsx
  7. 2 3
      apps/app/src/client/components/Me/AccessTokenScopeSelect.tsx
  8. 21 17
      apps/app/src/client/util/scope-util.test.ts
  9. 2 2
      apps/app/src/client/util/scope-util.ts
  10. 1 1
      apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group-relation.ts
  11. 1 1
      apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group.ts
  12. 1 1
      apps/app/src/features/growi-plugin/server/routes/apiv3/admin/index.ts
  13. 1 1
      apps/app/src/features/openai/server/routes/ai-assistant.ts
  14. 1 1
      apps/app/src/features/openai/server/routes/ai-assistants.ts
  15. 1 1
      apps/app/src/features/openai/server/routes/delete-ai-assistant.ts
  16. 1 1
      apps/app/src/features/openai/server/routes/delete-thread.ts
  17. 1 1
      apps/app/src/features/openai/server/routes/edit/index.ts
  18. 1 1
      apps/app/src/features/openai/server/routes/get-threads.ts
  19. 1 1
      apps/app/src/features/openai/server/routes/message/get-messages.ts
  20. 1 1
      apps/app/src/features/openai/server/routes/message/post-message.ts
  21. 1 1
      apps/app/src/features/openai/server/routes/set-default-ai-assistant.ts
  22. 1 1
      apps/app/src/features/openai/server/routes/thread.ts
  23. 1 1
      apps/app/src/features/openai/server/routes/update-ai-assistant.ts
  24. 26 24
      apps/app/src/features/page-bulk-export/server/routes/apiv3/page-bulk-export.ts
  25. 1 1
      apps/app/src/features/questionnaire/server/routes/apiv3/questionnaire.ts
  26. 1 1
      apps/app/src/features/templates/server/routes/apiv3/index.ts
  27. 1 1
      apps/app/src/interfaces/access-token.ts
  28. 1 1
      apps/app/src/server/crowi/index.js
  29. 1 1
      apps/app/src/server/middlewares/access-token-parser/access-token.integ.ts
  30. 1 2
      apps/app/src/server/middlewares/access-token-parser/access-token.ts
  31. 6 4
      apps/app/src/server/middlewares/access-token-parser/index.ts
  32. 1 2
      apps/app/src/server/models/access-token.ts
  33. 1 1
      apps/app/src/server/routes/apiv3/activity.ts
  34. 1 1
      apps/app/src/server/routes/apiv3/admin-home.ts
  35. 1 2
      apps/app/src/server/routes/apiv3/app-settings.js
  36. 1 1
      apps/app/src/server/routes/apiv3/attachment.js
  37. 1 1
      apps/app/src/server/routes/apiv3/bookmark-folder.ts
  38. 1 1
      apps/app/src/server/routes/apiv3/bookmarks.js
  39. 1 1
      apps/app/src/server/routes/apiv3/customize-setting.js
  40. 1 1
      apps/app/src/server/routes/apiv3/export.js
  41. 1 1
      apps/app/src/server/routes/apiv3/g2g-transfer.ts
  42. 1 1
      apps/app/src/server/routes/apiv3/import.js
  43. 1 1
      apps/app/src/server/routes/apiv3/in-app-notification.ts
  44. 1 1
      apps/app/src/server/routes/apiv3/notification-setting.js
  45. 1 1
      apps/app/src/server/routes/apiv3/page-listing.ts
  46. 1 1
      apps/app/src/server/routes/apiv3/page/check-page-existence.ts
  47. 1 1
      apps/app/src/server/routes/apiv3/page/create-page.ts
  48. 1 1
      apps/app/src/server/routes/apiv3/page/get-page-paths-with-descendant-count.ts
  49. 1 1
      apps/app/src/server/routes/apiv3/page/get-yjs-data.ts
  50. 1 1
      apps/app/src/server/routes/apiv3/page/index.ts
  51. 1 1
      apps/app/src/server/routes/apiv3/page/publish-page.ts
  52. 1 1
      apps/app/src/server/routes/apiv3/page/sync-latest-revision-body-to-yjs-draft.ts
  53. 1 1
      apps/app/src/server/routes/apiv3/page/unpublish-page.ts
  54. 1 1
      apps/app/src/server/routes/apiv3/page/update-page.ts
  55. 1 1
      apps/app/src/server/routes/apiv3/pages/index.js
  56. 1 1
      apps/app/src/server/routes/apiv3/personal-setting/delete-access-token.ts
  57. 1 1
      apps/app/src/server/routes/apiv3/personal-setting/delete-all-access-tokens.ts
  58. 1 2
      apps/app/src/server/routes/apiv3/personal-setting/generate-access-token.ts
  59. 1 1
      apps/app/src/server/routes/apiv3/personal-setting/get-access-tokens.ts
  60. 1 1
      apps/app/src/server/routes/apiv3/personal-setting/index.js
  61. 1 1
      apps/app/src/server/routes/apiv3/revisions.js
  62. 1 1
      apps/app/src/server/routes/apiv3/search.js
  63. 1 2
      apps/app/src/server/routes/apiv3/security-settings/index.js
  64. 1 1
      apps/app/src/server/routes/apiv3/share-links.js
  65. 1 1
      apps/app/src/server/routes/apiv3/slack-integration-legacy-settings.js
  66. 1 2
      apps/app/src/server/routes/apiv3/slack-integration-settings.js
  67. 1 1
      apps/app/src/server/routes/apiv3/user-group-relation.js
  68. 1 1
      apps/app/src/server/routes/apiv3/user-group.js
  69. 1 1
      apps/app/src/server/routes/apiv3/user/get-related-groups.ts
  70. 1 1
      apps/app/src/server/routes/apiv3/users.js
  71. 1 1
      apps/app/src/server/routes/attachment/get-brand-logo.ts
  72. 1 1
      apps/app/src/server/routes/index.js
  73. 1 1
      apps/app/src/server/util/scope-util.spec.ts
  74. 1 1
      apps/app/src/server/util/scope-utils.ts
  75. 1 0
      packages/core/src/interfaces/index.ts
  76. 1 0
      packages/core/src/interfaces/scope.ts
  77. 3 4
      packages/remark-attachment-refs/src/server/routes/refs.ts
  78. 2 1
      packages/remark-lsx/src/server/index.ts

+ 4 - 2
apps/app/public/static/locales/en_US/commons.json

@@ -203,7 +203,8 @@
         "share_link": "Grants permission to view share link features.",
         "bookmark": "Grants permission to view bookmark features.",
         "questionnaire": "Grants permission to view questionnaire features.",
-        "attachment": "Grants permission to view attachment features."
+        "attachment": "Grants permission to view attachment features.",
+        "page_bulk_export": "Grants permission to view page bulk export features."
       }
     },
     "write": {
@@ -248,7 +249,8 @@
         "share_link": "Grants permission to edit share link features.",
         "bookmark": "Grants permission to edit bookmark features.",
         "questionnaire": "Grants permission to edit questionnaire features.",
-        "attachment": "Grants permission to edit attachment features."
+        "attachment": "Grants permission to edit attachment features.",
+        "page_bulk_export": "Grants permission to edit page bulk export features."
       }
     }
   }

+ 4 - 2
apps/app/public/static/locales/fr_FR/commons.json

@@ -189,7 +189,8 @@
         "share_link": "Accorde la permission de voir les fonctionnalités de lien de partage.",
         "bookmark": "Accorde la permission de voir les fonctionnalités de signet.",
         "questionnaire": "Accorde la permission de voir les fonctionnalités de questionnaire.",
-        "attachment": "Accorde la permission de voir les fonctionnalités de pièce jointe."
+        "attachment": "Accorde la permission de voir les fonctionnalités de pièce jointe.",
+        "page_bulk_export": "Accorde la permission de voir les fonctionnalités d'exportation en masse de pages."
       }
     },
     "write": {
@@ -234,7 +235,8 @@
         "share_link": "Accorde la permission de modifier les fonctionnalités de lien de partage.",
         "bookmark": "Accorde la permission de modifier les fonctionnalités de signet.",
         "questionnaire": "Accorde la permission de modifier les fonctionnalités de questionnaire.",
-        "attachment": "Accorde la permission de modifier les fonctionnalités de pièce jointe."
+        "attachment": "Accorde la permission de modifier les fonctionnalités de pièce jointe.",
+        "page_bulk_export": "Accorde la permission de modifier les fonctionnalités d'exportation en masse de pages."
       }
     }
   }

+ 4 - 2
apps/app/public/static/locales/ja_JP/commons.json

@@ -206,7 +206,8 @@
         "share_link": "共有リンク機能の閲覧権限を付与できます。",
         "bookmark": "ブックマーク機能の閲覧権限を付与できます。",
         "questionnaire": "アンケート機能の閲覧権限を付与できます。",
-        "attachment": "添付ファイル機能の閲覧権限を付与できます。"
+        "attachment": "添付ファイル機能の閲覧権限を付与できます。",
+        "page_bulk_export": "ページの一括エクスポート機能の閲覧権限を付与できます。"
       }
     },
     "write": {
@@ -251,7 +252,8 @@
         "share_link": "共有リンク機能の編集権限を付与できます。",
         "bookmark": "ブックマーク機能の編集権限を付与できます。",
         "questionnaire": "アンケート機能の編集権限を付与できます。",
-        "attachment": "添付ファイル機能の編集権限を付与できます。"
+        "attachment": "添付ファイル機能の編集権限を付与できます。",
+        "page_bulk_export": "ページの一括エクスポート機能の編集権限を付与できます。"
       }
     }
   }

+ 4 - 2
apps/app/public/static/locales/zh_CN/commons.json

@@ -206,7 +206,8 @@
         "share_link": "授予查看共享链接功能的权限。",
         "bookmark": "授予查看书签功能的权限。",
         "questionnaire": "授予查看问卷功能的权限。",
-        "attachment": "授予查看附件功能的权限。"
+        "attachment": "授予查看附件功能的权限。",
+        "page_bulk_export": "授予查看页面批量导出功能的权限。"
       }
     },
     "write": {
@@ -251,7 +252,8 @@
         "share_link": "授予编辑共享链接功能的权限。",
         "bookmark": "授予编辑书签功能的权限。",
         "questionnaire": "授予编辑问卷功能的权限。",
-        "attachment": "授予编辑附件功能的权限。"
+        "attachment": "授予编辑附件功能的权限。",
+        "page_bulk_export": "授予编辑页面批量导出功能的权限。"
       }
     }
   }

+ 1 - 1
apps/app/src/client/components/Me/AccessTokenForm.tsx

@@ -1,10 +1,10 @@
 import React from 'react';
 
+import type { Scope } from '@growi/core/dist/interfaces';
 import { useTranslation } from 'next-i18next';
 import { useForm } from 'react-hook-form';
 
 import type { IAccessTokenInfo } from '~/interfaces/access-token';
-import type { Scope } from '~/interfaces/scope';
 
 import { AccessTokenScopeSelect } from './AccessTokenScopeSelect';
 

+ 1 - 1
apps/app/src/client/components/Me/AccessTokenScopeList.tsx

@@ -1,11 +1,11 @@
 import React from 'react';
 
+import type { Scope } from '@growi/core/dist/interfaces';
 import { useTranslation } from 'next-i18next';
 import type { UseFormRegisterReturn } from 'react-hook-form';
 
 import { useIsDeviceLargerThanMd } from '~/stores/ui';
 
-import type { Scope } from '../../../interfaces/scope';
 
 import styles from './AccessTokenScopeList.module.scss';
 

+ 2 - 3
apps/app/src/client/components/Me/AccessTokenScopeSelect.tsx

@@ -1,13 +1,12 @@
 import React, { useEffect, useState, useMemo } from 'react';
 
+import type { Scope } from '@growi/core/dist/interfaces';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type { UseFormRegisterReturn } from 'react-hook-form';
 
 import { extractScopes, getDisabledScopes, parseScopes } from '~/client/util/scope-util';
 import { useIsAdmin } from '~/stores-universal/context';
 
-import type { Scope } from '../../../interfaces/scope';
-import { SCOPE } from '../../../interfaces/scope';
-
 import { AccessTokenScopeList } from './AccessTokenScopeList';
 
 /**

+ 21 - 17
apps/app/src/client/util/scope-util.test.ts

@@ -1,7 +1,6 @@
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { describe, it, expect } from 'vitest';
 
-import { ALL_SIGN } from '../../interfaces/scope';
-
 import { parseScopes, getDisabledScopes, extractScopes } from './scope-util';
 
 describe('scope-util', () => {
@@ -60,34 +59,39 @@ describe('scope-util', () => {
   });
 
   it('should disable specific scopes when a wildcard is selected', () => {
-    const selectedScopes = [`read:${ALL_SIGN}`];
-    const availableScopes = ['read:user', 'read:admin', 'write:user', `read:${ALL_SIGN}`];
+    const selectedScopes = [SCOPE.READ.ALL];
+    const availableScopes = [
+      SCOPE.READ.FEATURES.PAGE,
+      SCOPE.READ.FEATURES.ATTACHMENT,
+      SCOPE.WRITE.FEATURES.PAGE,
+      SCOPE.READ.ALL,
+    ];
 
     const result = getDisabledScopes(selectedScopes, availableScopes);
 
     // Should disable all read: scopes except the wildcard itself
-    expect(result.has('read:user')).toBe(true);
-    expect(result.has('read:admin')).toBe(true);
-    expect(result.has(`read:${ALL_SIGN}`)).toBe(false);
-    expect(result.has('write:user')).toBe(false);
+    expect(result.has(SCOPE.READ.FEATURES.PAGE)).toBe(true);
+    expect(result.has(SCOPE.READ.FEATURES.ATTACHMENT)).toBe(true);
+    expect(result.has(SCOPE.WRITE.FEATURES.PAGE)).toBe(false);
+    expect(result.has(SCOPE.READ.ALL)).toBe(false);
   });
 
   it('should handle multiple wildcard selections', () => {
-    const selectedScopes = [`read:${ALL_SIGN}`, `write:${ALL_SIGN}`];
+    const selectedScopes = [SCOPE.READ.ALL, SCOPE.WRITE.ALL];
     const availableScopes = [
-      'read:user', 'read:admin', `read:${ALL_SIGN}`,
-      'write:user', 'write:admin', `write:${ALL_SIGN}`,
+      SCOPE.READ.FEATURES.PAGE, SCOPE.READ.FEATURES.ATTACHMENT, SCOPE.READ.ALL,
+      SCOPE.WRITE.FEATURES.PAGE, SCOPE.WRITE.FEATURES.ATTACHMENT, SCOPE.WRITE.ALL,
     ];
 
     const result = getDisabledScopes(selectedScopes, availableScopes);
 
     // Should disable all specific scopes under both wildcards
-    expect(result.has('read:user')).toBe(true);
-    expect(result.has('read:admin')).toBe(true);
-    expect(result.has('write:user')).toBe(true);
-    expect(result.has('write:admin')).toBe(true);
-    expect(result.has(`read:${ALL_SIGN}`)).toBe(false);
-    expect(result.has(`write:${ALL_SIGN}`)).toBe(false);
+    expect(result.has(SCOPE.READ.FEATURES.PAGE)).toBe(true);
+    expect(result.has(SCOPE.READ.FEATURES.ATTACHMENT)).toBe(true);
+    expect(result.has(SCOPE.WRITE.FEATURES.PAGE)).toBe(true);
+    expect(result.has(SCOPE.WRITE.FEATURES.ATTACHMENT)).toBe(true);
+    expect(result.has(SCOPE.READ.ALL)).toBe(false);
+    expect(result.has(SCOPE.WRITE.ALL)).toBe(false);
   });
 
   it('should extract all scope strings from a nested object', () => {

+ 2 - 2
apps/app/src/client/util/scope-util.ts

@@ -1,5 +1,5 @@
-import type { Scope } from '~/interfaces/scope';
-import { ALL_SIGN } from '~/interfaces/scope';
+import { ALL_SIGN, type Scope } from '@growi/core/dist/interfaces';
+
 
 // Data structure for the final merged scopes
 interface ScopeMap {

+ 1 - 1
apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group-relation.ts

@@ -3,7 +3,7 @@ import type { Router, Request } from 'express';
 
 import type { IExternalUserGroupRelationHasId } from '~/features/external-user-group/interfaces/external-user-group';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { serializeUserGroupRelationSecurely } from '~/server/models/serializers/user-group-relation-serializer';

+ 1 - 1
apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group.ts

@@ -9,7 +9,7 @@ import {
 import ExternalUserGroup from '~/features/external-user-group/server/models/external-user-group';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type { PageActionOnGroupDelete } from '~/interfaces/user-group';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';

+ 1 - 1
apps/app/src/features/growi-plugin/server/routes/apiv3/admin/index.ts

@@ -3,7 +3,7 @@ import express from 'express';
 import { body, query } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';

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

@@ -2,7 +2,7 @@ import { type IUserHasId } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/ai-assistants.ts

@@ -2,7 +2,7 @@ import { type IUserHasId } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';

+ 1 - 1
apps/app/src/features/openai/server/routes/delete-ai-assistant.ts

@@ -5,7 +5,7 @@ import { type ValidationChain, param } from 'express-validator';
 import { isHttpError } from 'http-errors';
 
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/delete-thread.ts

@@ -5,7 +5,7 @@ import { type ValidationChain, param } from 'express-validator';
 import { isHttpError } from 'http-errors';
 
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/edit/index.ts

@@ -8,7 +8,7 @@ import { zodResponseFormat } from 'openai/helpers/zod';
 import type { MessageDelta } from 'openai/resources/beta/threads/messages.mjs';
 import { z } from 'zod';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 // Necessary imports
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';

+ 1 - 1
apps/app/src/features/openai/server/routes/get-threads.ts

@@ -3,7 +3,7 @@ import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 import { type ValidationChain, param } from 'express-validator';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/message/get-messages.ts

@@ -3,7 +3,7 @@ import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 import { type ValidationChain, param } from 'express-validator';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/message/post-message.ts

@@ -1,4 +1,5 @@
 import type { IUserHasId } from '@growi/core/dist/interfaces';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler, Response } from 'express';
 import type { ValidationChain } from 'express-validator';
@@ -7,7 +8,6 @@ import type { AssistantStream } from 'openai/lib/AssistantStream';
 import type { MessageDelta } from 'openai/resources/beta/threads/messages.mjs';
 
 import { getOrCreateChatAssistant } from '~/features/openai/server/services/assistant';
-import { SCOPE } from '~/interfaces/scope';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

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

@@ -3,7 +3,7 @@ import type { Request, RequestHandler } from 'express';
 import { type ValidationChain, param, body } from 'express-validator';
 import { isHttpError } from 'http-errors';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/thread.ts

@@ -4,7 +4,7 @@ import type { Request, RequestHandler } from 'express';
 import type { ValidationChain } from 'express-validator';
 import { body } from 'express-validator';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/features/openai/server/routes/update-ai-assistant.ts

@@ -4,7 +4,7 @@ import type { Request, RequestHandler } from 'express';
 import { type ValidationChain, param } from 'express-validator';
 import { isHttpError } from 'http-errors';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 26 - 24
apps/app/src/features/page-bulk-export/server/routes/apiv3/page-bulk-export.ts

@@ -1,3 +1,4 @@
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request } from 'express';
 import { Router } from 'express';
@@ -18,6 +19,7 @@ interface AuthorizedRequest extends Request {
 }
 
 module.exports = (crowi: Crowi): Router => {
+  const accessTokenParser = crowi.accessTokenParser;
   const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
 
   const validators = {
@@ -28,31 +30,31 @@ module.exports = (crowi: Crowi): Router => {
     ],
   };
 
-  // TODO: https://redmine.weseek.co.jp/issues/166911
-  router.post('/', loginRequiredStrictly, validators.pageBulkExport, async(req: AuthorizedRequest, res: ApiV3Response) => {
-    const errors = validationResult(req);
-    if (!errors.isEmpty()) {
-      return res.status(400).json({ errors: errors.array() });
-    }
-
-    const { path, format, restartJob } = req.body;
-
-    try {
-      await pageBulkExportService?.createOrResetBulkExportJob(path, format, req.user, restartJob);
-      return res.apiv3({}, 204);
-    }
-    catch (err) {
-      logger.error(err);
-      if (err instanceof DuplicateBulkExportJobError) {
-        return res.apiv3Err(new ErrorV3(
-          'Duplicate bulk export job is in progress',
-          'page_export.duplicate_bulk_export_job_error', undefined,
-          { duplicateJob: { createdAt: err.duplicateJob.createdAt } },
-        ), 409);
+  router.post('/', accessTokenParser([SCOPE.WRITE.FEATURES.PAGE_BULK_EXPORT]),
+    loginRequiredStrictly, validators.pageBulkExport, async(req: AuthorizedRequest, res: ApiV3Response) => {
+      const errors = validationResult(req);
+      if (!errors.isEmpty()) {
+        return res.status(400).json({ errors: errors.array() });
       }
-      return res.apiv3Err(new ErrorV3('Failed to start bulk export', 'page_export.failed_to_export'));
-    }
-  });
+
+      const { path, format, restartJob } = req.body;
+
+      try {
+        await pageBulkExportService?.createOrResetBulkExportJob(path, format, req.user, restartJob);
+        return res.apiv3({}, 204);
+      }
+      catch (err) {
+        logger.error(err);
+        if (err instanceof DuplicateBulkExportJobError) {
+          return res.apiv3Err(new ErrorV3(
+            'Duplicate bulk export job is in progress',
+            'page_export.duplicate_bulk_export_job_error', undefined,
+            { duplicateJob: { createdAt: err.duplicateJob.createdAt } },
+          ), 409);
+        }
+        return res.apiv3Err(new ErrorV3('Failed to start bulk export', 'page_export.failed_to_export'));
+      }
+    });
 
   return router;
 

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

@@ -3,7 +3,7 @@ import type { Request } from 'express';
 import { Router } from 'express';
 import { body, validationResult } from 'express-validator';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';

+ 1 - 1
apps/app/src/features/templates/server/routes/apiv3/index.ts

@@ -8,7 +8,7 @@ import { param, query } from 'express-validator';
 
 import { PLUGIN_STORING_PATH } from '~/features/growi-plugin/server/consts';
 import { GrowiPlugin } from '~/features/growi-plugin/server/models';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/interfaces/access-token.ts

@@ -1,4 +1,4 @@
-import type { Scope } from './scope';
+import type { Scope } from '@growi/core/dist/interfaces';
 
 export type IAccessTokenInfo = {
   expiredAt: Date,

+ 1 - 1
apps/app/src/server/crowi/index.js

@@ -62,7 +62,7 @@ class Crowi {
 
   /**
    * For retrieving other packages
-   * @type {(req: import('express').Request, res: import('express').Response, next: import('express').NextFunction) => Promise<void>}
+   * @type {import('~/server/middlewares/access-token-parser').AccessTokenParser}
    */
   accessTokenParser;
 

+ 1 - 1
apps/app/src/server/middlewares/access-token-parser/access-token.integ.ts

@@ -3,7 +3,7 @@ import { serializeUserSecurely } from '@growi/core/dist/models/serializers';
 import type { Response } from 'express';
 import { mock } from 'vitest-mock-extended';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import type UserEvent from '~/server/events/user';
 import { AccessToken } from '~/server/models/access-token';

+ 1 - 2
apps/app/src/server/middlewares/access-token-parser/access-token.ts

@@ -1,8 +1,7 @@
-import type { IUserHasId } from '@growi/core/dist/interfaces';
+import type { IUserHasId, Scope } from '@growi/core/dist/interfaces';
 import { serializeUserSecurely } from '@growi/core/dist/models/serializers';
 import type { Response } from 'express';
 
-import type { Scope } from '~/interfaces/scope';
 import { AccessToken } from '~/server/models/access-token';
 import loggerFactory from '~/utils/logger';
 

+ 6 - 4
apps/app/src/server/middlewares/access-token-parser/index.ts

@@ -1,13 +1,15 @@
+import type { Scope } from '@growi/core/dist/interfaces';
 import type { NextFunction, Response } from 'express';
 
-import type { Scope } from '~/interfaces/scope';
-
 import { parserForAccessToken } from './access-token';
 import { parserForApiToken } from './api-token';
 import type { AccessTokenParserReq } from './interfaces';
 
-export const accessTokenParser = (scopes?: Scope[], opts?: {acceptLegacy: boolean}) => {
-  return async(req: AccessTokenParserReq, res: Response, next: NextFunction): Promise<void> => {
+export type AccessTokenParser = (scopes?: Scope[], opts?: {acceptLegacy: boolean})
+  => (req: AccessTokenParserReq, res: Response, next: NextFunction) => Promise<void>
+
+export const accessTokenParser: AccessTokenParser = (scopes, opts) => {
+  return async(req, res, next): Promise<void> => {
     // TODO: comply HTTP header of RFC6750 / Authorization: Bearer
     if (scopes == null || scopes.length === 0) {
       return next();

+ 1 - 2
apps/app/src/server/models/access-token.ts

@@ -1,6 +1,6 @@
 import crypto from 'crypto';
 
-import type { Ref, IUserHasId } from '@growi/core/dist/interfaces';
+import type { Ref, IUserHasId, Scope } from '@growi/core/dist/interfaces';
 import type {
   Document, Model, Types, HydratedDocument,
 } from 'mongoose';
@@ -8,7 +8,6 @@ import { Schema } from 'mongoose';
 import mongoosePaginate from 'mongoose-paginate-v2';
 import uniqueValidator from 'mongoose-unique-validator';
 
-import type { Scope } from '~/interfaces/scope';
 import loggerFactory from '~/utils/logger';
 
 import { getOrCreateModel } from '../util/mongoose-utils';

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

@@ -5,7 +5,7 @@ import express from 'express';
 import { query } from 'express-validator';
 
 import type { IActivity, ISearchFilter } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import Activity from '~/server/models/activity';
 import { configManager } from '~/server/service/config-manager';

+ 1 - 1
apps/app/src/server/routes/apiv3/admin-home.ts

@@ -1,4 +1,4 @@
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { configManager } from '~/server/service/config-manager';
 import { getGrowiVersion } from '~/utils/growi-version';

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

@@ -1,5 +1,5 @@
 import {
-  ConfigSource, toNonBlankString, toNonBlankStringOrUndefined,
+  ConfigSource, toNonBlankString, toNonBlankStringOrUndefined, SCOPE,
 } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import { body } from 'express-validator';
@@ -7,7 +7,6 @@ import { body } from 'express-validator';
 import { i18n } from '^/config/next-i18next.config';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { configManager } from '~/server/service/config-manager';
 import { getTranslation } from '~/server/service/i18next';

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

@@ -5,7 +5,7 @@ import multer from 'multer';
 import autoReap from 'multer-autoreap';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { AttachmentType } from '~/server/interfaces/attachment';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { Attachment } from '~/server/models/attachment';

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

@@ -3,7 +3,7 @@ import { body } from 'express-validator';
 import type { Types } from 'mongoose';
 
 import type { BookmarkFolderItems } from '~/interfaces/bookmark-info';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
 import { InvalidParentBookmarkFolderError } from '~/server/models/errors';

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

@@ -1,7 +1,7 @@
 import { serializeUserSecurely } from '@growi/core/dist/models/serializers';
 
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { serializeBookmarkSecurely } from '~/server/models/serializers/bookmark-serializer';

+ 1 - 1
apps/app/src/server/routes/apiv3/customize-setting.js

@@ -8,7 +8,7 @@ import multer from 'multer';
 
 import { GrowiPlugin } from '~/features/growi-plugin/server/models';
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { AttachmentType } from '~/server/interfaces/attachment';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { Attachment } from '~/server/models/attachment';

+ 1 - 1
apps/app/src/server/routes/apiv3/export.js

@@ -1,5 +1,5 @@
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { exportService } from '~/server/service/export';
 import loggerFactory from '~/utils/logger';

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

@@ -7,7 +7,7 @@ import express from 'express';
 import { body } from 'express-validator';
 import multer from 'multer';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { isG2GTransferError } from '~/server/models/vo/g2g-transfer-error';
 import { configManager } from '~/server/service/config-manager';

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

@@ -1,7 +1,7 @@
 import { ErrorV3 } from '@growi/core/dist/models';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { getImportService } from '~/server/service/import';
 import { generateOverwriteParams } from '~/server/service/import/overwrite-params';

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

@@ -3,7 +3,7 @@ import express from 'express';
 
 import { SupportedAction } from '~/interfaces/activity';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 

+ 1 - 1
apps/app/src/server/routes/apiv3/notification-setting.js

@@ -2,7 +2,7 @@ import { ErrorV3 } from '@growi/core/dist/models';
 import express from 'express';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { GlobalNotificationSettingType } from '~/server/models/GlobalNotificationSetting';
 import { configManager } from '~/server/service/config-manager';

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

@@ -9,7 +9,7 @@ import { query, oneOf } from 'express-validator';
 import type { HydratedDocument } from 'mongoose';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { configManager } from '~/server/service/config-manager';
 import type { IPageGrantService } from '~/server/service/page-grant';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/check-page-existence.ts

@@ -6,7 +6,7 @@ import type { ValidationChain } from 'express-validator';
 import { query } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/create-page.ts

@@ -16,7 +16,7 @@ import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import type { IApiv3PageCreateParams } from '~/interfaces/apiv3';
 import { subscribeRuleNames } from '~/interfaces/in-app-notification';
 import type { IOptionsForCreate } from '~/interfaces/page';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/get-page-paths-with-descendant-count.ts

@@ -4,7 +4,7 @@ import type { ValidationChain } from 'express-validator';
 import { query } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { PageModel } from '~/server/models/page';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/get-yjs-data.ts

@@ -5,7 +5,7 @@ import type { ValidationChain } from 'express-validator';
 import { param } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { PageModel } from '~/server/models/page';

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

@@ -16,7 +16,7 @@ import sanitize from 'sanitize-filename';
 
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import type { IPageGrantData } from '~/interfaces/page';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/publish-page.ts

@@ -5,7 +5,7 @@ import type { ValidationChain } from 'express-validator';
 import { param } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { PageModel } from '~/server/models/page';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/sync-latest-revision-body-to-yjs-draft.ts

@@ -5,7 +5,7 @@ import type { ValidationChain } from 'express-validator';
 import { param, body } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { PageModel } from '~/server/models/page';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/unpublish-page.ts

@@ -5,7 +5,7 @@ import type { ValidationChain } from 'express-validator';
 import { param } from 'express-validator';
 import mongoose from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import type { PageModel } from '~/server/models/page';

+ 1 - 1
apps/app/src/server/routes/apiv3/page/update-page.ts

@@ -15,7 +15,7 @@ import { isAiEnabled } from '~/features/openai/server/services';
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
 import { type IApiv3PageUpdateParams, PageUpdateErrorCode } from '~/interfaces/apiv3';
 import type { IOptionsForUpdate } from '~/interfaces/page';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';

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

@@ -9,7 +9,7 @@ import { body, query } from 'express-validator';
 
 import { SupportedTargetModel, SupportedAction } from '~/interfaces/activity';
 import { subscribeRuleNames } from '~/interfaces/in-app-notification';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { GlobalNotificationSettingEvent } from '~/server/models/GlobalNotificationSetting';
 import PageTagRelation from '~/server/models/page-tag-relation';

+ 1 - 1
apps/app/src/server/routes/apiv3/personal-setting/delete-access-token.ts

@@ -3,7 +3,7 @@ import type { Request, RequestHandler } from 'express';
 import { query } from 'express-validator';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';

+ 1 - 1
apps/app/src/server/routes/apiv3/personal-setting/delete-all-access-tokens.ts

@@ -3,7 +3,7 @@ import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';

+ 1 - 2
apps/app/src/server/routes/apiv3/personal-setting/generate-access-token.ts

@@ -1,12 +1,11 @@
 import type {
-  IUserHasId,
+  IUserHasId, Scope,
 } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 import { body } from 'express-validator';
 
 import { SupportedAction } from '~/interfaces/activity';
-import type { Scope } from '~/interfaces/scope';
 import type Crowi from '~/server/crowi';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { AccessToken } from '~/server/models/access-token';

+ 1 - 1
apps/app/src/server/routes/apiv3/personal-setting/get-access-tokens.ts

@@ -2,7 +2,7 @@ import type { IUserHasId } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';

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

@@ -5,7 +5,7 @@ import { body } from 'express-validator';
 import { i18n } from '^/config/next-i18next.config';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import loggerFactory from '~/utils/logger';
 

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

@@ -3,7 +3,7 @@ import { serializeUserSecurely } from '@growi/core/dist/models/serializers';
 import express from 'express';
 import { connection } from 'mongoose';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { Revision } from '~/server/models/revision';
 import { normalizeLatestRevisionIfBroken } from '~/server/service/revision/normalize-latest-revision-if-broken';

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

@@ -1,7 +1,7 @@
 import { ErrorV3 } from '@growi/core/dist/models';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import loggerFactory from '~/utils/logger';
 

+ 1 - 2
apps/app/src/server/routes/apiv3/security-settings/index.js

@@ -1,11 +1,10 @@
-import { ConfigSource } from '@growi/core/dist/interfaces';
+import { ConfigSource, SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import xss from 'xss';
 
 
 import { SupportedAction } from '~/interfaces/activity';
 import { PageDeleteConfigValue } from '~/interfaces/page-delete-config';
-import { SCOPE } from '~/interfaces/scope';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/server/routes/apiv3/share-links.js

@@ -4,7 +4,7 @@ import { ErrorV3 } from '@growi/core/dist/models';
 import express from 'express';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';

+ 1 - 1
apps/app/src/server/routes/apiv3/slack-integration-legacy-settings.js

@@ -3,7 +3,7 @@ import express from 'express';
 import { body } from 'express-validator';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { configManager } from '~/server/service/config-manager';
 import loggerFactory from '~/utils/logger';

+ 1 - 2
apps/app/src/server/routes/apiv3/slack-integration-settings.js

@@ -1,4 +1,4 @@
-import { ConfigSource } from '@growi/core/dist/interfaces';
+import { ConfigSource, SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import {
   SlackbotType, REQUEST_TIMEOUT_FOR_GTOP,
@@ -10,7 +10,6 @@ import {
 } from '@growi/slack/dist/utils/check-communicable';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import loggerFactory from '~/utils/logger';
 

+ 1 - 1
apps/app/src/server/routes/apiv3/user-group-relation.js

@@ -1,7 +1,7 @@
 import { ErrorV3 } from '@growi/core/dist/models';
 import express from 'express';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { serializeUserGroupRelationSecurely } from '~/server/models/serializers';
 import UserGroupRelation from '~/server/models/user-group-relation';

+ 1 - 1
apps/app/src/server/routes/apiv3/user-group.js

@@ -7,7 +7,7 @@ import {
 } from 'express-validator';
 
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { serializeUserGroupRelationSecurely } from '~/server/models/serializers/user-group-relation-serializer';
 import UserGroup from '~/server/models/user-group';

+ 1 - 1
apps/app/src/server/routes/apiv3/user/get-related-groups.ts

@@ -2,7 +2,7 @@ import type { IUserHasId } from '@growi/core';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import loggerFactory from '~/utils/logger';

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

@@ -11,7 +11,7 @@ import { isEmail } from 'validator';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import { deleteUserAiAssistant } from '~/features/openai/server/services/delete-ai-assistant';
 import { SupportedAction } from '~/interfaces/activity';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import Activity from '~/server/models/activity';
 import ExternalAccount from '~/server/models/external-account';

+ 1 - 1
apps/app/src/server/routes/attachment/get-brand-logo.ts

@@ -4,7 +4,7 @@ import type {
 } from 'express';
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import loggerFactory from '~/utils/logger';
 

+ 1 - 1
apps/app/src/server/routes/index.js

@@ -2,7 +2,7 @@ import csrf from 'csurf';
 import express from 'express';
 
 import { middlewareFactory as rateLimiterFactory } from '~/features/rate-limiter';
-import { SCOPE } from '~/interfaces/scope';
+import { SCOPE } from '@growi/core/dist/interfaces';
 
 import { accessTokenParser } from '../middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '../middlewares/add-activity';

+ 1 - 1
apps/app/src/server/util/scope-util.spec.ts

@@ -1,6 +1,6 @@
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { describe, it, expect } from 'vitest';
 
-import { SCOPE } from '../../interfaces/scope';
 
 import {
   isValidScope, hasAllScope, extractAllScope, extractScopes,

+ 1 - 1
apps/app/src/server/util/scope-utils.ts

@@ -1,6 +1,6 @@
 import {
   ACTION, ALL_SIGN, SCOPE, type Scope,
-} from '../../interfaces/scope';
+} from '@growi/core/dist/interfaces';
 
 export const isValidScope = (scope: Scope): boolean => {
   const scopeParts = scope.split(':').map(x => (x === ALL_SIGN ? 'ALL' : x.toUpperCase()));

+ 1 - 0
packages/core/src/interfaces/index.ts

@@ -17,3 +17,4 @@ export * from './subscription';
 export * from './tag';
 export * from './user';
 export * from './vite';
+export * from './scope';

+ 1 - 0
apps/app/src/interfaces/scope.ts → packages/core/src/interfaces/scope.ts

@@ -47,6 +47,7 @@ const SCOPE_SEED_USER = {
     bookmark: {},
     questionnaire: {},
     attachment: {},
+    page_bulk_export: {},
   },
 } as const;
 

+ 3 - 4
packages/remark-attachment-refs/src/server/routes/refs.ts

@@ -1,4 +1,5 @@
 import type { IPage, IUser, IAttachment } from '@growi/core';
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { serializeAttachmentSecurely } from '@growi/core/dist/models/serializers';
 import { OptionParser } from '@growi/core/dist/remark-plugins';
 import type { Request } from 'express';
@@ -83,8 +84,7 @@ export const routesFactory = (crowi): any => {
   /**
    * return an Attachment model
    */
-  // TODO: https://redmine.weseek.co.jp/issues/166911
-  router.get('/ref', accessTokenParser(), loginRequired, async(req: RequestWithUser, res) => {
+  router.get('/ref', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, async(req: RequestWithUser, res) => {
     const user = req.user;
     const { pagePath, fileNameOrId } = req.query;
     const filterXSS = new FilterXSS();
@@ -139,8 +139,7 @@ export const routesFactory = (crowi): any => {
   /**
    * return a list of Attachment
    */
-  // TODO: https://redmine.weseek.co.jp/issues/166911
-  router.get('/refs', accessTokenParser(), loginRequired, async(req: RequestWithUser, res) => {
+  router.get('/refs', accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }), loginRequired, async(req: RequestWithUser, res) => {
     const user = req.user;
     const { prefix, pagePath } = req.query;
     const options: Record<string, string | undefined> = JSON.parse(req.query.options?.toString() ?? '');

+ 2 - 1
packages/remark-lsx/src/server/index.ts

@@ -4,6 +4,7 @@ import { FilterXSS } from 'xss';
 
 import type { LsxApiOptions } from '../interfaces/api';
 
+import { SCOPE } from '@growi/core/dist/interfaces';
 import { listPages } from './routes/list-pages';
 
 const loginRequiredFallback = (req: Request, res: Response) => {
@@ -59,7 +60,7 @@ const middleware = (crowi: any, app: any): void => {
 
   app.get(
     '/_api/lsx',
-    accessTokenParser(), // TODO: https://redmine.weseek.co.jp/issues/166911
+    accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
     loginRequired,
     lsxValidator,
     paramValidator,