summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguillaume <guillaume.cassou@supinfo.com>2018-10-09 14:14:39 +0200
committerguillaume <guillaume.cassou@supinfo.com>2018-10-09 14:14:39 +0200
commit3b4f285fea4a90ee96bfce855e1539adcec9b7aa (patch)
tree61cbf1212c8d4052cf2bd3c37a497f1d8b204140
parent5b8c642d8fb16e00000a1d92bcd3a5c6bbd07bce (diff)
downloadwekan-3b4f285fea4a90ee96bfce855e1539adcec9b7aa.tar.gz
wekan-3b4f285fea4a90ee96bfce855e1539adcec9b7aa.tar.bz2
wekan-3b4f285fea4a90ee96bfce855e1539adcec9b7aa.zip
add ldap support | simplify authentications
-rw-r--r--Dockerfile82
-rw-r--r--client/components/main/layouts.js48
-rw-r--r--client/components/settings/connectionMethod.jade8
-rw-r--r--client/components/settings/connectionMethod.js22
-rw-r--r--client/components/settings/peopleBody.jade22
-rw-r--r--client/components/settings/peopleBody.js31
-rw-r--r--docker-compose.yml121
-rw-r--r--i18n/en.i18n.json7
-rw-r--r--models/settings.js2
-rw-r--r--models/users.js14
-rw-r--r--sandstorm-pkgdef.capnp4
-rw-r--r--server/migrations.js12
-rw-r--r--server/publications/people.js1
-rw-r--r--server/publications/users.js7
-rwxr-xr-xsnap-src/bin/config161
15 files changed, 493 insertions, 49 deletions
diff --git a/Dockerfile b/Dockerfile
index 376389a2..363748a0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -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
diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js
index 1d3c3690..6d1f95d4 100644
--- a/client/components/main/layouts.js
+++ b/client/components/main/layouts.js
@@ -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();
diff --git a/client/components/settings/connectionMethod.jade b/client/components/settings/connectionMethod.jade
index 598dd9dd..ac4c8c64 100644
--- a/client/components/settings/connectionMethod.jade
+++ b/client/components/settings/connectionMethod.jade
@@ -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}}
diff --git a/client/components/settings/connectionMethod.js b/client/components/settings/connectionMethod.js
index 4983a3ef..3d5cfd76 100644
--- a/client/components/settings/connectionMethod.js
+++ b/client/components/settings/connectionMethod.js
@@ -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();
},
-});
+}); \ No newline at end of file
diff --git a/client/components/settings/peopleBody.jade b/client/components/settings/peopleBody.jade
index a3506a24..4d06637e 100644
--- a/client/components/settings/peopleBody.jade
+++ b/client/components/settings/peopleBody.jade
@@ -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'}}") \ No newline at end of file
diff --git a/client/components/settings/peopleBody.js b/client/components/settings/peopleBody.js
index 7cc992f2..acc94081 100644
--- a/client/components/settings/peopleBody.js
+++ b/client/components/settings/peopleBody.js
@@ -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
},
});
diff --git a/docker-compose.yml b/docker-compose.yml
index 7509bbc9..4b4cd02d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -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
diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json
index 896c10a3..152f1d7c 100644
--- a/i18n/en.i18n.json
+++ b/i18n/en.i18n.json
@@ -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"
}
diff --git a/models/settings.js b/models/settings.js
index f7c4c85d..bb555cf9 100644
--- a/models/settings.js
+++ b/models/settings.js
@@ -223,7 +223,7 @@ if (Meteor.isServer) {
},
// Gets all connection methods to use it in the Template
- getConnectionsEnabled() {
+ getAuthenticationsEnabled() {
return {
ldap: isLdapEnabled(),
oauth2: isOauth2Enabled(),
diff --git a/models/users.js b/models/users.js
index 27d3e9fa..9a195850 100644
--- a/models/users.js
+++ b/models/users.js
@@ -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');
diff --git a/sandstorm-pkgdef.capnp b/sandstorm-pkgdef.capnp
index 7760ed88..206a8a35 100644
--- a/sandstorm-pkgdef.capnp
+++ b/sandstorm-pkgdef.capnp
@@ -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}}")
]
diff --git a/server/migrations.js b/server/migrations.js
index 91c34be2..1d62d796 100644
--- a/server/migrations.js
+++ b/server/migrations.js
@@ -321,3 +321,15 @@ Migrations.add('add-subtasks-allowed', () => {
},
}, noValidateMulti);
});
+
+Migrations.add('add-authenticationMethod', () => {
+ Users.update({
+ 'authenticationMethod': {
+ $exists: false,
+ },
+ }, {
+ $set: {
+ 'authenticationMethod': 'password',
+ },
+ }, noValidateMulti);
+});
diff --git a/server/publications/people.js b/server/publications/people.js
index 7c13bdcc..022a71b5 100644
--- a/server/publications/people.js
+++ b/server/publications/people.js
@@ -17,6 +17,7 @@ Meteor.publish('people', function(limit) {
'emails': 1,
'createdAt': 1,
'loginDisabled': 1,
+ 'authenticationMethod': 1
},
});
} else {
diff --git a/server/publications/users.js b/server/publications/users.js
index 31c07d26..f0c94153 100644
--- a/server/publications/users.js
+++ b/server/publications/users.js
@@ -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,
},
});
});
diff --git a/snap-src/bin/config b/snap-src/bin/config
index a54b13c2..076a2a57 100755
--- a/snap-src/bin/config
+++ b/snap-src/bin/config
@@ -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"