|
|
@@ -1,8 +1,6 @@
|
|
|
-import express, {
|
|
|
- Request, Router,
|
|
|
-} from 'express';
|
|
|
+import express, { Request, Router } from 'express';
|
|
|
import { pagePathUtils } from '@growi/core';
|
|
|
-import { query } from 'express-validator';
|
|
|
+import { query, oneOf } from 'express-validator';
|
|
|
|
|
|
import { PageDocument, PageModel } from '../../models/page';
|
|
|
import ErrorV3 from '../../models/vo/error-apiv3';
|
|
|
@@ -25,10 +23,14 @@ interface AuthorizedRequest extends Request {
|
|
|
* Validators
|
|
|
*/
|
|
|
const validator = {
|
|
|
- getPagesAroundTarget: [
|
|
|
+ pageIdAndPathRequired: [
|
|
|
query('id').isMongoId().withMessage('id is required'),
|
|
|
query('path').isString().withMessage('path is required'),
|
|
|
],
|
|
|
+ pageIdOrPathRequired: oneOf([
|
|
|
+ query('id').isMongoId(),
|
|
|
+ query('path').isString(),
|
|
|
+ ], 'id or path is required'),
|
|
|
};
|
|
|
|
|
|
/*
|
|
|
@@ -36,24 +38,23 @@ const validator = {
|
|
|
*/
|
|
|
export default (crowi: Crowi): Router => {
|
|
|
const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
|
|
|
- // Do not use loginRequired with isGuestAllowed true since page tree may show private pages' title
|
|
|
+ // Do not use loginRequired with isGuestAllowed true since page tree may show private page titles
|
|
|
const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
|
|
|
+ const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
|
|
|
|
|
|
const router = express.Router();
|
|
|
|
|
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
- router.get('/pages', accessTokenParser, loginRequiredStrictly, ...validator.getPagesAroundTarget, async(req: AuthorizedRequest, res: ApiV3Response): Promise<any> => {
|
|
|
+ router.get('/siblings', accessTokenParser, loginRequiredStrictly, ...validator.pageIdAndPathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response): Promise<any> => {
|
|
|
const { id, path } = req.query;
|
|
|
|
|
|
const Page: PageModel = crowi.model('Page');
|
|
|
|
|
|
let siblings: PageDocument[];
|
|
|
- let ancestors: PageDocument[];
|
|
|
let target: PageDocument;
|
|
|
try {
|
|
|
siblings = await Page.findSiblingsByPathAndViewer(path as string, req.user);
|
|
|
- ancestors = await Page.findAncestorsByPath(path as string);
|
|
|
|
|
|
target = siblings.filter(page => page._id.toString() === id)?.[0];
|
|
|
if (target == null) {
|
|
|
@@ -69,7 +70,29 @@ export default (crowi: Crowi): Router => {
|
|
|
siblings = siblings.filter(page => !isTopPage(page.path));
|
|
|
}
|
|
|
|
|
|
- return res.apiv3({ target, ancestors, pages: siblings });
|
|
|
+ return res.apiv3({ target, siblings });
|
|
|
+ });
|
|
|
+
|
|
|
+ // eslint-disable-next-line max-len
|
|
|
+ router.get('/ancestors', accessTokenParser, loginRequiredStrictly, validator.pageIdOrPathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response): Promise<any> => {
|
|
|
+ const { id, path } = req.query;
|
|
|
+
|
|
|
+ const Page: PageModel = crowi.model('Page');
|
|
|
+
|
|
|
+ let ancestors: PageDocument[];
|
|
|
+ try {
|
|
|
+ ancestors = await Page.findAncestorsByPathOrId((path || id) as string);
|
|
|
+
|
|
|
+ if (ancestors.length === 0 && !isTopPage(path as string)) {
|
|
|
+ throw Error('Ancestors must have at least one page.');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (err) {
|
|
|
+ logger.error('Error occurred while finding pages.', err);
|
|
|
+ return res.apiv3Err(new ErrorV3('Error occurred while finding pages.'));
|
|
|
+ }
|
|
|
+
|
|
|
+ return res.apiv3({ ancestors });
|
|
|
});
|
|
|
|
|
|
return router;
|