Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Add permission to enable personal access token to specific roles #12309

Merged
merged 4 commits into from
Nov 21, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions imports/personal-access-tokens/client/personalAccessTokens.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const PersonalAccessTokens = new Mongo.Collection('personal_access_tokens');

Template.accountTokens.helpers({
isAllowed() {
return RocketChat.settings.get('API_Enable_Personal_Access_Tokens');
return RocketChat.authz.hasAllPermission(['create-personal-access-tokens']);
},
tokens() {
return (PersonalAccessTokens.find({}).fetch()[0] && PersonalAccessTokens.find({}).fetch()[0].tokens) || [];
Expand Down Expand Up @@ -46,7 +46,7 @@ Template.accountTokens.events({
return toastr.error(t(error.error));
}
showSuccessModal(token);
instance.find('#input-token-name').value = '';
instance.find('#tokenName').value = '';
});
},
'click .remove-personal-access-token'() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Meteor.methods({
if (!Meteor.userId()) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:generateToken' });
}
if (!RocketChat.settings.get('API_Enable_Personal_Access_Tokens')) {
throw new Meteor.Error('error-personal-access-tokens-are-current-disabled', 'Personal Access Tokens are currently disabled', { method: 'personalAccessTokens:generateToken' });
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'create-personal-access-tokens')) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:generateToken' });
}

const token = Random.secret();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Meteor.methods({
if (!Meteor.userId()) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:regenerateToken' });
}
if (!RocketChat.settings.get('API_Enable_Personal_Access_Tokens')) {
throw new Meteor.Error('error-personal-access-tokens-are-current-disabled', 'Personal Access Tokens are currently disabled', { method: 'personalAccessTokens:regenerateToken' });
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'create-personal-access-tokens')) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:regenerateToken' });
}

const tokenExist = RocketChat.models.Users.findPersonalAccessTokenByTokenNameAndUserId({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Meteor.methods({
if (!Meteor.userId()) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:removeToken' });
}
if (!RocketChat.settings.get('API_Enable_Personal_Access_Tokens')) {
throw new Meteor.Error('error-personal-access-tokens-are-current-disabled', 'Personal Access Tokens are currently disabled', { method: 'personalAccessTokens:removeToken' });
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'create-personal-access-tokens')) {
throw new Meteor.Error('not-authorized', 'Not Authorized', { method: 'personalAccessTokens:removeToken' });
}
const tokenExist = RocketChat.models.Users.findPersonalAccessTokenByTokenNameAndUserId({
userId: Meteor.userId(),
Expand Down
1 change: 0 additions & 1 deletion imports/personal-access-tokens/server/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import './api/methods';
import './settings';
import './models';
import './publications';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Meteor.publish('personalAccessTokens', function() {
if (!this.userId) {
return this.ready();
}
if (!RocketChat.settings.get('API_Enable_Personal_Access_Tokens')) {
if (!RocketChat.authz.hasPermission(this.userId, 'create-personal-access-tokens')) {
return this.ready();
}
const self = this;
Expand Down
5 changes: 0 additions & 5 deletions imports/personal-access-tokens/server/settings.js

This file was deleted.

4 changes: 2 additions & 2 deletions packages/rocketchat-api/server/v1/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@ RocketChat.API.v1.addRoute('users.regeneratePersonalAccessToken', { authRequired

RocketChat.API.v1.addRoute('users.getPersonalAccessTokens', { authRequired: true }, {
get() {
if (!RocketChat.settings.get('API_Enable_Personal_Access_Tokens')) {
throw new Meteor.Error('error-personal-access-tokens-are-current-disabled', 'Personal Access Tokens are currently disabled');
if (!RocketChat.authz.hasPermission(this.userId, 'create-personal-access-tokens')) {
throw new Meteor.Error('not-authorized', 'Not Authorized');
}
const loginTokens = RocketChat.models.Users.getLoginTokensByUserId(this.userId).fetch()[0];
const getPersonalAccessTokens = () => loginTokens.services.resume.loginTokens
Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-authorization/server/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Meteor.startup(function() {
{ _id: 'create-c', roles : ['admin', 'user', 'bot'] },
{ _id: 'create-d', roles : ['admin', 'user', 'bot'] },
{ _id: 'create-p', roles : ['admin', 'user', 'bot'] },
{ _id: 'create-personal-access-tokens', roles : ['admin', 'user'] },
{ _id: 'create-user', roles : ['admin'] },
{ _id: 'clean-channel-history', roles : ['admin'] },
{ _id: 'delete-c', roles : ['admin', 'owner'] },
Expand Down
2 changes: 0 additions & 2 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@
"API_Enable_CORS": "Enable CORS",
"API_Enable_Direct_Message_History_EndPoint": "Enable Direct Message History Endpoint",
"API_Enable_Direct_Message_History_EndPoint_Description": "This enables the `/api/v1/im.history.others` which allows the viewing of direct messages sent by other users that the caller is not part of.",
"API_Enable_Personal_Access_Tokens": "Enable Personal Access Tokens to REST API",
"API_Enable_Personal_Access_Tokens_Description": "Enable personal access tokens for use with the REST API",
"API_Enable_Shields": "Enable Shields",
"API_Enable_Shields_Description": "Enable shields available at `/api/v1/shield.svg`",
"API_GitHub_Enterprise_URL": "Server URL",
Expand Down
2 changes: 1 addition & 1 deletion packages/rocketchat-ui-account/client/accountFlex.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Template.accountFlex.helpers({
return RocketChat.settings.get('Accounts_AllowUserProfileChange');
},
accessTokensEnabled() {
return RocketChat.settings.get('API_Enable_Personal_Access_Tokens');
return RocketChat.authz.hasAllPermission(['create-personal-access-tokens']);
},
encryptionEnabled() {
return RocketChat.settings.get('E2E_Enable');
Expand Down
15 changes: 15 additions & 0 deletions server/startup/migrations/v136.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RocketChat.Migrations.add({
version: 136,
up() {
const personalTokensEnabled = RocketChat.settings.get('API_Enable_Personal_Access_Tokens');
const roles = RocketChat.models.Roles.find({ scope: 'Users' }).fetch().map((role) => role._id);

if (personalTokensEnabled) {
RocketChat.models.Permissions.upsert({ _id: 'create-personal-access-tokens' }, { $set: { roles } });
}

RocketChat.models.Settings.remove({
_id: 'API_Enable_Personal_Access_Tokens',
});
},
});
36 changes: 8 additions & 28 deletions tests/end-to-end/api/01-users.js
Original file line number Diff line number Diff line change
Expand Up @@ -1247,17 +1247,7 @@ describe('[Users]', function() {
describe('Personal Access Tokens', () => {
const tokenName = `${ Date.now() }token`;
describe('successful cases', () => {
it('Enable "API_Enable_Personal_Access_Tokens" setting...', (done) => {
request.post('/api/v1/settings/API_Enable_Personal_Access_Tokens')
.set(credentials)
.send({ value: true })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
});
it('Grant necessary permission "create-personal-accss-tokens" to user', (done) => updatePermission('create-personal-access-tokens', ['admin']).then(done));
describe('[/users.generatePersonalAccessToken]', () => {
it('should return a personal access token to user', (done) => {
request.post(api('users.generatePersonalAccessToken'))
Expand Down Expand Up @@ -1359,18 +1349,8 @@ describe('[Users]', function() {
});
});
describe('unsuccessful cases', () => {
it('disable "API_Enable_Personal_Access_Tokens" setting...', (done) => {
request.post('/api/v1/settings/API_Enable_Personal_Access_Tokens')
.set(credentials)
.send({ value: false })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
});
describe('should return an error when setting "API_Enable_Personal_Access_Tokens" is disabled for the following routes', () => {
it('Remove necessary permission "create-personal-accss-tokens" to user', (done) => updatePermission('create-personal-access-tokens', []).then(done));
describe('should return an error when the user dont have the necessary permission "create-personal-access-tokens"', () => {
it('/users.generatePersonalAccessToken', (done) => {
request.post(api('users.generatePersonalAccessToken'))
.set(credentials)
Expand All @@ -1381,7 +1361,7 @@ describe('[Users]', function() {
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.errorType).to.be.equal('error-personal-access-tokens-are-current-disabled');
expect(res.body.errorType).to.be.equal('not-authorized');
})
.end(done);
});
Expand All @@ -1395,7 +1375,7 @@ describe('[Users]', function() {
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.errorType).to.be.equal('error-personal-access-tokens-are-current-disabled');
expect(res.body.errorType).to.be.equal('not-authorized');
})
.end(done);
});
Expand All @@ -1406,7 +1386,7 @@ describe('[Users]', function() {
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.errorType).to.be.equal('error-personal-access-tokens-are-current-disabled');
expect(res.body.errorType).to.be.equal('not-authorized');
})
.end(done);
});
Expand All @@ -1420,7 +1400,7 @@ describe('[Users]', function() {
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.errorType).to.be.equal('error-personal-access-tokens-are-current-disabled');
expect(res.body.errorType).to.be.equal('not-authorized');
})
.end(done);
});
Expand All @@ -1434,7 +1414,7 @@ describe('[Users]', function() {
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body.errorType).to.be.equal('error-personal-access-tokens-are-current-disabled');
expect(res.body.errorType).to.be.equal('not-authorized');
})
.end(done);
});
Expand Down