roles -> role, null -> COMMENTER for user roles

This commit is contained in:
Wyatt Johnson
2017-11-27 11:53:40 -07:00
parent 9386912b9b
commit 13865ff29e
38 changed files with 206 additions and 199 deletions
+6 -12
View File
@@ -34,11 +34,11 @@ function getUserCreateAnswers(options) {
password: options.password,
confirmPassword: options.password,
username: options.name,
roles: []
role: 'COMMENTER'
};
if (options.role && USER_ROLES.indexOf(options.role) > -1) {
user.roles = [options.role];
user.roles = options.role;
}
return Promise.resolve(user);
@@ -87,9 +87,9 @@ function getUserCreateAnswers(options) {
}
},
{
name: 'roles',
name: 'role',
message: 'User Role',
type: 'checkbox',
type: 'list',
choices: USER_ROLES
}
]);
@@ -106,13 +106,7 @@ async function createUser(options) {
}
const user = await UsersService.createLocalUser(answers.email.trim(), answers.password.trim(), answers.username.trim());
if (answers.roles.length > 0) {
for (const role of answers.roles) {
await UsersService.addRoleToUser(user.id, role);
}
}
await UsersService.setRole(user.id, answers.role);
await UsersService.sendEmailConfirmation(user, answers.email.trim());
console.log(`Created User ${user.id}.`);
@@ -250,7 +244,7 @@ function listUsers() {
user.id,
user.username,
user.profiles.map((p) => p.provider).join(', '),
user.roles.join(', '),
user.role,
user.status,
state
]);
@@ -17,7 +17,7 @@ function getUserFlaggedType(actions) {
.some((action) =>
action.__typename === 'FlagAction' &&
action.user &&
action.user.roles.some((role) => staffRoles.includes(role))
staffRoles.includes(action.user.role)
) ? 'Staff' : 'User';
}
@@ -25,7 +25,7 @@ export default withFragments({
}
user {
id
roles
role
}
}
${getSlotFragmentSpreads(slots, 'comment')}
@@ -66,7 +66,7 @@ const Table = ({users, setRole, onHeaderClickHandler, setUserBanStatus, viewUser
<td className="mdl-data-table__cell--non-numeric">
<Dropdown
containerClassName="talk-admin-community-people-dd-role"
value={row.roles[0] || ''}
value={row.role || ''}
placeholder={t('community.role')}
onChange={(role) => setRole(row.id, role)}>
<Option value={''} label={t('community.none')} />
@@ -30,7 +30,7 @@ export default withFragments({
}
}
}
roles
role
actions{
id
created_at
+1 -2
View File
@@ -1,4 +1,3 @@
import intersection from 'lodash/intersection';
import get from 'lodash/get';
// =========================================================================
@@ -60,6 +59,6 @@ export const can = (user, ...perms) => {
throw new Error(`${perm} is not a valid role or permission`);
}
return intersection(role, user.roles).length > 0;
return role.includes(user.role);
});
};
+4 -10
View File
@@ -48,21 +48,16 @@ const setUsername = async (ctx, id, username) => {
return UsersService.setUsername(id, username, ctx.user.id);
};
const addRole = (ctx, id, role) => {
return UsersService.addRoleToUser(id, role);
};
const removeRole = (ctx, id, role) => {
return UsersService.removeRoleFromUser(id, role);
const setRole = (ctx, id, role) => {
return UsersService.setRole(id, role);
};
module.exports = (ctx) => {
let mutators = {
User: {
addRole: () => Promise.reject(errors.ErrNotAuthorized),
changeUsername: () => Promise.reject(errors.ErrNotAuthorized),
ignoreUser: () => Promise.reject(errors.ErrNotAuthorized),
removeRole: () => Promise.reject(errors.ErrNotAuthorized),
setRole: () => Promise.reject(errors.ErrNotAuthorized),
setUserBanStatus: () => Promise.reject(errors.ErrNotAuthorized),
setUserSuspensionStatus: () => Promise.reject(errors.ErrNotAuthorized),
setUserUsernameStatus: () => Promise.reject(errors.ErrNotAuthorized),
@@ -76,8 +71,7 @@ module.exports = (ctx) => {
mutators.User.stopIgnoringUser = (action) => stopIgnoringUser(ctx, action);
if (ctx.user.can(UPDATE_USER_ROLES)) {
mutators.User.addRole = (id, role) => addRole(ctx, id, role);
mutators.User.removeRole = (id, role) => removeRole(ctx, id, role);
mutators.User.setRole = (id, role) => setRole(ctx, id, role);
}
if (ctx.user.can(CHANGE_USERNAME)) {
+2 -5
View File
@@ -55,11 +55,8 @@ const RootMutation = {
updateAssetStatus: async (_, {id, input: status}, {mutators: {Asset}}) => {
await Asset.updateStatus(id, status);
},
addUserRole: async (_, {id, role}, {mutators: {User}}) => {
await User.addRole(id, role);
},
removeUserRole: async (_, {id, role}, {mutators: {User}}) => {
await User.removeRole(id, role);
setUserRole: async (_, {id, role}, {mutators: {User}}) => {
await User.setRole(id, role);
},
setCommentStatus: async (_, {id, status}, {mutators: {Comment}, pubsub}) => {
const comment = await Comment.setStatus({id, status});
+2 -2
View File
@@ -67,11 +67,11 @@ const User = {
const connection = await Users.getByQuery({ids: user.ignoresUsers});
return connection.nodes;
},
roles({id, roles}, _, {user}) {
role({id, role}, _, {user}) {
// If the user is not an admin, only return the current user's roles.
if (user && (user.can(UPDATE_USER_ROLES) || user.id === id)) {
return roles;
return role;
}
return null;
+5 -7
View File
@@ -182,7 +182,7 @@ type User {
actions: [Action!]
# the current roles of the user.
roles: [USER_ROLES!]
role: USER_ROLES
# the current profiles of the user.
profiles: [UserProfile]
@@ -1380,7 +1380,7 @@ type SetUsernameResponse implements Response {
errors: [UserError!]
}
type ModifyUserRoleResponse implements Response {
type SetUserRoleResponse implements Response {
# An array of errors relating to the mutation that occurred.
errors: [UserError!]
@@ -1447,11 +1447,9 @@ type RootMutation {
# Removes a tag.
removeTag(tag: ModifyTagInput!): ModifyTagResponse
# Adds a role to a user.
addUserRole(id: ID!, role: USER_ROLES!): ModifyUserRoleResponse
# Removes a role from a user.
removeUserRole(id: ID!, role: USER_ROLES!): ModifyUserRoleResponse
# Set's a given users role to the one provided. If `null` is passed, the user
# will not have any role.
setUserRole(id: ID!, role: USER_ROLES): SetUserRoleResponse
# Updates settings on a given asset.
# Mutation is restricted.
+2 -2
View File
@@ -20,7 +20,7 @@ const ErrNotAuthorized = require('../errors').ErrNotAuthorized;
authorization.has = (user, ...roles) => {
// If no user is specified, then they can't have the roles you want!
if (!user || !user.roles) {
if (!user) {
return false;
}
@@ -31,7 +31,7 @@ authorization.has = (user, ...roles) => {
// If there's a user, and roles, then check to see that the user has at least
// one of those roles.
return roles.some((role) => user.roles.includes(role));
return roles.some((role) => user.role === role);
};
/**
+56
View File
@@ -0,0 +1,56 @@
const UserModel = require('../models/user');
const findNewRole = (roles) => {
if (roles.includes('ADMIN')) {
return 'ADMIN';
} else if (roles.includes('MODERATOR')) {
return 'MODERATOR';
} else if (roles.includes('STAFF')) {
return 'STAFF';
}
return 'COMMENTER';
};
module.exports = {
async up() {
const cursor = await UserModel.collection.find({
roles: {
$exists: true,
},
});
const updates = [];
while (await cursor.hasNext()) {
const user = await cursor.next();
updates.push({
query: {
id: user.id,
},
update: {
$set: {
role: Array.isArray(user.roles) ? findNewRole(user.roles) : 'COMMENTER',
},
$unset: {
roles: '',
},
},
});
}
if (updates.length > 0) {
// Create a new batch operation.
const bulk = UserModel.collection.initializeUnorderedBulkOp();
for (const {query, update} of updates) {
bulk.find(query).updateOne(update);
}
// Execute the bulk update operation.
await bulk.execute();
}
}
};
+2 -1
View File
@@ -1,5 +1,6 @@
module.exports = [
'ADMIN',
'MODERATOR',
'STAFF'
'STAFF',
'COMMENTER',
];
+6 -7
View File
@@ -4,7 +4,6 @@ const Schema = mongoose.Schema;
const uuid = require('uuid');
const TagLinkSchema = require('./schema/tag_link');
const TokenSchema = require('./schema/token');
const intersection = require('lodash/intersection');
const can = require('../perms');
// USER_ROLES is the array of roles that is permissible as a user role.
@@ -87,13 +86,13 @@ const UserSchema = new Schema({
// Tokens are the individual personal access tokens for a given user.
tokens: [TokenSchema],
// Roles provides an array of roles (as strings) that is associated with a
// user.
roles: [{
// Role is the specific user role that the user holds.
role: {
type: String,
enum: USER_ROLES,
required: true
}],
required: true,
default: 'COMMENTER',
},
// Status stores the user status information regarding permissions,
// capabilities and moderation state.
@@ -225,7 +224,7 @@ UserSchema.index({
* returns true if a commenter is staff
*/
UserSchema.method('isStaff', function () {
return intersection(['ADMIN', 'MODERATOR', 'STAFF'], this.roles).length !== 0;
return this.role !== 'COMMENTER';
});
/**
+1 -1
View File
@@ -29,7 +29,7 @@
},
"talk": {
"migration": {
"minVersion": 1510174676
"minVersion": 1511801783
}
},
"repository": {
+1 -4
View File
@@ -1,4 +1,3 @@
const intersection = require('lodash/intersection');
/**
* check will ensure that the user has the desired roles.
@@ -6,9 +5,7 @@ const intersection = require('lodash/intersection');
* @param {Object} user user being checked for roles
* @param {Array<String>} roles roles to check that the user has
*/
const check = (user, roles) => {
return intersection(roles, user.roles).length > 0;
};
const check = (user, roles) => roles.some((role) => role === user.role);
module.exports = {
check
@@ -26,4 +26,4 @@ ApproveCommentAction.propTypes = {
comment: PropTypes.object,
};
export default ApproveCommentAction;
export default ApproveCommentAction;
+1 -1
View File
@@ -97,7 +97,7 @@ class TagsService {
// If the tag has roles defined, and the current user has at least one of
// the required roles, then modify the tag without checking for ownership.
if (tag.permissions && tag.permissions.roles && tag.permissions.roles.some((role) => user.roles.include(role))) {
if (tag.permissions && tag.permissions.roles && tag.permissions.roles.includes(user.role)) {
return {tagLink, ownership: false};
}
+3 -18
View File
@@ -370,7 +370,6 @@ class UsersService {
user = new UserModel({
username,
lowercaseUsername: username.toLowerCase(),
roles: [],
profiles: [{id, provider}],
status: {
username: {
@@ -521,7 +520,6 @@ class UsersService {
username,
lowercaseUsername: username.toLowerCase(),
password: hashedPassword,
roles: [],
profiles: [
{
id: email,
@@ -557,25 +555,12 @@ class UsersService {
}
/**
* Adds a role to a user.
* Sets a given user's role to the one provided.
* @param {String} id id of a user
* @param {String} role role to add
*/
static addRoleToUser(id, role) {
return UserModel.update({id}, {$addToSet: {roles: role}}, {runValidators: true});
}
/**
* Removes a role from a user.
* @param {String} id id of a user
* @param {String} role role to remove
*/
static async removeRoleFromUser(id, role) {
return UserModel.update({id}, {
$pull: {
roles: role
}
}, {runValidators: true});
static setRole(id, role) {
return UserModel.update({id}, {$set: {role}}, {runValidators: true});
}
/**
+1 -1
View File
@@ -13,7 +13,7 @@ describe('graph.Context', () => {
let c;
beforeEach(() => {
c = new Context({user: new User({id: '1', roles: ['ADMIN']})});
c = new Context({user: new User({id: '1', role: 'ADMIN'})});
});
it('creates a context with a user', (done) => {
+2 -2
View File
@@ -46,7 +46,7 @@ describe('graph.loaders.Metrics', () => {
beforeEach(() => ActionModel.create(actions));
it(`returns the correct amount of metrics flagged=${flagged}`, () => {
const context = new Context({user: new UserModel({roles: ['ADMIN']})});
const context = new Context({user: new UserModel({role: 'ADMIN'})});
return graphql(schema, query, {}, context, {
from: (new Date()).setMinutes((new Date()).getMinutes() - 5),
@@ -112,7 +112,7 @@ describe('graph.loaders.Metrics', () => {
beforeEach(() => ActionModel.create(actions));
it(`returns the correct amount of metrics flagged=${flagged}`, () => {
const context = new Context({user: new UserModel({roles: ['ADMIN']})});
const context = new Context({user: new UserModel({role: 'ADMIN'})});
return graphql(schema, query, {}, context, {
from: (new Date()).setMinutes((new Date()).getMinutes() - 5),
+2 -2
View File
@@ -31,7 +31,7 @@ describe('graph.mutations.addTag', () => {
`;
it('moderators can add tags to comments', async () => {
const user = new UserModel({roles: ['MODERATOR']});
const user = new UserModel({role: 'MODERATOR'});
const context = new Context({user});
const res = await graphql(schema, query, {}, context, {id: comment.id, asset_id: asset.id, name: 'BEST'}, 'AddCommentTag');
if (res.errors && res.errors.length) {
@@ -48,7 +48,7 @@ describe('graph.mutations.addTag', () => {
Object.entries({
'anonymous': undefined,
'regular commenter': new UserModel({}),
'banned moderator': new UserModel({roles: ['MODERATOR'], banned: true})
'banned moderator': new UserModel({role: 'MODERATOR', banned: true})
}).forEach(([ userDescription, user ]) => {
it(userDescription, async () => {
const context = new Context({user});
+11 -8
View File
@@ -47,16 +47,19 @@ describe('graph.mutations.changeUsername', () => {
`;
[
{roles: null},
{roles: ['STAFF']},
{roles: []},
{roles: ['MODERATOR']},
{roles: ['ADMIN']},
{roles: ['ADMIN', 'MODERATOR']},
].forEach(({roles}) => {
it(`can change the username with roles ${roles && roles.length ? roles : JSON.stringify(roles)}`, async () => {
{role: 'COMMENTER'},
{role: 'STAFF'},
{role: 'COMMENTER'},
{role: 'MODERATOR'},
{role: 'ADMIN'},
].forEach(({role}) => {
it(`can change the username with roles ${role}`, async () => {
let username = 'spock';
// Update the user role.
await UsersService.setRole(user.id, role);
user.role = role;
let ctx = new Context({user});
let res = await graphql(schema, changeUsernameMutation, {}, ctx, {
+6 -7
View File
@@ -208,15 +208,14 @@ describe('graph.mutations.createComment', () => {
beforeEach(() => AssetModel.create({id: '123'}));
[
{roles: [], tag: null},
{roles: ['ADMIN'], tag: 'STAFF'},
{roles: ['MODERATOR'], tag: 'STAFF'},
{roles: ['ADMIN', 'MODERATOR'], tag: 'STAFF'}
].forEach(({roles, tag}) => {
describe(`user.roles=${JSON.stringify(roles)}`, () => {
{role: 'COMMENTER', tag: null},
{role: 'ADMIN', tag: 'STAFF'},
{role: 'MODERATOR', tag: 'STAFF'},
].forEach(({role, tag}) => {
describe(`user.role=${JSON.stringify(role)}`, () => {
it(`creates comment ${tag ? `with tag=${tag}` : 'without tags'}`, async () => {
const context = new Context({user: new UserModel({roles})});
const context = new Context({user: new UserModel({role})});
const {data, errors} = await graphql(schema, query, {}, context);
+2 -2
View File
@@ -34,7 +34,7 @@ describe('graph.mutations.removeTag', () => {
`;
it('moderators can add remove tags from comments', async () => {
const user = new UserModel({roles: ['MODERATOR']});
const user = new UserModel({role: 'MODERATOR'});
const context = new Context({user});
// add a tag first
@@ -66,7 +66,7 @@ describe('graph.mutations.removeTag', () => {
Object.entries({
'anonymous': undefined,
'regular commenter': new UserModel({}),
'banned moderator': new UserModel({roles: ['MODERATOR'], banned: true})
'banned moderator': new UserModel({role: 'MODERATOR', banned: true})
}).forEach(([userDescription, user]) => {
it(userDescription, async function () {
const context = new Context({user});
+11 -12
View File
@@ -57,18 +57,17 @@ describe('graph.mutations.banUser', () => {
`;
[
{self: true, error: 'NOT_AUTHORIZED', roles: null},
{self: true, error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{self: true, error: 'NOT_AUTHORIZED', roles: []},
{error: 'NOT_AUTHORIZED', roles: null},
{error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{error: 'NOT_AUTHORIZED', roles: []},
{error: false, roles: ['MODERATOR']},
{error: false, roles: ['ADMIN']},
{error: false, roles: ['ADMIN', 'MODERATOR']},
].forEach(({self, error, roles}) => {
it(`${error ? 'can not' : 'can'} ban ${self ? 'themself' : 'another user'} as a user with roles ${roles && roles.length ? roles : JSON.stringify(roles)}`, async () => {
const actor = new UserModel({roles});
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{self: true, error: 'NOT_AUTHORIZED', role: 'STAFF'},
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'STAFF'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: false, role: 'MODERATOR'},
{error: false, role: 'ADMIN'},
].forEach(({self, error, role}) => {
it(`${error ? 'can not' : 'can'} ban ${self ? 'themself' : 'another user'} as a user with role=${role}`, async () => {
const actor = new UserModel({role});
// If we're testing self assign, set the id of the actor to the user
// we're acting on.
@@ -60,18 +60,17 @@ describe('graph.mutations.suspendUser', () => {
`;
[
{self: true, error: 'NOT_AUTHORIZED', roles: null},
{self: true, error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{self: true, error: 'NOT_AUTHORIZED', roles: []},
{error: 'NOT_AUTHORIZED', roles: null},
{error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{error: 'NOT_AUTHORIZED', roles: []},
{error: false, roles: ['MODERATOR']},
{error: false, roles: ['ADMIN']},
{error: false, roles: ['ADMIN', 'MODERATOR']},
].forEach(({self, error, roles}) => {
it(`${error ? 'can not' : 'can'} suspend ${self ? 'themself' : 'another user'} as a user with roles ${roles && roles.length ? roles : JSON.stringify(roles)}`, async () => {
const actor = new UserModel({roles});
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{self: true, error: 'NOT_AUTHORIZED', role: 'STAFF'},
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'STAFF'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: false, role: 'MODERATOR'},
{error: false, role: 'ADMIN'},
].forEach(({self, error, role}) => {
it(`${error ? 'can not' : 'can'} suspend ${self ? 'themself' : 'another user'} as a user with role ${role}`, async () => {
const actor = new UserModel({role});
// If we're testing self assign, set the id of the actor to the user
// we're acting on.
@@ -33,18 +33,17 @@ const {expect} = chai;
`;
[
{self: true, error: 'NOT_AUTHORIZED', roles: null},
{self: true, error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{self: true, error: 'NOT_AUTHORIZED', roles: []},
{error: 'NOT_AUTHORIZED', roles: null},
{error: 'NOT_AUTHORIZED', roles: ['STAFF']},
{error: 'NOT_AUTHORIZED', roles: []},
{error: false, roles: ['MODERATOR']},
{error: false, roles: ['ADMIN']},
{error: false, roles: ['ADMIN', 'MODERATOR']},
].forEach(({self, error, roles}) => {
it(`${error ? 'can not' : 'can'} ${name} a username with the user roles ${roles && roles.length ? roles : JSON.stringify(roles)}${self ? ' on themself' : ''}`, async () => {
const actor = new UserModel({roles});
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{self: true, error: 'NOT_AUTHORIZED', role: 'STAFF'},
{self: true, error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: 'NOT_AUTHORIZED', role: 'STAFF'},
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{error: false, role: 'MODERATOR'},
{error: false, role: 'ADMIN'},
].forEach(({self, error, role}) => {
it(`${error ? 'can not' : 'can'} ${name} a username with the user role ${role}${self ? ' on themself' : ''}`, async () => {
const actor = new UserModel({role});
// If we're testing self assign, set the id of the actor to the user
// we're acting on.
@@ -27,12 +27,13 @@ describe('graph.mutations.updateAssetSettings', () => {
describe('context with different user roles', () => {
[
{error: 'NOT_AUTHORIZED'},
{roles: ['ADMIN', 'MODERATOR']},
{roles: ['MODERATOR']},
].forEach(({roles, error}) => {
it(roles ? roles.join(', ') : '<None>', async () => {
const user = new UserModel({roles});
{role: 'COMMENTER', error: 'NOT_AUTHORIZED'},
{role: 'STAFF', error: 'NOT_AUTHORIZED'},
{role: 'ADMIN'},
{role: 'MODERATOR'},
].forEach(({role, error}) => {
it(`role = ${role}`, async () => {
const user = new UserModel({role});
const ctx = new Context({user});
const settings = {
@@ -28,12 +28,12 @@ describe('graph.mutations.updateAssetStatus', () => {
describe('context with different user roles', () => {
[
{error: 'NOT_AUTHORIZED'},
{roles: ['ADMIN', 'MODERATOR']},
{roles: ['MODERATOR']},
].forEach(({roles, error}) => {
it(roles ? roles.join(', ') : '<None>', async () => {
const user = new UserModel({roles});
{role: 'COMMENTER', error: 'NOT_AUTHORIZED'},
{role: 'ADMIN'},
{role: 'MODERATOR'},
].forEach(({role, error}) => {
it(`role = ${role}`, async () => {
const user = new UserModel({role});
const ctx = new Context({user});
const closedAt = (new Date()).toISOString();
+7 -12
View File
@@ -26,17 +26,12 @@ describe('graph.mutations.updateSettings', () => {
describe('context with different user roles', () => {
[
{error: 'NOT_AUTHORIZED'},
{error: 'NOT_AUTHORIZED', roles: []},
{roles: ['ADMIN']},
{roles: ['ADMIN', 'MODERATOR']},
{roles: ['MODERATOR']},
].forEach(({roles, error}) => {
it(roles ? roles.join(', ') : '<None>', async () => {
let user;
if (roles != null) {
user = new UserModel({roles});
}
{error: 'NOT_AUTHORIZED', role: 'COMMENTER'},
{role: 'ADMIN'},
{role: 'MODERATOR'},
].forEach(({role, error}) => {
it(`role = ${role}`, async () => {
const user = new UserModel({role});
const ctx = new Context({user});
const newSettings = {
@@ -74,7 +69,7 @@ describe('graph.mutations.updateSettings', () => {
});
describe('nested objects', () => {
const user = new UserModel({roles: ['ADMIN']});
const user = new UserModel({role: 'ADMIN'});
const ctx = new Context({user});
it('should handle nested objects', async () => {
+6 -12
View File
@@ -56,18 +56,12 @@ describe('graph.queries.settings', () => {
];
[
{bl: true},
{bl: true, roles: []},
{bl: false, roles: ['ADMIN']},
{bl: false, roles: ['ADMIN', 'MODERATOR']},
{bl: false, roles: ['MODERATOR']},
].forEach(({bl, roles}) => {
it(roles && roles.length > 0 ? roles.join(', ') : '<None>', async () => {
let user;
if (roles != null) {
user = new UserModel({roles});
}
{bl: true, role: 'COMMENTER'},
{bl: false, role: 'ADMIN'},
{bl: false, role: 'MODERATOR'},
].forEach(({bl, role}) => {
it(`role = ${role}`, async () => {
let user = new UserModel({role});
const ctx = new Context({user});
const res = await graphql(schema, QUERY, {}, ctx);
+7 -7
View File
@@ -60,13 +60,13 @@ describe('graph.queries.user', () => {
`;
[
{roles: [], can: false},
{roles: ['STAFF'], can: false},
{roles: ['STAFF', 'MODERATOR'], can: true},
{roles: ['STAFF', 'MODERATOR', 'ADMIN'], can: true},
].forEach(({roles, can}) => {
it(`${can ? 'can' : 'can not'} query with roles = ${roles.length > 0 ? roles : '<none>'}`, async () => {
const actor = new UserModel({roles});
{role: 'COMMENTER', can: false},
{role: 'STAFF', can: false},
{role: 'MODERATOR', can: true},
{role: 'ADMIN', can: true},
].forEach(({role, can}) => {
it(`${can ? 'can' : 'can not'} query with role = ${role}`, async () => {
const actor = new UserModel({role});
const ctx = new Context({user: actor});
const {data, errors} = await graphql(schema, query, {}, ctx, {
+6 -6
View File
@@ -6,13 +6,13 @@ const authz = require('../../../middleware/authorization');
describe('middleware.authorization', () => {
describe('#has', () => {
it('allows if no roles are specified', () => {
expect(authz.has({roles: []})).to.be.true;
expect(authz.has({role: 'COMMENTER'})).to.be.true;
});
it('allows if the correct roles are met', () => {
expect(authz.has({roles: ['ADMIN']}, 'ADMIN', 'MODERATOR')).to.be.true;
expect(authz.has({role: 'ADMIN'}, 'ADMIN', 'MODERATOR')).to.be.true;
});
it('disallows if the role required is missing', () => {
expect(authz.has({roles: []}, 'ADMIN', 'MODERATOR')).to.be.false;
expect(authz.has({role: 'COMMENTER'}, 'ADMIN', 'MODERATOR')).to.be.false;
});
});
@@ -24,17 +24,17 @@ describe('middleware.authorization', () => {
};
it('allows if no roles are specified', () => {
needed()({user: {roles: []}}, {}, (err) => {
needed()({user: {role: 'COMMENTER'}}, {}, (err) => {
expect(err).to.be.undefined;
});
});
it('allows if the correct roles are met', () => {
needed()({user: {roles: ['ADMIN']}}, {}, (err) => {
needed()({user: {role: 'ADMIN'}}, {}, (err) => {
expect(err).to.be.undefined;
});
});
it('disallows if the role required is missing', () => {
needed('ADMIN', 'MODERATOR')({user: {roles: []}}, {}, (err) => {
needed('ADMIN', 'MODERATOR')({user: {role: 'COMMENTER'}}, {}, (err) => {
expect(err).to.not.be.undefined;
});
});
+7 -7
View File
@@ -40,7 +40,7 @@ describe('/api/v1/assets', () => {
for (const role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/assets')
.set(passport.inject({roles: [role]}));
.set(passport.inject({role}));
const body = res.body;
@@ -57,7 +57,7 @@ describe('/api/v1/assets', () => {
for (const role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/assets?value=term2')
.set(passport.inject({roles: [role]}));
.set(passport.inject({role}));
const body = res.body;
@@ -79,7 +79,7 @@ describe('/api/v1/assets', () => {
for (const role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/assets?value=term3')
.set(passport.inject({roles: [role]}));
.set(passport.inject({role}));
const body = res.body;
expect(body).to.have.property('count', 0);
@@ -93,7 +93,7 @@ describe('/api/v1/assets', () => {
for (const role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/assets?filter=closed')
.set(passport.inject({roles: [role]}));
.set(passport.inject({role}));
const body = res.body;
expect(body).to.have.property('count', 1);
@@ -109,7 +109,7 @@ describe('/api/v1/assets', () => {
for (const role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/assets?filter=open')
.set(passport.inject({roles: [role]}));
.set(passport.inject({role}));
const body = res.body;
expect(body).to.have.property('count', 1);
@@ -134,7 +134,7 @@ describe('/api/v1/assets', () => {
const res = await chai.request(app)
.put(`/api/v1/assets/${asset.id}/status`)
.set(passport.inject({roles: ['ADMIN']}))
.set(passport.inject({role: 'ADMIN'}))
.send({closedAt: today});
expect(res).to.have.status(204);
@@ -153,7 +153,7 @@ describe('/api/v1/assets', () => {
const promise = chai.request(app)
.put(`/api/v1/assets/${asset.id}/status`)
.set(passport.inject({roles: ['MODERATOR']}))
.set(passport.inject({role: 'MODERATOR'}))
.send({closedAt: today});
await expect(promise).to.eventually.be.rejected;
});
+3 -5
View File
@@ -20,9 +20,7 @@ describe('/api/v1/settings', () => {
for (let role of ['ADMIN', 'MODERATOR']) {
const res = await chai.request(app)
.get('/api/v1/settings')
.set(passport.inject({
roles: [role]
}));
.set(passport.inject({role}));
expect(res).to.have.status(200);
expect(res).to.be.json;
expect(res.body).to.have.property('moderation', 'PRE');
@@ -35,7 +33,7 @@ describe('/api/v1/settings', () => {
it('should update the settings', () => {
return chai.request(app)
.put('/api/v1/settings')
.set(passport.inject({roles: ['ADMIN']}))
.set(passport.inject({role: 'ADMIN'}))
.send({moderation: 'POST'})
.then((res) => {
expect(res).to.have.status(204);
@@ -50,7 +48,7 @@ describe('/api/v1/settings', () => {
it('should require ADMIN role', () => {
const promise = chai.request(app)
.put('/api/v1/settings')
.set(passport.inject({roles: ['MODERATOR']}))
.set(passport.inject({role: 'MODERATOR'}))
.send({moderation: 'POST'});
return expect(promise).to.eventually.be.rejected;
});
+2 -2
View File
@@ -30,7 +30,7 @@ describe('/api/v1/users/:user_id/email/confirm', () => {
return chai.request(app)
.post(`/api/v1/users/${mockUser.id}/email/confirm`)
.set(passport.inject({roles: ['ADMIN']}))
.set(passport.inject({role: 'ADMIN'}))
.then((res) => {
expect(res).to.have.status(204);
expect(mailer.task.tasks).to.have.length(1);
@@ -40,7 +40,7 @@ describe('/api/v1/users/:user_id/email/confirm', () => {
it('should send a 404 on not matching a user', () => {
return chai.request(app)
.post(`/api/v1/users/${mockUser.id}/email/confirm`)
.set(passport.inject({roles: ['ADMIN']}))
.set(passport.inject({role: 'ADMIN'}))
.then((res) => {
expect(res).to.have.status(204);
expect(mailer.task.tasks).to.have.length(1);
+1 -1
View File
@@ -168,7 +168,7 @@ describe('services.UsersService', () => {
it('should not ignore a staff member', async () => {
const user = mockUsers[0];
const usersToIgnore = [mockUsers[1]];
await UsersService.addRoleToUser(usersToIgnore[0].id, 'STAFF');
await UsersService.setRole(usersToIgnore[0].id, 'STAFF');
try {
await UsersService.ignoreUsers(user.id, usersToIgnore.map((u) => u.id));