Browse Source

Merge pull request #7609 from weseek/feat/120698-120954-give-read-only

feat: Create giveReadOnly and removeReadOnly endpoints
Yuki Takei 2 years ago
parent
commit
ccfaf31133
2 changed files with 125 additions and 6 deletions
  1. 18 6
      apps/app/src/server/models/user.js
  2. 107 0
      apps/app/src/server/routes/apiv3/users.js

+ 18 - 6
apps/app/src/server/models/user.js

@@ -7,7 +7,6 @@ import loggerFactory from '~/utils/logger';
 
 const crypto = require('crypto');
 
-const debug = require('debug')('growi:models:user');
 const mongoose = require('mongoose');
 const mongoosePaginate = require('mongoose-paginate-v2');
 const uniqueValidator = require('mongoose-unique-validator');
@@ -68,6 +67,7 @@ module.exports = function(crowi) {
     },
     lastLoginAt: { type: Date },
     admin: { type: Boolean, default: 0, index: true },
+    readOnly: { type: Boolean, default: 0 },
     isInvitationEmailSended: { type: Boolean, default: false },
   }, {
     timestamps: true,
@@ -265,31 +265,43 @@ module.exports = function(crowi) {
   };
 
   userSchema.methods.removeFromAdmin = async function() {
-    debug('Remove from admin', this);
+    logger.debug('Remove from admin', this);
     this.admin = 0;
     return this.save();
   };
 
   userSchema.methods.makeAdmin = async function() {
-    debug('Admin', this);
+    logger.debug('Admin', this);
     this.admin = 1;
     return this.save();
   };
 
+  userSchema.methods.giveReadOnly = async function() {
+    logger.debug('Give read only flag', this);
+    this.readOnly = 1;
+    return this.save();
+  };
+
+  userSchema.methods.removeReadOnly = async function() {
+    logger.debug('Remove read only flag', this);
+    this.readOnly = 0;
+    return this.save();
+  };
+
   userSchema.methods.asyncMakeAdmin = async function(callback) {
     this.admin = 1;
     return this.save();
   };
 
   userSchema.methods.statusActivate = async function() {
-    debug('Activate User', this);
+    logger.debug('Activate User', this);
     this.status = STATUS_ACTIVE;
     const userData = await this.save();
     return userEvent.emit('activated', userData);
   };
 
   userSchema.methods.statusSuspend = async function() {
-    debug('Suspend User', this);
+    logger.debug('Suspend User', this);
     this.status = STATUS_SUSPENDED;
     if (this.email === undefined || this.email === null) { // migrate old data
       this.email = '-';
@@ -304,7 +316,7 @@ module.exports = function(crowi) {
   };
 
   userSchema.methods.statusDelete = async function() {
-    debug('Delete User', this);
+    logger.debug('Delete User', this);
 
     const now = new Date();
     const deletedLabel = `deleted_at_${now.getTime()}`;

+ 107 - 0
apps/app/src/server/routes/apiv3/users.js

@@ -542,6 +542,113 @@ module.exports = (crowi) => {
       return res.apiv3Err(new ErrorV3(err));
     }
   });
+
+  /**
+   * @swagger
+   *
+   *  paths:
+   *    /users/{id}/give-read-only:
+   *      put:
+   *        tags: [Users]
+   *        operationId: ReadOnlyUser
+   *        summary: /users/{id}/give-read-only
+   *        description: Give user read only flag
+   *        parameters:
+   *          - name: id
+   *            in: path
+   *            required: true
+   *            description: id of user for read only
+   *            schema:
+   *              type: string
+   *        responses:
+   *          200:
+   *            description: Give user read only flag success
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  properties:
+   *                    userData:
+   *                      type: object
+   *                      description: data of read only user
+   */
+  router.put('/:id/give-read-only', loginRequiredStrictly, adminRequired, addActivity, async(req, res) => {
+    const { id } = req.params;
+
+    try {
+      const userData = await User.findById(id);
+
+      if (userData == null) {
+        return res.apiv3Err(new ErrorV3('User not found'), 404);
+      }
+
+      await userData.giveReadOnly();
+
+      const serializedUserData = serializeUserSecurely(userData);
+
+      // TODO: https://redmine.weseek.co.jp/issues/121247
+      // activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_USERS_GIVE_ADMIN });
+
+      return res.apiv3({ userData: serializedUserData });
+    }
+    catch (err) {
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(err));
+    }
+  });
+
+  /**
+   * @swagger
+   *
+   *  paths:
+   *    /users/{id}/remove-read-only:
+   *      put:
+   *        tags: [Users]
+   *        operationId: removeReadOnlyUser
+   *        summary: /users/{id}/remove-read-only
+   *        description: Remove user read only flag
+   *        parameters:
+   *          - name: id
+   *            in: path
+   *            required: true
+   *            description: id of user for removing read only flag
+   *            schema:
+   *              type: string
+   *        responses:
+   *          200:
+   *            description: Remove user read only flag success
+   *            content:
+   *              application/json:
+   *                schema:
+   *                  properties:
+   *                    userData:
+   *                      type: object
+   *                      description: data of removed read only user
+   */
+  router.put('/:id/remove-read-only', loginRequiredStrictly, adminRequired, addActivity, async(req, res) => {
+    const { id } = req.params;
+
+    try {
+      const userData = await User.findById(id);
+
+      if (userData == null) {
+        return res.apiv3Err(new ErrorV3('User not found'), 404);
+      }
+
+      await userData.removeReadOnly();
+
+      const serializedUserData = serializeUserSecurely(userData);
+
+      // TODO: https://redmine.weseek.co.jp/issues/121247
+      // activityEvent.emit('update', res.locals.activity._id, { action: SupportedAction.ACTION_ADMIN_USERS_REMOVE_ADMIN });
+
+      return res.apiv3({ userData: serializedUserData });
+    }
+    catch (err) {
+      logger.error('Error', err);
+      return res.apiv3Err(new ErrorV3(err));
+    }
+  });
+
   /**
    * @swagger
    *