Adjusted query/tag flow

This commit is contained in:
Wyatt Johnson
2017-05-09 15:01:01 -06:00
parent b8e530ca1f
commit 2e1bc8d75a
25 changed files with 476 additions and 343 deletions
+140 -15
View File
@@ -18,18 +18,25 @@ const Wordlist = require('../../services/wordlist');
*/
const createComment = ({user, loaders: {Comments}, pubsub}, {body, asset_id, parent_id = null}, status = 'NONE') => {
// Add the staff tag for comments created as a staff member.
let tags = [];
if (user.hasRoles('ADMIN') || user.hasRoles('MODERATOR')) {
tags = [{
tag: {
name: 'STAFF'
}
}];
}
return CommentsService.publicCreate({
body,
asset_id,
parent_id,
status,
tags,
author_id: user.id
})
.then(async (comment) => {
if (user.hasRoles('ADMIN') || user.hasRoles('MODERATOR')) {
await CommentsService.addTag(comment.id, 'STAFF', user.id);
}
.then((comment) => {
// If the loaders are present, clear the caches for these values because we
// just added a new comment, hence the counts should be updated. We should
@@ -204,21 +211,139 @@ const setCommentStatus = ({user, loaders: {Comments}}, {id, status}) => {
};
/**
* Adds a tag to a Comment
* @param {String} id identifier of the comment (uuid)
* @param {String} tag name of the tag
* Adds a tag to a Comment.
*/
const addCommentTag = ({user, loaders: {Comments}}, {id, tag}) => {
return CommentsService.addTag(id, tag, user.id);
const addCommentTag = async ({user, loaders: {Assets, Comments, Settings}}, {id, asset_id, name}) => {
// If the current user does not have the ADMIN or MODERATOR role
if (!user || !user.can('mutation:addCommentTag')) {
throw errors.ErrNotAuthorized;
}
// Load the settings from the dataloader, it will be cached if it was
// retrieved already.
let settings = await AssetsService.rectifySettings(AssetsService.findById(asset_id));
// Try to find the tag in the asset tags. This will contain the permission
// information.
let tag = settings.tags.find((globalTag) => {
return globalTag.name === name && globalTag.models.include('COMMENTS');
});
// Create the new tagLink that will be created to attach to the comment.
let tagLink = {
tag,
assigned_by: user.id,
created_at: new Date()
};
// If the tag was found, we need to ensure that the current user can indeed
// set this tag on the comment.
if (tag) {
// If the tag has roles defined, and the current user has at least one of
// the required roles, then add the tag without checking for ownership.
if (tag.permissions && tag.permissions.roles && tag.permissions.roles.some((role) => user.roles.include(role))) {
return CommentsService.addTag(id, tagLink, false);
}
// If the permissions allow for self assignment, then ensure that the query
// is compose with that in mind.
if (tag.permissions && tag.permissions.self) {
// Otherwise, we assume that we have to check to see that the user indeed
// owns the resource before allowing the tag to get added.
return CommentsService.addTag(id, tagLink, true);
}
throw errors.ErrNotAuthorized;
}
// Only admin/moderators can add unique tags, these are tags that are not in
// the global list.
if (!(user.hasRoles('ADMIN') || user.hasRoles('MODERATOR'))) {
throw errors.ErrNotAuthorized;
}
// Generate the tag in the event now that we have to create the tag for this
// specific comment.
tagLink.tag = {
name,
permissions: {
public: true,
self: false,
roles: []
},
models: ['COMMENTS'],
created_at: new Date()
};
// Actually attach the new tag that we created to the comment.
return CommentsService.addTag(id, tagLink, false);
};
/**
* Removes a tag from a Comment
* @param {String} id identifier of the comment (uuid)
* @param {String} tag name of the tag
* Removes a tag from a Comment.
*/
const removeCommentTag = ({user, loaders: {Comments}}, {id, tag}) => {
return CommentsService.removeTag(id, tag);
const removeCommentTag = async ({user, loaders: {Comments}}, {id, asset_id, name}) => {
// If the current user does not have the ADMIN or MODERATOR role
if (!user || !user.can('mutation:removeCommentTag')) {
throw errors.ErrNotAuthorized;
}
// Load the settings from the dataloader, it will be cached if it was
// retrieved already.
let settings = await AssetsService.rectifySettings(AssetsService.findById(asset_id));
// Try to find the tag in the asset tags. This will contain the permission
// information.
let tag = settings.tags.find((globalTag) => {
return globalTag.name === name && globalTag.models.include('COMMENTS');
});
// Create the new tagLink that will be created to attach to the comment.
let tagLink = {
tag,
assigned_by: user.id
};
// If the tag was found, we need to ensure that the current user can indeed
// remove this tag on the comment.
if (tag) {
// If the tag has roles defined, and the current user has at least one of
// the required roles, then remove the tag without checking for ownership.
if (tag.permissions && tag.permissions.roles && tag.permissions.roles.some((role) => user.roles.include(role))) {
return CommentsService.removeTag(id, tagLink, false);
}
// If the permissions allow for self assignment, then ensure that the query
// is compose with that in mind.
if (tag.permissions && tag.permissions.self) {
// Otherwise, we assume that we have to check to see that the user indeed
// owns the resource before allowing the tag to get removed.
return CommentsService.removeTag(id, tagLink, true);
}
throw errors.ErrNotAuthorized;
}
// Only admin/moderators can remove unique tags, these are tags that are not
// in the global list.
if (!(user.hasRoles('ADMIN') || user.hasRoles('MODERATOR'))) {
throw errors.ErrNotAuthorized;
}
// Generate the tag in the event now that we have to create the tag for this
// specific comment.
tagLink.tag = {
name
};
// Actually attach the new tag that we created to the comment.
return CommentsService.removeTag(id, tagLink, false);
};
module.exports = (context) => {
+4
View File
@@ -16,6 +16,8 @@ const RootMutation = require('./root_mutation');
const RootQuery = require('./root_query');
const Settings = require('./settings');
const Subscription = require('./subscription');
const TagLink = require('./tag_link');
const Tag = require('./tag');
const UserError = require('./user_error');
const User = require('./user');
const ValidationUserError = require('./validation_user_error');
@@ -39,6 +41,8 @@ let resolvers = {
RootQuery,
Settings,
Subscription,
TagLink,
Tag,
UserError,
User,
ValidationUserError,
+5 -6
View File
@@ -1,5 +1,4 @@
const wrapResponse = require('../helpers/response');
const CommentsService = require('../../services/comments');
const RootMutation = {
createComment(_, {comment}, {mutators: {Comment}}) {
@@ -29,12 +28,12 @@ const RootMutation = {
setCommentStatus(_, {id, status}, {mutators: {Comment}}) {
return wrapResponse(null)(Comment.setCommentStatus({id, status}));
},
addCommentTag(_, {id, tag}, {mutators: {Comment}}) {
return wrapResponse('comment')(Comment.addCommentTag({id, tag}).then(() => CommentsService.findById(id)));
},
removeCommentTag(_, {id, tag}, {mutators: {Comment}}) {
return wrapResponse('comment')(Comment.removeCommentTag({id, tag}).then(() => CommentsService.findById(id)));
addCommentTag(_, {id, asset_id, name}, {mutators: {Comment}}) {
return wrapResponse('comment')(Comment.addCommentTag({id, asset_id, name}));
},
removeCommentTag(_, {id, asset_id, name}, {mutators: {Comment}}) {
return wrapResponse('comment')(Comment.removeCommentTag({id, asset_id, name}));
}
};
module.exports = RootMutation;
+5
View File
@@ -0,0 +1,5 @@
const Tag = {
};
module.exports = Tag;
+9
View File
@@ -0,0 +1,9 @@
const TagLink = {
assigned_by({assigned_by}, _, {user, loaders: {Users}}) {
if (user && user.hasRole('ADMIN')) {
return Users.getByID.load(assigned_by);
}
}
};
module.exports = TagLink;
+26 -10
View File
@@ -52,14 +52,30 @@ type User {
status: USER_STATUS
}
# Tag represents the underlying Tag that can be either stored in a global list
# or added uniquely to the entity.
type Tag {
# the actual tag for the comment.
id: String!
# the user that assigned the tag. If NULL then the system automatically tagged it.
added_by: String
# The actual name of the tag entry.
name: String!
# the time when the tag was assigned.
# The time that this Tag was created.
created_at: Date!
}
# TagLink is used to associate a given Tag with a Model via a TagLink.
type TagLink {
# The underlying Tag that is either duplicated from the global list or created
# uniquely for this specific model.
tag: Tag!
# The user that assigned the tag. This TagLink could have been created by the
# system, in which case this will be null. It could also be null if the
# current user is not an Admin/Moderator.
assigned_by: User
# The date that the TagLink was created.
created_at: Date!
}
@@ -176,7 +192,7 @@ type Comment {
body: String!
# the tags on the comment
tags: [Tag]
tags: [TagLink!]
# the user who authored the comment.
user: User
@@ -702,15 +718,15 @@ type SetCommentStatusResponse implements Response {
# Response to addCommentTag mutation
type AddCommentTagResponse implements Response {
# An array of errors relating to the mutation that occured.
comment: Comment
errors: [UserError]
}
# Response to removeCommentTag mutation
type RemoveCommentTagResponse implements Response {
# An array of errors relating to the mutation that occured.
comment: Comment
errors: [UserError]
}
@@ -751,10 +767,10 @@ type RootMutation {
setCommentStatus(id: ID!, status: COMMENT_STATUS!): SetCommentStatusResponse
# Add tag to comment.
addCommentTag(id: ID!, tag: String!): AddCommentTagResponse
addCommentTag(id: ID!, asset_id: ID!, name: String!): AddCommentTagResponse
# Remove tag from comment.
removeCommentTag(id: ID!, tag: String!): RemoveCommentTagResponse
removeCommentTag(id: ID!, asset_id: ID!, name: String!): RemoveCommentTagResponse
# Ignore comments by another user
ignoreUser(id: ID!): IgnoreUserResponse