Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
113b1a0
Define new user page visibility setting in config definitions
arvid-e Nov 27, 2025
3f7c80a
Add hide user page setting to general setting api
arvid-e Nov 27, 2025
f03ce22
Rename user page visibility setting
arvid-e Dec 1, 2025
639b6cf
Add user page visibility setting to general admin settings
arvid-e Dec 9, 2025
089a629
Add user page visibility setting to general security settings update …
arvid-e Dec 9, 2025
39c2a41
Create react component for user page visibility settings
arvid-e Dec 9, 2025
2cbf0c5
Change setting variable name
arvid-e Dec 10, 2025
0bb6616
Update setting description
arvid-e Dec 10, 2025
5e1be4f
Write translations for user page visibility setting
arvid-e Dec 15, 2025
0814c1c
fix ja_JP/admin.json
yuki-takei Dec 15, 2025
4e0a11d
Merge pull request #10592 from growilabs/feat/174782-user-page-visibi…
yuki-takei Dec 15, 2025
a6b6fbc
Hide user pages by checking URI in TreeItemLayout
arvid-e Dec 16, 2025
181e9a6
Add swr hook for getting user page visibility setting
arvid-e Dec 16, 2025
83aacc2
Add prop for hiding user pages in ItemsTree
arvid-e Dec 16, 2025
101b6c6
Import hook and use user page visibility setting in ItemsTree
arvid-e Dec 16, 2025
3b15e5c
Change name of page visibility boolean
arvid-e Dec 16, 2025
3399a29
Change to backend solution
arvid-e Dec 23, 2025
87d0779
Revert change in TreeItemLayout
arvid-e Dec 23, 2025
d5c5438
Move user page hiding implementation to PageListingService
arvid-e Dec 24, 2025
5242e7e
Merge pull request #10612 from growilabs/feat/175920-change-user-page…
arvid-e Dec 25, 2025
0471f06
Block viewing other users pages
arvid-e Dec 24, 2025
81d11a0
Add reminder and change contant name
arvid-e Dec 24, 2025
ffda7ab
Change to correct config name for hiding user pages
arvid-e Dec 25, 2025
e5f737e
Change to using regex to block the /user page also
arvid-e Dec 25, 2025
7716f94
Block user pages using page route middleware
arvid-e Jan 5, 2026
8e38216
Fix lint error
arvid-e Jan 5, 2026
b636aeb
Revert middleware solution
arvid-e Jan 6, 2026
9af9e27
Add solution in page data injection
arvid-e Jan 6, 2026
a6a03ea
Block api calls for user pages
arvid-e Jan 6, 2026
3f8c22d
View user pages for admins
arvid-e Jan 6, 2026
a2c2a26
Format code
arvid-e Jan 6, 2026
3a2c8cf
Format code
arvid-e Jan 6, 2026
fbdc265
Fix lint error
arvid-e Jan 6, 2026
624a90e
Disallow user page viewing for the admin
arvid-e Jan 7, 2026
dc1954e
Add hideUserPages argument to interface
arvid-e Jan 7, 2026
2577f65
Add ending comma
arvid-e Jan 7, 2026
d82d837
Remove and own page check in page filter
arvid-e Jan 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/app/public/static/locales/en_US/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
"enable_force_delete_user_homepage_on_user_deletion": "When you delete a user, the user's homepage and all its sub pages will be completely deleted",
"desc": "You will be able to delete a deleted user's homepage."
},
"user_page_visibility": {
"user_page_visibility": "User page visibility",
"hide_user_pages": "Hide user pages",
"desc": "Hides all user related pages for general users"
},
"session": "Session",
"max_age": "Max age (msec)",
"max_age_desc": "Specifies the number (in milliseconds) to expire users session.<br>Default: 2592000000 (30days)",
Expand Down
5 changes: 5 additions & 0 deletions apps/app/public/static/locales/fr_FR/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
"enable_force_delete_user_homepage_on_user_deletion": "Supprimer la page d'accueil et ses pages enfants",
"desc": "Les pages d'accueil utilisateurs pourront être supprimées."
},
"user_page_visibility": {
"user_page_visibility": "Visibilité de la page utilisateur",
"hide_user_pages": "Masquer les pages utilisateur",
"desc": "Masque toutes les pages liées aux utilisateurs pour les utilisateurs généraux"
},
"session": "Session",
"max_age": "Âge maximal (ms)",
"max_age_desc": "Spécifie (en milliseconde) l'âge maximal d'une session <br>Par défaut: 2592000000 (30 jours)",
Expand Down
5 changes: 5 additions & 0 deletions apps/app/public/static/locales/ja_JP/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
"enable_force_delete_user_homepage_on_user_deletion": "ユーザーを削除したとき、ユーザーホームページとその配下のページを完全削除する",
"desc": "削除済みユーザーのユーザーホームページを削除できるようになります。"
},
"user_page_visibility": {
"user_page_visibility": "ユーザーページの表示/非表示",
"hide_user_pages": "ユーザーページを非表示にする",
"desc": "一般ユーザーに対して、すべてのユーザー関連ページを非表示にする"
},
"session": "セッション",
"max_age": "有効期間 (ミリ秒)",
"max_age_desc": "ユーザーのセッション情報の有効期間をミリ秒で指定できます。<br>デフォルト値: 2592000000 (30日間)",
Expand Down
5 changes: 5 additions & 0 deletions apps/app/public/static/locales/ko_KR/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
"enable_force_delete_user_homepage_on_user_deletion": "사용자를 삭제할 때, 사용자의 홈페이지와 모든 하위 페이지가 완전히 삭제됩니다.",
"desc": "삭제된 사용자의 홈페이지를 삭제할 수 있습니다."
},
"user_page_visibility": {
"user_page_visibility": "사용자 페이지 가시성",
"hide_user_pages": "사용자 페이지 숨기기",
"desc": "일반 사용자를 위해 모든 사용자 관련 페이지를 숨깁니다"
},
"session": "세션",
"max_age": "최대 수명 (밀리초)",
"max_age_desc": "사용자 세션이 만료되는 시간(밀리초)을 지정합니다.<br>기본값: 2592000000 (30일)",
Expand Down
5 changes: 5 additions & 0 deletions apps/app/public/static/locales/zh_CN/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
"enable_force_delete_user_homepage_on_user_deletion": "删除用户时,该用户的主页及其所有子页面将被完全删除",
"desc": "您可以删除已删除用户的主页。"
},
"user_page_visibility": {
"user_page_visibility": "用户页面可见性",
"hide_user_pages": "隐藏用户页面",
"desc": "对一般用户隐藏所有用户相关页面"
},
"session": "会议",
"max_age": "有效期间 (msec)",
"max_age_desc": "指定使用户会话过期的数量(以毫秒为单位)。<br>默认值: 2592000000 (30天)",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable react/no-danger */
import React from 'react';

import type AdminGeneralSecurityContainer from '~/client/services/AdminGeneralSecurityContainer';

type Props = {
adminGeneralSecurityContainer: AdminGeneralSecurityContainer;
t: (key: string) => string;
};

export const UserPageVisibilitySettings: React.FC<Props> = ({ adminGeneralSecurityContainer, t }) => {
return (
<>
<h4 className="mb-3">{t('security_settings.user_page_visibility.user_page_visibility')}</h4>
<div className="row mb-4">
<div className="col-md-10 offset-md-2">
<div className="form-check form-switch form-check-success">
<input
type="checkbox"
className="form-check-input"
id="is-user-pages-visible"
checked={adminGeneralSecurityContainer.state.isHidingUserPages}
onChange={() => { adminGeneralSecurityContainer.changeUserPageVisibility() }}
/>
<label className="form-label form-check-label" htmlFor="is-user-pages-visible">
{t('security_settings.user_page_visibility.hide_user_pages')}
</label>
</div>
<p
className="form-text text-muted small mt-2"
dangerouslySetInnerHTML={{ __html: t('security_settings.user_page_visibility.desc') }}
/>
</div>
</div>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PageDeleteRightsSettings } from './PageDeleteRightsSettings';
import { PageListDisplaySettings } from './PageListDisplaySettings';
import { SessionMaxAgeSettings } from './SessionMaxAgeSettings';
import { UserHomepageDeletionSettings } from './UserHomepageDeletionSettings';
import { UserPageVisibilitySettings } from './UserPageVisibilitySettings';

type FormData = {
sessionMaxAge: string;
Expand Down Expand Up @@ -48,6 +49,7 @@ const SecuritySettingComponent: React.FC<Props> = ({ adminGeneralSecurityContain
hideRestrictedByGroup: adminGeneralSecurityContainer.state.currentGroupRestrictionDisplayMode === 'Hidden',
hideRestrictedByOwner: adminGeneralSecurityContainer.state.currentOwnerRestrictionDisplayMode === 'Hidden',
isUsersHomepageDeletionEnabled: adminGeneralSecurityContainer.state.isUsersHomepageDeletionEnabled,
isHidingUserPages: adminGeneralSecurityContainer.state.isHidingUserPages,
isForceDeleteUserHomepageOnUserDeletion: adminGeneralSecurityContainer.state.isForceDeleteUserHomepageOnUserDeletion,
isRomUserAllowedToComment: adminGeneralSecurityContainer.state.isRomUserAllowedToComment,
});
Expand Down Expand Up @@ -78,6 +80,7 @@ const SecuritySettingComponent: React.FC<Props> = ({ adminGeneralSecurityContain
<PageAccessRightsSettings adminGeneralSecurityContainer={adminGeneralSecurityContainer} t={t} />
<PageDeleteRightsSettings adminGeneralSecurityContainer={adminGeneralSecurityContainer} t={t} />
<UserHomepageDeletionSettings adminGeneralSecurityContainer={adminGeneralSecurityContainer} t={t} />
<UserPageVisibilitySettings adminGeneralSecurityContainer={adminGeneralSecurityContainer} t={t} />
<CommentManageRightsSettings adminGeneralSecurityContainer={adminGeneralSecurityContainer} t={t} />
<SessionMaxAgeSettings register={register} t={t} />

Expand Down
9 changes: 9 additions & 0 deletions apps/app/src/client/services/AdminGeneralSecurityContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default class AdminGeneralSecurityContainer extends Container {
expandOtherOptionsForCompleteDeletion: false,
isShowRestrictedByOwner: false,
isUsersHomepageDeletionEnabled: false,
isHidingUserPages: false,
isForceDeleteUserHomepageOnUserDeletion: false,
isRomUserAllowedToComment: false,
isLocalEnabled: false,
Expand All @@ -60,6 +61,7 @@ export default class AdminGeneralSecurityContainer extends Container {
this.changeOwnerRestrictionDisplayMode = this.changeOwnerRestrictionDisplayMode.bind(this);
this.changeGroupRestrictionDisplayMode = this.changeGroupRestrictionDisplayMode.bind(this);
this.changePageDeletionAuthority = this.changePageDeletionAuthority.bind(this);
this.changeUserPageVisibility = this.changeUserPageVisibility.bind(this);
this.changePageCompleteDeletionAuthority = this.changePageCompleteDeletionAuthority.bind(this);
this.changePageRecursiveDeletionAuthority = this.changePageRecursiveDeletionAuthority.bind(this);
this.changePageRecursiveCompleteDeletionAuthority = this.changePageRecursiveCompleteDeletionAuthority.bind(this);
Expand All @@ -83,6 +85,7 @@ export default class AdminGeneralSecurityContainer extends Container {
currentOwnerRestrictionDisplayMode: generalSetting.hideRestrictedByOwner === false ? 'Displayed' : 'Hidden',
currentGroupRestrictionDisplayMode: generalSetting.hideRestrictedByGroup === false ? 'Displayed' : 'Hidden',
isUsersHomepageDeletionEnabled: generalSetting.isUsersHomepageDeletionEnabled,
isHidingUserPages: generalSetting.isHidingUserPages,
isForceDeleteUserHomepageOnUserDeletion: generalSetting.isForceDeleteUserHomepageOnUserDeletion,
isRomUserAllowedToComment: generalSetting.isRomUserAllowedToComment,
sessionMaxAge: generalSetting.sessionMaxAge,
Expand Down Expand Up @@ -155,6 +158,10 @@ export default class AdminGeneralSecurityContainer extends Container {
this.setState({ currentPageDeletionAuthority: val });
}

changeUserPageVisibility() {
this.setState({ isHidingUserPages: !this.state.isHidingUserPages });
}

/**
* Change pageCompleteDeletionAuthority
*/
Expand Down Expand Up @@ -252,6 +259,7 @@ export default class AdminGeneralSecurityContainer extends Container {
hideRestrictedByGroup: formData.hideRestrictedByGroup,
hideRestrictedByOwner: formData.hideRestrictedByOwner,
isUsersHomepageDeletionEnabled: formData.isUsersHomepageDeletionEnabled,
isHidingUserPages: formData.isHidingUserPages,
isForceDeleteUserHomepageOnUserDeletion: formData.isForceDeleteUserHomepageOnUserDeletion,
isRomUserAllowedToComment: formData.isRomUserAllowedToComment,
} : {
Expand All @@ -265,6 +273,7 @@ export default class AdminGeneralSecurityContainer extends Container {
hideRestrictedByGroup: this.state.currentGroupRestrictionDisplayMode === 'Hidden',
hideRestrictedByOwner: this.state.currentOwnerRestrictionDisplayMode === 'Hidden',
isUsersHomepageDeletionEnabled: this.state.isUsersHomepageDeletionEnabled,
isHidingUserPages: this.state.isHidingUserPages,
isForceDeleteUserHomepageOnUserDeletion: this.state.isForceDeleteUserHomepageOnUserDeletion,
isRomUserAllowedToComment: this.state.isRomUserAllowedToComment,
};
Expand Down
17 changes: 17 additions & 0 deletions apps/app/src/pages/[[...path]].page.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v7.3 ベースのコードのように見える

master ブランチからの乖離が激しいので follow してから再実装してください

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import type {
} from '@growi/core';
import { isIPageInfo } from '@growi/core';
import { isClient, pagePathUtils, pathUtils } from '@growi/core/dist/utils';
import {
isUserPage,
isUsersTopPage,
} from '@growi/core/dist/utils/page-path-utils';
import EventEmitter from 'events';
import ExtensibleCustomError from 'extensible-custom-error';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
Expand Down Expand Up @@ -640,6 +644,19 @@ async function injectPageData(

props.pageWithMeta = null;

const hideUserPages = configManager.getConfig('security:isHidingUserPages');

if (hideUserPages && page) {
const isTopPage = isUsersTopPage(page.path);
const isSpecificUserPage = isUserPage(page.path);

if (isTopPage || isSpecificUserPage) {
props.pageWithMeta = null;
props.isNotFound = true;
return;
}
}

// populate & check if the revision is latest
if (page != null) {
page.initLatestRevisionField(revisionId);
Expand Down
16 changes: 16 additions & 0 deletions apps/app/src/server/models/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,22 @@ export class PageQueryBuilder {
return this;
}

addConditionToListByNotMatchPathAndChildren(str: string): PageQueryBuilder {
const path = normalizePath(str);

if (isTopPage(path)) {
return this;
}

const startsPattern = escapeStringRegexp(path);

this.query = this.query.and({
path: { $not: new RegExp(`^${startsPattern}(/|$)`) },
});

return this;
}

addConditionToListByMatch(str: string): PageQueryBuilder {
// No request is set for "/"
if (str === '/') {
Expand Down
24 changes: 22 additions & 2 deletions apps/app/src/server/routes/apiv3/page-listing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
import { getIdForRef, isIPageInfoForEntity } from '@growi/core';
import { SCOPE } from '@growi/core/dist/interfaces';
import { ErrorV3 } from '@growi/core/dist/models';
import { isUserPage, isUsersTopPage } from '@growi/core/dist/utils/page-path-utils';
import type { Request, Router } from 'express';
import express from 'express';
import { query, oneOf } from 'express-validator';
Expand Down Expand Up @@ -143,13 +144,15 @@ const routerFactory = (crowi: Crowi): Router => {
loginRequired, validator.pageIdOrPathRequired, apiV3FormValidator, async(req: AuthorizedRequest, res: ApiV3Response) => {
const { id, path } = req.query;

const hideUserPages = await configManager.getConfig('security:isHidingUserPages');
const hideRestrictedByOwner = await configManager.getConfig('security:list-policy:hideRestrictedByOwner');
const hideRestrictedByGroup = await configManager.getConfig('security:list-policy:hideRestrictedByGroup');

try {
const pages = await pageListingService.findChildrenByParentPathOrIdAndViewer(
(id || path) as string, req.user, !hideRestrictedByOwner, !hideRestrictedByGroup,
(id || path) as string, req.user, !hideRestrictedByOwner, !hideRestrictedByGroup, hideUserPages === true,
);

return res.apiv3({ children: pages });
}
catch (err) {
Expand Down Expand Up @@ -219,10 +222,27 @@ const routerFactory = (crowi: Crowi): Router => {
const pageGrantService: IPageGrantService = crowi.pageGrantService!;

try {
const pages = pageIds != null
let pages = pageIds != null
? await Page.findByIdsAndViewer(pageIds as string[], req.user, null, true)
: await Page.findByPathAndViewer(path as string, req.user, null, false, true);

const hideUserPages = crowi.configManager.getConfig('security:isHidingUserPages');

if (hideUserPages) {
pages = pages.filter((page) => {
const targetPath = page.path;
const isTargetUserPage = isUserPage(targetPath) || isUsersTopPage(targetPath);

if (isTargetUserPage) return false;

return true;
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この filter もうちょっとシンプルに書ける

}

if (pages.length === 0 && path != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path != null という条件はなんのために必要なんだっけ?

return res.apiv3Err(new ErrorV3('Page is not found', 'not_found'), 404);
}

const foundIds = pages.map(page => page._id);

let shortBodiesMap;
Expand Down
8 changes: 7 additions & 1 deletion apps/app/src/server/routes/apiv3/security-settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const validator = {
'Deny', 'Readonly',
]),
body('pageCompleteDeletionAuthority').if(value => value != null).isString().isIn(Object.values(PageDeleteConfigValue)),
body('isHidingUserPages').if(value => value != null).isBoolean(),
body('hideRestrictedByOwner').if(value => value != null).isBoolean(),
body('hideRestrictedByGroup').if(value => value != null).isBoolean(),
body('isUsersHomepageDeletionEnabled').if(value => value != null).isBoolean(),
Expand Down Expand Up @@ -139,6 +140,9 @@ const validator = {
* pageCompleteDeletionAuthority:
* type: string
* description: type of pageDeletionAuthority
* isHidingUserPages:
* type: boolean
* description: hide all user pages from general users
* hideRestrictedByOwner:
* type: boolean
* description: enable hide by owner
Expand Down Expand Up @@ -457,7 +461,6 @@ module.exports = (crowi) => {
* $ref: '#/components/schemas/GitHubOAuthSetting'
*/
router.get('/', accessTokenParser([SCOPE.READ.ADMIN.SECURITY]), loginRequiredStrictly, adminRequired, async(req, res) => {

const securityParams = {
generalSetting: {
restrictGuestMode: crowi.aclService.getGuestModeValue(),
Expand All @@ -467,6 +470,7 @@ module.exports = (crowi) => {
pageRecursiveCompleteDeletionAuthority: await configManager.getConfig('security:pageRecursiveCompleteDeletionAuthority'),
isAllGroupMembershipRequiredForPageCompleteDeletion:
await configManager.getConfig('security:isAllGroupMembershipRequiredForPageCompleteDeletion'),
isHidingUserPages: await configManager.getConfig('security:isHidingUserPages'),
hideRestrictedByOwner: await configManager.getConfig('security:list-policy:hideRestrictedByOwner'),
hideRestrictedByGroup: await configManager.getConfig('security:list-policy:hideRestrictedByGroup'),
isUsersHomepageDeletionEnabled: await configManager.getConfig('security:user-homepage-deletion:isEnabled'),
Expand Down Expand Up @@ -747,6 +751,7 @@ module.exports = (crowi) => {
'security:pageCompleteDeletionAuthority': req.body.pageCompleteDeletionAuthority,
'security:pageRecursiveCompleteDeletionAuthority': req.body.pageRecursiveCompleteDeletionAuthority,
'security:isAllGroupMembershipRequiredForPageCompleteDeletion': req.body.isAllGroupMembershipRequiredForPageCompleteDeletion,
'security:isHidingUserPages': req.body.isHidingUserPages,
'security:list-policy:hideRestrictedByOwner': req.body.hideRestrictedByOwner,
'security:list-policy:hideRestrictedByGroup': req.body.hideRestrictedByGroup,
'security:user-homepage-deletion:isEnabled': req.body.isUsersHomepageDeletionEnabled,
Expand Down Expand Up @@ -783,6 +788,7 @@ module.exports = (crowi) => {
pageRecursiveCompleteDeletionAuthority: await configManager.getConfig('security:pageRecursiveCompleteDeletionAuthority'),
isAllGroupMembershipRequiredForPageCompleteDeletion:
await configManager.getConfig('security:isAllGroupMembershipRequiredForPageCompleteDeletion'),
isHidingUserPages: await configManager.getConfig('security:isHidingUserPages'),
hideRestrictedByOwner: await configManager.getConfig('security:list-policy:hideRestrictedByOwner'),
hideRestrictedByGroup: await configManager.getConfig('security:list-policy:hideRestrictedByGroup'),
isUsersHomepageDeletionEnabled: await configManager.getConfig('security:user-homepage-deletion:isEnabled'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const CONFIG_KEYS = [
'security:pageRecursiveDeletionAuthority',
'security:pageRecursiveCompleteDeletionAuthority',
'security:isAllGroupMembershipRequiredForPageCompleteDeletion',
'security:isHidingUserPages',
'security:user-homepage-deletion:isEnabled',
'security:user-homepage-deletion:isForceDeleteUserHomepageOnUserDeletion',
'security:isRomUserAllowedToComment',
Expand Down Expand Up @@ -661,6 +662,9 @@ export const CONFIG_DEFINITIONS = {
'security:isAllGroupMembershipRequiredForPageCompleteDeletion': defineConfig<boolean>({
defaultValue: true,
}),
'security:isHidingUserPages': defineConfig<boolean>({
defaultValue: false,
}),
'security:user-homepage-deletion:isEnabled': defineConfig<boolean>({
defaultValue: false,
}),
Expand Down
7 changes: 7 additions & 0 deletions apps/app/src/server/service/page-listing/page-listing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface IPageListingService {
user?: IUser,
showPagesRestrictedByOwner?: boolean,
showPagesRestrictedByGroup?: boolean,
hideUserPages?: boolean,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この行は不要ではないか?

): Promise<IPageForTreeItem[]>,
}

Expand Down Expand Up @@ -50,6 +51,7 @@ class PageListingService implements IPageListingService {
user?: IUser,
showPagesRestrictedByOwner = false,
showPagesRestrictedByGroup = false,
hideUserPages = false,
): Promise<IPageForTreeItem[]> {
const Page = mongoose.model<HydratedDocument<PageDocument>, PageModel>('Page');
let queryBuilder: PageQueryBuilder;
Expand All @@ -63,6 +65,11 @@ class PageListingService implements IPageListingService {
// Use $eq for user-controlled sources. see: https://codeql.github.com/codeql-query-help/javascript/js-sql-injection/#recommendation
queryBuilder = new PageQueryBuilder(Page.find({ parent: { $eq: parentId } }), true);
}

if (hideUserPages) {
queryBuilder.addConditionToListByNotMatchPathAndChildren('/user');
}

await queryBuilder.addViewerCondition(user, null, undefined, showPagesRestrictedByOwner, showPagesRestrictedByGroup);

const pages: HydratedDocument<Omit<IPageForTreeItem, 'processData'>>[] = await queryBuilder
Expand Down