add ldap support | simplify authentications

This commit is contained in:
guillaume 2018-10-09 14:14:39 +02:00
parent 5b8c642d8f
commit 3b4f285fea
15 changed files with 493 additions and 49 deletions

View file

@ -18,12 +18,52 @@ ARG MATOMO_WITH_USERNAME
ARG BROWSER_POLICY_ENABLED
ARG TRUSTED_URL
ARG WEBHOOKS_ATTRIBUTES
ARG OAUTH2_ENABLED
ARG OAUTH2_CLIENT_ID
ARG OAUTH2_SECRET
ARG OAUTH2_SERVER_URL
ARG OAUTH2_AUTH_ENDPOINT
ARG OAUTH2_USERINFO_ENDPOINT
ARG OAUTH2_TOKEN_ENDPOINT
ARG LDAP_ENABLE
ARG LDAP_PORT
ARG LDAP_HOST
ARG LDAP_BASEDN
ARG LDAP_LOGIN_FALLBACK
ARG LDAP_RECONNECT
ARG LDAP_TIMEOUT
ARG LDAP_IDLE_TIMEOUT
ARG LDAP_CONNECT_TIMEOUT
ARG LDAP_AUTHENTIFICATION
ARG LDAP_AUTHENTIFICATION_USERDN
ARG LDAP_AUTHENTIFICATION_PASSWORD
ARG LDAP_LOG_ENABLED
ARG LDAP_BACKGROUND_SYNC
ARG LDAP_BACKGROUND_SYNC_INTERVAL
ARG LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED
ARG LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS
ARG LDAP_ENCRYPTION
ARG LDAP_CA_CERT
ARG LDAP_REJECT_UNAUTHORIZED
ARG LDAP_USER_SEARCH_FILTER
ARG LDAP_USER_SEARCH_SCOPE
ARG LDAP_USER_SEARCH_FIELD
ARG LDAP_SEARCH_PAGE_SIZE
ARG LDAP_SEARCH_SIZE_LIMIT
ARG LDAP_GROUP_FILTER_ENABLE
ARG LDAP_GROUP_FILTER_OBJECTCLASS
ARG LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE
ARG LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE
ARG LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT
ARG LDAP_GROUP_FILTER_GROUP_NAME
ARG LDAP_UNIQUE_IDENTIFIER_FIELD
ARG LDAP_UTF8_NAMES_SLUGIFY
ARG LDAP_USERNAME_FIELD
ARG LDAP_MERGE_EXISTING_USERS
ARG LDAP_SYNC_USER_DATA
ARG LDAP_SYNC_USER_DATA_FIELDMAP
ARG LDAP_SYNC_GROUP_ROLES
ARG LDAP_DEFAULT_DOMAIN
# Set the environment variables (defaults where required)
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
@ -45,12 +85,52 @@ ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential pyth
BROWSER_POLICY_ENABLED=true \
TRUSTED_URL="" \
WEBHOOKS_ATTRIBUTES="" \
OAUTH2_ENABLED=false \
OAUTH2_CLIENT_ID="" \
OAUTH2_SECRET="" \
OAUTH2_SERVER_URL="" \
OAUTH2_AUTH_ENDPOINT="" \
OAUTH2_USERINFO_ENDPOINT="" \
OAUTH2_TOKEN_ENDPOINT=""
OAUTH2_TOKEN_ENDPOINT="" \
LDAP_ENABLE=false \
LDAP_PORT=389 \
LDAP_HOST="" \
LDAP_BASEDN="" \
LDAP_LOGIN_FALLBACK=false \
LDAP_RECONNECT=true \
LDAP_TIMEOUT=10000 \
LDAP_IDLE_TIMEOUT=10000 \
LDAP_CONNECT_TIMEOUT=10000 \
LDAP_AUTHENTIFICATION=false \
LDAP_AUTHENTIFICATION_USERDN="" \
LDAP_AUTHENTIFICATION_PASSWORD="" \
LDAP_LOG_ENABLED=false \
LDAP_BACKGROUND_SYNC=false \
LDAP_BACKGROUND_SYNC_INTERVAL=100 \
LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED=false \
LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS=false \
LDAP_ENCRYPTION=false \
LDAP_CA_CERT="" \
LDAP_REJECT_UNAUTHORIZED=false \
LDAP_USER_SEARCH_FILTER="" \
LDAP_USER_SEARCH_SCOPE="" \
LDAP_USER_SEARCH_FIELD="" \
LDAP_SEARCH_PAGE_SIZE=0 \
LDAP_SEARCH_SIZE_LIMIT=0 \
LDAP_GROUP_FILTER_ENABLE=false \
LDAP_GROUP_FILTER_OBJECTCLASS="" \
LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE="" \
LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE="" \
LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT="" \
LDAP_GROUP_FILTER_GROUP_NAME="" \
LDAP_UNIQUE_IDENTIFIER_FIELD="" \
LDAP_UTF8_NAMES_SLUGIFY=true \
LDAP_USERNAME_FIELD="" \
LDAP_MERGE_EXISTING_USERS=false \
LDAP_SYNC_USER_DATA=false \
LDAP_SYNC_USER_DATA_FIELDMAP="" \
LDAP_SYNC_GROUP_ROLES="" \
LDAP_DEFAULT_DOMAIN="" \
# Copy the app to the image
COPY ${SRC_PATH} /home/wekan/app

View file

@ -6,7 +6,23 @@ const i18nTagToT9n = (i18nTag) => {
return i18nTag;
};
const validator = {
set: function(obj, prop, value) {
if (prop === 'state' && value !== 'signIn') {
$('.at-form-authentication').hide();
} else if (prop === 'state' && value === 'signIn') {
$('.at-form-authentication').show();
}
// The default behavior to store the value
obj[prop] = value;
// Indicate success
return true;
}
};
Template.userFormsLayout.onRendered(() => {
AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
const i18nTag = navigator.language;
if (i18nTag) {
T9n.setLanguage(i18nTagToT9n(i18nTag));
@ -65,37 +81,37 @@ Template.userFormsLayout.events({
}
});
},
'submit form'(event) {
const connectionMethod = $('.select-connection').val();
'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 (connectionMethod === 'default') {
if (authenticationMethodSelected === 'password') {
return;
}
// TODO : find a way to block "submit #at-pwd-form" of the at_pwd_form.js
// Stop submit #at-pwd-form
event.preventDefault();
event.stopImmediatePropagation();
const inputs = event.target.getElementsByTagName('input');
const email = inputs.namedItem('at-field-username_and_email').value;
const password = inputs.namedItem('at-field-password').value;
const email = $('#at-field-username_and_email').val();
const password = $('#at-field-password').val();
// Ldap account
if (connectionMethod === 'ldap') {
if (authenticationMethodSelected === 'ldap') {
// Check if the user can use the ldap connection
Meteor.subscribe('user-connection-method', email, {
Meteor.subscribe('user-authenticationMethod', email, {
onReady() {
const ldap = Users.findOne();
if (ldap) {
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('/');
} else {
return error;
}
return error;
});
}
return this.stop();

View file

@ -1,6 +1,6 @@
template(name='connectionMethod')
div.at-form-connection
label Authentication method
select.select-connection
each connections
div.at-form-authentication
label {{_ 'authentication-method'}}
select.select-authentication
each authentications
option(value="{{value}}") {{_ value}}

View file

@ -1,20 +1,20 @@
Template.connectionMethod.onCreated(function() {
this.connectionMethods = new ReactiveVar([]);
this.authenticationMethods = new ReactiveVar([]);
Meteor.call('getConnectionsEnabled', (_, result) => {
Meteor.call('getAuthenticationsEnabled', (_, result) => {
if (result) {
// TODO : add a management of different languages
// (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
this.connectionMethods.set([
{value: 'default'},
// Gets only the connection methods availables
this.authenticationMethods.set([
{value: 'password'},
// Gets only the authentication methods availables
...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})),
]);
}
// If only the default authentication available, hides the select boxe
const content = $('.at-form-connection');
if (!(this.connectionMethods.get().length > 1)) {
const content = $('.at-form-authentication');
if (!(this.authenticationMethods.get().length > 1)) {
content.hide();
} else {
content.show();
@ -24,11 +24,11 @@ Template.connectionMethod.onCreated(function() {
Template.connectionMethod.onRendered(() => {
// Moves the select boxe in the first place of the at-pwd-form div
$('.at-form-connection').detach().prependTo('.at-pwd-form');
$('.at-form-authentication').detach().prependTo('.at-pwd-form');
});
Template.connectionMethod.helpers({
connections() {
return Template.instance().connectionMethods.get();
authentications() {
return Template.instance().authenticationMethods.get();
},
});
});

View file

@ -27,6 +27,7 @@ template(name="peopleGeneral")
th {{_ 'verified'}}
th {{_ 'createdAt'}}
th {{_ 'active'}}
th {{_ 'authentication-method'}}
th
each user in peopleList
+peopleRow(userId=user._id)
@ -52,6 +53,7 @@ template(name="peopleRow")
| {{_ 'no'}}
else
| {{_ 'yes'}}
td {{_ userData.authenticationMethod }}
td
a.edit-user
| {{_ 'edit'}}
@ -66,12 +68,18 @@ template(name="editUserPopup")
| {{_ 'username'}}
span.error.hide.username-taken
| {{_ 'error-username-taken'}}
input.js-profile-username(type="text" value=user.username)
if isLdap
input.js-profile-username(type="text" value=user.username readonly)
else
input.js-profile-username(type="text" value=user.username)
label
| {{_ 'email'}}
span.error.hide.email-taken
| {{_ 'error-email-taken'}}
input.js-profile-email(type="email" value="{{user.emails.[0].address}}")
if isLdap
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
else
input.js-profile-email(type="email" value="{{user.emails.[0].address}}")
label
| {{_ 'admin'}}
select.select-role.js-profile-isadmin
@ -82,9 +90,17 @@ template(name="editUserPopup")
select.select-active.js-profile-isactive
option(value="false") {{_ 'yes'}}
option(value="true" selected="{{user.loginDisabled}}") {{_ 'no'}}
label
| {{_ 'authentication-type'}}
select.select-authenticationMethod.js-authenticationMethod
each authentications
if isSelected value
option(value="{{value}}" selected) {{_ value}}
else
option(value="{{value}}") {{_ value}}
hr
label
| {{_ 'password'}}
input.js-profile-password(type="password")
input.primary.wide(type="submit" value="{{_ 'save'}}")
input.primary.wide(type="submit" value="{{_ 'save'}}")

View file

@ -62,10 +62,39 @@ Template.peopleRow.helpers({
},
});
Template.editUserPopup.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.editUserPopup.helpers({
user() {
return Users.findOne(this.userId);
},
authentications() {
return Template.instance().authenticationMethods.get();
},
isSelected(match) {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
return selected === match;
},
isLdap() {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
return selected === 'ldap';
}
});
BlazeComponent.extendComponent({
@ -91,6 +120,7 @@ Template.editUserPopup.events({
const isAdmin = tpl.find('.js-profile-isadmin').value.trim();
const isActive = tpl.find('.js-profile-isactive').value.trim();
const email = tpl.find('.js-profile-email').value.trim();
const authentication = tpl.find('.js-authenticationMethod').value.trim();
const isChangePassword = password.length > 0;
const isChangeUserName = username !== user.username;
@ -101,6 +131,7 @@ Template.editUserPopup.events({
'profile.fullname': fullname,
'isAdmin': isAdmin === 'true',
'loginDisabled': isActive === 'true',
'authenticationMethod': authentication
},
});

View file

@ -63,6 +63,9 @@ services:
# What to send to Outgoing Webhook, or leave out. Example, that includes all that are default: cardId,listId,oldListId,boardId,comment,user,card,commentId .
# example: WEBHOOKS_ATTRIBUTES=cardId,listId,oldListId,boardId,comment,user,card,commentId
- WEBHOOKS_ATTRIBUTES=''
# Enable the OAuth2 connection
# example: OAUTH2_ENABLED=true
- OAUTH2_ENABLED=false
# OAuth2 docs: https://github.com/wekan/wekan/wiki/OAuth2
# OAuth2 Client ID, for example from Rocket.Chat. Example: abcde12345
# example: OAUTH2_CLIENT_ID=abcde12345
@ -82,6 +85,124 @@ services:
# OAuth2 Token Endpoint. Example: /oauth/token
# example: OAUTH2_TOKEN_ENDPOINT=/oauth/token
- OAUTH2_TOKEN_ENDPOINT=''
# LDAP_ENABLE : Enable or not the connection by the LDAP
# example : LDAP_ENABLE=true
- LDAP_ENABLE=false
# LDAP_PORT : The port of the LDAP server
# example : LDAP_PORT=389
- LDAP_PORT=389
# LDAP_HOST : The host server for the LDAP server
# example : LDAP_HOST=localhost
- LDAP_HOST=''
# LDAP_BASEDN : The base DN for the LDAP Tree
# example : LDAP_BASEDN=ou=user,dc=example,dc=org
- LDAP_BASEDN=''
# LDAP_LOGIN_FALLBACK : Fallback on the default authentication method
# example : LDAP_LOGIN_FALLBACK=true
- LDAP_LOGIN_FALLBACK=false
# LDAP_RECONNECT : Reconnect to the server if the connection is lost
# example : LDAP_RECONNECT=false
- LDAP_RECONNECT=true
# LDAP_TIMEOUT : Overall timeout, in milliseconds
# example : LDAP_TIMEOUT=12345
- LDAP_TIMEOUT=10000
# LDAP_IDLE_TIMEOUT : Specifies the timeout for idle LDAP connections in milliseconds
# example : LDAP_IDLE_TIMEOUT=12345
- LDAP_IDLE_TIMEOUT=10000
# LDAP_CONNECT_TIMEOUT : Connection timeout, in milliseconds
# example : LDAP_CONNECT_TIMEOUT=12345
- LDAP_CONNECT_TIMEOUT=10000
# LDAP_AUTHENTIFICATION : If the LDAP needs a user account to search
# example : LDAP_AUTHENTIFICATION=true
- LDAP_AUTHENTIFICATION=false
# LDAP_AUTHENTIFICATION_USERDN : The search user DN
# example : LDAP_AUTHENTIFICATION_USERDN=cn=admin,dc=example,dc=org
- LDAP_AUTHENTIFICATION_USERDN=''
# LDAP_AUTHENTIFICATION_PASSWORD : The password for the search user
# example : AUTHENTIFICATION_PASSWORD=admin
- LDAP_AUTHENTIFICATION_PASSWORD=''
# LDAP_LOG_ENABLED : Enable logs for the module
# example : LDAP_LOG_ENABLED=true
- LDAP_LOG_ENABLED=false
# LDAP_BACKGROUND_SYNC : If the sync of the users should be done in the background
# example : LDAP_BACKGROUND_SYNC=true
- LDAP_BACKGROUND_SYNC=false
# LDAP_BACKGROUND_SYNC_INTERVAL : At which interval does the background task sync in milliseconds
# example : LDAP_BACKGROUND_SYNC_INTERVAL=12345
- LDAP_BACKGROUND_SYNC_INTERVAL=100
# LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED :
# example : LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED=true
- LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED=false
# LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS :
# example : LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS=true
- LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS=false
# LDAP_ENCRYPTION : If using LDAPS
# example : LDAP_ENCRYPTION=true
- LDAP_ENCRYPTION=false
# LDAP_CA_CERT : The certification for the LDAPS server
# example : LDAP_CA_CERT=-----BEGIN CERTIFICATE-----MIIE+zCCA+OgAwIBAgIkAhwR/6TVLmdRY6hHxvUFWc0+Enmu/Hu6cj+G2FIdAgIC...-----END CERTIFICATE-----
- LDAP_CA_CERT=''
# LDAP_REJECT_UNAUTHORIZED : Reject Unauthorized Certificate
# example : LDAP_REJECT_UNAUTHORIZED=true
- LDAP_REJECT_UNAUTHORIZED=false
# LDAP_USER_SEARCH_FILTER : Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
# example : LDAP_USER_SEARCH_FILTER=
- LDAP_USER_SEARCH_FILTER=''
# LDAP_USER_SEARCH_SCOPE : Base (search only in the provided DN), one (search only in the provided DN and one level deep), or subtree (search the whole subtree)
# example : LDAP_USER_SEARCH_SCOPE=one
- LDAP_USER_SEARCH_SCOPE=''
# LDAP_USER_SEARCH_FIELD : Which field is used to find the user
# example : LDAP_USER_SEARCH_FIELD=uid
- LDAP_USER_SEARCH_FIELD=''
# LDAP_SEARCH_PAGE_SIZE : Used for pagination (0=unlimited)
# example : LDAP_SEARCH_PAGE_SIZE=12345
- LDAP_SEARCH_PAGE_SIZE=0
# LDAP_SEARCH_SIZE_LIMIT : The limit number of entries (0=unlimited)
# example : LDAP_SEARCH_SIZE_LIMIT=12345
- LDAP_SEARCH_SIZE_LIMIT=0
# LDAP_GROUP_FILTER_ENABLE : Enable group filtering
# example : LDAP_GROUP_FILTER_ENABLE=true
- LDAP_GROUP_FILTER_ENABLE=false
# LDAP_GROUP_FILTER_OBJECTCLASS : The object class for filtering
# example : LDAP_GROUP_FILTER_OBJECTCLASS=group
- LDAP_GROUP_FILTER_OBJECTCLASS=''
# LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE :
# example :
- LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE=''
# LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE :
# example :
- LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE=''
# LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT :
# example :
- LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT=''
# LDAP_GROUP_FILTER_GROUP_NAME :
# example :
- LDAP_GROUP_FILTER_GROUP_NAME=''
# LDAP_UNIQUE_IDENTIFIER_FIELD : This field is sometimes class GUID (Globally Unique Identifier)
# example : LDAP_UNIQUE_IDENTIFIER_FIELD=guid
- LDAP_UNIQUE_IDENTIFIER_FIELD=''
# LDAP_UTF8_NAMES_SLUGIFY : Convert the username to utf8
# example : LDAP_UTF8_NAMES_SLUGIFY=false
- LDAP_UTF8_NAMES_SLUGIFY=true
# LDAP_USERNAME_FIELD : Which field contains the ldap username
# example : LDAP_USERNAME_FIELD=username
- LDAP_USERNAME_FIELD=''
# LDAP_MERGE_EXISTING_USERS :
# example : LDAP_MERGE_EXISTING_USERS=true
- LDAP_MERGE_EXISTING_USERS=false
# LDAP_SYNC_USER_DATA :
# example : LDAP_SYNC_USER_DATA=true
- LDAP_SYNC_USER_DATA=false
# LDAP_SYNC_USER_DATA_FIELDMAP :
# example : LDAP_SYNC_USER_DATA_FIELDMAP={\"cn\":\"name\", \"mail\":\"email\"}
- LDAP_SYNC_USER_DATA_FIELDMAP=''
# LDAP_SYNC_GROUP_ROLES :
# example :
- LDAP_SYNC_GROUP_ROLES=''
# LDAP_DEFAULT_DOMAIN : The default domain of the ldap it is used to create email if the field is not map correctly with the LDAP_SYNC_USER_DATA_FIELDMAP
# example :
- LDAP_DEFAULT_DOMAIN=''
depends_on:
- wekandb

View file

@ -607,5 +607,10 @@
"r-d-check-of-list": "of checklist",
"r-d-add-checklist": "Add checklist",
"r-d-remove-checklist": "Remove checklist",
"r-when-a-card-is-moved": "When a card is moved to another list"
"r-when-a-card-is-moved": "When a card is moved to another list",
"ldap": "Ldap",
"oauth2": "Oauth2",
"cas": "Cas",
"authentication-method": "Authentication method",
"authentication-type": "Authentication type"
}

View file

@ -223,7 +223,7 @@ if (Meteor.isServer) {
},
// Gets all connection methods to use it in the Template
getConnectionsEnabled() {
getAuthenticationsEnabled() {
return {
ldap: isLdapEnabled(),
oauth2: isOauth2Enabled(),

View file

@ -127,10 +127,10 @@ Users.attachSchema(new SimpleSchema({
type: Boolean,
optional: true,
},
// TODO : write a migration and check if using a ldap parameter is better than a connection_type parameter
ldap: {
type: Boolean,
optional: true,
'authenticationMethod': {
type: String,
optional: false,
defaultValue: 'password',
},
}));
@ -499,6 +499,7 @@ if (Meteor.isServer) {
user.emails = [{ address: email, verified: true }];
const initials = user.services.oidc.fullname.match(/\b[a-zA-Z]/g).join('').toUpperCase();
user.profile = { initials, fullname: user.services.oidc.fullname };
user['authenticationMethod'] = 'oauth2';
// see if any existing user has this email address or username, otherwise create new
const existingUser = Meteor.users.findOne({$or: [{'emails.address': email}, {'username':user.username}]});
@ -511,6 +512,7 @@ if (Meteor.isServer) {
existingUser.emails = user.emails;
existingUser.username = user.username;
existingUser.profile = user.profile;
existingUser['authenticationMethod'] = user['authenticationMethod'];
Meteor.users.remove({_id: existingUser._id}); // remove existing record
return existingUser;
@ -525,7 +527,7 @@ if (Meteor.isServer) {
// If ldap, bypass the inviation code if the self registration isn't allowed.
// TODO : pay attention if ldap field in the user model change to another content ex : ldap field to connection_type
if (options.ldap || !disableRegistration) {
user.ldap = true;
user['authenticationMethod'] = 'ldap';
return user;
}
@ -645,7 +647,7 @@ if (Meteor.isServer) {
const disableRegistration = Settings.findOne().disableRegistration;
// If ldap, bypass the inviation code if the self registration isn't allowed.
// TODO : pay attention if ldap field in the user model change to another content ex : ldap field to connection_type
if (!doc.ldap && disableRegistration) {
if (doc['authenticationMethod'] !== 'ldap' && disableRegistration) {
const invitationCode = InvitationCodes.findOne({code: doc.profile.icode, valid: true});
if (!invitationCode) {
throw new Meteor.Error('error-invitation-code-not-exist');

View file

@ -245,12 +245,14 @@ const myCommand :Spk.Manifest.Command = (
(key = "BROWSER_POLICY_ENABLED", value="true"),
(key = "TRUSTED_URL", value=""),
(key = "WEBHOOKS_ATTRIBUTES", value=""),
(key = "OAUTH2_CLIENT_ID", value=""),
(key = "OAUTH2_ENABLED", value=""),
(key = "OAUTH2_CLIENT_ID", value="false"),
(key = "OAUTH2_SECRET", value=""),
(key = "OAUTH2_SERVER_URL", value=""),
(key = "OAUTH2_AUTH_ENDPOINT", value=""),
(key = "OAUTH2_USERINFO_ENDPOINT", value=""),
(key = "OAUTH2_TOKEN_ENDPOINT", value=""),
(key = "LDAP_ENABLE", value="false"),
(key = "SANDSTORM", value = "1"),
(key = "METEOR_SETTINGS", value = "{\"public\": {\"sandstorm\": true}}")
]

View file

@ -321,3 +321,15 @@ Migrations.add('add-subtasks-allowed', () => {
},
}, noValidateMulti);
});
Migrations.add('add-authenticationMethod', () => {
Users.update({
'authenticationMethod': {
$exists: false,
},
}, {
$set: {
'authenticationMethod': 'password',
},
}, noValidateMulti);
});

View file

@ -17,6 +17,7 @@ Meteor.publish('people', function(limit) {
'emails': 1,
'createdAt': 1,
'loginDisabled': 1,
'authenticationMethod': 1
},
});
} else {

View file

@ -18,12 +18,11 @@ Meteor.publish('user-admin', function() {
});
});
Meteor.publish('user-connection-method', function(match) {
Meteor.publish('user-authenticationMethod', function(match) {
check(match, String);
return Users.find({$or: [{email: match}, {username: match}]}, {
return Users.find({$or: [{_id: match}, {email: match}, {username: match}]}, {
fields: {
ldap: 1,
'authenticationMethod': 1,
},
});
});

View file

@ -3,7 +3,7 @@
# All supported keys are defined here together with descriptions and default values
# list of supported keys
keys="MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT"
keys="MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN"
# default values
DESCRIPTION_MONGODB_BIND_UNIX_SOCKET="mongodb binding unix socket:\n"\
@ -82,6 +82,10 @@ DESCRIPTION_WEBHOOKS_ATTRIBUTES="What to send to Outgoing Webhook, or leave out.
DEFAULT_WEBHOOKS_ATTRIBUTES=""
KEY_WEBHOOKS_ATTRIBUTES="webhooks-attributes"
DESCRIPTION_OAUTH2_ENABLED="Enable the OAuth2 connection"
DEFAULT_OAUTH2_ENABLED="false"
KEY_OAUTH2_ENABLED="oauth2-enabled"
DESCRIPTION_OAUTH2_CLIENT_ID="OAuth2 Client ID, for example from Rocket.Chat. Example: abcde12345"
DEFAULT_OAUTH2_CLIENT_ID=""
KEY_OAUTH2_CLIENT_ID="oauth2-client-id"
@ -106,3 +110,158 @@ DESCRIPTION_OAUTH2_TOKEN_ENDPOINT="OAuth2 token endpoint. Example: /oauth/token"
DEFAULT_OAUTH2_TOKEN_ENDPOINT=""
KEY_OAUTH2_TOKEN_ENDPOINT="oauth2-token-endpoint"
DESCRIPTION_LDAP_ENABLE="Enable or not the connection by the LDAP"
DEFAULT_LDAP_ENABLE="false"
KEY_LDAP_ENABLE="ldap-enable"
DESCRIPTION_LDAP_PORT="The port of the LDAP server"
DEFAULT_LDAP_PORT="389"
KEY_LDAP_PORT="ldap-port"
DESCRIPTION_LDAP_HOST="The host server for the LDAP server"
DEFAULT_LDAP_HOST=""
KEY_LDAP_HOST="ldap-host"
DESCRIPTION_LDAP_BASEDN="The base DN for the LDAP Tree"
DEFAULT_LDAP_BASEDN=""
KEY_LDAP_BASEDN="ldap-basedn"
DESCRIPTION_LDAP_LOGIN_FALLBACK="Fallback on the default authentication method"
DEFAULT_LDAP_LOGIN_FALLBACK="false"
KEY_LDAP_LOGIN_FALLBACK="ldap-login-fallback"
DESCRIPTION_LDAP_RECONNECT="Reconnect to the server if the connection is lost"
DEFAULT_LDAP_RECONNECT="true"
KEY_LDAP_RECONNECT="ldap-reconnect"
DESCRIPTION_LDAP_TIMEOUT="Overall timeout, in milliseconds."
DEFAULT_LDAP_TIMEOUT="10000"
KEY_LDAP_TIMEOUT="ldap-timeout"
DESCRIPTION_LDAP_IDLE_TIMEOUT="Specifies the timeout for idle LDAP connections in milliseconds"
DEFAULT_LDAP_IDLE_TIMEOUT="10000"
KEY_LDAP_IDLE_TIMEOUT="ldap-idle-timeout"
DESCRIPTION_LDAP_CONNECT_TIMEOUT="Connection timeout, in milliseconds."
DEFAULT_LDAP_CONNECT_TIMEOUT="10000"
KEY_LDAP_CONNECT_TIMEOUT="ldap-connect-timeout"
DESCRIPTION_LDAP_AUTHENTIFICATION="If the LDAP needs a user account to search"
DEFAULT_LDAP_AUTHENTIFICATION="false"
KEY_LDAP_AUTHENTIFICATION="ldap-authentication"
DESCRIPTION_LDAP_AUTHENTIFICATION_USERDN="The search user DN"
DEFAULT_LDAP_AUTHENTIFICATION_USERDN=""
KEY_LDAP_AUTHENTIFICATION_USERDN="ldap-authentication-userdn"
DESCRIPTION_LDAP_AUTHENTIFICATION_PASSWORD="The password for the search user"
DEFAULT_LDAP_AUTHENTIFICATION_PASSWORD=""
KEY_LDAP_AUTHENTIFICATION_PASSWORD="ldap-authentication-password"
DESCRIPTION_LDAP_LOG_ENABLED="Enable logs for the module"
DEFAULT_LDAP_LOG_ENABLED="false"
KEY_LDAP_LOG_ENABLED="ldap-log-enabled"
DESCRIPTION_LDAP_BACKGROUND_SYNC="If the sync of the users should be done in the background"
DEFAULT_LDAP_BACKGROUND_SYNC="false"
KEY_LDAP_BACKGROUND_SYNC="ldap-background-sync"
DESCRIPTION_LDAP_BACKGROUND_SYNC_INTERVAL="At which interval does the background task sync in milliseconds"
DEFAULT_LDAP_BACKGROUND_SYNC_INTERVAL="100"
KEY_LDAP_BACKGROUND_SYNC_INTERVAL="ldap-background-sync-interval"
DESCRIPTION_LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED=""
DEFAULT_LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED="false"
KEY_LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED="ldap-background-sync-keep-existant-users-updated"
DESCRIPTION_LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS=""
DEFAULT_LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS="false"
KEY_LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS="ldap-background-sync-import-new-users"
DESCRIPTION_LDAP_ENCRYPTION="If using LDAPS"
DEFAULT_LDAP_ENCRYPTION="false"
KEY_LDAP_ENCRYPTION="ldap-encryption"
DESCRIPTION_LDAP_CA_CERT="The certification for the LDAPS server"
DEFAULT_LDAP_CA_CERT=""
KEY_LDAP_CA_CERT="ldap-ca-cert"
DESCRIPTION_LDAP_REJECT_UNAUTHORIZED="Reject Unauthorized Certificate"
DEFAULT_LDAP_REJECT_UNAUTHORIZED="false"
KEY_LDAP_REJECT_UNAUTHORIZED="ldap-reject-unauthorized"
DESCRIPTION_LDAP_USER_SEARCH_FILTER="Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed"
DEFAULT_LDAP_USER_SEARCH_FILTER=""
KEY_LDAP_USER_SEARCH_FILTER="ldap-user-search-filter"
DESCRIPTION_LDAP_USER_SEARCH_SCOPE="Base (search only in the provided DN), one (search only in the provided DN and one level deep), or subtree (search the whole subtree)."
DEFAULT_LDAP_USER_SEARCH_SCOPE=""
KEY_LDAP_USER_SEARCH_SCOPE="ldap-user-search-scope"
DESCRIPTION_LDAP_USER_SEARCH_FIELD="Which field is used to find the user"
DEFAULT_LDAP_USER_SEARCH_FIELD=""
KEY_LDAP_USER_SEARCH_FIELD="ldap-user-search-field"
DESCRIPTION_LDAP_SEARCH_PAGE_SIZE="Used for pagination (0=unlimited)"
DEFAULT_LDAP_SEARCH_PAGE_SIZE="0"
KEY_LDAP_SEARCH_PAGE_SIZE="ldap-search-page-size"
DESCRIPTION_LDAP_SEARCH_SIZE_LIMIT="The limit number of entries (0=unlimited)"
DEFAULT_LDAP_SEARCH_SIZE_LIMIT="0"
KEY_LDAP_SEARCH_SIZE_LIMIT="ldap-search-size-limit"
DESCRIPTION_LDAP_GROUP_FILTER_ENABLE="Enable group filtering"
DEFAULT_LDAP_GROUP_FILTER_ENABLE="false"
KEY_LDAP_GROUP_FILTER_ENABLE="ldap-group-filter-enable"
DESCRIPTION_LDAP_GROUP_FILTER_OBJECTCLASS="The object class for filtering"
DEFAULT_LDAP_GROUP_FILTER_OBJECTCLASS=""
KEY_LDAP_GROUP_FILTER_OBJECTCLASS="ldap-group-filter-objectclass"
DESCRIPTION_LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE=""
DEFAULT_LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE=""
KEY_LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE="ldap-group-filter-id-attribute"
DESCRIPTION_LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE=""
DEFAULT_LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE=""
KEY_LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE="ldap-group-filter-member-attribute"
DESCRIPTION_LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT=""
DEFAULT_LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT=""
KEY_LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT="ldap-group-filter-member-format"
DESCRIPTION_LDAP_GROUP_FILTER_GROUP_NAME=""
DEFAULT_LDAP_GROUP_FILTER_GROUP_NAME=""
KEY_LDAP_GROUP_FILTER_GROUP_NAME="ldap-group-filter-member-format"
DESCRIPTION_LDAP_UNIQUE_IDENTIFIER_FIELD="This field is sometimes class GUID (Globally Unique Identifier)"
DEFAULT_LDAP_UNIQUE_IDENTIFIER_FIELD=""
KEY_LDAP_UNIQUE_IDENTIFIER_FIELD="ldap-unique-identifier-field"
DESCRIPTION_LDAP_UTF8_NAMES_SLUGIFY="Convert the username to utf8"
DEFAULT_LDAP_UTF8_NAMES_SLUGIFY="true"
KEY_LDAP_UTF8_NAMES_SLUGIFY="ldap-utf8-names-slugify"
DESCRIPTION_LDAP_USERNAME_FIELD="Which field contains the ldap username"
DEFAULT_LDAP_USERNAME_FIELD=""
KEY_LDAP_USERNAME_FIELD="ldap-username-field"
DESCRIPTION_LDAP_MERGE_EXISTING_USERS=""
DEFAULT_LDAP_MERGE_EXISTING_USERS="false"
KEY_LDAP_MERGE_EXISTING_USERS="ldap-merge-existing-users"
DESCRIPTION_LDAP_SYNC_USER_DATA=""
DEFAULT_LDAP_SYNC_USER_DATA="false"
KEY_LDAP_SYNC_USER_DATA="ldap-sync-user-data"
DESCRIPTION_LDAP_SYNC_USER_DATA_FIELDMAP=""
DEFAULT_LDAP_SYNC_USER_DATA_FIELDMAP=""
KEY_LDAP_SYNC_USER_DATA_FIELDMAP="ldap-sync-user-data-fieldmap"
DESCRIPTION_LDAP_SYNC_GROUP_ROLES=""
DEFAULT_LDAP_SYNC_GROUP_ROLES=""
KEY_LDAP_SYNC_GROUP_ROLES="ldap-sync-group-roles"
DESCRIPTION_LDAP_DEFAULT_DOMAIN="The default domain of the ldap it is used to create email if the field is not map correctly with the LDAP_SYNC_USER_DATA_FIELDMAP"
DEFAULT_LDAP_DEFAULT_DOMAIN=""
KEY_LDAP_DEFAULT_DOMAIN="ldap-default-domain"