mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 17:45:56 +08:00
Adds Tag Model that will be apply to different models.
This commit is contained in:
@@ -30,27 +30,6 @@ const StatusSchema = new Schema({
|
||||
_id: false
|
||||
});
|
||||
|
||||
/**
|
||||
* The Mongo schema for a Comment Tag.
|
||||
* @type {Schema}
|
||||
*/
|
||||
const TagSchema = new Schema({
|
||||
name: String,
|
||||
|
||||
// The User ID of the user that assigned the status.
|
||||
assigned_by: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
|
||||
created_at: {
|
||||
type: Date,
|
||||
default: Date
|
||||
}
|
||||
}, {
|
||||
_id: false
|
||||
});
|
||||
|
||||
/**
|
||||
* The Mongo schema for a Comment.
|
||||
* @type {Schema}
|
||||
@@ -74,7 +53,6 @@ const CommentSchema = new Schema({
|
||||
enum: STATUSES,
|
||||
default: 'NONE'
|
||||
},
|
||||
tags: [TagSchema],
|
||||
parent_id: String,
|
||||
|
||||
// Additional metadata stored on the field.
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
const mongoose = require('../services/mongoose');
|
||||
const uuid = require('uuid');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
// in settings
|
||||
// --> decide who can apply them (self, role, anyone) and
|
||||
|
||||
// Who can see the tag (self, by role, anyone)
|
||||
const PRIVACY_TYPES = [
|
||||
'ADMIN',
|
||||
'SELF',
|
||||
'PUBLIC'
|
||||
];
|
||||
|
||||
// The type of item that the tag is apply on.
|
||||
const ITEM_TYPES = [
|
||||
'ASSETS',
|
||||
'COMMENTS',
|
||||
'USERS'
|
||||
];
|
||||
|
||||
/**
|
||||
* The Mongo schema for a Comment Tag.
|
||||
* @type {Schema}
|
||||
*/
|
||||
const TagSchema = new Schema({
|
||||
id: {
|
||||
type: String,
|
||||
default: uuid.v4,
|
||||
unique: true
|
||||
},
|
||||
|
||||
name: {
|
||||
type: String,
|
||||
unique: true
|
||||
},
|
||||
|
||||
item_type: {
|
||||
type: String,
|
||||
enum: ITEM_TYPES
|
||||
},
|
||||
|
||||
item_id: String,
|
||||
|
||||
// The User ID of the user that assigned the status.
|
||||
assigned_by: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
|
||||
privacy_type: {
|
||||
type: String,
|
||||
enum: PRIVACY_TYPES
|
||||
},
|
||||
|
||||
// Additional metadata stored on the field.
|
||||
metadata: Schema.Types.Mixed
|
||||
}, {
|
||||
_id: false
|
||||
});
|
||||
|
||||
const Tag = mongoose.model('Tag', TagSchema);
|
||||
|
||||
module.exports = Tag;
|
||||
+4
-2
@@ -185,7 +185,9 @@ const USER_GRAPH_OPERATIONS = [
|
||||
'mutation:suspendUser',
|
||||
'mutation:setCommentStatus',
|
||||
'mutation:addCommentTag',
|
||||
'mutation:removeCommentTag'
|
||||
'mutation:removeCommentTag',
|
||||
'mutation:addUserTag',
|
||||
'mutation:removeUserTag'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -207,7 +209,7 @@ UserSchema.method('can', function(...actions) {
|
||||
|
||||
// {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', 'mutation:removeUserTag', 'mutation: addUserTag'].includes(a)) && ! userCanModifyTags(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+14
-53
@@ -3,10 +3,8 @@ const CommentModel = require('../models/comment');
|
||||
const ActionModel = require('../models/action');
|
||||
const ActionsService = require('./actions');
|
||||
|
||||
const ALLOWED_TAGS = [
|
||||
{name: 'STAFF'},
|
||||
{name: 'BEST'},
|
||||
];
|
||||
const TagModel = require('../models/tag');
|
||||
const TagsService = require('./tags');
|
||||
|
||||
const STATUSES = [
|
||||
'ACCEPTED',
|
||||
@@ -53,37 +51,14 @@ module.exports = class CommentsService {
|
||||
*/
|
||||
static addTag(id, name, assigned_by) {
|
||||
|
||||
if (ALLOWED_TAGS.find((t) => t.name === name) == null) {
|
||||
return Promise.reject(new Error('tag not allowed'));
|
||||
}
|
||||
return TagsService.insertCommentTag({
|
||||
name,
|
||||
item_id: id,
|
||||
item_type: 'COMMENTS',
|
||||
user_id: assigned_by,
|
||||
});
|
||||
|
||||
const filter = {
|
||||
id,
|
||||
'tags.name': {$ne: name},
|
||||
};
|
||||
const update = {
|
||||
$push: {tags: {
|
||||
name,
|
||||
assigned_by,
|
||||
created_at: new Date()
|
||||
}}
|
||||
};
|
||||
return CommentModel.update(filter, update)
|
||||
.then(({nModified}) => {
|
||||
switch (nModified) {
|
||||
case 0:
|
||||
|
||||
// either the tag was already there, or the comment doesn't exist with that id...
|
||||
throw new Error('Could not add tag to comment. Either the comment doesn\'t exist or the tag is already present.');
|
||||
case 1:
|
||||
|
||||
// tag added
|
||||
return;
|
||||
default:
|
||||
|
||||
// this should never happen because no multi parameter and unique index on id
|
||||
}
|
||||
});
|
||||
// Add the ID to the comment
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,25 +68,11 @@ module.exports = class CommentsService {
|
||||
* @param {String} name the name of the tag to add
|
||||
*/
|
||||
static removeTag(id, name) {
|
||||
const filter = {
|
||||
id,
|
||||
'tags.name': name,
|
||||
};
|
||||
const update = {$pull: {tags: {name}}};
|
||||
return CommentModel.update(filter, update)
|
||||
.then(({nModified}) => {
|
||||
switch (nModified) {
|
||||
case 0:
|
||||
throw new Error('Could not remove tag from comment. Either the comment doesn\'t exist or the tag is not present');
|
||||
case 1:
|
||||
|
||||
// tag removed
|
||||
return;
|
||||
default:
|
||||
|
||||
// this should never happen because no multi parameter and unique index on id
|
||||
}
|
||||
});
|
||||
return TagModel.remove({
|
||||
item_type: 'COMMENTS',
|
||||
item_id: id,
|
||||
name
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,4 +65,5 @@ require('../models/action');
|
||||
require('../models/asset');
|
||||
require('../models/comment');
|
||||
require('../models/setting');
|
||||
require('../models/tag');
|
||||
require('../models/user');
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
const TagModel = require('../models/tag');
|
||||
|
||||
const ALLOWED_COMMENT_TAGS = [
|
||||
{name: 'STAFF'},
|
||||
{name: 'BEST'},
|
||||
];
|
||||
|
||||
module.exports = class TagsService {
|
||||
|
||||
/**
|
||||
* Finds an action by the id.
|
||||
* @param {String} id identifier of the tag (uuid)
|
||||
*/
|
||||
static findById(id) {
|
||||
return TagModel.findOne({id});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tag.
|
||||
* @param {string} name the actual tag
|
||||
* @param {String} item_id identifier of the comment (uuid)
|
||||
* @param {String} item_type type of the object being tag (COMMENTS)
|
||||
* @param {String} user_id user id that assigned the tag (uuid)
|
||||
* @param {String} privacy_type visibility of the tag on the comment
|
||||
* @return {Promise}
|
||||
*/
|
||||
static insertCommentTag(tag) {
|
||||
|
||||
if (ALLOWED_COMMENT_TAGS.find((t) => t.name === tag.name) == null) {
|
||||
return Promise.reject(new Error('tag not allowed'));
|
||||
}
|
||||
|
||||
// Tags are made unique by using a query that can be reproducable, i.e.,
|
||||
// not containing user inputable values.
|
||||
let query = {
|
||||
name: tag.name,
|
||||
item_id: tag.item_id,
|
||||
item_type: tag.item_type,
|
||||
assigned_by: tag.user_id,
|
||||
privacy_type: tag.privacy_type
|
||||
};
|
||||
|
||||
// Create/Update the tag.
|
||||
return TagModel.findOneAndUpdate(query, tag, {
|
||||
|
||||
// Ensure that if it's new, we return the new object created.
|
||||
new: true,
|
||||
|
||||
// Perform an upsert in the event that this doesn't exist.
|
||||
upsert: true,
|
||||
|
||||
// Set the default values if not provided based on the mongoose models.
|
||||
setDefaultsOnInsert: true
|
||||
})
|
||||
.then(({nModified}) => {
|
||||
switch (nModified) {
|
||||
case 0:
|
||||
|
||||
// either the tag was already there, or the comment doesn't exist with that id...
|
||||
throw new Error('Could not add tag to comment. Either the comment doesn\'t exist or the tag is already present.');
|
||||
case 1:
|
||||
|
||||
// tag added
|
||||
return;
|
||||
default:
|
||||
|
||||
// this should never happen because no multi parameter and unique index on id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
@@ -4,6 +4,7 @@ const {graphql} = require('graphql');
|
||||
const schema = require('../../../../graph/schema');
|
||||
const Context = require('../../../../graph/context');
|
||||
const UserModel = require('../../../../models/user');
|
||||
const TagModel = require('../../../../models/tag');
|
||||
const SettingsService = require('../../../../services/settings');
|
||||
const CommentsService = require('../../../../services/comments');
|
||||
|
||||
@@ -37,7 +38,12 @@ describe('graph.mutations.addCommentTag', () => {
|
||||
console.error(response.errors);
|
||||
}
|
||||
expect(response.errors).to.be.empty;
|
||||
expect(response.data.addCommentTag.comment.tags).to.deep.equal([{name: 'BEST'}]);
|
||||
TagModel.find({
|
||||
item_id: response.data.addCommentTag.comment.id,
|
||||
name: 'BEST'
|
||||
}).then((tags) => {
|
||||
expect(tags).to.have.length(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('users who cant add tags', () => {
|
||||
|
||||
Reference in New Issue
Block a user