Jelajahi Sumber

setup loginRequired/adminRequired middlewares

Yuki Takei 5 tahun lalu
induk
melakukan
c96c45234a

+ 7 - 1
src/server/middlewares/admin-required.js

@@ -2,7 +2,7 @@ const loggerFactory = require('@alias/logger');
 
 const logger = loggerFactory('growi:middleware:admin-required');
 
-module.exports = (crowi) => {
+module.exports = (crowi, fallback = null) => {
 
   return async(req, res, next) => {
     if (req.user != null && (req.user instanceof Object) && '_id' in req.user) {
@@ -13,11 +13,17 @@ module.exports = (crowi) => {
 
       logger.warn('This user is not admin.');
 
+      if (fallback != null) {
+        return fallback(req, res);
+      }
       return res.redirect('/');
     }
 
     logger.warn('This user has not logged in.');
 
+    if (fallback != null) {
+      return fallback(req, res);
+    }
     return res.redirect('/login');
   };
 

+ 8 - 1
src/server/middlewares/login-required.js

@@ -6,8 +6,9 @@ const logger = loggerFactory('growi:middleware:login-required');
  * require login handler
  *
  * @param {boolean} isGuestAllowed whethere guest user is allowed (default false)
+ * @param {function} fallback fallback function which will be triggered when the check cannot be passed
  */
-module.exports = (crowi, isGuestAllowed = false) => {
+module.exports = (crowi, isGuestAllowed = false, fallback = null) => {
 
   return function(req, res, next) {
 
@@ -45,9 +46,15 @@ module.exports = (crowi, isGuestAllowed = false) => {
     // is api path
     const path = req.path || '';
     if (path.match(/^\/_api\/.+$/)) {
+      if (fallback != null) {
+        return fallback(req, res);
+      }
       return res.sendStatus(403);
     }
 
+    if (fallback != null) {
+      return fallback(req, res);
+    }
     req.session.redirectTo = req.originalUrl;
     return res.redirect('/login');
   };

+ 38 - 8
src/server/service/socket-io.js

@@ -26,16 +26,13 @@ class SocketIoService {
       transports: ['websocket'],
     });
 
-    // setup passport session
-    const sessionMiddleware = socketioSession(expressSession(this.crowi.sessionConfig), passport);
-    this.io.use(sessionMiddleware.express_session);
-    this.io.use(sessionMiddleware.passport_initialize);
-    this.io.use(sessionMiddleware.passport_session);
-
-    this.io.use(this.checkConnectionLimits.bind(this));
-
     // create namespace for admin
     this.adminNamespace = this.io.of('/admin');
+
+    this.setupSessionMiddleware();
+    this.setupLoginRequiredMiddleware();
+    this.setupAdminRequiredMiddleware();
+    this.setupCheckConnectionLimitsMiddleware();
   }
 
   getDefaultSocket() {
@@ -53,6 +50,39 @@ class SocketIoService {
     return this.adminNamespace;
   }
 
+  setupSessionMiddleware() {
+    const sessionMiddleware = socketioSession(expressSession(this.crowi.sessionConfig), passport);
+    this.io.use(sessionMiddleware.express_session);
+    this.io.use(sessionMiddleware.passport_initialize);
+    this.io.use(sessionMiddleware.passport_session);
+  }
+
+  setupLoginRequiredMiddleware() {
+    const loginRequired = require('../middlewares/login-required')(this.crowi, true, (req, res) => {
+      throw new Error('Login is required to connect.');
+    });
+
+    // convert Connect/Express middleware to Socket.io middleware
+    this.io.use((socket, next) => {
+      loginRequired(socket.request, {}, next);
+    });
+  }
+
+  setupAdminRequiredMiddleware() {
+    const adminRequired = require('../middlewares/admin-required')(this.crowi, (req, res) => {
+      throw new Error('Admin priviledge is required to connect.');
+    });
+
+    // convert Connect/Express middleware to Socket.io middleware
+    this.getAdminSocket().use((socket, next) => {
+      adminRequired(socket.request, {}, next);
+    });
+  }
+
+  setupCheckConnectionLimitsMiddleware() {
+    this.io.use(this.checkConnectionLimits.bind(this));
+  }
+
   async getClients(namespace) {
     return new Promise((resolve, reject) => {
       namespace.clients((error, clients) => {