|
@@ -756,7 +756,7 @@ module.exports = (crowi) => {
|
|
|
* tags: [Users]
|
|
* tags: [Users]
|
|
|
* operationId: removeUser
|
|
* operationId: removeUser
|
|
|
* summary: /users/{id}/remove
|
|
* summary: /users/{id}/remove
|
|
|
- * description: Delete user
|
|
|
|
|
|
|
+ * description: Delete user and if isUserPageDeletionEnabled delete user home pages
|
|
|
* parameters:
|
|
* parameters:
|
|
|
* - name: id
|
|
* - name: id
|
|
|
* in: path
|
|
* in: path
|
|
@@ -766,7 +766,7 @@ module.exports = (crowi) => {
|
|
|
* type: string
|
|
* type: string
|
|
|
* responses:
|
|
* responses:
|
|
|
* 200:
|
|
* 200:
|
|
|
- * description: Deleting user success
|
|
|
|
|
|
|
+ * description: Deleting user success and if isUserPageDeletionEnabled delete user home pages success
|
|
|
* content:
|
|
* content:
|
|
|
* application/json:
|
|
* application/json:
|
|
|
* schema:
|
|
* schema:
|
|
@@ -774,72 +774,88 @@ module.exports = (crowi) => {
|
|
|
* userData:
|
|
* userData:
|
|
|
* type: object
|
|
* type: object
|
|
|
* description: data of delete user
|
|
* description: data of delete user
|
|
|
|
|
+ * deletedPagePaths:
|
|
|
|
|
+ * type: array
|
|
|
|
|
+ * description: a list of deleted pages path
|
|
|
|
|
+ * isRecursively:
|
|
|
|
|
+ * type: boolean
|
|
|
|
|
+ * description: a flag indicating whether the page has been recursively deleted
|
|
|
|
|
+ * isCompletely:
|
|
|
|
|
+ * type: boolean
|
|
|
|
|
+ * description: a flag indicating whether the page has been completely deleted
|
|
|
*/
|
|
*/
|
|
|
router.delete('/:id/remove', loginRequiredStrictly, adminRequired, certifyUserOperationOtherThenYourOwn, addActivity, async(req, res) => {
|
|
router.delete('/:id/remove', loginRequiredStrictly, adminRequired, certifyUserOperationOtherThenYourOwn, addActivity, async(req, res) => {
|
|
|
const { id } = req.params;
|
|
const { id } = req.params;
|
|
|
const isUserPageDeletionEnabled = crowi.configManager.getConfig('crowi', 'security:isUserPageDeletionEnabled');
|
|
const isUserPageDeletionEnabled = crowi.configManager.getConfig('crowi', 'security:isUserPageDeletionEnabled');
|
|
|
|
|
|
|
|
- let serializedUserData;
|
|
|
|
|
- let username;
|
|
|
|
|
|
|
+ const isCompletely = true;
|
|
|
|
|
+ const isRecursively = true;
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
const userData = await User.findById(id);
|
|
const userData = await User.findById(id);
|
|
|
// !! DO NOT MOVE username FROM THIS POSITION !! -- 05.31.2023
|
|
// !! DO NOT MOVE username FROM THIS POSITION !! -- 05.31.2023
|
|
|
// catch username before delete user because username will be change to deleted_at_*
|
|
// catch username before delete user because username will be change to deleted_at_*
|
|
|
- username = userData.username;
|
|
|
|
|
|
|
+ const username = userData.username;
|
|
|
|
|
+
|
|
|
await UserGroupRelation.remove({ relatedUser: userData });
|
|
await UserGroupRelation.remove({ relatedUser: userData });
|
|
|
await userData.statusDelete();
|
|
await userData.statusDelete();
|
|
|
await ExternalAccount.remove({ user: userData });
|
|
await ExternalAccount.remove({ user: userData });
|
|
|
|
|
|
|
|
- serializedUserData = serializeUserSecurely(userData);
|
|
|
|
|
|
|
+ const serializedUserData = serializeUserSecurely(userData);
|
|
|
|
|
|
|
|
activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_USERS_REMOVE });
|
|
activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_USERS_REMOVE });
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
- logger.error('Error', err);
|
|
|
|
|
- return res.apiv3Err(new ErrorV3(err));
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- if (isUserPageDeletionEnabled) {
|
|
|
|
|
- // find userHomePage
|
|
|
|
|
- const userHomePage = await Page.findUserHomePage(username);
|
|
|
|
|
|
|
+ // TODO: Check page deletion logic are correct
|
|
|
|
|
+ // see: https://redmine.weseek.co.jp/issues/123556
|
|
|
|
|
+ // TODO: Commonize the page deletion logic
|
|
|
|
|
+ // see: https://redmine.weseek.co.jp/issues/123550
|
|
|
|
|
+ if (isUserPageDeletionEnabled) {
|
|
|
|
|
+ const userHomePage = await Page.findUserHomePage(username);
|
|
|
|
|
|
|
|
- // return error if no deletalbe page
|
|
|
|
|
- if (userHomePage == null) {
|
|
|
|
|
- logger.error('userHomePage is not found');
|
|
|
|
|
- const msg = 'user collection deleted but user home page is not found';
|
|
|
|
|
- return res.apiv3Err(new ErrorV3(msg));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (userHomePage == null) {
|
|
|
|
|
+ logger.error('user home page is not found.');
|
|
|
|
|
+ throw new ErrorV3('user collection deleted but user home page is not found');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // delete completely
|
|
|
|
|
- const isCompletely = true;
|
|
|
|
|
- // delete recursively
|
|
|
|
|
- const isRecursively = true;
|
|
|
|
|
|
|
+ const pagesToDelete = [userHomePage];
|
|
|
|
|
+ const pagesCanBeDeleted = crowi.pageService.filterPagesByCanDeleteCompletely(
|
|
|
|
|
+ pagesToDelete,
|
|
|
|
|
+ req.user,
|
|
|
|
|
+ isRecursively,
|
|
|
|
|
+ isUserPageDeletionEnabled,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
- // chack delete completely able userhomepage
|
|
|
|
|
- const pagesToDelete = [userHomePage];
|
|
|
|
|
- const pagesCanBeDeleted = crowi.pageService.filterPagesByCanDeleteCompletely(pagesToDelete, req.user, isRecursively, isUserPageDeletionEnabled);
|
|
|
|
|
|
|
+ if (pagesCanBeDeleted.length === 0) {
|
|
|
|
|
+ logger.warn('no pages can be deleted.');
|
|
|
|
|
+ throw new ErrorV3('user collection deleted but no pages can be deleted');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // return error if no deletalbe page
|
|
|
|
|
- if (pagesCanBeDeleted.length === 0) {
|
|
|
|
|
- logger.warn('No pages can be deleted.');
|
|
|
|
|
- const msg = 'user collection deleted but no pages can be deleted';
|
|
|
|
|
- return res.apiv3Err(new ErrorV3(msg));
|
|
|
|
|
|
|
+ const activityParameters = {
|
|
|
|
|
+ ip: req.ip,
|
|
|
|
|
+ endpoint: req.originalUrl,
|
|
|
|
|
+ };
|
|
|
|
|
+ const options = { isCompletely, isRecursively };
|
|
|
|
|
+ crowi.pageService.deleteMultiplePages(pagesCanBeDeleted, req.user, options, activityParameters);
|
|
|
|
|
+
|
|
|
|
|
+ return res.apiv3({
|
|
|
|
|
+ userData: serializedUserData,
|
|
|
|
|
+ deletedPagePaths: pagesCanBeDeleted.map(p => p.path),
|
|
|
|
|
+ isRecursively,
|
|
|
|
|
+ isCompletely,
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // run delete
|
|
|
|
|
- const activityParameters = {
|
|
|
|
|
- ip: req.ip,
|
|
|
|
|
- endpoint: req.originalUrl,
|
|
|
|
|
- };
|
|
|
|
|
- const options = { isCompletely, isRecursively };
|
|
|
|
|
- crowi.pageService.deleteMultiplePages(pagesCanBeDeleted, req.user, options, activityParameters);
|
|
|
|
|
-
|
|
|
|
|
return res.apiv3({
|
|
return res.apiv3({
|
|
|
- userData: serializedUserData, paths: pagesCanBeDeleted.map(p => p.path), isRecursively, isCompletely,
|
|
|
|
|
|
|
+ userData: serializedUserData,
|
|
|
|
|
+ deletedPagePaths: [],
|
|
|
|
|
+ isRecursively,
|
|
|
|
|
+ isCompletely,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- return res.apiv3({ userData: serializedUserData });
|
|
|
|
|
|
|
+ catch (err) {
|
|
|
|
|
+ logger.error('Error', err);
|
|
|
|
|
+ return res.apiv3Err(new ErrorV3(err));
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
/**
|