mirror of
https://github.com/wassname/talk.git
synced 2026-07-29 11:28:24 +08:00
roles -> role, null -> COMMENTER for user roles
This commit is contained in:
+6
-12
@@ -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,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
@@ -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)) {
|
||||
|
||||
@@ -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});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module.exports = [
|
||||
'ADMIN',
|
||||
'MODERATOR',
|
||||
'STAFF'
|
||||
'STAFF',
|
||||
'COMMENTER',
|
||||
];
|
||||
|
||||
+6
-7
@@ -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
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"talk": {
|
||||
"migration": {
|
||||
"minVersion": 1510174676
|
||||
"minVersion": 1511801783
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
|
||||
+1
-4
@@ -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
@@ -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
@@ -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});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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});
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user