|
@@ -1,9 +1,9 @@
|
|
|
-
|
|
|
|
|
import type {
|
|
import type {
|
|
|
IUserHasId,
|
|
IUserHasId,
|
|
|
} from '@growi/core/dist/interfaces';
|
|
} from '@growi/core/dist/interfaces';
|
|
|
import { ErrorV3 } from '@growi/core/dist/models';
|
|
import { ErrorV3 } from '@growi/core/dist/models';
|
|
|
import type { Request, RequestHandler } from 'express';
|
|
import type { Request, RequestHandler } from 'express';
|
|
|
|
|
+import { body } from 'express-validator';
|
|
|
|
|
|
|
|
import { SupportedAction } from '~/interfaces/activity';
|
|
import { SupportedAction } from '~/interfaces/activity';
|
|
|
import type Crowi from '~/server/crowi';
|
|
import type Crowi from '~/server/crowi';
|
|
@@ -11,6 +11,7 @@ import { generateAddActivityMiddleware } from '~/server/middlewares/add-activity
|
|
|
import { AccessToken } from '~/server/models/access-token';
|
|
import { AccessToken } from '~/server/models/access-token';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
|
|
|
|
+import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
|
|
|
import type { ApiV3Response } from '../interfaces/apiv3-response';
|
|
import type { ApiV3Response } from '../interfaces/apiv3-response';
|
|
|
|
|
|
|
|
const logger = loggerFactory('growi:routes:apiv3:personal-setting:generate-access-tokens');
|
|
const logger = loggerFactory('growi:routes:apiv3:personal-setting:generate-access-tokens');
|
|
@@ -25,9 +26,45 @@ interface GenerateAccessTokenRequest extends Request<undefined, ApiV3Response, R
|
|
|
user: IUserHasId,
|
|
user: IUserHasId,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
type GenerateAccessTokenHandlerFactory = (crowi: Crowi) => RequestHandler[];
|
|
type GenerateAccessTokenHandlerFactory = (crowi: Crowi) => RequestHandler[];
|
|
|
|
|
|
|
|
|
|
+const validator = [
|
|
|
|
|
+ body('expiredAt')
|
|
|
|
|
+ .exists()
|
|
|
|
|
+ .withMessage('expiredAt is required')
|
|
|
|
|
+ .custom((value) => {
|
|
|
|
|
+ const expiredAt = new Date(value);
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+
|
|
|
|
|
+ // Check if date is valid
|
|
|
|
|
+ if (Number.isNaN(expiredAt.getTime())) {
|
|
|
|
|
+ throw new Error('Invalid date format');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Check if date is in the future
|
|
|
|
|
+ if (expiredAt <= now) {
|
|
|
|
|
+ throw new Error('Expiration date must be in the future');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }),
|
|
|
|
|
+
|
|
|
|
|
+ body('description')
|
|
|
|
|
+ .optional()
|
|
|
|
|
+ .isString()
|
|
|
|
|
+ .withMessage('description must be a string')
|
|
|
|
|
+ .isLength({ max: 200 })
|
|
|
|
|
+ .withMessage('description must be less than or equal to 200 characters'),
|
|
|
|
|
+
|
|
|
|
|
+ body('scope')
|
|
|
|
|
+ .optional()
|
|
|
|
|
+ .isArray()
|
|
|
|
|
+ .withMessage('scope must be an array')
|
|
|
|
|
+ .custom(() => {
|
|
|
|
|
+ // TODO: Check if all values are valid
|
|
|
|
|
+ }),
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
export const generateAccessTokenHandlerFactory: GenerateAccessTokenHandlerFactory = (crowi) => {
|
|
export const generateAccessTokenHandlerFactory: GenerateAccessTokenHandlerFactory = (crowi) => {
|
|
|
|
|
|
|
|
const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi);
|
|
const loginRequiredStrictly = require('../../../middlewares/login-required')(crowi);
|
|
@@ -36,7 +73,10 @@ export const generateAccessTokenHandlerFactory: GenerateAccessTokenHandlerFactor
|
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
return [
|
|
|
- loginRequiredStrictly, addActivity,
|
|
|
|
|
|
|
+ loginRequiredStrictly,
|
|
|
|
|
+ addActivity,
|
|
|
|
|
+ validator,
|
|
|
|
|
+ apiV3FormValidator,
|
|
|
async(req: GenerateAccessTokenRequest, res: ApiV3Response) => {
|
|
async(req: GenerateAccessTokenRequest, res: ApiV3Response) => {
|
|
|
|
|
|
|
|
const { user, body } = req;
|
|
const { user, body } = req;
|