Skip to content

Commit

Permalink
[IMPROVE] Allow custom rocketchat username for crowd users and enable…
Browse files Browse the repository at this point in the history
… login via email/crowd_username (#12981)

* Fix to close issue #12979

- Enable custom rocketchat usernames for crowd users
- Enable login via rocketchat username, crowd_username and email address
- Don't authenticate local users against crowd
- Allow/Disallow resyncing/overwride of local usernames with crowd usernames in crowd options
- Consistent user sync on login and on cron sync

* Fix to close issue #12979

Integrate PR suggestions/improvements

* Change mongodb queries

* Access settings directly via imported settings object
  • Loading branch information
steerben authored and rodrigok committed Feb 22, 2019
1 parent cdfc3c0 commit 5f0180d
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 18 deletions.
99 changes: 81 additions & 18 deletions packages/rocketchat-crowd/server/crowd.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ export class CROWD {
this.crowdClient.pingSync();
}

fetchCrowdUser(username) {
const userResponse = this.crowdClient.user.findSync(username);
fetchCrowdUser(crowd_username) {
const userResponse = this.crowdClient.user.findSync(crowd_username);

return {
displayname: userResponse['display-name'],
username: userResponse.name,
email: userResponse.email,
active: userResponse.active,
crowd_username,
};
}

Expand All @@ -78,15 +79,65 @@ export class CROWD {
return;
}

logger.info('Going to crowd:', username);
const auth = this.crowdClient.user.authenticateSync(username, password);
logger.info('Extracting crowd_username');
let user = null;
let crowd_username = username;

if (username.indexOf('@') !== -1) {
const email = username;

user = Meteor.users.findOne({ 'emails.address': email }, { fields: { username: 1, crowd_username: 1, crowd: 1 } });
if (user) {
crowd_username = user.crowd_username;
} else {
logger.debug('Could not find a user by email', username);
}
}

if (user == null) {
user = Meteor.users.findOne({ username }, { fields: { username: 1, crowd_username: 1, crowd: 1 } });
if (user) {
crowd_username = user.crowd_username;
} else {
logger.debug('Could not find a user by username');
}
}

if (user == null) {
user = Meteor.users.findOne({ crowd_username: username }, { fields: { username: 1, crowd_username: 1, crowd: 1 } });
if (user) {
crowd_username = user.crowd_username;
} else {
logger.debug('Could not find a user with by crowd_username', username);
}
}

if (user && !crowd_username) {
logger.debug('Local user found, redirecting to fallback login');
return {
crowd: false,
};
}

if (!user && crowd_username) {
logger.debug('New user. User is not synced yet.');
}
logger.debug('Going to crowd:', crowd_username);
const auth = this.crowdClient.user.authenticateSync(crowd_username, password);

if (!auth) {
return;
}

const crowdUser = this.fetchCrowdUser(username);
const crowdUser = this.fetchCrowdUser(crowd_username);

if (user && settings.get('CROWD_Allow_Custom_Username') === true) {
crowdUser.username = user.username;
}

if (user) {
crowdUser._id = user._id;
}
crowdUser.password = password;

return crowdUser;
Expand All @@ -96,7 +147,7 @@ export class CROWD {
const self = this;
const user = {
username: self.cleanUsername(crowdUser.username),
crowd_username: crowdUser.username,
crowd_username: crowdUser.crowd_username,
emails: [{
address : crowdUser.email,
verified: true,
Expand Down Expand Up @@ -134,29 +185,33 @@ export class CROWD {
logger.info('Sync started...');

users.forEach(function(user) {
let username = user.hasOwnProperty('crowd_username') ? user.crowd_username : user.username;
logger.info('Syncing user', username);
let crowd_username = user.hasOwnProperty('crowd_username') ? user.crowd_username : user.username;
logger.info('Syncing user', crowd_username);

let crowdUser = null;

try {
crowdUser = self.fetchCrowdUser(username);
crowdUser = self.fetchCrowdUser(crowd_username);
} catch (error) {
logger.debug(error);
logger.error('Could not sync user with username', username);
logger.error('Could not sync user with username', crowd_username);

const email = user.emails[0].address;
logger.info('Attempting to find for user by email', email);

const response = self.crowdClient.searchSync('user', `email=" ${ email } "`);
if (!response || response.users.length === 0) {
logger.warning('Could not find user in CROWD with username or email:', username, email);
logger.warning('Could not find user in CROWD with username or email:', crowd_username, email);
return;
}
username = response.users[0].name;
logger.info('User found. Syncing user', username);
crowd_username = response.users[0].name;
logger.info('User found by email. Syncing user', crowd_username);

crowdUser = self.fetchCrowdUser(crowd_username);
}

crowdUser = self.fetchCrowdUser(response.users[0].name);
if (settings.get('CROWD_Allow_Custom_Username') === true) {
crowdUser.username = user.username;
}

self.syncDataToUser(crowdUser, user._id);
Expand All @@ -172,8 +227,7 @@ export class CROWD {

updateUserCollection(crowdUser) {
const userQuery = {
crowd: true,
username: crowdUser.username,
_id: crowdUser._id,
};

// find our existing user if they exist
Expand Down Expand Up @@ -227,11 +281,20 @@ Accounts.registerLoginHandler('crowd', function(loginRequest) {
const crowd = new CROWD();
const user = crowd.authenticate(loginRequest.username, loginRequest.crowdPassword);

if (user && (user.crowd === false)) {
logger.debug(`User ${ loginRequest.username } is not a valid crowd user, falling back`);
return fallbackDefaultAccountSystem(this, loginRequest.username, loginRequest.crowdPassword);
}

if (!user) {
logger.debug(`User ${ loginRequest.username } is not allowd to access Rocket.Chat`);
return new Meteor.Error('not-authorized', 'User is not authorized by crowd');
}

return crowd.updateUserCollection(user);
} catch (error) {
logger.debug(error);
logger.error('Crowd user not authenticated due to an error, falling back');
return fallbackDefaultAccountSystem(this, loginRequest.username, loginRequest.crowdPassword);
logger.error('Crowd user not authenticated due to an error');
}
});

Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-crowd/server/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Meteor.startup(function() {
this.add('CROWD_Sync_User_Data', false, { type: 'boolean', enableQuery, i18nLabel: 'Sync_Users' });
this.add('CROWD_Sync_Interval', 'Every 60 mins', { type: 'string', enableQuery: enableSyncQuery, i18nLabel: 'Sync_Interval', i18nDescription: 'Crowd_sync_interval_Description' });
this.add('CROWD_Clean_Usernames', true, { type: 'boolean', enableQuery, i18nLabel: 'Clean_Usernames', i18nDescription: 'Crowd_clean_usernames_Description' });
this.add('CROWD_Allow_Custom_Username', true, { type: 'boolean', i18nLabel: 'CROWD_Allow_Custom_Username' });
this.add('CROWD_Test_Connection', 'crowd_test_connection', { type: 'action', actionText: 'Test_Connection', i18nLabel: 'Test_Connection' });
this.add('CROWD_Sync_Users', 'crowd_sync_users', { type: 'action', actionText: 'Sync_Users', i18nLabel: 'Sync_Users' });
});
Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,7 @@
"Created_at_s_by_s": "Created at <strong>%s</strong> by <strong>%s</strong>",
"Created_at_s_by_s_triggered_by_s": "Created at <strong>%s</strong> by <strong>%s</strong> triggered by <strong>%s</strong>",
"CRM_Integration": "CRM Integration",
"CROWD_Allow_Custom_Username": "Allow custom username in Rocket.Chat",
"CROWD_Reject_Unauthorized": "Reject Unauthorized",
"Crowd_sync_interval_Description": "The interval between synchronizations. Example `every 24 hours` or `on the first day of the week`, more examples at [Cron Text Parser](http://bunkat.github.io/later/parsers.html#text)",
"Current_Chats": "Current Chats",
Expand Down

0 comments on commit 5f0180d

Please sign in to comment.