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

Merge pull request #10053 from weseek/imprv/167156-prevent-rom-users-from-issuing-and-using-new-access-tokens

impv: Prevent rom users from issuing and using new access tokens
Shun Miyazawa 10 месяцев назад
Родитель
Сommit
03b1e2f0d6

+ 1 - 0
apps/app/config/logger/config.dev.js

@@ -44,4 +44,5 @@ module.exports = {
   // 'growi:cli:ItemsTree': 'debug',
   'growi:searchResultList': 'debug',
   'growi:service:openai': 'debug',
+  'growi:middleware:access-token-parser:access-token': 'debug',
 };

+ 12 - 4
apps/app/src/client/components/Me/ApiSettings.tsx

@@ -2,6 +2,8 @@ import React from 'react';
 
 import { useTranslation } from 'next-i18next';
 
+import { useCurrentUser } from '~/stores-universal/context';
+
 import { AccessTokenSettings } from './AccessTokenSettings';
 import { ApiTokenSettings } from './ApiTokenSettings';
 
@@ -9,6 +11,9 @@ import { ApiTokenSettings } from './ApiTokenSettings';
 const ApiSettings = React.memo((): JSX.Element => {
 
   const { t } = useTranslation();
+  const { data: currentUser, isLoading: isLoadingCurrentUserData } = useCurrentUser();
+
+  const shouldHideAccessTokenSettings = isLoadingCurrentUserData || !currentUser?.readOnly;
 
   return (
     <>
@@ -16,10 +21,13 @@ const ApiSettings = React.memo((): JSX.Element => {
         <h2 className="border-bottom pb-2 my-4 fs-4">{ t('API Token Settings') }</h2>
         <ApiTokenSettings />
       </div>
-      <div className="mt-4">
-        <h2 className="border-bottom pb-2 my-4 fs-4">{ t('Access Token Settings') }</h2>
-        <AccessTokenSettings />
-      </div>
+
+      {shouldHideAccessTokenSettings && (
+        <div className="mt-4">
+          <h2 className="border-bottom pb-2 my-4 fs-4">{ t('Access Token Settings') }</h2>
+          <AccessTokenSettings />
+        </div>
+      )}
     </>
   );
 });

+ 5 - 0
apps/app/src/server/middlewares/access-token-parser/access-token.ts

@@ -35,6 +35,11 @@ export const parserForAccessToken = (scopes: Scope[]) => {
       return;
     }
 
+    if (userByAccessToken.readOnly) {
+      logger.debug('The access token\'s associated user is read-only');
+      return;
+    }
+
     // transforming attributes
     req.user = serializeUserSecurely(userByAccessToken);
     if (req.user == null) {

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

@@ -8,6 +8,7 @@ import type Crowi from '~/server/crowi';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
 import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
+import { excludeReadOnlyUser } from '~/server/middlewares/exclude-read-only-user';
 import { AccessToken } from '~/server/models/access-token';
 import loggerFactory from '~/utils/logger';
 
@@ -40,6 +41,7 @@ export const deleteAccessTokenHandlersFactory: DeleteAccessTokenHandlersFactory
   return [
     accessTokenParser([SCOPE.WRITE.USER_SETTINGS.API.ACCESS_TOKEN]),
     loginRequiredStrictly,
+    excludeReadOnlyUser,
     addActivity,
     validator,
     apiV3FormValidator,

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

@@ -7,6 +7,7 @@ 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';
+import { excludeReadOnlyUser } from '~/server/middlewares/exclude-read-only-user';
 import { AccessToken } from '~/server/models/access-token';
 import loggerFactory from '~/utils/logger';
 
@@ -29,6 +30,7 @@ export const deleteAllAccessTokensHandlersFactory: DeleteAllAccessTokensHandlers
   return [
     accessTokenParser([SCOPE.WRITE.USER_SETTINGS.API.ACCESS_TOKEN]),
     loginRequiredStrictly,
+    excludeReadOnlyUser,
     addActivity,
     async(req: DeleteAllAccessTokensRequest, res: ApiV3Response) => {
       const { user } = req;

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

@@ -8,6 +8,7 @@ import { body } from 'express-validator';
 import { SupportedAction } from '~/interfaces/activity';
 import type Crowi from '~/server/crowi';
 import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity';
+import { excludeReadOnlyUser } from '~/server/middlewares/exclude-read-only-user';
 import { AccessToken } from '~/server/models/access-token';
 import { isValidScope } from '~/server/util/scope-utils';
 import loggerFactory from '~/utils/logger';
@@ -81,6 +82,7 @@ export const generateAccessTokenHandlerFactory: GenerateAccessTokenHandlerFactor
 
   return [
     loginRequiredStrictly,
+    excludeReadOnlyUser,
     addActivity,
     validator,
     apiV3FormValidator,

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

@@ -6,6 +6,7 @@ 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';
+import { excludeReadOnlyUser } from '~/server/middlewares/exclude-read-only-user';
 import { AccessToken } from '~/server/models/access-token';
 import loggerFactory from '~/utils/logger';
 
@@ -27,6 +28,7 @@ export const getAccessTokenHandlerFactory: GetAccessTokenHandlerFactory = (crowi
   return [
     accessTokenParser([SCOPE.READ.USER_SETTINGS.API.ACCESS_TOKEN]),
     loginRequiredStrictly,
+    excludeReadOnlyUser,
     addActivity,
     async(req: GetAccessTokenRequest, res: ApiV3Response) => {
       const { user } = req;