[NEW] REST endpoint to remove User from Role (#20485)

* [WIP] added test

* [WIP] added api endpoint to remove role from user

* [WIP] added test with Subscription Scope

* Update roles.js

* fix endpoint params

* update tests

* remove .only

Co-authored-by: Lucas Sartor Chauvin <lucassartorchauvin@gmail.com>
Co-authored-by: Leonardo Ostjen Couto <leonardoostjen@gmail.com>
pull/22593/head^2
Cosnavel 5 years ago committed by GitHub
parent dc7d633d0e
commit dca177fc03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 63
      app/api/server/v1/roles.js
  2. 56
      tests/end-to-end/api/13-roles.js

@ -1,7 +1,7 @@
import { Meteor } from 'meteor/meteor';
import { Match, check } from 'meteor/check';
import { Roles } from '../../../models';
import { Roles, Users } from '../../../models';
import { API } from '../api';
import { getUsersInRole, hasPermission } from '../../../authorization/server';
import { settings } from '../../../settings/server/index';
@ -156,7 +156,7 @@ API.v1.addRoute('roles.update', { authRequired: true }, {
if (roleData.name) {
const otherRole = Roles.findOneByIdOrName(roleData.name);
if (otherRole && otherRole._id !== role.roleId) {
if (otherRole && otherRole._id !== role._id) {
throw new Meteor.Error('error-duplicate-role-names-not-allowed', 'Role name already exists');
}
}
@ -213,3 +213,62 @@ API.v1.addRoute('roles.delete', { authRequired: true }, {
return API.v1.success();
},
});
API.v1.addRoute('roles.removeUserFromRole', { authRequired: true }, {
post() {
check(this.bodyParams, {
roleName: String,
username: String,
});
const data = {
roleName: this.bodyParams.roleName,
username: this.bodyParams.username,
};
if (!hasPermission(this.userId, 'access-permissions')) {
throw new Meteor.Error('error-not-allowed', 'Accessing permissions is not allowed');
}
const user = Users.findOneByUsername(data.username);
if (!user) {
throw new Meteor.Error('error-invalid-user', 'There is no user with this username');
}
const role = Roles.findOneByIdOrName(data.roleName);
if (!role) {
throw new Meteor.Error('error-invalid-roleId', 'This role does not exist');
}
if (user.roles.indexOf(role.name) === -1) {
throw new Meteor.Error('error-user-not-in-role', 'User is not in this role');
}
if (role._id === 'admin') {
const adminCount = Roles.findUsersInRole('admin', role.scope).count();
if (adminCount === 1) {
throw new Meteor.Error('error-admin-required', 'You need to have at least one admin');
}
}
Roles.removeUserRoles(user._id, role.name, role.scope);
if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'removed',
_id: role._id,
u: {
_id: user._id,
username: user.username,
},
scope: role.scope,
});
}
return API.v1.success({
role,
});
},
});

@ -31,19 +31,18 @@ function createRole(name, scope, description) {
});
}
function addUserToRole(roleId, username) {
function addUserToRole(roleName, username) {
return new Promise((resolve) => {
request.post(api('roles.addUserToRole'))
.set(credentials)
.send({
roleName: roleId,
roleName,
username,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('role._id', roleId);
})
.end((err, req) => {
resolve(req.body.role);
@ -385,4 +384,55 @@ describe('[Roles]', function() {
.end(done);
});
});
describe('POST [/roles.removeUserFromRole]', () => {
let usersScopedRole;
let subscriptionsScopedRole;
before(async () => {
usersScopedRole = await createRole(`usersScopedRole-${ Date.now() }`, 'Users');
subscriptionsScopedRole = await createRole(`subscriptionsScopedRole-${ Date.now() }`, 'Subscriptions');
await addUserToRole(usersScopedRole.name, login.user);
await addUserToRole(subscriptionsScopedRole.name, login.user);
});
it('should unassign a role with User scope from an user', (done) => {
request.post(api('roles.removeUserFromRole'))
.set(credentials)
.send({
roleName: usersScopedRole.name,
username: login.user,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('role._id', usersScopedRole._id);
expect(res.body).to.have.nested.property('role.name', usersScopedRole.name);
expect(res.body).to.have.nested.property('role.scope', usersScopedRole.scope);
expect(res.body).to.have.nested.property('role.description', usersScopedRole.description);
})
.end(done);
});
it('should unassign a role with Subscriptions scope from an user', (done) => {
request.post(api('roles.removeUserFromRole'))
.set(credentials)
.send({
roleName: subscriptionsScopedRole.name,
username: login.user,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.nested.property('role._id', subscriptionsScopedRole._id);
expect(res.body).to.have.nested.property('role.name', subscriptionsScopedRole.name);
expect(res.body).to.have.nested.property('role.scope', subscriptionsScopedRole.scope);
expect(res.body).to.have.nested.property('role.description', subscriptionsScopedRole.description);
})
.end(done);
});
});
});

Loading…
Cancel
Save