Skip to content

Commit

Permalink
[NEW] Mandatory 2fa for role (#9748)
Browse files Browse the repository at this point in the history
* Added setting to force user roles to use 2fa

* Added conditional check to force user to configure 2fa when needed

* Added Missing String; Improved Code Quality

* Update permissionsRole.js
  • Loading branch information
Hudell authored and rodrigok committed Dec 21, 2018
1 parent 25c3a62 commit 1eee223
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
<option value="Users" selected="{{$eq scope 'Users'}}">{{_ "Global"}}</option>
<option value="Subscriptions" selected="{{$eq scope 'Subscriptions'}}">{{_ "Rooms"}}</option>
</select>

<br/>
<label for="mandatory2fa">{{_ "Users must use Two Factor Authentication"}} :</label>
<input type="checkbox" name="mandatory2fa" checked="{{mandatory2fa}}">

<div class="form-buttons">
{{#if editable}}
<button name="delete" class="button danger delete-role">{{_ "Delete"}}</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ Template.permissionsRole.events({
const roleData = {
description: e.currentTarget.elements.description.value,
scope: e.currentTarget.elements.scope.value,
mandatory2fa: e.currentTarget.elements.mandatory2fa.checked,
};

if (this._id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Meteor.methods({
roleData.scope = 'Users';
}

const update = RocketChat.models.Roles.createOrUpdate(roleData.name, roleData.scope, roleData.description);
const update = RocketChat.models.Roles.createOrUpdate(roleData.name, roleData.scope, roleData.description, false, roleData.mandatory2fa);
if (RocketChat.settings.get('UI_DisplayRoles')) {
RocketChat.Notifications.notifyLogged('roles-change', {
type: 'changed',
Expand Down
6 changes: 5 additions & 1 deletion packages/rocketchat-authorization/server/models/Roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ModelRoles extends RocketChat.models._Base {
});
}

createOrUpdate(name, scope = 'Users', description, protectedRole) {
createOrUpdate(name, scope = 'Users', description, protectedRole, mandatory2fa) {
const updateData = {};
updateData.name = name;
updateData.scope = scope;
Expand All @@ -39,6 +39,10 @@ class ModelRoles extends RocketChat.models._Base {
updateData.protected = protectedRole;
}

if (mandatory2fa != null) {
updateData.mandatory2fa = mandatory2fa;
}

this.upsert({ _id: name }, { $set: updateData });
}

Expand Down
2 changes: 1 addition & 1 deletion packages/rocketchat-authorization/server/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,6 @@ Meteor.startup(function() {
];

for (const role of defaultRoles) {
RocketChat.models.Roles.upsert({ _id: role.name }, { $setOnInsert: { scope: role.scope, description: role.description || '', protected: true } });
RocketChat.models.Roles.upsert({ _id: role.name }, { $setOnInsert: { scope: role.scope, description: role.description || '', protected: true, mandatory2fa: false } });
}
});
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 @@ -2871,6 +2871,7 @@
"Users": "Users",
"Users_added": "The users have been added",
"Users_in_role": "Users in role",
"Users must use Two Factor Authentication": "Users must use Two Factor Authentication",
"UTF8_Names_Slugify": "UTF8 Names Slugify",
"UTF8_Names_Validation": "UTF8 Names Validation",
"UTF8_Names_Validation_Description": "RegExp that will be used to validate usernames and channel names",
Expand Down
33 changes: 20 additions & 13 deletions packages/rocketchat-ui-master/client/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,27 @@
{{#if requirePasswordChange}}
{{> loginLayout center="resetPassword"}}
{{else}}
{{> videoCall overlay=true}}
<div id="user-card-popover"></div>
<div id="rocket-chat" class="{{embeddedVersion}} menu-nav">
{{#unless removeSidenav}}
{{> sideNav }}
{{/unless}}
<div class="{{#unless $eq old false}} rc-old {{/unless}} main-content content-background-color {{readReceiptsEnabled}} {{#if modal}}main-modal{{/if}}">
{{> Template.dynamic template=center}}
{{#if require2faSetup}}
<div class="rc-old">
{{> Template.dynamic template="accountSecurity"}}
</div>
</div>
<div class="rc-old connection-status">
{{> status}}
</div>
{{> audioNotification }}
{{else}}
{{> videoCall overlay=true}}
<div id="user-card-popover"></div>
<div id="rocket-chat" class="{{embeddedVersion}} menu-nav">
{{#unless removeSidenav}}
{{> sideNav }}
{{/unless}}
<div class="{{#unless $eq old false}} rc-old {{/unless}} main-content content-background-color {{readReceiptsEnabled}} {{#if modal}}main-modal{{/if}}">
{{> Template.dynamic template=center}}
</div>
</div>

<div class="rc-old connection-status">
{{> status}}
</div>
{{> audioNotification }}
{{/if}}
{{/if}}
{{/unless}}
{{ CustomScriptLoggedIn }}
Expand Down
11 changes: 11 additions & 0 deletions packages/rocketchat-ui-master/client/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ Template.main.helpers({
const user = Meteor.user();
return user && user.requirePasswordChange === true;
},
require2faSetup() {
const user = Meteor.user();

// User is already using 2fa
if (user.services.totp !== undefined && user.services.totp.enabled) {
return false;
}

const mandatoryRole = RocketChat.models.Roles.findOne({ _id: { $in: user.roles }, mandatory2fa: true });
return mandatoryRole !== undefined;
},
CustomScriptLoggedOut() {
const script = RocketChat.settings.get('Custom_Script_Logged_Out') || '';
if (script.trim()) {
Expand Down

0 comments on commit 1eee223

Please sign in to comment.