users.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. const loggerFactory = require('@alias/logger');
  2. const logger = loggerFactory('growi:routes:apiv3:user-group');
  3. const express = require('express');
  4. const router = express.Router();
  5. const { body } = require('express-validator/check');
  6. const { isEmail } = require('validator');
  7. const validator = {};
  8. /**
  9. * @swagger
  10. * tags:
  11. * name: Users
  12. */
  13. module.exports = (crowi) => {
  14. const loginRequiredStrictly = require('../../middleware/login-required')(crowi);
  15. const adminRequired = require('../../middleware/admin-required')(crowi);
  16. const csrf = require('../../middleware/csrf')(crowi);
  17. const {
  18. ErrorV3,
  19. User,
  20. Page,
  21. ExternalAccount,
  22. } = crowi.models;
  23. const { ApiV3FormValidator } = crowi.middlewares;
  24. /**
  25. * @swagger
  26. *
  27. * paths:
  28. * /_api/v3/users:
  29. * get:
  30. * tags: [Users]
  31. * description: Get users
  32. * responses:
  33. * 200:
  34. * description: users are fetched
  35. * content:
  36. * application/json:
  37. * schema:
  38. * properties:
  39. * users:
  40. * type: object
  41. * description: a result of `Users.find`
  42. */
  43. router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
  44. try {
  45. const page = parseInt(req.query.page) || 1;
  46. const result = await User.findUsersWithPagination({ page });
  47. const { docs: users, total: totalUsers, limit: pagingLimit } = result;
  48. return res.apiv3({ users, totalUsers, pagingLimit });
  49. }
  50. catch (err) {
  51. const msg = 'Error occurred in fetching user group list';
  52. logger.error('Error', err);
  53. return res.apiv3Err(new ErrorV3(msg, 'user-group-list-fetch-failed'));
  54. }
  55. });
  56. validator.inviteEmail = [
  57. // isEmail prevents line breaks, so use isString
  58. body('shapedEmailList').custom((value) => {
  59. const array = value.filter((value) => { return isEmail(value) });
  60. if (array.length === 0) {
  61. throw new Error('At least one valid email address is required');
  62. }
  63. return array;
  64. }),
  65. ];
  66. /**
  67. * @swagger
  68. *
  69. * paths:
  70. * /_api/v3/users/invite:
  71. * post:
  72. * tags: [Users]
  73. * description: Create new users and send Emails
  74. * parameters:
  75. * - name: shapedEmailList
  76. * in: query
  77. * description: Invitation emailList
  78. * schema:
  79. * type: object
  80. * - name: sendEmail
  81. * in: query
  82. * description: Whether to send mail
  83. * schema:
  84. * type: boolean
  85. * responses:
  86. * 200:
  87. * description: Inviting user success
  88. * content:
  89. * application/json:
  90. * schema:
  91. * properties:
  92. * createdUserList:
  93. * type: object
  94. * description: Users successfully created
  95. * existingEmailList:
  96. * type: object
  97. * description: Users email that already exists
  98. */
  99. router.post('/invite', loginRequiredStrictly, adminRequired, csrf, validator.inviteEmail, ApiV3FormValidator, async(req, res) => {
  100. try {
  101. const emailList = await User.createUsersByInvitation(req.body.shapedEmailList, req.body.sendEmail);
  102. return res.apiv3({ emailList });
  103. }
  104. catch (err) {
  105. logger.error('Error', err);
  106. return res.apiv3Err(new ErrorV3(err));
  107. }
  108. });
  109. /**
  110. * @swagger
  111. *
  112. * paths:
  113. * /_api/v3/users/{id}/giveAdmin:
  114. * put:
  115. * tags: [Users]
  116. * description: Give user admin
  117. * parameters:
  118. * - name: id
  119. * in: path
  120. * required: true
  121. * description: id of user for admin
  122. * schema:
  123. * type: string
  124. * responses:
  125. * 200:
  126. * description: Give user admin success
  127. * content:
  128. * application/json:
  129. * schema:
  130. * properties:
  131. * userData:
  132. * type: object
  133. * description: data of admin user
  134. */
  135. router.put('/:id/giveAdmin', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  136. const { id } = req.params;
  137. try {
  138. const userData = await User.findById(id);
  139. await userData.makeAdmin();
  140. return res.apiv3({ userData });
  141. }
  142. catch (err) {
  143. logger.error('Error', err);
  144. return res.apiv3Err(new ErrorV3(err));
  145. }
  146. });
  147. /**
  148. * @swagger
  149. *
  150. * paths:
  151. * /_api/v3/users/{id}/removeAdmin:
  152. * put:
  153. * tags: [Users]
  154. * description: Remove user admin
  155. * parameters:
  156. * - name: id
  157. * in: path
  158. * required: true
  159. * description: id of user for removing admin
  160. * schema:
  161. * type: string
  162. * responses:
  163. * 200:
  164. * description: Remove user admin success
  165. * content:
  166. * application/json:
  167. * schema:
  168. * properties:
  169. * userData:
  170. * type: object
  171. * description: data of removed admin user
  172. */
  173. router.put('/:id/removeAdmin', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  174. const { id } = req.params;
  175. try {
  176. const userData = await User.findById(id);
  177. await userData.removeFromAdmin();
  178. return res.apiv3({ userData });
  179. }
  180. catch (err) {
  181. logger.error('Error', err);
  182. return res.apiv3Err(new ErrorV3(err));
  183. }
  184. });
  185. /**
  186. * @swagger
  187. *
  188. * paths:
  189. * /_api/v3/users/{id}/activate:
  190. * put:
  191. * tags: [Users]
  192. * description: Activate user
  193. * parameters:
  194. * - name: id
  195. * in: path
  196. * required: true
  197. * description: id of activate user
  198. * schema:
  199. * type: string
  200. * responses:
  201. * 200:
  202. * description: Activationg user success
  203. * content:
  204. * application/json:
  205. * schema:
  206. * properties:
  207. * userData:
  208. * type: object
  209. * description: data of activate user
  210. */
  211. router.put('/:id/activate', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  212. // check user upper limit
  213. const isUserCountExceedsUpperLimit = await User.isUserCountExceedsUpperLimit();
  214. if (isUserCountExceedsUpperLimit) {
  215. const msg = 'Unable to activate because user has reached limit';
  216. logger.error('Error', msg);
  217. return res.apiv3Err(new ErrorV3(msg));
  218. }
  219. const { id } = req.params;
  220. try {
  221. const userData = await User.findById(id);
  222. await userData.statusActivate();
  223. return res.apiv3({ userData });
  224. }
  225. catch (err) {
  226. logger.error('Error', err);
  227. return res.apiv3Err(new ErrorV3(err));
  228. }
  229. });
  230. /**
  231. * @swagger
  232. *
  233. * paths:
  234. * /_api/v3/users/{id}/deactivate:
  235. * put:
  236. * tags: [Users]
  237. * description: Deactivate user
  238. * parameters:
  239. * - name: id
  240. * in: path
  241. * required: true
  242. * description: id of deactivate user
  243. * schema:
  244. * type: string
  245. * responses:
  246. * 200:
  247. * description: Deactivationg user success
  248. * content:
  249. * application/json:
  250. * schema:
  251. * properties:
  252. * userData:
  253. * type: object
  254. * description: data of deactivate user
  255. */
  256. router.put('/:id/deactivate', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  257. const { id } = req.params;
  258. try {
  259. const userData = await User.findById(id);
  260. await userData.statusSuspend();
  261. return res.apiv3({ userData });
  262. }
  263. catch (err) {
  264. logger.error('Error', err);
  265. return res.apiv3Err(new ErrorV3(err));
  266. }
  267. });
  268. /**
  269. * @swagger
  270. *
  271. * paths:
  272. * /_api/v3/users/{id}/remove:
  273. * delete:
  274. * tags: [Users]
  275. * description: Delete user
  276. * parameters:
  277. * - name: id
  278. * in: path
  279. * required: true
  280. * description: id of delete user
  281. * schema:
  282. * type: string
  283. * responses:
  284. * 200:
  285. * description: Deleting user success
  286. * content:
  287. * application/json:
  288. * schema:
  289. * properties:
  290. * userData:
  291. * type: object
  292. * description: data of delete user
  293. */
  294. router.delete('/:id/remove', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  295. const { id } = req.params;
  296. try {
  297. const userData = await User.findById(id);
  298. await userData.statusDelete();
  299. await ExternalAccount.remove({ user: userData });
  300. await Page.removeByPath(`/user/${userData.username}`);
  301. return res.apiv3({ userData });
  302. }
  303. catch (err) {
  304. logger.error('Error', err);
  305. return res.apiv3Err(new ErrorV3(err));
  306. }
  307. });
  308. return router;
  309. };