Forráskód Böngészése

Merge remote-tracking branch 'upstream/feature-improve-authentication' into feature-improve-authentication

Lauri Ojansivu 6 éve
szülő
commit
7125357a44

+ 2 - 4
client/components/main/layouts.jade

@@ -23,10 +23,8 @@ template(name="userFormsLayout")
         br
     section.auth-dialog
       +Template.dynamic(template=content)
-      +connectionMethod
-      if isCas
-        .at-form
-          button#cas(class='at-btn submit' type='submit') {{casSignInLabel}}
+      if currentSetting.displayAuthenticationMethod
+        +connectionMethod
       div.at-form-lang
         select.select-lang.js-userform-set-language
           each languages

+ 72 - 60
client/components/main/layouts.js

@@ -20,13 +20,19 @@ const validator = {
   },
 };
 
-Template.userFormsLayout.onCreated(() => {
-  Meteor.subscribe('setting');
-
+Template.userFormsLayout.onCreated(function() {
+  const instance = this;
+  instance.currentSetting = new ReactiveVar();
+
+  Meteor.subscribe('setting', {
+    onReady() {
+      instance.currentSetting.set(Settings.findOne());
+      return this.stop();
+    },
+  });
 });
 
 Template.userFormsLayout.onRendered(() => {
-
   AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
 
   const i18nTag = navigator.language;
@@ -37,12 +43,10 @@ Template.userFormsLayout.onRendered(() => {
 });
 
 Template.userFormsLayout.helpers({
-
   currentSetting() {
-    return Settings.findOne();
+    return Template.instance().currentSetting.get();
   },
 
-
   afterBodyStart() {
     return currentSetting.customHTMLafterBodyStart;
   },
@@ -75,17 +79,6 @@ Template.userFormsLayout.helpers({
     const curLang = T9n.getLanguage() || 'en';
     return t9nTag === curLang;
   },
-/*
-  isCas() {
-    return Meteor.settings.public &&
-      Meteor.settings.public.cas &&
-      Meteor.settings.public.cas.loginUrl;
-  },
-
-  casSignInLabel() {
-    return TAPi18n.__('casSignIn', {}, T9n.getLanguage() || 'en');
-  },
-*/
 });
 
 Template.userFormsLayout.events({
@@ -94,55 +87,74 @@ Template.userFormsLayout.events({
     T9n.setLanguage(i18nTagToT9n(i18nTag));
     evt.preventDefault();
   },
-  'click button#cas'() {
+  'click #at-btn'(event, instance) {
+    if (FlowRouter.getRouteName() === 'atSignIn') {
+      authentication(event, instance);
+    }
+  },
+});
+
+Template.defaultLayout.events({
+  'click .js-close-modal': () => {
+    Modal.close();
+  },
+});
+
+async function authentication(event, instance) {
+  const match = $('#at-field-username_and_email').val();
+  const password = $('#at-field-password').val();
+
+  if (!match || !password) return;
+
+  const result = await getAuthenticationMethod(instance.currentSetting.get(), match);
+
+  if (result === 'password') return;
+
+  // Stop submit #at-pwd-form
+  event.preventDefault();
+  event.stopImmediatePropagation();
+
+  switch (result) {
+  case 'ldap':
+    Meteor.loginWithLDAP(match, password, function() {
+      FlowRouter.go('/');
+    });
+    break;
+
+  case 'cas':
     Meteor.loginWithCas(function() {
-      if (FlowRouter.getRouteName() === 'atSignIn') {
-        FlowRouter.go('/');
-      }
+      FlowRouter.go('/');
     });
-  },
-  'click #at-btn'(event) {
-    /* All authentication method can be managed/called here.
-       !! DON'T FORGET to correctly fill the fields of the user during its creation if necessary authenticationMethod : String !!
-    */
-    const authenticationMethodSelected = $('.select-authentication').val();
-    // Local account
-    if (authenticationMethodSelected === 'password') {
-      return;
-    }
+    break;
 
-    // Stop submit #at-pwd-form
-    event.preventDefault();
-    event.stopImmediatePropagation();
+  default:
+    break;
+  }
+}
 
-    const email = $('#at-field-username_and_email').val();
-    const password = $('#at-field-password').val();
+function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthenticationMethod}, match) {
+  if (displayAuthenticationMethod) {
+    return $('.select-authentication').val();
+  }
+  return getUserAuthenticationMethod(defaultAuthenticationMethod, match);
+}
 
-    // Ldap account
-    if (authenticationMethodSelected === 'ldap') {
-      // Check if the user can use the ldap connection
-      Meteor.subscribe('user-authenticationMethod', email, {
+function getUserAuthenticationMethod(defaultAuthenticationMethod, match) {
+  return new Promise((resolve) => {
+    try {
+      Meteor.subscribe('user-authenticationMethod', match, {
         onReady() {
           const user = Users.findOne();
-          if (user === undefined || user.authenticationMethod === 'ldap') {
-            // Use the ldap connection package
-            Meteor.loginWithLDAP(email, password, function(error) {
-              if (!error) {
-                // Connection
-                return FlowRouter.go('/');
-              }
-              return error;
-            });
-          }
-          return this.stop();
+
+          const authenticationMethod = user
+            ? user.authenticationMethod
+            : defaultAuthenticationMethod;
+
+          resolve(authenticationMethod);
         },
       });
+    } catch(error) {
+      resolve(defaultAuthenticationMethod);
     }
-  },
-});
-
-Template.defaultLayout.events({
-  'click .js-close-modal': () => {
-    Modal.close();
-  },
-});
+  });
+}

+ 19 - 0
client/components/settings/settingBody.jade

@@ -141,6 +141,16 @@ template(name='layoutSettings')
         span {{_ 'yes'}}
         input.form-control#hide-logo(type="radio" name="hideLogo" value="false" checked="{{#unless currentSetting.hideLogo}}checked{{/unless}}")
         span {{_ 'no'}}
+    li.layout-form
+      .title {{_ 'display-authentication-method'}}
+      .form-group.flex
+        input.form-control#display-authentication-method(type="radio" name="displayAuthenticationMethod" value="true" checked="{{#if currentSetting.displayAuthenticationMethod}}checked{{/if}}")
+        span {{_ 'yes'}}
+        input.form-control#display-authentication-method(type="radio" name="displayAuthenticationMethod" value="false" checked="{{#unless currentSetting.displayAuthenticationMethod}}checked{{/unless}}")
+        span {{_ 'no'}}
+    li.layout-form
+      .title {{_ 'default-authentication-method'}}
+      +selectAuthenticationMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
     li.layout-form
       .title {{_ 'custom-product-name'}}
       .form-group
@@ -153,3 +163,12 @@ template(name='layoutSettings')
       textarea#customHTMLbeforeBodyEnd.form-control= currentSetting.customHTMLbeforeBodyEnd
     li
       button.js-save-layout.primary {{_ 'save'}}
+
+
+template(name='selectAuthenticationMethod')
+  select#defaultAuthenticationMethod
+    each authentications
+      if isSelected value
+        option(value="{{value}}" selected) {{_ value}}
+      else
+        option(value="{{value}}") {{_ value}}

+ 35 - 5
client/components/settings/settingBody.js

@@ -62,6 +62,9 @@ BlazeComponent.extendComponent({
   toggleHideLogo() {
     $('#hide-logo').toggleClass('is-checked');
   },
+  toggleDisplayAuthenticationMethod() {
+    $('#display-authentication-method').toggleClass('is-checked');
+  },
   switchMenu(event) {
     const target = $(event.target);
     if (!target.hasClass('active')) {
@@ -140,17 +143,20 @@ BlazeComponent.extendComponent({
 
     const productName = $('#product-name').val().trim();
     const hideLogoChange = ($('input[name=hideLogo]:checked').val() === 'true');
+    const displayAuthenticationMethod = ($('input[name=displayAuthenticationMethod]:checked').val() === 'true');
+    const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
     const customHTMLafterBodyStart = $('#customHTMLafterBodyStart').val().trim();
     const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd').val().trim();
 
     try {
-
       Settings.update(Settings.findOne()._id, {
         $set: {
           productName,
           hideLogo: hideLogoChange,
           customHTMLafterBodyStart,
           customHTMLbeforeBodyEnd,
+          displayAuthenticationMethod,
+          defaultAuthenticationMethod,
         },
       });
     } catch (e) {
@@ -165,17 +171,14 @@ BlazeComponent.extendComponent({
 
   sendSMTPTestEmail() {
     Meteor.call('sendSMTPTestEmail', (err, ret) => {
-      if (!err && ret) { /* eslint-disable no-console */
+      if (!err && ret) {
         const message = `${TAPi18n.__(ret.message)}: ${ret.email}`;
-        console.log(message);
         alert(message);
       } else {
         const reason = err.reason || '';
         const message = `${TAPi18n.__(err.error)}\n${reason}`;
-        console.log(message, err);
         alert(message);
       }
-      /* eslint-enable no-console */
     });
   },
 
@@ -190,6 +193,7 @@ BlazeComponent.extendComponent({
       'click button.js-send-smtp-test-email': this.sendSMTPTestEmail,
       'click a.js-toggle-hide-logo': this.toggleHideLogo,
       'click button.js-save-layout': this.saveLayout,
+      'click a.js-toggle-display-authentication-method': this.toggleDisplayAuthenticationMethod,
     }];
   },
 }).register('setting');
@@ -262,3 +266,29 @@ BlazeComponent.extendComponent({
     }];
   },
 }).register('announcementSettings');
+
+
+Template.selectAuthenticationMethod.onCreated(function() {
+  this.authenticationMethods = new ReactiveVar([]);
+
+  Meteor.call('getAuthenticationsEnabled', (_, result) => {
+    if (result) {
+      // TODO : add a management of different languages
+      // (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
+      this.authenticationMethods.set([
+        {value: 'password'},
+        // Gets only the authentication methods availables
+        ...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})),
+      ]);
+    }
+  });
+});
+
+Template.selectAuthenticationMethod.helpers({
+  authentications() {
+    return Template.instance().authenticationMethods.get();
+  },
+  isSelected(match) {
+    return Template.instance().data.authenticationMethod === match;
+  },
+});

+ 10 - 1
models/settings.js

@@ -40,6 +40,14 @@ Settings.attachSchema(new SimpleSchema({
     type: String,
     optional: true,
   },
+  displayAuthenticationMethod: {
+    type: Boolean,
+    optional: true,
+  },
+  defaultAuthenticationMethod: {
+    type: String,
+    optional: false,
+  },
   hideLogo: {
     type: Boolean,
     optional: true,
@@ -85,7 +93,8 @@ if (Meteor.isServer) {
       const from = `Boards Support <support@${domain}>`;
       const defaultSetting = {disableRegistration: false, mailServer: {
         username: '', password: '', host: '', port: '', enableTLS: false, from,
-      }, createdAt: now, modifiedAt: now};
+      }, createdAt: now, modifiedAt: now, displayAuthenticationMethod: true,
+      defaultAuthenticationMethod: 'password'};
       Settings.insert(defaultSetting);
     }
     const newSetting = Settings.findOne();

+ 24 - 0
server/migrations.js

@@ -398,3 +398,27 @@ Migrations.add('add-custom-html-before-body-end', () => {
     },
   }, noValidateMulti);
 });
+
+Migrations.add('add-displayAuthenticationMethod', () => {
+  Settings.update({
+    displayAuthenticationMethod: {
+      $exists: false,
+    },
+  }, {
+    $set: {
+      displayAuthenticationMethod: true,
+    },
+  }, noValidateMulti);
+});
+
+Migrations.add('add-defaultAuthenticationMethod', () => {
+  Settings.update({
+    defaultAuthenticationMethod: {
+      $exists: false,
+    },
+  }, {
+    $set: {
+      defaultAuthenticationMethod: 'password',
+    },
+  }, noValidateMulti);
+});

+ 11 - 1
server/publications/settings.js

@@ -1,5 +1,15 @@
 Meteor.publish('setting', () => {
-  return Settings.find({}, {fields:{disableRegistration: 1, productName: 1, hideLogo: 1, customHTMLafterBodyStart: 1, customHTMLbeforeBodyEnd: 1}});
+  return Settings.find({}, {
+    fields:{
+      disableRegistration: 1,
+      productName: 1,
+      hideLogo: 1,
+      customHTMLafterBodyStart: 1,
+      customHTMLbeforeBodyEnd: 1,
+      displayAuthenticationMethod: 1,
+      defaultAuthenticationMethod: 1,
+    },
+  });
 });
 
 Meteor.publish('mailServer', function () {