Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
32 changes: 32 additions & 0 deletions app/api/server/v1/roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,35 @@ API.v1.addRoute('roles.update', { authRequired: true }, {
});
},
});

API.v1.addRoute('roles.delete', { authRequired: true }, {
post() {
check(this.bodyParams, {
roleId: String,
});

if (!hasPermission(this.userId, 'access-permissions')) {
throw new Meteor.Error('error-action-not-allowed', 'Accessing permissions is not allowed');
}

const role = Roles.findOneByIdOrName(this.bodyParams.roleId);

if (!role) {
throw new Meteor.Error('error-invalid-roleId', 'This role does not exist');
}

if (role.protected) {
throw new Meteor.Error('error-role-protected', 'Cannot delete a protected role');
}

const existingUsers = Roles.findUsersInRole(role._id, role.scope);

if (existingUsers && existingUsers.count() > 0) {
throw new Meteor.Error('error-role-in-use', 'Cannot delete role because it\'s in use');
}

Roles.remove(role._id);

return API.v1.success();
},
});
75 changes: 75 additions & 0 deletions tests/end-to-end/api/13-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ function createRole(name, scope, description) {
});
}

function addUserToRole(roleId, username) {
return new Promise((resolve) => {
request.post(api('roles.addUserToRole'))
.set(credentials)
.send({
roleName: roleId,
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);
});
});
}

describe('[Roles]', function() {
this.retries(0);

Expand Down Expand Up @@ -310,4 +330,59 @@ describe('[Roles]', function() {
.end(done);
});
});

describe('POST [/roles.delete]', () => {
let roleWithUser;
let roleWithoutUser;
before(async () => {
roleWithUser = await createRole(`roleWithUser-${ Date.now() }`, 'Users');
roleWithoutUser = await createRole(`roleWithoutUser-${ Date.now() }`, 'Users');

await addUserToRole(roleWithUser._id, login.user);
});

it('should delete a role that it is not being used', (done) => {
request.post(api('roles.delete'))
.set(credentials)
.send({
roleId: roleWithoutUser._id,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
});

it('should NOT delete a role that it is protected', (done) => {
request.post(api('roles.delete'))
.set(credentials)
.send({
roleId: 'admin',
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.nested.property('error', 'Cannot delete a protected role [error-role-protected]');
})
.end(done);
});

it('should NOT delete a role that it is being used', (done) => {
request.post(api('roles.delete'))
.set(credentials)
.send({
roleId: roleWithUser._id,
})
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.nested.property('error', 'Cannot delete role because it\'s in use [error-role-in-use]');
})
.end(done);
});
});
});