From 105bdf3679b73c98c62811a77da56af6e8381911 Mon Sep 17 00:00:00 2001 From: Chris Brame Date: Thu, 11 May 2017 02:27:46 -0400 Subject: [PATCH] Fixes #13 --- src/controllers/api/v1/tickets.js | 2 +- src/emitter/events.js | 36 ++++++++++++++++++++++- src/models/user.js | 20 +++++++++++++ src/permissions/index.js | 47 ++++++++++++++++++++++++++++++- src/permissions/roles.js | 29 ++++++++++--------- 5 files changed, 118 insertions(+), 16 deletions(-) diff --git a/src/controllers/api/v1/tickets.js b/src/controllers/api/v1/tickets.js index 757725fcc..e3ad5b329 100644 --- a/src/controllers/api/v1/tickets.js +++ b/src/controllers/api/v1/tickets.js @@ -398,7 +398,7 @@ api_tickets.createPublicTicket = function(req, res) { ticket.save(function(err, t) { if (err) return next(err); - emitter.emit('ticket:created', {socketId: null, ticket: t}); + emitter.emit('ticket:created', {socketId: '', ticket: t}); return next(null, {user: savedUser, group: group, ticket: t}); }); diff --git a/src/emitter/events.js b/src/emitter/events.js index 04cf9c2c2..fc2c01446 100644 --- a/src/emitter/events.js +++ b/src/emitter/events.js @@ -23,6 +23,7 @@ var userSchema = require('../models/user'); var notificationSchema = require('../models/notification'); var emailTemplates = require('email-templates'); var templateDir = path.resolve(__dirname, '..', 'mailer', 'templates'); +var permissions = require('../permissions'); var notifications = require('../notifications'); // Load Push Events @@ -89,10 +90,43 @@ var notifications = require('../notifications'); // Load Push Events }); }, function (c) { + if (!ticket.group.public) return c(); + var rolesWithPublic = permissions.getRoles('ticket:public'); + rolesWithPublic = _.map(rolesWithPublic, 'id'); + userSchema.getUsersByRoles(rolesWithPublic, function(err, users) { + if (err) return c(); + async.each(users, function(user, cb) { + if (!permissions.canThis(user.role, 'ticket:notifications_create')) return cb(); + + var notification = new notificationSchema({ + owner: user, + title: 'Ticket #' + ticket.uid + ' Created', + message: ticket.subject, + type: 0, + data: {ticket: ticket}, + unread: true + }); + + notification.save(function(err, data) { + if (err) return cb(err); + + notifications.pushNotification(data); + + return cb(null, data); + }); + + }, function(err) { + return c(err); + }); + }); + }, + function (c) { + // Public Ticket Notification is handled above. + if (ticket.group.public) return c(); async.each(ticket.group.members, function(member, cb) { if (_.isUndefined(member)) return cb(); - if (member.role != 'mod' && member.role != 'admin') return cb(null); + if (!permissions.canThis(member.role, 'ticket:notifications_create')) return cb(); var notification = new notificationSchema({ owner: member, diff --git a/src/models/user.js b/src/models/user.js index cce951f1d..896b9a241 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -404,6 +404,26 @@ userSchema.statics.getAssigneeUsers = function(callback) { }); }; +/** + * Gets users based on roles + * + * @memberof User + * @static + * @method getUsersByRoles + * + * @param {Array} roles Array of role ids + * @param {QueryCallback} callback MongoDB Query Callback + */ +userSchema.statics.getUsersByRoles = function(roles, callback) { + if (_.isUndefined(roles)) return callback('Invalid roles array', null); + if (!_.isArray(roles)) + roles = [roles]; + + var q = this.model(COLLECTION).find({role: {$in: roles}, deleted: false}); + + return q.exec(callback); +}; + /** * Creates a user with the given data object * diff --git a/src/permissions/index.js b/src/permissions/index.js index 318c36ebc..6fea2992b 100644 --- a/src/permissions/index.js +++ b/src/permissions/index.js @@ -55,7 +55,52 @@ var canThis = function(role, a) { return _.indexOf(typePerm, action) !== -1; }; +var getRoles = function(action) { + if (_.isUndefined(action)) return false; + + var rolesWithAction = []; + + _.each(roles, function(role) { + var actionType = action.split(':')[0]; + var theAction = action.split(':')[1]; + + if (_.isUndefined(actionType) || _.isUndefined(theAction)) return false; + if (_.indexOf(role.allowedAction, '*') !== -1) { + rolesWithAction.push(role); + return; + } + + var result = _.filter(role.allowedAction, function(value) { + if (_s.startsWith(value, actionType + ':')) return value; + }); + + if (_.isUndefined(result) || _.size(result) < 1) return; + if (_.size(result) === 1) { + if (result[0] === '*') { + rolesWithAction.push(role); + return; + } + } + + var typePerm = result[0].split(':')[1].split(' '); + typePerm = _.uniq(typePerm); + + if (_.indexOf(typePerm, '*') !== -1) { + rolesWithAction.push(role); + return; + } + + if (_.indexOf(typePerm, theAction) !== -1) + rolesWithAction.push(role); + }); + + rolesWithAction = _.uniq(rolesWithAction); + + return rolesWithAction; +}; + module.exports = { roles: roles, - canThis: canThis + canThis: canThis, + getRoles: getRoles }; diff --git a/src/permissions/roles.js b/src/permissions/roles.js index 993463504..a652fcde7 100644 --- a/src/permissions/roles.js +++ b/src/permissions/roles.js @@ -17,19 +17,22 @@ Permissions for TruDesk. Define Roles / Groups. --- group:action action action - * = all permissions for grp - create = create permission for grp - delete = delete permission for grp - edit = edit permission for grp - editSelf = edit Self Created Items - assignee = allowed to be assigned to a ticket - view = view permission for grp - ticket:attachment = can add attachment - ticket:removeAttachment = can remove attachment - ticket:viewHistory = can view ticket history on single page - ticket:setAssignee = can set ticket Assignee - ticket:public = can view public created tickets - plugins:manage = user can add/remove Plugins + * = all permissions for grp + create = create permission for grp + delete = delete permission for grp + edit = edit permission for grp + editSelf = edit Self Created Items + assignee = allowed to be assigned to a ticket + view = view permission for grp + + ticket:attachment = can add attachment + ticket:removeAttachment = can remove attachment + ticket:viewHistory = can view ticket history on single page + ticket:setAssignee = can set ticket Assignee + ticket:public = can view public created tickets + ticket:notifications_create = send notification on ticket created + + plugins:manage = user can add/remove Plugins */ var roles = { admin: {