Skip to content

Commit 065bea0

Browse files
committed
Restoration of /page-listing/info
1 parent c6c81ac commit 065bea0

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

apps/app/src/server/routes/apiv3/page-listing.ts

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,160 @@ const routerFactory = (crowi: Crowi): Router => {
174174
},
175175
);
176176

177+
/**
178+
* @swagger
179+
*
180+
* /page-listing/info:
181+
* get:
182+
* tags: [PageListing]
183+
* security:
184+
* - bearer: []
185+
* - accessTokenInQuery: []
186+
* summary: /page-listing/info
187+
* description: Get summary information of pages
188+
* parameters:
189+
* - name: pageIds
190+
* in: query
191+
* description: Array of page IDs to retrieve information for (One of pageIds or path is required)
192+
* schema:
193+
* type: array
194+
* items:
195+
* type: string
196+
* - name: path
197+
* in: query
198+
* description: Path of the page to retrieve information for (One of pageIds or path is required)
199+
* schema:
200+
* type: string
201+
* - name: attachBookmarkCount
202+
* in: query
203+
* schema:
204+
* type: boolean
205+
* - name: attachShortBody
206+
* in: query
207+
* schema:
208+
* type: boolean
209+
* responses:
210+
* 200:
211+
* description: Get the information of a page
212+
* content:
213+
* application/json:
214+
* schema:
215+
* type: object
216+
* additionalProperties:
217+
* $ref: '#/components/schemas/PageInfoAll'
218+
*/
219+
router.get(
220+
'/info',
221+
accessTokenParser([SCOPE.READ.FEATURES.PAGE], { acceptLegacy: true }),
222+
validator.pageIdsOrPathRequired,
223+
validator.infoParams,
224+
apiV3FormValidator,
225+
async (req: AuthorizedRequest, res: ApiV3Response) => {
226+
const {
227+
pageIds,
228+
path,
229+
attachBookmarkCount: attachBookmarkCountParam,
230+
attachShortBody: attachShortBodyParam,
231+
} = req.query;
232+
233+
const attachBookmarkCount: boolean = attachBookmarkCountParam === 'true';
234+
const attachShortBody: boolean = attachShortBodyParam === 'true';
235+
236+
const Page = mongoose.model<HydratedDocument<PageDocument>, PageModel>(
237+
'Page',
238+
);
239+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
240+
const Bookmark = mongoose.model<any, any>('Bookmark');
241+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
242+
const pageService = crowi.pageService;
243+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
244+
const pageGrantService: IPageGrantService = crowi.pageGrantService!;
245+
246+
try {
247+
const pages =
248+
pageIds != null
249+
? await Page.findByIdsAndViewer(
250+
pageIds as string[],
251+
req.user,
252+
null,
253+
true,
254+
)
255+
: await Page.findByPathAndViewer(
256+
path as string,
257+
req.user,
258+
null,
259+
false,
260+
true,
261+
);
262+
263+
const foundIds = pages.map((page) => page._id);
264+
265+
let shortBodiesMap: Record<string, string | null> | undefined;
266+
if (attachShortBody) {
267+
shortBodiesMap = await pageService.shortBodiesMapByPageIds(
268+
foundIds,
269+
req.user,
270+
);
271+
}
272+
273+
let bookmarkCountMap: Record<string, number> | undefined;
274+
if (attachBookmarkCount) {
275+
bookmarkCountMap = (await Bookmark.getPageIdToCountMap(
276+
foundIds,
277+
)) as Record<string, number>;
278+
}
279+
280+
const idToPageInfoMap: Record<string, IPageInfo | IPageInfoForListing> =
281+
{};
282+
283+
const isGuestUser = req.user == null;
284+
285+
const userRelatedGroups = await pageGrantService.getUserRelatedGroups(
286+
req.user,
287+
);
288+
289+
for (const page of pages) {
290+
const basicPageInfo = {
291+
...pageService.constructBasicPageInfo(page, isGuestUser),
292+
bookmarkCount:
293+
bookmarkCountMap != null
294+
? (bookmarkCountMap[page._id.toString()] ?? 0)
295+
: 0,
296+
};
297+
298+
// TODO: use pageService.getCreatorIdForCanDelete to get creatorId (https://redmine.weseek.co.jp/issues/140574)
299+
const canDeleteCompletely = pageService.canDeleteCompletely(
300+
page,
301+
page.creator == null ? null : getIdForRef(page.creator),
302+
req.user,
303+
false,
304+
userRelatedGroups,
305+
); // use normal delete config
306+
307+
const pageInfo = !isIPageInfoForEntity(basicPageInfo)
308+
? basicPageInfo
309+
: ({
310+
...basicPageInfo,
311+
isAbleToDeleteCompletely: canDeleteCompletely,
312+
revisionShortBody:
313+
shortBodiesMap != null
314+
? (shortBodiesMap[page._id.toString()] ?? undefined)
315+
: undefined,
316+
} satisfies IPageInfoForListing);
317+
318+
idToPageInfoMap[page._id.toString()] = pageInfo;
319+
}
320+
321+
return res.apiv3(idToPageInfoMap);
322+
} catch (err) {
323+
logger.error('Error occurred while fetching page informations.', err);
324+
return res.apiv3Err(
325+
new ErrorV3('Error occurred while fetching page informations.'),
326+
);
327+
}
328+
},
329+
);
330+
177331
/**
178332
* @swagger
179333
*

0 commit comments

Comments
 (0)