Bläddra i källkod

Merge pull request #3336 from weseek/fix/install-process

Fix/install process
Yuki Takei 5 år sedan
förälder
incheckning
6ec96c3787

+ 17 - 1
src/client/js/components/InstallerForm.jsx

@@ -13,9 +13,12 @@ class InstallerForm extends React.Component {
 
     this.state = {
       isValidUserName: true,
+      isSubmitButtonDisabled: false,
       selectedLang: {},
     };
     // this.checkUserName = this.checkUserName.bind(this);
+
+    this.clickHandler = this.clickHandler.bind(this);
   }
 
   componentWillMount() {
@@ -39,6 +42,13 @@ class InstallerForm extends React.Component {
     this.setState({ selectedLang: meta });
   }
 
+  clickHandler() {
+    this.setState({ isSubmitButtonDisabled: true });
+    setTimeout(() => {
+      this.setState({ isSubmitButtonDisabled: false });
+    }, 3000);
+  }
+
   render() {
     const hasErrorClass = this.state.isValidUserName ? '' : ' has-error';
     const unavailableUserId = this.state.isValidUserName
@@ -149,7 +159,13 @@ class InstallerForm extends React.Component {
             <input type="hidden" name="_csrf" value={this.props.csrf} />
 
             <div className="input-group mt-4 mb-3 d-flex justify-content-center">
-              <button type="submit" className="btn-fill btn btn-register" id="register">
+              <button
+                type="submit"
+                className="btn-fill btn btn-register"
+                id="register"
+                disabled={this.state.isSubmitButtonDisabled}
+                onClick={this.clickHandler}
+              >
                 <div className="eff"></div>
                 <span className="btn-label"><i className="icon-user-follow" /></span>
                 <span className="btn-label-text">{ this.props.t('Create') }</span>

+ 0 - 5
src/server/crowi/index.js

@@ -469,11 +469,6 @@ Crowi.prototype.setupRoutesAtLast = function() {
   require('../routes')(this, this.express);
 };
 
-Crowi.prototype.setupAfterInstall = function() {
-  this.pluginService.autoDetectAndLoadPlugins();
-  this.setupRoutesAtLast();
-};
-
 /**
  * require API for plugins
  *

+ 12 - 4
src/server/middlewares/application-installed.js

@@ -2,12 +2,20 @@ module.exports = (crowi) => {
   const { appService } = crowi;
 
   return async(req, res, next) => {
-    const isInstalled = await appService.isDBInitialized();
+    const isDBInitialized = await appService.isDBInitialized();
 
-    if (!isInstalled) {
-      return res.redirect('/installer');
+    // when already installed
+    if (isDBInitialized) {
+      return next();
     }
 
-    return next();
+    // when other server have initialized DB
+    const isDBInitializedAfterForceReload = await appService.isDBInitialized(true);
+    if (isDBInitializedAfterForceReload) {
+      await appService.setupAfterInstall();
+      return res.safeRedirect(req.originalUrl);
+    }
+
+    return res.redirect('/installer');
   };
 };

+ 2 - 2
src/server/middlewares/application-not-installed.js

@@ -2,9 +2,9 @@ module.exports = (crowi) => {
   const { appService } = crowi;
 
   return async(req, res, next) => {
-    const isInstalled = await appService.isDBInitialized();
+    const isDBInitialized = await appService.isDBInitialized(true);
 
-    if (isInstalled) {
+    if (isDBInitialized) {
       req.flash('errorMessage', req.t('message.application_already_installed'));
       return res.redirect('admin');
     }

+ 34 - 33
src/server/routes/index.js

@@ -33,37 +33,33 @@ module.exports = function(crowi, app) {
 
   /* eslint-disable max-len, comma-spacing, no-multi-spaces */
 
-  app.get('/'                        , applicationInstalled, loginRequired , autoReconnectToSearch, page.showTopPage);
-
   // API v3
   app.use('/api-docs', require('./apiv3/docs')(crowi));
   app.use('/_api/v3', require('./apiv3')(crowi));
 
+  app.get('/'                         , applicationInstalled, loginRequired , autoReconnectToSearch, page.showTopPage);
+
+  app.get('/login/error/:reason'      , applicationInstalled, login.error);
+  app.get('/login'                    , applicationInstalled, login.preLogin, login.login);
+  app.get('/login/invited'            , applicationInstalled, login.invited);
+  app.post('/login/activateInvited'   , applicationInstalled, form.invited                         , csrf, login.invited);
+  app.post('/login'                   , applicationInstalled, form.login                           , csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
+
+  app.post('/register'                , applicationInstalled, form.register                        , csrf, login.register);
+  app.get('/register'                 , applicationInstalled, login.preLogin, login.register);
+  app.get('/logout'                   , applicationInstalled, logout.logout);
+
+  app.get('/admin'                    , applicationInstalled, loginRequiredStrictly , adminRequired , admin.index);
+  app.get('/admin/app'                , applicationInstalled, loginRequiredStrictly , adminRequired , admin.app.index);
+
   // installer
   if (!isInstalled) {
     const installer = require('./installer')(crowi);
-    app.get('/installer'               , applicationNotInstalled , installer.index);
-    app.post('/installer'              , applicationNotInstalled , form.register , csrf, installer.install);
+    app.get('/installer'              , applicationNotInstalled , installer.index);
+    app.post('/installer'             , applicationNotInstalled , form.register , csrf, installer.install);
     return;
   }
 
-  app.get('/login/error/:reason'     , login.error);
-  app.get('/login'                   , applicationInstalled     , login.preLogin, login.login);
-  app.get('/login/invited'           , login.invited);
-  app.post('/login/activateInvited'  , form.invited                         , csrf, login.invited);
-  app.post('/login'                  , form.login                           , csrf, loginPassport.loginWithLocal, loginPassport.loginWithLdap, loginPassport.loginFailure);
-  app.post('/_api/login/testLdap'    , loginRequiredStrictly , form.login , loginPassport.testLdapCredentials);
-
-  app.post('/register'               , form.register                        , csrf, login.register);
-  app.get('/register'                , applicationInstalled     , login.preLogin, login.register);
-  app.get('/logout'                  , logout.logout);
-
-  app.get('/admin'                          , loginRequiredStrictly , adminRequired , admin.index);
-  app.get('/admin/app'                      , loginRequiredStrictly , adminRequired , admin.app.index);
-
-  // security admin
-  app.get('/admin/security'                     , loginRequiredStrictly , adminRequired , admin.security.index);
-
   // OAuth
   app.get('/passport/google'                      , loginPassport.loginWithGoogle, loginPassport.loginFailure);
   app.get('/passport/github'                      , loginPassport.loginWithGitHub, loginPassport.loginFailure);
@@ -77,29 +73,34 @@ module.exports = function(crowi, app) {
   app.get('/passport/oidc/callback'               , loginPassport.loginPassportOidcCallback     , loginPassport.loginFailure);
   app.post('/passport/saml/callback'              , loginPassport.loginPassportSamlCallback     , loginPassport.loginFailure);
 
+  app.post('/_api/login/testLdap'    , loginRequiredStrictly , form.login , loginPassport.testLdapCredentials);
+
+  // security admin
+  app.get('/admin/security'          , loginRequiredStrictly , adminRequired , admin.security.index);
+
   // markdown admin
-  app.get('/admin/markdown'                   , loginRequiredStrictly , adminRequired , admin.markdown.index);
+  app.get('/admin/markdown'          , loginRequiredStrictly , adminRequired , admin.markdown.index);
 
   // customize admin
-  app.get('/admin/customize'                , loginRequiredStrictly , adminRequired , admin.customize.index);
+  app.get('/admin/customize'         , loginRequiredStrictly , adminRequired , admin.customize.index);
 
   // search admin
-  app.get('/admin/search'              , loginRequiredStrictly , adminRequired , admin.search.index);
+  app.get('/admin/search'            , loginRequiredStrictly , adminRequired , admin.search.index);
 
   // notification admin
-  app.get('/admin/notification'              , loginRequiredStrictly , adminRequired , admin.notification.index);
-  app.get('/admin/notification/slackAuth'    , loginRequiredStrictly , adminRequired , admin.notification.slackAuth);
-  app.get('/admin/notification/slackSetting/disconnect', loginRequiredStrictly , adminRequired , admin.notification.disconnectFromSlack);
-  app.get('/admin/global-notification/new'   , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
-  app.get('/admin/global-notification/:id'   , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
+  app.get('/admin/notification'                         , loginRequiredStrictly , adminRequired , admin.notification.index);
+  app.get('/admin/notification/slackAuth'               , loginRequiredStrictly , adminRequired , admin.notification.slackAuth);
+  app.get('/admin/notification/slackSetting/disconnect' , loginRequiredStrictly , adminRequired , admin.notification.disconnectFromSlack);
+  app.get('/admin/global-notification/new'              , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
+  app.get('/admin/global-notification/:id'              , loginRequiredStrictly , adminRequired , admin.globalNotification.detail);
 
-  app.get('/admin/users'                , loginRequiredStrictly , adminRequired , admin.user.index);
+  app.get('/admin/users'                                , loginRequiredStrictly , adminRequired , admin.user.index);
 
-  app.get('/admin/users/external-accounts'               , loginRequiredStrictly , adminRequired , admin.externalAccount.index);
+  app.get('/admin/users/external-accounts'              , loginRequiredStrictly , adminRequired , admin.externalAccount.index);
 
   // user-groups admin
-  app.get('/admin/user-groups'             , loginRequiredStrictly, adminRequired, admin.userGroup.index);
-  app.get('/admin/user-group-detail/:id'   , loginRequiredStrictly, adminRequired, admin.userGroup.detail);
+  app.get('/admin/user-groups'                          , loginRequiredStrictly, adminRequired, admin.userGroup.index);
+  app.get('/admin/user-group-detail/:id'                , loginRequiredStrictly, adminRequired, admin.userGroup.detail);
 
   // importer management for admin
   app.get('/admin/importer'                     , loginRequiredStrictly , adminRequired , admin.importer.index);

+ 1 - 1
src/server/routes/installer.js

@@ -85,7 +85,7 @@ module.exports = function(crowi) {
     // create initial pages
     await createInitialPages(adminUser, language);
 
-    crowi.setupAfterInstall();
+    appService.setupAfterInstall();
     appService.publishPostInstallationMessage();
 
     // login with passport

+ 20 - 17
src/server/service/app.js

@@ -38,17 +38,9 @@ class AppService extends S2sMessageHandlable {
   async handleS2sMessage(s2sMessage) {
     logger.info('Invoke post installation process by pubsub notification');
 
-    const { crowi, configManager, s2sMessagingService } = this;
-
-    // load config and setup
-    await configManager.loadConfigs();
-
-    const isInstalled = this.crowi.configManager.getConfig('crowi', 'app:installed');
-    if (isInstalled) {
-      crowi.setupAfterInstall();
-
-      // remove message handler
-      s2sMessagingService.removeMessageHandler(this);
+    const isDBInitialized = await this.isDBInitialized(true);
+    if (isDBInitialized) {
+      this.setupAfterInstall();
     }
   }
 
@@ -64,9 +56,6 @@ class AppService extends S2sMessageHandlable {
       catch (e) {
         logger.error('Failed to publish post installation message with S2sMessagingService: ', e.message);
       }
-
-      // remove message handler
-      s2sMessagingService.removeMessageHandler(this);
     }
 
   }
@@ -113,9 +102,23 @@ class AppService extends S2sMessageHandlable {
     await this.configManager.updateConfigsInTheSameNamespace('crowi', initialConfig, true);
   }
 
-  async isDBInitialized() {
-    const appInstalled = await this.configManager.getConfigFromDB('crowi', 'app:installed');
-    return appInstalled;
+  async isDBInitialized(forceReload) {
+    if (forceReload) {
+      // load configs
+      await this.configManager.loadConfigs();
+    }
+    return this.configManager.getConfigFromDB('crowi', 'app:installed');
+  }
+
+  async setupAfterInstall() {
+    this.crowi.pluginService.autoDetectAndLoadPlugins();
+    this.crowi.setupRoutesAtLast();
+
+    // remove message handler
+    const { s2sMessagingService } = this;
+    if (s2sMessagingService != null) {
+      this.s2sMessagingService.removeMessageHandler(this);
+    }
   }
 
 }