Kaynağa Gözat

ensure to re-setup LdapStrategy when configurations are changed

Yuki Takei 8 yıl önce
ebeveyn
işleme
ce3e415bd8

+ 7 - 4
lib/crowi/index.js

@@ -36,6 +36,7 @@ function Crowi (rootdir, env)
   this.searcher = null;
   this.mailer = {};
   this.interceptorManager = {};
+  this.passportService = null;
 
   this.tokens = null;
 
@@ -264,10 +265,12 @@ Crowi.prototype.setupPassport = function() {
 
   const PassportService = require('../service/passport');
 
-  const passportService = new PassportService(this);
-  passportService.setupLocalStrategy();
-  passportService.setupLdapStrategy();
-  passportService.setupSerializer();
+  if (this.passportService == null) {
+    this.passportService = new PassportService(this);
+  }
+  this.passportService.setupLocalStrategy();
+  this.passportService.setupLdapStrategy();
+  this.passportService.setupSerializer();
 
   return Promise.resolve();
 }

+ 45 - 0
lib/routes/admin.js

@@ -516,6 +516,25 @@ module.exports = function(crowi, app) {
     }
   };
 
+  actions.api.securityPassportLdapSetting = function(req, res) {
+    var form = req.form.settingForm;
+
+    if (!req.form.isValid) {
+      return res.json({status: false, message: req.form.errors.join('\n')});
+    }
+
+    debug('form content', form);
+    return saveSettingAsync(form)
+      .then(() => {
+        // re-setup strategy (force: true)
+        crowi.passportService.setupLdapStrategy(true);
+        return;
+      })
+      .then(() => {
+        res.json({status: true});
+      });
+  };
+
   actions.api.customizeSetting = function(req, res) {
     var form = req.form.settingForm;
 
@@ -579,6 +598,13 @@ module.exports = function(crowi, app) {
     });
   };
 
+  /**
+   * save settings, update config cache, and response json
+   *
+   * @param {any} req
+   * @param {any} res
+   * @param {any} form
+   */
   function saveSetting(req, res, form)
   {
     Config.updateNamespaceByArray('crowi', form, function(err, config) {
@@ -587,6 +613,25 @@ module.exports = function(crowi, app) {
     });
   }
 
+  /**
+   * save settings, update config cache ONLY. (this method don't response json)
+   *
+   * @param {any} form
+   * @returns
+   */
+  function saveSettingAsync(form) {
+    return new Promise((resolve, reject) => {
+      Config.updateNamespaceByArray('crowi', form, (err, config) => {
+        if (err) {
+          return reject(err)
+        };
+
+        Config.updateConfigCache('crowi', config);
+        return resolve();
+      });
+    });
+  }
+
   function validateMailSetting(req, form, callback)
   {
     var mailer = crowi.mailer;

+ 1 - 1
lib/routes/index.js

@@ -62,7 +62,7 @@ module.exports = function(crowi, app) {
   app.post('/_api/admin/security/general'       , loginRequired(crowi, app) , middleware.adminRequired() , form.admin.securityGeneral, admin.api.securitySetting);
   app.post('/_api/admin/security/google'        , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.securityGoogle, admin.api.securitySetting);
   app.post('/_api/admin/security/mechanism'     , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.securityMechanism, admin.api.securitySetting);
-  app.post('/_api/admin/security/passport-ldap' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.securityPassportLdap, admin.api.securitySetting);
+  app.post('/_api/admin/security/passport-ldap' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.securityPassportLdap, admin.api.securityPassportLdapSetting);
   app.post('/_api/admin/security/passport-ldap-test' , loginRequired(crowi, app) , middleware.adminRequired() , csrf, form.admin.securityPassportLdap, admin.api.securitySetting);
 
   // markdown admin

+ 8 - 1
lib/routes/login-passport.js

@@ -4,7 +4,9 @@ module.exports = function(crowi, app) {
   var debug = require('debug')('crowi:routes:login-passport')
     , passport = require('passport')
     , config = crowi.getConfig()
-    , Config = crowi.model('Config');
+    , Config = crowi.model('Config')
+    , passportService = crowi.passportService
+    ;
 
   /**
    * success handler
@@ -40,6 +42,11 @@ module.exports = function(crowi, app) {
    * @param {*} next
    */
   const loginWithLdap = (req, res, next) => {
+    if (!passportService.isLdapStrategySetup) {
+      debug('LdapStrategy has not been set up');
+      return next();
+    }
+
     const loginForm = req.body.loginForm;
 
     if (!req.form.isValid) {

+ 69 - 4
lib/service/passport.js

@@ -14,6 +14,32 @@ class PassportService {
 
   constructor(crowi) {
     this.crowi = crowi;
+
+    /**
+     * the flag whether LocalStrategy is set up successfully
+     */
+    this.isLocalStrategySetup = false;
+
+    /**
+     * the flag whether LdapStrategy is set up successfully
+     */
+    this.isLdapStrategySetup = false;
+
+    /**
+     * the flag whether serializer/deserializer are set up successfully
+     */
+    this.isSerializerSetup = false;
+  }
+
+  /**
+   * reset LocalStrategy
+   *
+   * @memberof PassportService
+   */
+  resetLocalStrategy() {
+    debug('LocalStrategy: reset');
+    passport.unuse('local');
+    this.isLocalStrategySetup = false;
   }
 
   /**
@@ -21,7 +47,15 @@ class PassportService {
    *
    * @memberof PassportService
    */
-  setupLocalStrategy() {
+  setupLocalStrategy(isForce) {
+    if (isForce === true) {
+      this.resetLocalStrategy();
+    }
+    // check whether the strategy has already been set up
+    if (this.isLocalStrategySetup) {
+      throw new Error('LocalStrategy has already been set up');
+    }
+
     debug('LocalStrategy: setting up..');
 
     const User = this.crowi.model('User');
@@ -43,13 +77,36 @@ class PassportService {
         });
       }
     ));
+
+    this.isLocalStrategySetup = true;
     debug('LocalStrategy: setup is done');
   }
 
-  /*
+  /**
+   * reset LdapStrategy
+   *
+   * @memberof PassportService
+   */
+  resetLdapStrategy() {
+    debug('LdapStrategy: reset');
+    passport.unuse('ldapauth');
+    this.isLdapStrategySetup = false;
+  }
+
+  /**
    * Asynchronous configuration retrieval
+   *
+   * @memberof PassportService
    */
-  setupLdapStrategy() {
+  setupLdapStrategy(isForce) {
+    if (isForce === true) {
+      this.resetLdapStrategy();
+    }
+    // check whether the strategy has already been set up
+    if (this.isLdapStrategySetup) {
+      throw new Error('LdapStrategy has already been set up');
+    }
+
     debug('LdapStrategy: setting up..');
 
     const config = this.crowi.config;
@@ -78,7 +135,7 @@ class PassportService {
       debug(`LdapStrategy: bindDN=${bindDN}`);
       debug(`LdapStrategy: bindCredentials=${bindCredentials}`);
     }
-    debug(`LdapStrategy searchFilter:    ${searchFilter}`);
+    debug(`LdapStrategy: searchFilter=${searchFilter}`);
 
     // Asynchronous configuration retrieval
     const getLDAPConfiguration = (req, callback) => {
@@ -120,6 +177,7 @@ class PassportService {
       }
     ));
 
+    this.isLdapStrategySetup = true;
     debug('LdapStrategy: setup is done');
   }
 
@@ -129,6 +187,11 @@ class PassportService {
    * @memberof PassportService
    */
   setupSerializer() {
+    // check whether the serializer/deserializer have already been set up
+    if (this.isSerializerSetup) {
+      throw new Error('serializer/deserializer have already been set up');
+    }
+
     debug('setting up serializer and deserializer');
 
     const User = this.crowi.model('User');
@@ -141,6 +204,8 @@ class PassportService {
         done(err, user);
       });
     });
+
+    this.isSerializerSetup = true;
   }
 
 }