mirror of
https://github.com/wekan/wekan.git
synced 2025-09-22 01:50:48 +02:00
Improve authentication
This commit is contained in:
parent
6f0e0748e1
commit
c2118f4830
7 changed files with 169 additions and 67 deletions
|
@ -23,10 +23,8 @@ template(name="userFormsLayout")
|
||||||
br
|
br
|
||||||
section.auth-dialog
|
section.auth-dialog
|
||||||
+Template.dynamic(template=content)
|
+Template.dynamic(template=content)
|
||||||
+connectionMethod
|
if currentSetting.displayAuthenticationMethod
|
||||||
if isCas
|
+connectionMethod
|
||||||
.at-form
|
|
||||||
button#cas(class='at-btn submit' type='submit') {{casSignInLabel}}
|
|
||||||
div.at-form-lang
|
div.at-form-lang
|
||||||
select.select-lang.js-userform-set-language
|
select.select-lang.js-userform-set-language
|
||||||
each languages
|
each languages
|
||||||
|
|
|
@ -20,13 +20,19 @@ const validator = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Template.userFormsLayout.onCreated(() => {
|
Template.userFormsLayout.onCreated(function() {
|
||||||
Meteor.subscribe('setting');
|
const instance = this;
|
||||||
|
instance.currentSetting = new ReactiveVar();
|
||||||
|
|
||||||
|
Meteor.subscribe('setting', {
|
||||||
|
onReady() {
|
||||||
|
instance.currentSetting.set(Settings.findOne());
|
||||||
|
return this.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.userFormsLayout.onRendered(() => {
|
Template.userFormsLayout.onRendered(() => {
|
||||||
|
|
||||||
AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
|
AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
|
||||||
|
|
||||||
const i18nTag = navigator.language;
|
const i18nTag = navigator.language;
|
||||||
|
@ -37,12 +43,10 @@ Template.userFormsLayout.onRendered(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.userFormsLayout.helpers({
|
Template.userFormsLayout.helpers({
|
||||||
|
|
||||||
currentSetting() {
|
currentSetting() {
|
||||||
return Settings.findOne();
|
return Template.instance().currentSetting.get();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
afterBodyStart() {
|
afterBodyStart() {
|
||||||
return currentSetting.customHTMLafterBodyStart;
|
return currentSetting.customHTMLafterBodyStart;
|
||||||
},
|
},
|
||||||
|
@ -75,17 +79,6 @@ Template.userFormsLayout.helpers({
|
||||||
const curLang = T9n.getLanguage() || 'en';
|
const curLang = T9n.getLanguage() || 'en';
|
||||||
return t9nTag === curLang;
|
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({
|
Template.userFormsLayout.events({
|
||||||
|
@ -94,49 +87,9 @@ Template.userFormsLayout.events({
|
||||||
T9n.setLanguage(i18nTagToT9n(i18nTag));
|
T9n.setLanguage(i18nTagToT9n(i18nTag));
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
},
|
},
|
||||||
'click button#cas'() {
|
'click #at-btn'(event, instance) {
|
||||||
Meteor.loginWithCas(function() {
|
if (FlowRouter.getRouteName() === 'atSignIn') {
|
||||||
if (FlowRouter.getRouteName() === 'atSignIn') {
|
authentication(event, instance);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop submit #at-pwd-form
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
|
|
||||||
const email = $('#at-field-username_and_email').val();
|
|
||||||
const password = $('#at-field-password').val();
|
|
||||||
|
|
||||||
// Ldap account
|
|
||||||
if (authenticationMethodSelected === 'ldap') {
|
|
||||||
// Check if the user can use the ldap connection
|
|
||||||
Meteor.subscribe('user-authenticationMethod', email, {
|
|
||||||
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();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -146,3 +99,57 @@ Template.defaultLayout.events({
|
||||||
Modal.close();
|
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();
|
||||||
|
|
||||||
|
if (result === 'ldap') {
|
||||||
|
return Meteor.loginWithLDAP(match, password, function() {
|
||||||
|
FlowRouter.go('/');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result === 'cas') {
|
||||||
|
return Meteor.loginWithCas(function() {
|
||||||
|
FlowRouter.go('/');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthenticationMethod}, match) {
|
||||||
|
if (displayAuthenticationMethod) {
|
||||||
|
return $('.select-authentication').val();
|
||||||
|
}
|
||||||
|
return getUserAuthenticationMethod(defaultAuthenticationMethod, match);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserAuthenticationMethod(defaultAuthenticationMethod, match) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
Meteor.subscribe('user-authenticationMethod', match, {
|
||||||
|
onReady() {
|
||||||
|
const user = Users.findOne();
|
||||||
|
|
||||||
|
const authenticationMethod = user
|
||||||
|
? user.authenticationMethod
|
||||||
|
: defaultAuthenticationMethod;
|
||||||
|
|
||||||
|
resolve(authenticationMethod);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch(error) {
|
||||||
|
resolve(defaultAuthenticationMethod);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -141,6 +141,16 @@ template(name='layoutSettings')
|
||||||
span {{_ 'yes'}}
|
span {{_ 'yes'}}
|
||||||
input.form-control#hide-logo(type="radio" name="hideLogo" value="false" checked="{{#unless currentSetting.hideLogo}}checked{{/unless}}")
|
input.form-control#hide-logo(type="radio" name="hideLogo" value="false" checked="{{#unless currentSetting.hideLogo}}checked{{/unless}}")
|
||||||
span {{_ 'no'}}
|
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
|
li.layout-form
|
||||||
.title {{_ 'custom-product-name'}}
|
.title {{_ 'custom-product-name'}}
|
||||||
.form-group
|
.form-group
|
||||||
|
@ -153,3 +163,12 @@ template(name='layoutSettings')
|
||||||
textarea#customHTMLbeforeBodyEnd.form-control= currentSetting.customHTMLbeforeBodyEnd
|
textarea#customHTMLbeforeBodyEnd.form-control= currentSetting.customHTMLbeforeBodyEnd
|
||||||
li
|
li
|
||||||
button.js-save-layout.primary {{_ 'save'}}
|
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}}
|
|
@ -62,6 +62,9 @@ BlazeComponent.extendComponent({
|
||||||
toggleHideLogo() {
|
toggleHideLogo() {
|
||||||
$('#hide-logo').toggleClass('is-checked');
|
$('#hide-logo').toggleClass('is-checked');
|
||||||
},
|
},
|
||||||
|
toggleDisplayAuthenticationMethod() {
|
||||||
|
$('#display-authentication-method').toggleClass('is-checked');
|
||||||
|
},
|
||||||
switchMenu(event) {
|
switchMenu(event) {
|
||||||
const target = $(event.target);
|
const target = $(event.target);
|
||||||
if (!target.hasClass('active')) {
|
if (!target.hasClass('active')) {
|
||||||
|
@ -140,17 +143,20 @@ BlazeComponent.extendComponent({
|
||||||
|
|
||||||
const productName = $('#product-name').val().trim();
|
const productName = $('#product-name').val().trim();
|
||||||
const hideLogoChange = ($('input[name=hideLogo]:checked').val() === 'true');
|
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 customHTMLafterBodyStart = $('#customHTMLafterBodyStart').val().trim();
|
||||||
const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd').val().trim();
|
const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd').val().trim();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Settings.update(Settings.findOne()._id, {
|
Settings.update(Settings.findOne()._id, {
|
||||||
$set: {
|
$set: {
|
||||||
productName,
|
productName,
|
||||||
hideLogo: hideLogoChange,
|
hideLogo: hideLogoChange,
|
||||||
customHTMLafterBodyStart,
|
customHTMLafterBodyStart,
|
||||||
customHTMLbeforeBodyEnd,
|
customHTMLbeforeBodyEnd,
|
||||||
|
displayAuthenticationMethod,
|
||||||
|
defaultAuthenticationMethod
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -190,6 +196,7 @@ BlazeComponent.extendComponent({
|
||||||
'click button.js-send-smtp-test-email': this.sendSMTPTestEmail,
|
'click button.js-send-smtp-test-email': this.sendSMTPTestEmail,
|
||||||
'click a.js-toggle-hide-logo': this.toggleHideLogo,
|
'click a.js-toggle-hide-logo': this.toggleHideLogo,
|
||||||
'click button.js-save-layout': this.saveLayout,
|
'click button.js-save-layout': this.saveLayout,
|
||||||
|
'click a.js-toggle-display-authentication-method': this.toggleDisplayAuthenticationMethod
|
||||||
}];
|
}];
|
||||||
},
|
},
|
||||||
}).register('setting');
|
}).register('setting');
|
||||||
|
@ -262,3 +269,31 @@ BlazeComponent.extendComponent({
|
||||||
}];
|
}];
|
||||||
},
|
},
|
||||||
}).register('announcementSettings');
|
}).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) {
|
||||||
|
console.log('this : ', this);
|
||||||
|
console.log('instance : ', Template.instance());
|
||||||
|
return Template.instance().data.authenticationMethod === match;
|
||||||
|
}
|
||||||
|
});
|
|
@ -40,6 +40,14 @@ Settings.attachSchema(new SimpleSchema({
|
||||||
type: String,
|
type: String,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
displayAuthenticationMethod: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
defaultAuthenticationMethod: {
|
||||||
|
type: String,
|
||||||
|
optional: false,
|
||||||
|
},
|
||||||
hideLogo: {
|
hideLogo: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
optional: true,
|
optional: true,
|
||||||
|
@ -85,7 +93,8 @@ if (Meteor.isServer) {
|
||||||
const from = `Boards Support <support@${domain}>`;
|
const from = `Boards Support <support@${domain}>`;
|
||||||
const defaultSetting = {disableRegistration: false, mailServer: {
|
const defaultSetting = {disableRegistration: false, mailServer: {
|
||||||
username: '', password: '', host: '', port: '', enableTLS: false, from,
|
username: '', password: '', host: '', port: '', enableTLS: false, from,
|
||||||
}, createdAt: now, modifiedAt: now};
|
}, createdAt: now, modifiedAt: now, displayAuthenticationMethod: true,
|
||||||
|
defaultAuthenticationMethod: 'password'};
|
||||||
Settings.insert(defaultSetting);
|
Settings.insert(defaultSetting);
|
||||||
}
|
}
|
||||||
const newSetting = Settings.findOne();
|
const newSetting = Settings.findOne();
|
||||||
|
|
|
@ -398,3 +398,27 @@ Migrations.add('add-custom-html-before-body-end', () => {
|
||||||
},
|
},
|
||||||
}, noValidateMulti);
|
}, 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)
|
||||||
|
});
|
|
@ -1,5 +1,15 @@
|
||||||
Meteor.publish('setting', () => {
|
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 () {
|
Meteor.publish('mailServer', function () {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue