diff --git a/client/coral-admin/src/containers/LayoutContainer.js b/client/coral-admin/src/containers/LayoutContainer.js
index fea730c98..8a3e0b0d2 100644
--- a/client/coral-admin/src/containers/LayoutContainer.js
+++ b/client/coral-admin/src/containers/LayoutContainer.js
@@ -27,7 +27,7 @@ class LayoutContainer extends Component {
const {handleLogout, toggleShortcutModal, TALK_RECAPTCHA_PUBLIC} = this.props;
if (loadingUser) { return ; }
- if (roleUtils.canAccessAdmin(user)) {
+ if (!loggedIn) {
return {
*/
const genComments = ({user}, ids) => {
let comments;
- if (user && user.hasRoles('ADMIN')) {
+ if (user && user.canViewOthersComments()) {
comments = CommentModel.find({
id: {
$in: ids
diff --git a/graph/mutators/comment.js b/graph/mutators/comment.js
index e2f2d3bac..9557c1dcf 100644
--- a/graph/mutators/comment.js
+++ b/graph/mutators/comment.js
@@ -22,7 +22,7 @@ const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, par
tags = tags.map(tag => ({name: tag}));
// If admin or moderator, adding STAFF tag
- if (user.hasRoles('ADMIN') || user.hasRoles('MODERATOR')) {
+ if (user.isStaff()) {
tags.push({name: 'STAFF'});
}
diff --git a/graph/resolvers/comment.js b/graph/resolvers/comment.js
index 19ea11efe..fb01a1585 100644
--- a/graph/resolvers/comment.js
+++ b/graph/resolvers/comment.js
@@ -23,14 +23,13 @@ const Comment = {
},
replyCount({id}, {excludeIgnored}, {user, loaders: {Comments}}) {
if (user && excludeIgnored) {
- return Comments.countByParentIDPersonalized({id, excludeIgnored});
+ return Comments.countByParentIDPersonalized({id, excludeIgnored});
}
- return Comments.countByParentID.load(id);
+ return Comments.countByParentID.load(id);
},
actions({id}, _, {user, loaders: {Actions}}) {
- // Only return the actions if the user is not an admin.
- if (user && user.hasRoles('ADMIN')) {
+ if (user && user.canViewActions()) {
return Actions.getByID.load(id);
}
diff --git a/graph/resolvers/root_query.js b/graph/resolvers/root_query.js
index 4dcb7ea11..9deaba5f6 100644
--- a/graph/resolvers/root_query.js
+++ b/graph/resolvers/root_query.js
@@ -1,6 +1,6 @@
const RootQuery = {
assets(_, args, {loaders: {Assets}, user}) {
- if (user == null || !user.hasRoles('ADMIN')) {
+ if (user == null || !user.canQueryAssets()) {
return null;
}
@@ -22,7 +22,7 @@ const RootQuery = {
comments(_, {query: {action_type, statuses, asset_id, parent_id, limit, cursor, sort, excludeIgnored}}, {user, loaders: {Comments, Actions}}) {
let query = {statuses, asset_id, parent_id, limit, cursor, sort, excludeIgnored};
- if (user != null && user.hasRoles('ADMIN') && action_type) {
+ if (user != null && user.canViewOthersComments() && action_type) {
return Actions.getByTypes({action_type, item_type: 'COMMENTS'})
.then((ids) => {
@@ -37,7 +37,7 @@ const RootQuery = {
return Comments.get.load(id);
},
commentCount(_, {query: {action_type, statuses, asset_id, parent_id}}, {user, loaders: {Actions, Comments}}) {
- if (user == null || !user.hasRoles('ADMIN')) {
+ if (user == null || !user.canViewOthersComments()) {
return null;
}
@@ -54,7 +54,7 @@ const RootQuery = {
},
assetMetrics(_, {from, to, sort, limit = 10}, {user, loaders: {Metrics: {Assets}}}) {
- if (user == null || !user.hasRoles('ADMIN')) {
+ if (user == null || !user.canQueryAssets()) {
return null;
}
@@ -66,7 +66,7 @@ const RootQuery = {
},
commentMetrics(_, {from, to, sort, limit = 10}, {user, loaders: {Metrics: {Comments}}}) {
- if (user == null || !user.hasRoles('ADMIN')) {
+ if (user == null || !user.canViewCommentMetrics()) {
return null;
}
@@ -100,7 +100,7 @@ const RootQuery = {
// so hide it in the event that we aren't an admin.
users(_, {query: {action_type, limit, cursor, sort}}, {user, loaders: {Users, Actions}}) {
- if (user == null || !user.hasRoles('ADMIN')) {
+ if (user == null || !user.canViewOtherUsers()) {
return null;
}
diff --git a/graph/resolvers/user.js b/graph/resolvers/user.js
index d8ed7ee15..03e1b121a 100644
--- a/graph/resolvers/user.js
+++ b/graph/resolvers/user.js
@@ -5,7 +5,7 @@ const User = {
actions({id}, _, {user, loaders: {Actions}}) {
// Only return the actions if the user is not an admin.
- if (user && user.hasRoles('ADMIN')) {
+ if (user && user.canViewActions()) {
return Actions.getByID.load(id);
}
@@ -14,7 +14,7 @@ const User = {
// If the user is not an admin, only return comment list for the owner of
// the comments.
- if (user && (user.hasRoles('ADMIN') || user.id === id)) {
+ if (user && (user.canViewOthersComments() || user.id === id)) {
return Comments.getByQuery({author_id: id, sort: 'REVERSE_CHRONOLOGICAL'});
}
@@ -23,7 +23,7 @@ const User = {
roles({id, roles}, _, {user}) {
// If the user is not an admin, only return the current user's roles.
- if (user && (user.hasRoles('ADMIN') || user.id === id)) {
+ if (user && (user.canChangeRoles() || user.id === id)) {
return roles;
}
diff --git a/models/user.js b/models/user.js
index ec215b3fa..179e6f7a5 100644
--- a/models/user.js
+++ b/models/user.js
@@ -1,6 +1,7 @@
const mongoose = require('../services/mongoose');
const bcrypt = require('bcrypt');
const uuid = require('uuid');
+const intersection = require('lodash/intersection');
// USER_ROLES is the array of roles that is permissible as a user role.
const USER_ROLES = [
@@ -158,14 +159,74 @@ UserSchema.index({
});
/**
- * Returns true if the user has all the roles specified.
+ * returns true if the user can look up assets through the api
*/
-UserSchema.method('hasRoles', function(...roles) {
- return roles.every((role) => {
+UserSchema.method('canQueryAssets', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
- // TODO: remove toUpperCase() once we've migrated usage.
- return this.roles.indexOf(role.toUpperCase()) >= 0;
- });
+/**
+ * returns true if the user can view actions
+ */
+UserSchema.method('canViewActions', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * returns true if the user can view non-null or non-ACCEPTED comments
+ */
+UserSchema.method('canViewNonNullOrAcceptedComments', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * returns true when a user can view comments that are not their own
+ */
+UserSchema.method('canViewOthersComments', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * returns true when a user can view comment metrics
+ */
+UserSchema.method('canViewCommentMetrics', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * returns true if a commenter is staff
+ */
+UserSchema.method('isStaff', function () {
+ return !!intersection(['ADMIN', 'MODERATOR', 'STAFF'], this.roles).length;
+});
+
+/**
+ * returns true when a user can see other user info
+ */
+UserSchema.method('canViewOtherUsers', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * when a user can modify tags
+ */
+UserSchema.method('canModifyTags', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+/**
+ * when a user can change roles
+ */
+UserSchema.method('canChangeUserRoles', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+UserSchema.method('canSetCommentStatus', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
+});
+
+UserSchema.method('canSetUserStatus', function () {
+ return !!intersection(['ADMIN', 'MODERATOR'], this.roles).length;
});
/**
@@ -216,13 +277,12 @@ UserSchema.method('can', function(...actions) {
return false;
}
- if (actions.some((action) => action === 'mutation:setUserStatus' || action === 'mutation:suspendUser' || action === 'mutation:setCommentStatus') && !this.hasRoles('ADMIN')) {
+ if (actions.some((action) => action === 'mutation:setUserStatus' || action === 'mutation:suspendUser' || action === 'mutation:setCommentStatus') && !this.canSetUserStatus()) {
return false;
}
// {add,remove}CommentTag - requires admin and/or moderator role
- const userCanModifyTags = user => ['ADMIN', 'MODERATOR'].some(r => user.hasRoles(r));
- if (actions.some(a => ['mutation:removeCommentTag', 'mutation:addCommentTag'].includes(a)) && ! userCanModifyTags(this)) {
+ if (actions.some(a => ['mutation:removeCommentTag', 'mutation:addCommentTag'].includes(a)) && ! this.canModifyTags()) {
return false;
}
diff --git a/test/server/graph/mutations/addCommentTag.js b/test/server/graph/mutations/addCommentTag.js
index 018e96631..1386d8339 100644
--- a/test/server/graph/mutations/addCommentTag.js
+++ b/test/server/graph/mutations/addCommentTag.js
@@ -44,6 +44,7 @@ describe('graph.mutations.addCommentTag', () => {
Object.entries({
'anonymous': undefined,
'regular commenter': new UserModel({}),
+ 'staff': new UserModel({roles: ['STAFF']}),
'banned moderator': new UserModel({roles: ['MODERATOR'], status: 'BANNED'})
}).forEach(([ userDescription, user ]) => {
it(userDescription, async function () {