yusuketk 6 лет назад
Родитель
Сommit
9b819be192
3 измененных файлов с 201 добавлено и 242 удалено
  1. 96 4
      src/client/js/components/LoginForm.jsx
  2. 17 2
      src/client/js/login.jsx
  3. 88 236
      src/server/views/login.html

+ 96 - 4
src/client/js/components/LoginForm.jsx

@@ -12,6 +12,8 @@ class LoginForm extends React.Component {
     };
 
     this.renderLocalOrLdapLoginForm = this.renderLocalOrLdapLoginForm.bind(this);
+    this.renderExternalAuthLoginForm = this.renderExternalAuthLoginForm.bind(this);
+    this.renderExternalAuthInput = this.renderExternalAuthInput.bind(this);
   }
 
   renderLocalOrLdapLoginForm() {
@@ -54,21 +56,110 @@ class LoginForm extends React.Component {
     );
   }
 
+  renderExternalAuthInput(auth) {
+    const { t } = this.props;
+    return (
+      <div className="input-group justify-content-center d-flex mt-5">
+        <form role="form" action={`/passport/${auth}`} className="d-inline-flex flex-column">
+          <input type="hidden" name="_csrf" value="{{ csrf() }}" />
+          <button type="submit" className="btn btn-fill px-0 py-2" id={auth}>
+            <div className="eff"></div>
+            <span className="btn-label p-3"><i className={`fa fa-${auth}`}></i></span>
+            <span className="btn-label-text p-3">{ t('Sign in') }</span>
+          </button>
+          <div className="small text-center">by {auth} Account</div>
+        </form>
+      </div>
+    );
+  }
+
+  // [TODO]
+  // onHoverCollapseOnMobile() {
+  // if (isExternalAuthCollapsible) {
+  //   const isMobile = /iphone|ipad|android/.test(window.navigator.userAgent.toLowerCase());
+
+  //   if (!isMobile) {
+  //     $(".collapse-anchor").hover(
+  //       function () {
+  //         $('.collapse-external-auth').collapse('show');
+  //       },
+  //       function () {
+  //         $('.collapse-external-auth').collapse('hide');
+  //       }
+  //     );
+  //   }
+  // }
+  // }
+
+  renderExternalAuthLoginForm() {
+    const { isLocalStrategySetup, isLdapStrategySetup, isExternalAuthEnabledMap } = this.props;
+    const isExternalAuthCollapsible = isLocalStrategySetup || isLdapStrategySetup;
+    const collapsibleClass = isExternalAuthCollapsible ? 'collapse collapse-external-auth collapse-anchor' : '';
+
+    return (
+      <>
+        <div className="border-bottom"></div>
+        <div id="external-auth" className={`external-auth ${collapsibleClass}`}>
+          <div className="spacer"></div>
+          <div className="d-flex flex-row justify-content-between flex-wrap">
+            {isExternalAuthEnabledMap.keys().map((auth) => {
+              if (isExternalAuthEnabledMap(auth)) {
+                return this.renderExternalAuthInput(auth);
+              } else {
+                return;
+              }
+            })}
+          </div>
+          <div className="spacer"></div>
+        </div>
+        <div className="border-bottom"></div>
+        <div className="text-center">
+          <button
+            type="button"
+            className="collapse-anchor btn btn-xs btn-collapse-external-auth mb-3"
+            data-toggle={isExternalAuthCollapsible ? 'collapse' : ''}
+            data-target="#external-auth"
+            aria-expanded="false"
+            aria-controls="external-auth"
+          >
+            External Auth
+          </button>
+        </div>
+      </>
+    );
+  }
+
   render() {
 
     const {
-      isRegistering,
+      t,
+      isRegistrationEnabled,
       isLocalStrategySetup,
       isLdapStrategySetup,
+      isExternalAuthEnabledMap,
     } = this.props;
 
     const isLocalOrLdapStrategiesEnabled = isLocalStrategySetup || isLdapStrategySetup;
-    const registerFormClass = isRegistering ? 'to-flip' : '';
+    const registerFormClass = isRegistrationEnabled ? 'to-flip' : '';
+    const isExternalAuthEnabled = Object.values(isExternalAuthEnabledMap).some(elem => elem);
+
     return (
       <div className={`login-dialog mx-auto flipper ${registerFormClass}`} id="login-dialog">
         <div className="row">
           <div className="col-12">
-            { isLocalOrLdapStrategiesEnabled && this.renderLocalOrLdapLoginForm() }
+            <div className="front">
+              { isLocalOrLdapStrategiesEnabled && this.renderLocalOrLdapLoginForm() }
+              { isExternalAuthEnabled && this.renderExternalAuthLoginForm() }
+            </div>
+          </div>
+        </div>
+        <div className="row">
+          <div className="col-12 text-right py-2">
+            {isRegistrationEnabled && (
+              <a href="#register" id="register" className="link-switch">
+                <i className="ti-check-box"></i> { t('Sign up is here') }
+              </a>
+            )}
           </div>
         </div>
       </div>
@@ -80,9 +171,10 @@ class LoginForm extends React.Component {
 LoginForm.propTypes = {
   // i18next
   t: PropTypes.func.isRequired,
-  isRegistering: PropTypes.bool,
+  isRegistrationEnabled: PropTypes.bool,
   isLocalStrategySetup: PropTypes.bool,
   isLdapStrategySetup: PropTypes.bool,
+  isExternalAuthEnabledMap: PropTypes.object,
 };
 
 export default withTranslation()(LoginForm);

+ 17 - 2
src/client/js/login.jsx

@@ -11,12 +11,27 @@ const i18n = i18nFactory();
 // render loginForm
 const loginFormElem = document.getElementById('login-form');
 if (loginFormElem) {
-  const isRegistering = loginFormElem.dataset.isRegistering === 'true';
+  const isRegistrationEnabled = loginFormElem.dataset.isRegistrationEnabled === 'true';
   const isLdapStrategySetup = loginFormElem.dataset.isLdapStrategySetup === 'true';
   const isLocalStrategySetup = loginFormElem.dataset.isLocalStrategySetup === 'true';
+  const isExternalAuthEnabledMap = {
+    google: loginFormElem.dataset.isGoogleAuthEnabled,
+    github: loginFormElem.dataset.isGithubAuthEnabled,
+    facebook: loginFormElem.dataset.isFacebookAuthEnabled,
+    twitter: loginFormElem.dataset.isTwitterAuthEnabled,
+    oidc: loginFormElem.dataset.isOidcAuthEnabled,
+    saml: loginFormElem.dataset.isSamlAuthEnabled,
+    basic: loginFormElem.dataset.isBasicAuthEnabled,
+  };
+
   ReactDOM.render(
     <I18nextProvider i18n={i18n}>
-      <LoginForm isRegistering={isRegistering} isLdapStrategySetup={isLdapStrategySetup} isLocalStrategySetup={isLocalStrategySetup} />
+      <LoginForm
+        isRegistrationEnabled={isRegistrationEnabled}
+        isLdapStrategySetup={isLdapStrategySetup}
+        isLocalStrategySetup={isLocalStrategySetup}
+        isExternalAuthEnabledMap={isExternalAuthEnabledMap}
+      />
     </I18nextProvider>,
     loginFormElem,
   );

+ 88 - 236
src/server/views/login.html

@@ -113,248 +113,98 @@
       <div id="login-form"
         data-is-local-strategy-setup="{{ isLocalStrategySetup }}"
         data-is-ldap-strategy-setup="{{ isLdapStrategySetup }}"
-        data-is-is-registering="{{ req.query.register or req.body.registerForm or isRegistering }}"
+        data-is-registration-enabled="{{ req.query.register or req.body.registerForm or isRegistering }}"
+        data-is-google-auth-enabled="{{ getConfig('crowi', 'security:passport-google:isEnabled') }}"
+        data-is-github-auth-enabled="{{ getConfig('crowi', 'security:passport-github:isEnabled') }}"
+        data-is-facebool-auth-enabled="{{ getConfig('crowi', 'security:passport-facebook:isEnabled') }}"
+        data-is-twitter-auth-enabled="{{ getConfig('crowi', 'security:passport-twitter:isEnabled') }}"
+        data-is-oidc-auth-enabled="{{ getConfig('crowi', 'security:passport-oidc:isEnabled') }}"
+        data-is-saml-auth-enabled="{{ getConfig('crowi', 'security:passport-saml:isEnabled') }}"
+        data-is-basic-auth-enabled="{{ getConfig('crowi', 'security:passport-basic:isEnabled') }}"
       ></div>
-      <!--<div class="row mb-5">
-        <div class="col-md-12">
-          <div class="login-dialog mx-auto flipper {% if req.query.register or req.body.registerForm or isRegistering %}to-flip{% endif %}" id="login-dialog">
-
-            <div class="col-12">
-              <div class="front">
-
-
-
-                {% if (
-                  getConfig('crowi', 'security:passport-google:isEnabled') ||
-                  getConfig('crowi', 'security:passport-github:isEnabled') ||
-                  getConfig('crowi', 'security:passport-facebook:isEnabled') ||
-                  getConfig('crowi', 'security:passport-twitter:isEnabled')||
-                  getConfig('crowi', 'security:passport-oidc:isEnabled') ||
-                  getConfig('crowi', 'security:passport-saml:isEnabled') ||
-                  getConfig('crowi', 'security:passport-basic:isEnabled')
-                ) %}
-                <div class="border-bottom"></div>
-                <div id="external-auth" class="external-auth {% if isExternalAuthCollapsible %}collapse collapse-external-auth collapse-anchor{% endif %}">
-                  <div class="spacer"></div>
-                  <div class="d-flex flex-row justify-content-between flex-wrap">
-                    {% if getConfig('crowi', 'security:passport-google:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/google" class="d-inline-flex flex-column">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="google">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-google"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">by Google Account</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-github:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/github" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="github">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-github"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">by GitHub Account</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-facebook:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/facebook" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="facebook">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-facebook"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">by Facebook Account</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-twitter:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/twitter" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="twitter">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-twitter"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">by Twitter Account</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-oidc:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/oidc" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="oidc">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-openid"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">{{ getConfig('crowi', 'security:passport-oidc:providerName') || "OpenID Connect" }}</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-saml:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/saml" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="saml">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-key"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">with SAML</div>
-                      </form>
-                    </div>
-                    {% endif %}
-                    {% if getConfig('crowi', 'security:passport-basic:isEnabled') %}
-                    <div class="input-group justify-content-center d-flex mt-5">
-                      <form role="form" action="/passport/basic" class="d-inline-flex flex-column">
-                        <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                        <button type="submit" class="btn btn-fill px-0 py-2" id="basic">
-                          <div class="eff"></div>
-                          <span class="btn-label p-3"><i class="fa fa-lock"></i></span>
-                          <span class="btn-label-text p-3">{{ t('Sign in') }}</span>
-                        </button>
-                        <div class="small text-center">with Basic Auth</div>
-                      </form>
-                    </div>
-                  {% endif %}
-                  </div>{# ./d-flex flex-row flex-wrap #}
-                  <div class="spacer"></div>
-                </div>
-                <div class="border-bottom"></div>
-                <div class="text-center">
-                  <button class="collapse-anchor btn btn-xs btn-collapse-external-auth mb-3"
-                      data-toggle="{% if isExternalAuthCollapsible %}collapse{% endif %}" data-target="#external-auth" aria-expanded="false" aria-controls="external-auth">
-                    External Auth
-                  </button>
-                </div>
-                {% else %}
-                <div class="border-bottom mb-3"></div>
-                {% endif %}
-
-                {% if isExternalAuthCollapsible %}
-                <script>
-                  const isMobile = /iphone|ipad|android/.test(window.navigator.userAgent.toLowerCase());
-
-                  if (!isMobile) {
-                    $(".collapse-anchor").hover(
-                      function() {
-                        $('.collapse-external-auth').collapse('show');
-                      },
-                      function() {
-                        $('.collapse-external-auth').collapse('hide');
-                      }
-                    );
-                  }
-                </script>
-                {% endif %}
-
-                <div class="row">
-                  <div class="col-12 text-right py-2">
-                    {% if isRegistrationEnabled %}
-                    <a href="#register" id="register" class="link-switch">
-                      <i class="ti-check-box"></i> {{ t('Sign up is here') }}
-                    </a>
-                    {% else %}
-                    &nbsp;
-                    {% endif %}
-                  </div>
-                </div>
-
-              </div>
-
-              {% if isRegistrationEnabled %}
-              <div class="back">
-                {% if getConfig('crowi', 'security:registrationMode') == 'Restricted' %}
-                <p class="alert alert-warning">
-                  {{ t('page_register.notice.restricted') }}<br>
-                  {{ t('page_register.notice.restricted_defail') }}
-                </p>
-                {% endif %}
-
-                <form role="form" action="/register" method="post" id="register-form">
-                  <div class="input-group" id="input-group-username">
-                    <div class="input-group-prepend">
-                      <span class="input-group-text"><i class="icon-user"></i></span>
-                    </div>
-                    <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="registerForm[username]" value="{{ req.body.registerForm.username }}" required>
-                  </div>
-                  <p class="form-text text-danger">
-                    <span id="help-block-username"></span>
-                  </p>
-
-                  <div class="input-group">
-                    <div class="input-group-prepend">
-                      <span class="input-group-text"><i class="icon-tag"></i></span>
-                    </div>
-                    <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ req.body.registerForm.name }}" required>
-                  </div>
-
-                  <div class="input-group">
-                    <div class="input-group-prepend">
-                      <span class="input-group-text"><i class="icon-envelope"></i></span>
-                    </div>
-                    <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ req.body.registerForm.email }}" required>
-                  </div>
-                  {% if getConfig('crowi', 'security:registrationWhiteList') && getConfig('crowi', 'security:registrationWhiteList').length %}
-                  <p class="form-text">
-                    {{ t('page_register.form_help.email') }}
-                  </p>
-                  <ul>
-                    {% for em in getConfig('crowi', 'security:registrationWhiteList') %}
-                    <li><code>{{ em }}</code></li>
-                    {% endfor %}
-                  </ul>
-                  {% endif %}
-
-                  <div class="input-group">
-                    <div class="input-group-prepend">
-                      <span class="input-group-text"><i class="icon-lock"></i></span>
-                    </div>
-                    <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="registerForm[password]" required>
-                  </div>
-
-                  <div class="input-group justify-content-center mt-5">
-                    <input type="hidden" name="_csrf" value="{{ csrf() }}">
-                    <button type="submit" class="btn btn-fill px-0 py-2" id="register">
-                      <div class="eff"></div>
-                      <span class="btn-label p-3"><i class="icon-user-follow"></i></span>
-                      <span class="btn-label-text p-3">{{ t('Sign up') }}</span>
-                    </button>
-                  </div>
-
-                </form>
-
-                <div class="border-bottom mb-3"></div>
-
-                <div class="row">
-                  <div class="text-right col-12 py-1">
-                    <a href="#login" id="login" class="link-switch">
-                      <i class="icon-fw icon-login"></i>{{ t('Sign in is here') }}
-                    </a>
-                  </div>
-                </div>
-              </div>
-
-              {% endif %} {# if isRegistrationEnabled id false #}
+
+
+      {% if isRegistrationEnabled %}
+      <div class="back">
+        {% if getConfig('crowi', 'security:registrationMode') == 'Restricted' %}
+        <p class="alert alert-warning">
+          {{ t('page_register.notice.restricted') }}<br> {{ t('page_register.notice.restricted_defail') }}
+        </p>
+        {% endif %}
+
+        <form role="form" action="/register" method="post" id="register-form">
+          <div class="input-group" id="input-group-username">
+            <div class="input-group-prepend">
+              <span class="input-group-text"><i class="icon-user"></i></span>
             </div>
+            <input type="text" class="form-control" placeholder="{{ t('User ID') }}" name="registerForm[username]" value="{{ req.body.registerForm.username }}"
+              required>
+          </div>
+          <p class="form-text text-danger">
+            <span id="help-block-username"></span>
+          </p>
 
-            <a href="https://growi.org" class="link-growi-org pl-3">
-              <span class="growi">GROWI</span>.<span class="org">ORG
-            </a>
+          <div class="input-group">
+            <div class="input-group-prepend">
+              <span class="input-group-text"><i class="icon-tag"></i></span>
+            </div>
+            <input type="text" class="form-control" placeholder="{{ t('Name') }}" name="registerForm[name]" value="{{ req.body.registerForm.name }}"
+              required>
+          </div>
+
+          <div class="input-group">
+            <div class="input-group-prepend">
+              <span class="input-group-text"><i class="icon-envelope"></i></span>
+            </div>
+            <input type="email" class="form-control" placeholder="{{ t('Email') }}" name="registerForm[email]" value="{{ req.body.registerForm.email }}"
+              required>
+          </div>
+          {% if getConfig('crowi', 'security:registrationWhiteList') && getConfig('crowi', 'security:registrationWhiteList').length
+          %}
+          <p class="form-text">
+            {{ t('page_register.form_help.email') }}
+          </p>
+          <ul>
+            {% for em in getConfig('crowi', 'security:registrationWhiteList') %}
+            <li><code>{{ em }}</code></li>
+            {% endfor %}
+          </ul>
+          {% endif %}
+
+          <div class="input-group">
+            <div class="input-group-prepend">
+              <span class="input-group-text"><i class="icon-lock"></i></span>
+            </div>
+            <input type="password" class="form-control" placeholder="{{ t('Password') }}" name="registerForm[password]" required>
+          </div>
+
+          <div class="input-group justify-content-center mt-5">
+            <input type="hidden" name="_csrf" value="{{ csrf() }}">
+            <button type="submit" class="btn btn-fill px-0 py-2" id="register">
+              <div class="eff"></div>
+              <span class="btn-label p-3"><i class="icon-user-follow"></i></span>
+              <span class="btn-label-text p-3">{{ t('Sign up') }}</span>
+            </button>
+          </div>
+
+        </form>
+
+        <div class="border-bottom mb-3"></div>
 
+        <div class="row">
+          <div class="text-right col-12 py-1">
+            <a href="#login" id="login" class="link-switch">
+              <i class="icon-fw icon-login"></i>{{ t('Sign in is here') }}
+            </a>
           </div>
         </div>
-     </div> -->
+      </div>
+      {% endif %} {# if isRegistrationEnabled id false #}
+
+      <a href="https://growi.org" class="link-growi-org pl-3">
+        <span class="growi">GROWI</span>.<span class="org">ORG
+      </a>
+    </div>
   </div>
 </div>
 
@@ -391,3 +241,5 @@
   });
 </script> -->
 {% endblock %}
+
+