|
|
@@ -4,7 +4,6 @@ import { pathUtils } from '@growi/core/dist/utils';
|
|
|
import escapeStringRegexp from 'escape-string-regexp';
|
|
|
import type { Request, Response } from 'express';
|
|
|
import createError, { isHttpError } from 'http-errors';
|
|
|
-import mongoose from 'mongoose';
|
|
|
|
|
|
import type { LsxApiParams, LsxApiResponseData } from '../../../interfaces/api';
|
|
|
import { addDepthCondition } from './add-depth-condition';
|
|
|
@@ -67,93 +66,86 @@ interface IListPagesRequest
|
|
|
user: IUser;
|
|
|
}
|
|
|
|
|
|
-export const listPages = async (
|
|
|
- req: IListPagesRequest,
|
|
|
- res: Response,
|
|
|
-): Promise<Response> => {
|
|
|
- const user = req.user;
|
|
|
-
|
|
|
- const Config = mongoose.model('Config');
|
|
|
- const hideUserPageConfig = await Config.findOne({
|
|
|
- key: 'security:isHidingUserPages',
|
|
|
- });
|
|
|
-
|
|
|
- const hideUserPageConfigValue = hideUserPageConfig?.value;
|
|
|
- const hideUserPagesEnabled = hideUserPageConfigValue === 'true';
|
|
|
- const isAdmin = user?.admin ?? false;
|
|
|
- const shouldHideUserPages = hideUserPagesEnabled && !isAdmin;
|
|
|
-
|
|
|
- if (req.query.pagePath == null) {
|
|
|
- return res.status(400).send("the 'pagepath' query must not be null.");
|
|
|
- }
|
|
|
-
|
|
|
- const params: LsxApiParams = {
|
|
|
- pagePath: removeTrailingSlash(req.query.pagePath),
|
|
|
- offset: req.query?.offset,
|
|
|
- limit: req.query?.limit,
|
|
|
- options: req.query?.options ?? {},
|
|
|
- };
|
|
|
+export const listPages = ({ excludedPaths }: { excludedPaths: string[] }) => {
|
|
|
+ return async (req: IListPagesRequest, res: Response): Promise<Response> => {
|
|
|
+ const params: LsxApiParams = {
|
|
|
+ pagePath: removeTrailingSlash(req.query.pagePath),
|
|
|
+ offset: req.query?.offset,
|
|
|
+ limit: req.query?.limit,
|
|
|
+ options: req.query?.options ?? {},
|
|
|
+ };
|
|
|
|
|
|
- const { pagePath, offset, limit, options } = params;
|
|
|
- const builder = await generateBaseQuery(params.pagePath, user);
|
|
|
- let builderQuery = builder.query;
|
|
|
+ const { pagePath, offset, limit, options } = params;
|
|
|
+ const user = req.user;
|
|
|
|
|
|
- if (shouldHideUserPages) {
|
|
|
- builderQuery = builderQuery.and([{ path: { $not: /^\/user(\/|$)/ } }]);
|
|
|
- }
|
|
|
+ const builder = await generateBaseQuery(params.pagePath, user);
|
|
|
+ let query = builder.query;
|
|
|
|
|
|
- // count viewers of `/`
|
|
|
- let toppageViewersCount: number;
|
|
|
- try {
|
|
|
- toppageViewersCount = await getToppageViewersCount();
|
|
|
- } catch (error) {
|
|
|
- // biome-ignore lint/suspicious/noConsole: Allow to use console.error here
|
|
|
- console.error('Error occurred in getToppageViewersCount:', error);
|
|
|
- return res.status(500).send('An internal server error occurred.');
|
|
|
- }
|
|
|
+ if (excludedPaths.length > 0) {
|
|
|
+ const escapedPaths = excludedPaths.map((p) => {
|
|
|
+ const cleanPath = p.startsWith('/') ? p.substring(1) : p;
|
|
|
+ return cleanPath.replace(/\//g, '\\/');
|
|
|
+ });
|
|
|
|
|
|
- let query = builder.query;
|
|
|
- try {
|
|
|
- // depth
|
|
|
- if (options?.depth != null) {
|
|
|
- query = addDepthCondition(
|
|
|
- query,
|
|
|
- params.pagePath,
|
|
|
- OptionParser.parseRange(options.depth),
|
|
|
- );
|
|
|
- }
|
|
|
- // filter
|
|
|
- if (options?.filter != null) {
|
|
|
- query = addFilterCondition(query, pagePath, options.filter);
|
|
|
+ const regex = new RegExp(`^\\/(${escapedPaths.join('|')})(\\/|$)`);
|
|
|
+ query = query.and([{ path: { $not: regex } }]);
|
|
|
}
|
|
|
- if (options?.except != null) {
|
|
|
- query = addExceptCondition(query, pagePath, options.except);
|
|
|
- }
|
|
|
-
|
|
|
- // get total num before adding num/sort conditions
|
|
|
- const total = await query.clone().count();
|
|
|
-
|
|
|
- // num
|
|
|
- query = addNumCondition(query, offset, limit);
|
|
|
- // sort
|
|
|
- query = addSortCondition(query, options?.sort, options?.reverse);
|
|
|
|
|
|
- const pages = await query.exec();
|
|
|
- const cursor = (offset ?? 0) + pages.length;
|
|
|
+ // count viewers of `/`
|
|
|
+ let toppageViewersCount: number;
|
|
|
+ try {
|
|
|
+ toppageViewersCount = await getToppageViewersCount();
|
|
|
+ } catch (error) {
|
|
|
+ // biome-ignore lint/suspicious/noConsole: Allow to use console.error here
|
|
|
+ console.error('Error occurred in getToppageViewersCount:', error);
|
|
|
+ return res.status(500).send('An internal server error occurred.');
|
|
|
+ }
|
|
|
|
|
|
- const responseData: LsxApiResponseData = {
|
|
|
- pages,
|
|
|
- cursor,
|
|
|
- total,
|
|
|
- toppageViewersCount,
|
|
|
- };
|
|
|
- return res.status(200).send(responseData);
|
|
|
- } catch (error) {
|
|
|
- // biome-ignore lint/suspicious/noConsole: Allow to use console.error here
|
|
|
- console.error('Error occurred while processing listPages request:', error);
|
|
|
- if (isHttpError(error)) {
|
|
|
- return res.status(error.status).send(error.message);
|
|
|
+ try {
|
|
|
+ // depth
|
|
|
+ if (options?.depth != null) {
|
|
|
+ query = addDepthCondition(
|
|
|
+ query,
|
|
|
+ params.pagePath,
|
|
|
+ OptionParser.parseRange(options.depth),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // filter
|
|
|
+ if (options?.filter != null) {
|
|
|
+ query = addFilterCondition(query, pagePath, options.filter);
|
|
|
+ }
|
|
|
+ if (options?.except != null) {
|
|
|
+ query = addExceptCondition(query, pagePath, options.except);
|
|
|
+ }
|
|
|
+
|
|
|
+ // get total num before adding num/sort conditions
|
|
|
+ const total = await query.clone().count();
|
|
|
+
|
|
|
+ // num
|
|
|
+ query = addNumCondition(query, offset, limit);
|
|
|
+ // sort
|
|
|
+ query = addSortCondition(query, options?.sort, options?.reverse);
|
|
|
+
|
|
|
+ const pages = await query.exec();
|
|
|
+ const cursor = (offset ?? 0) + pages.length;
|
|
|
+
|
|
|
+ const responseData: LsxApiResponseData = {
|
|
|
+ pages,
|
|
|
+ cursor,
|
|
|
+ total,
|
|
|
+ toppageViewersCount,
|
|
|
+ };
|
|
|
+ return res.status(200).send(responseData);
|
|
|
+ } catch (error) {
|
|
|
+ // biome-ignore lint/suspicious/noConsole: Allow to use console.error here
|
|
|
+ console.error(
|
|
|
+ 'Error occurred while processing listPages request:',
|
|
|
+ error,
|
|
|
+ );
|
|
|
+ if (isHttpError(error)) {
|
|
|
+ return res.status(error.status).send(error.message);
|
|
|
+ }
|
|
|
+ return res.status(500).send('An internal server error occurred.');
|
|
|
}
|
|
|
- return res.status(500).send('An internal server error occurred.');
|
|
|
- }
|
|
|
+ };
|
|
|
};
|