mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 07:20:12 +01:00
252 lines
6.9 KiB
JavaScript
252 lines
6.9 KiB
JavaScript
import {slug, getLdapUsername, getLdapEmail, getLdapUserUniqueID, syncUserData, addLdapUser} from './sync';
|
|
import LDAP from './ldap';
|
|
import { log_debug, log_info, log_warn, log_error } from './logger';
|
|
|
|
function fallbackDefaultAccountSystem(bind, username, password) {
|
|
if (typeof username === 'string') {
|
|
if (username.indexOf('@') === -1) {
|
|
username = {username};
|
|
} else {
|
|
username = {email: username};
|
|
}
|
|
}
|
|
|
|
log_info('Fallback to default account system: ', username );
|
|
|
|
const loginRequest = {
|
|
user: username,
|
|
password: {
|
|
digest: SHA256(password),
|
|
algorithm: 'sha-256',
|
|
},
|
|
};
|
|
log_debug('Fallback options: ', loginRequest);
|
|
|
|
return Accounts._runLoginHandlers(bind, loginRequest);
|
|
}
|
|
|
|
Accounts.registerLoginHandler('ldap', function(loginRequest) {
|
|
if (!loginRequest.ldap || !loginRequest.ldapOptions) {
|
|
return undefined;
|
|
}
|
|
|
|
log_info('Init LDAP login', loginRequest.username);
|
|
|
|
if (LDAP.settings_get('LDAP_ENABLE') !== true) {
|
|
return fallbackDefaultAccountSystem(this, loginRequest.username, loginRequest.ldapPass);
|
|
}
|
|
|
|
const self = this;
|
|
const ldap = new LDAP();
|
|
let ldapUser;
|
|
|
|
try {
|
|
|
|
ldap.connectSync();
|
|
|
|
if (!!LDAP.settings_get('LDAP_USER_AUTHENTICATION')) {
|
|
ldap.bindUserIfNecessary(loginRequest.username, loginRequest.ldapPass);
|
|
ldapUser = ldap.searchUsersSync(loginRequest.username)[0];
|
|
} else {
|
|
|
|
const users = ldap.searchUsersSync(loginRequest.username);
|
|
|
|
if (users.length !== 1) {
|
|
log_info('Search returned', users.length, 'record(s) for', loginRequest.username);
|
|
throw new Error('User not Found');
|
|
}
|
|
|
|
if (ldap.authSync(users[0].dn, loginRequest.ldapPass) === true) {
|
|
if (ldap.isUserInGroup(loginRequest.username, users[0])) {
|
|
ldapUser = users[0];
|
|
} else {
|
|
throw new Error('User not in a valid group');
|
|
}
|
|
} else {
|
|
log_info('Wrong password for', loginRequest.username);
|
|
}
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
log_error(error);
|
|
}
|
|
|
|
if (!ldapUser) {
|
|
if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') === true) {
|
|
return fallbackDefaultAccountSystem(self, loginRequest.username, loginRequest.ldapPass);
|
|
}
|
|
|
|
throw new Meteor.Error('LDAP-login-error', `LDAP Authentication failed with provided username [${ loginRequest.username }]`);
|
|
}
|
|
|
|
// Look to see if user already exists
|
|
|
|
let userQuery;
|
|
|
|
const Unique_Identifier_Field = getLdapUserUniqueID(ldapUser);
|
|
let user;
|
|
// Attempt to find user by unique identifier
|
|
|
|
if (Unique_Identifier_Field) {
|
|
userQuery = {
|
|
'services.ldap.id': Unique_Identifier_Field.value,
|
|
};
|
|
|
|
log_info('Querying user');
|
|
log_debug('userQuery', userQuery);
|
|
|
|
user = Meteor.users.findOne(userQuery);
|
|
}
|
|
|
|
// Attempt to find user by username
|
|
|
|
let username;
|
|
let email;
|
|
|
|
if (LDAP.settings_get('LDAP_USERNAME_FIELD') !== '') {
|
|
username = slug(getLdapUsername(ldapUser));
|
|
} else {
|
|
username = slug(loginRequest.username);
|
|
}
|
|
|
|
if(LDAP.settings_get('LDAP_EMAIL_FIELD') !== '') {
|
|
email = getLdapEmail(ldapUser);
|
|
}
|
|
|
|
|
|
if (!user) {
|
|
if(email && LDAP.settings_get('LDAP_EMAIL_MATCH_REQUIRE') === true) {
|
|
if(LDAP.settings_get('LDAP_EMAIL_MATCH_VERIFIED') === true) {
|
|
userQuery = {
|
|
'_id' : username,
|
|
'emails.0.address' : email,
|
|
'emails.0.verified' : true
|
|
};
|
|
} else {
|
|
userQuery = {
|
|
'_id' : username,
|
|
'emails.0.address' : email
|
|
};
|
|
}
|
|
} else {
|
|
userQuery = {
|
|
username
|
|
};
|
|
}
|
|
|
|
log_debug('userQuery', userQuery);
|
|
|
|
user = Meteor.users.findOne(userQuery);
|
|
}
|
|
|
|
// Attempt to find user by e-mail address only
|
|
|
|
if (!user && email && LDAP.settings_get('LDAP_EMAIL_MATCH_ENABLE') === true) {
|
|
|
|
log_info('No user exists with username', username, '- attempting to find by e-mail address instead');
|
|
|
|
if(LDAP.settings_get('LDAP_EMAIL_MATCH_VERIFIED') === true) {
|
|
userQuery = {
|
|
'emails.0.address': email,
|
|
'emails.0.verified' : true
|
|
};
|
|
} else {
|
|
userQuery = {
|
|
'emails.0.address' : email
|
|
};
|
|
}
|
|
|
|
log_debug('userQuery', userQuery);
|
|
|
|
user = Meteor.users.findOne(userQuery);
|
|
|
|
}
|
|
|
|
// Login user if they exist
|
|
if (user) {
|
|
if (user.authenticationMethod !== 'ldap' && LDAP.settings_get('LDAP_MERGE_EXISTING_USERS') !== true) {
|
|
log_info('User exists without "authenticationMethod : ldap"');
|
|
throw new Meteor.Error('LDAP-login-error', `LDAP Authentication succeded, but there's already a matching Wekan account in MongoDB`);
|
|
}
|
|
|
|
log_info('Logging user');
|
|
|
|
const stampedToken = Accounts._generateStampedLoginToken();
|
|
const update_data = {
|
|
$push: {
|
|
'services.resume.loginTokens': Accounts._hashStampedToken(stampedToken),
|
|
},
|
|
};
|
|
|
|
if (LDAP.settings_get('LDAP_SYNC_ADMIN_STATUS') === true) {
|
|
log_debug('Updating admin status');
|
|
const targetGroups = LDAP.settings_get('LDAP_SYNC_ADMIN_GROUPS').split(',');
|
|
const groups = ldap.getUserGroups(username, ldapUser).filter((value) => targetGroups.includes(value));
|
|
|
|
user.isAdmin = groups.length > 0;
|
|
Meteor.users.update({_id: user._id}, {$set: {isAdmin: user.isAdmin}});
|
|
}
|
|
|
|
if( LDAP.settings_get('LDAP_SYNC_GROUP_ROLES') === true ) {
|
|
log_debug('Updating Groups/Roles');
|
|
const groups = ldap.getUserGroups(username, ldapUser);
|
|
|
|
if( groups.length > 0 ) {
|
|
Roles.setUserRoles(user._id, groups );
|
|
log_info(`Updated roles to:${ groups.join(',')}`);
|
|
}
|
|
}
|
|
|
|
Meteor.users.update(user._id, update_data );
|
|
|
|
syncUserData(user, ldapUser);
|
|
|
|
if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') === true) {
|
|
Accounts.setPassword(user._id, loginRequest.ldapPass, {logout: false});
|
|
}
|
|
|
|
return {
|
|
userId: user._id,
|
|
token: stampedToken.token,
|
|
};
|
|
}
|
|
|
|
// Create new user
|
|
|
|
log_info('User does not exist, creating', username);
|
|
|
|
if (LDAP.settings_get('LDAP_USERNAME_FIELD') === '') {
|
|
username = undefined;
|
|
}
|
|
|
|
if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') !== true) {
|
|
loginRequest.ldapPass = undefined;
|
|
}
|
|
|
|
const result = addLdapUser(ldapUser, username, loginRequest.ldapPass);
|
|
|
|
if (LDAP.settings_get('LDAP_SYNC_ADMIN_STATUS') === true) {
|
|
log_debug('Updating admin status');
|
|
const targetGroups = LDAP.settings_get('LDAP_SYNC_ADMIN_GROUPS').split(',');
|
|
const groups = ldap.getUserGroups(username, ldapUser).filter((value) => targetGroups.includes(value));
|
|
|
|
result.isAdmin = groups.length > 0;
|
|
Meteor.users.update({_id: result.userId}, {$set: {isAdmin: result.isAdmin}});
|
|
}
|
|
|
|
if( LDAP.settings_get('LDAP_SYNC_GROUP_ROLES') === true ) {
|
|
const groups = ldap.getUserGroups(username, ldapUser);
|
|
if( groups.length > 0 ) {
|
|
Roles.setUserRoles(result.userId, groups );
|
|
log_info(`Set roles to:${ groups.join(',')}`);
|
|
}
|
|
}
|
|
|
|
|
|
if (result instanceof Error) {
|
|
throw result;
|
|
}
|
|
|
|
return result;
|
|
});
|