UNPKG

@tiledesk/tiledesk-server

Version:
613 lines (477 loc) 25.8 kB
var express = require('express'); var router = express.Router({mergeParams: true}); var Project_user = require("../models/project_user"); var mongoose = require('mongoose'); var User = require("../models/user"); var emailService = require("../services/emailService"); var Project = require("../models/project"); var pendinginvitation = require("../services/pendingInvitationService"); const authEvent = require('../event/authEvent'); var winston = require('../config/winston'); var RoleConstants = require("../models/roleConstants"); var ProjectUserUtil = require("../utils/project_userUtil"); const uuidv4 = require('uuid/v4'); var passport = require('passport'); require('../middleware/passport')(passport); var validtoken = require('../middleware/valid-token') var roleChecker = require('../middleware/has-role'); const puEvent = require('../event/projectUserEvent'); router.post('/invite', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) { winston.debug('Invite ProjectUser body ', req.body); let id_project = req.projectid; let email = req.body.email; if (email) { email = email.toLowerCase(); } winston.debug('Invite ProjectUser with email ' + email + ' on project ' + req.projectid); User.findOne({ email: email, status: 100 }, (err, user) => { if (err) { winston.error("Error in searching for a possible existing project user with email " + email); return res.status(500).send({ success: false, error: "An error occurred during the invite process" }); } if (!user) { // User not registered on Tiledesk Platform -> Save email and project_id in pending invitation // TODO req.user.firstname is null for bot visitor return pendinginvitation.saveInPendingInvitation(req.projectid, req.project.name, email, req.body.role, req.user._id, req.user.firstname, req.user.lastname).then(function (savedPendingInvitation) { var eventData = { req: req, savedPendingInvitation: savedPendingInvitation }; winston.debug("eventData", eventData); authEvent.emit('project_user.invite.pending', eventData); return res.json({ msg: "User not found, save invite in pending ", pendingInvitation: savedPendingInvitation }); }).catch(function (err) { return res.send(err); }); } else if (req.user.id == user._id) { // If the current user id is = to the id of found user return an error. To a user is not allowed to invite oneself. winston.debug('Invite User: found user ' + user._id + ' is equal to current user ' + req.user.id + '. Is not allowed to invite oneself.') return res.status(403).send({ success: false, msg: 'Forbidden. It is not allowed to invite oneself', code: 4000 }); } else { /** * *** IT IS NOT ALLOWED TO INVITE A USER WHO IS ALREADY A MEMBER OF THE PROJECT *** * FIND THE PROJECT USERS FOR THE PROJECT ID PASSED BY THE CLIENT IN THE BODY OF THE REQUEST * IF THE ID OF THE USER FOUND FOR THE EMAIL (PASSED IN THE BODY OF THE REQUEST - see above) * MATCHES ONE OF THE USER ID CONTENTS IN THE PROJECTS USER OBJECT STOP THE WORKFLOW AND RETURN AN ERROR */ // rolequery // var role = [RoleConstants.OWNER, RoleConstants.ADMIN, RoleConstants.SUPERVISOR, RoleConstants.AGENT]; // winston.debug("role", role); // winston.debug("PROJECT USER ROUTES - req projectid", req.projectid); return Project_user.findOne({ id_project: req.projectid, id_user: user._id, roleType: RoleConstants.TYPE_AGENTS, status: "active"}, function (err, puser) { // return Project_user.find({ id_project: req.projectid, role: { $in : role }, status: "active"}, function (err, projectuser) { //puser = projectuser winston.debug('PRJCT-USERS FOUND (FILTERED FOR THE PROJECT ID) ', puser ) if (err) { winston.error("Error inviting an already existing user: ", err); return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project }) } // if (!roles.includes(req.body.role)) { // return res.status(400).send({ success: false, msg: 'Invalid role specified: ' + req.body.role }); // } let user_available = typeof req.body.user_available === 'boolean' ? req.body.user_available : true if (puser) { if (puser.trashed !== true) { winston.warn("Trying to invite an already project member user") return res.status(403).send({ success: false, msg: 'Forbidden. User is already a member', code: 4001 }); } winston.debug('NO ERROR, SO CREATE AND SAVE A NEW PROJECT USER ') var newProject_user = new Project_user({ // _id: new mongoose.Types.ObjectId(), id_project: req.projectid, id_user: user._id, role: req.body.role, roleType : RoleConstants.TYPE_AGENTS, user_available: user_available, createdBy: req.user.id, updatedBy: req.user.id }); return newProject_user.save(function (err, savedProject_user) { if (err) { winston.error("Error update existing project user before inviting it ", err) return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project }) } emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, id_project, user.firstname, user.lastname, req.body.role) updatedPuser.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, updatedPuserPopulated){ var pu = updatedPuserPopulated.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(savedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat); var eventData = {req:req, updatedPuserPopulated: pu}; winston.debug("eventData",eventData); authEvent.emit('project_user.invite', eventData); }); return res.status(200).send(updatedPuser); }) } else { let newProject_user = new Project_user({ id_project: id_project, id_user: user._id, role: req.body.role, roleType : RoleConstants.TYPE_AGENTS, user_available: user_available, createdBy: req.user.id, updatedBy: req.user.id }) newProject_user.save((err, savedProject_user) => { if (err) { winston.error("Error saving new project user: ", err) return res.status(500).send({ success: false, msg: "An error occurred on inviting user " + email + " on project " + id_project }) } emailService.sendYouHaveBeenInvited(email, req.user.firstname, req.user.lastname, req.project.name, id_project, user.firstname, user.lastname, req.body.role) savedProject_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, savedProject_userPopulated){ var pu = savedProject_userPopulated.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(savedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat); var eventData = {req:req, savedProject_userPopulated: pu}; winston.debug("eventData",eventData); authEvent.emit('project_user.invite', eventData); }); return res.status(200).send(savedProject_user); }) } }) } }); }); router.post('/', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], function (req, res) { var newProject_user = new Project_user({ id_project: req.projectid, //il fullname???? uuid_user: uuidv4(), // role: RoleConstants.USER, // - Create project_user endpoint by agent (Ticketing) now is with Guest Role role: RoleConstants.GUEST, roleType : RoleConstants.TYPE_USERS, user_available: false, tags: req.body.tags, createdBy: req.user.id, updatedBy: req.user.id }); return newProject_user.save(function (err, savedProject_user) { if (err) { winston.error('--- > ERROR ', err) return res.status(500).send({ success: false, msg: 'Error saving object.' }); } return res.json(savedProject_user); }); }) router.put('/', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], function (req, res) { winston.debug("projectuser patch", req.body); var update = {}; if (req.body.user_available!=undefined) { update.user_available = req.body.user_available; } if (req.body.profileStatus!=undefined) { update.profileStatus = req.body.profileStatus; } if (req.body.max_assigned_chat!=undefined) { update.max_assigned_chat = req.body.max_assigned_chat; } if (req.body.number_assigned_requests!=undefined) { update.number_assigned_requests = req.body.number_assigned_requests; } if (req.body.attributes!=undefined) { update.attributes = req.body.attributes; } if (req.body["settings.email.notification.conversation.assigned.toyou"]!=undefined) { update["settings.email.notification.conversation.assigned.toyou"] = req.body["settings.email.notification.conversation.assigned.toyou"]; } if (req.body["settings.email.notification.conversation.pooled"]!=undefined) { update["settings.email.notification.conversation.pooled"] = req.body["settings.email.notification.conversation.pooled"]; } if (req.body.tags!=undefined) { update.tags = req.body.tags; } Project_user.findByIdAndUpdate(req.projectuser.id, update, { new: true, upsert: true }, function (err, updatedProject_user) { if (err) { winston.error("Error gettting project_user for update", err); return res.status(500).send({ success: false, msg: 'Error updating object.' }); } updatedProject_user.populate({ path:'id_user', select: { 'firstname': 1, 'lastname': 1 }}, function (err, updatedProject_userPopulated) { var pu = updatedProject_userPopulated.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(updatedProject_userPopulated, req.project.settings && req.project.settings.max_agent_assigned_chat); authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: req}); }); res.json(updatedProject_user); }); }); router.put('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('admin', ['subscription'])], function (req, res) { winston.debug("project_userid update", req.body); var update = {}; if (req.body.role!=undefined) { update.role = req.body.role; } if (req.body.user_available!=undefined) { update.user_available = req.body.user_available; } if (req.body.profileStatus!=undefined) { update.profileStatus = req.body.profileStatus; } if (req.body.max_assigned_chat!=undefined) { update.max_assigned_chat = req.body.max_assigned_chat; } if (req.body.number_assigned_requests!=undefined) { update.number_assigned_requests = req.body.number_assigned_requests; } if (req.body.attributes!=undefined) { update.attributes = req.body.attributes; } const allowedStatuses = ['active', 'disabled']; if (req.body.status !== undefined && allowedStatuses.includes(req.body.status)) { update.status = req.body.status; } if (req.body["settings.email.notification.conversation.assigned.toyou"]!=undefined) { update["settings.email.notification.conversation.assigned.toyou"] = req.body["settings.email.notification.conversation.assigned.toyou"]; } if (req.body["settings.email.notification.conversation.pooled"]!=undefined) { update["settings.email.notification.conversation.pooled"] = req.body["settings.email.notification.conversation.pooled"]; } if (req.body.tags!=undefined) { update.tags = req.body.tags; } winston.debug("project_userid update", update); Project_user.findByIdAndUpdate(req.params.project_userid, update, { new: true, upsert: true }, function (err, updatedProject_user) { if (err) { winston.error("Error gettting project_user for update", err); return res.status(500).send({ success: false, msg: 'Error updating object.' }); } updatedProject_user.populate({path:'id_user', select:{'firstname':1, 'lastname':1}},function (err, updatedProject_userPopulated){ if (err) { winston.error("Error gettting updatedProject_userPopulated for update", err); } var pu = updatedProject_userPopulated.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(updatedProject_user, req.project.settings && req.project.settings.max_agent_assigned_chat); authEvent.emit('project_user.update', {updatedProject_userPopulated:pu, req: req}); }); res.json(updatedProject_user); }); }); // TODO fai servizio di patch degli attributi come request // TODO blocca cancellazione owner? router.delete('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) { const { hard, soft } = req.query; const pu_id = req.params.project_userid; winston.debug(req.body); if (soft === "true") { // Soft Delete Project_user.findByIdAndUpdate(pu_id, { trashed: true }, { new: true }, (err, project_user) => { if (err) { winston.error("Error gettting project_user for soft delete", err); return res.status(500).send({ success: false, msg: 'Error deleting Project User with id ' + pu_id }); } winston.debug("Soft deleted project_user", project_user); if (!project_user) { winston.warn("Project user not found for soft delete with id " + pu_id); return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id }); } puEvent.emit('project_user.deleted', project_user); // Event 'project_user.delete' not working - Check it and improve it to manage soft/hard delete return res.status(200).send(project_user); }) } else if (hard === "true") { // Hard Delete Project_user.findByIdAndRemove(pu_id, { new: false }, (err, project_user) => { if (err) { winston.error("Error gettting project_user for hard delete", err); return res.status(500).send({ success: false, msg: 'Error deleting Project user with id ' + pu_id }); } if (!project_user) { winston.warn("Project user not found for soft delete with id " + pu_id); return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id }); } winston.debug("Hard deleted project_user", project_user); if (project_user) { project_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, project_userPopulated) { authEvent.emit('project_user.delete', { req: req, project_userPopulated: project_userPopulated }); }); } puEvent.emit('project_user.deleted', project_user); return res.status(200).send(project_user); }); } else { // Disable Project_user.findByIdAndUpdate(pu_id, { status: "disabled", user_available: false }, { new: true }, (err, project_user) => { if (err) { winston.error("Error gettting project_user for disable user", err); return res.status(500).send({ success: false, msg: 'Error disabling Project User with id ' + pu_id }); } if (!project_user) { winston.warn("Project user not found for soft delete with id " + pu_id); return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id }); } winston.debug("Disabled project_user", project_user); // Event 'project_user.delete' not working - Check it and improve it to manage disable project user return res.status(200).send(project_user); }); } }); // Restore a soft-deleted (trashed) project user. Fails if not found or not trashed. router.put('/:project_userid/restore', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], function (req, res) { const pu_id = req.params.project_userid; Project_user.findOne({ _id: pu_id, id_project: req.projectid }, function (err, project_user) { if (err) { winston.error("Error finding project_user for restore", err); return res.status(500).send({ success: false, msg: 'Error restoring Project User with id ' + pu_id }); } if (!project_user) { winston.warn("Project user not found for restore with id " + pu_id); return res.status(404).send({ success: false, error: 'Project user not found with id ' + pu_id }); } if (project_user.trashed !== true) { winston.warn("Project user is not trashed, cannot restore id " + pu_id); return res.status(400).send({ success: false, error: 'Project user is not trashed, cannot restore' }); } Project_user.findByIdAndUpdate(pu_id, { trashed: false, status: 'active' }, { new: true }, function (err, updatedProject_user) { if (err) { winston.error("Error restoring project_user", err); return res.status(500).send({ success: false, msg: 'Error restoring Project User with id ' + pu_id }); } winston.debug("Restored project_user", updatedProject_user); updatedProject_user.populate({ path: 'id_user', select: { 'firstname': 1, 'lastname': 1 } }, function (err, updatedProject_userPopulated) { if (err) { winston.error("Error populating restored project_user", err); } else { var pu = updatedProject_userPopulated.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(updatedProject_user, req.project && req.project.settings && req.project.settings.max_agent_assigned_chat); authEvent.emit('project_user.update', { updatedProject_userPopulated: pu, req: req }); } }); return res.status(200).send(updatedProject_user); }); }); }); router.get('/me', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res, next) { if (!req.project) { return res.status(404).send({ success: false, msg: 'Project not found.' }); } var project_user = req.projectuser; var pu = project_user.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(project_user, req.project.settings && req.project.settings.max_agent_assigned_chat); res.json([pu]); }); router.get('/:project_userid', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res) { // router.get('/details/:project_userid', function (req, res) { // winston.debug("PROJECT USER ROUTES - req projectid", req.projectid); Project_user.findOne({ _id: req.params.project_userid, id_project: req.projectid}). populate('id_user'). //qui cache importante ma populatevirtual exec(function (err, project_user) { if (err) { winston.error("Error gettting project_user for get", err); return res.status(500).send({ success: false, msg: 'Error getting object.' }); } if (!project_user) { return res.status(404).send({ success: false, msg: 'Object not found.' }); } // res.json(project_user); var pu = project_user.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(project_user, req.project.settings && req.project.settings.max_agent_assigned_chat); res.json(pu); }); }); router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('user', ['subscription'])], async (req, res, next) => { //changed for smtp // router.get('/users/search', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], async (req, res, next) => { winston.debug("--> users search "); if (!req.project) { return res.status(404).send({ success: false, msg: 'Project not found.' }); } let query = {email: req.query.email}; winston.debug('query: ', query); let user = await User.findOne(query).exec(); winston.debug('user: ', user); if (!user) { return res.status(404).send({ success: false, msg: 'Object not found.' }); } let project_user = await Project_user.findOne({id_user: user._id, id_project: req.projectid}).exec(); winston.debug('project_user: ', project_user); if (!project_user) { return res.status(403).json({msg: "Unauthorized. This is not a your teammate." }); } return res.json({_id: user._id}); }); /** * GET PROJECT-USER BY PROJECT ID AND CURRENT USER ID // */ router.get('/users/:user_id', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['subscription'])], function (req, res, next) { winston.debug("--> users USER ID ", req.params.user_id); if (!req.project) { return res.status(404).send({ success: false, msg: 'Project not found.' }); } var isObjectId = mongoose.Types.ObjectId.isValid(req.params.user_id); winston.debug("isObjectId:"+ isObjectId); var queryProjectUser ={ id_project: req.projectid}; if (isObjectId) { queryProjectUser.id_user = req.params.user_id }else { queryProjectUser.uuid_user = req.params.user_id } var q1 = Project_user.findOne(queryProjectUser); if (isObjectId) { q1.populate('id_user'); //qui cache importante ma populatevirtual } // Project_user.findOne({ id_user: req.params.user_id, id_project: req.projectid }). q1.exec(function (err, project_user) { if (err) { winston.error("Error gettting project_user for get users", err); return res.status(500).send({ success: false, msg: 'Error getting object.' }); } if (!project_user) { return res.status(404).send({ success: false, msg: 'Object not found.' }); } // res.json(project_user); var pu = project_user.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(project_user, req.project.settings && req.project.settings.max_agent_assigned_chat); res.json([pu]); }); }); // TODO if project is deleted // 2020-03-31T17:25:45.939421+00:00 app[web.1]: // 2020-03-31T17:25:45.998260+00:00 app[web.1]: error: uncaughtException: Cannot read property 'settings' of undefined // 2020-03-31T17:25:45.998262+00:00 app[web.1]: TypeError: Cannot read property 'settings' of undefined // 2020-03-31T17:25:45.998262+00:00 app[web.1]: at /app/routes/project_user.js:372:68 // 2020-03-31T17:25:45.998263+00:00 app[web.1]: at /app/node_modules/mongoose/lib/model.js:4779:16 // 2020-03-31T17:25:45.998263+00:00 app[web.1]: at /app/node_modules/mongoose/lib/utils.js:276:16 // 2020-03-31T17:25:45.998263+00:00 app[web.1]: at /app/node_modules/mongoose/lib/model.js:4798:21 // 2020-03-31T17:25:45.998264+00:00 app[web.1]: at _hooks.execPost (/app/node_modules/mongoose/lib/query.js:4364:11) // 2020-03-31T17:25:45.998264+00:00 app[web.1]: at /app/node_modules/kareem/index.js:135:16 // 2020-03-31T17:25:45.998269+00:00 app[web.1]: at processTicksAndRejections (internal/process/next_tick.js:74:9) {"error":{},"stack":"TypeError: Cannot read property 'settings' of undefined\n at /app/routes/project_user.js:372 // /** * RETURN THE PROJECT-USERS OBJECTS FILTERD BY PROJECT-ID AND WITH NESTED THE USER OBJECT * WF: 1. GET PROJECT-USER by the passed project ID * 2. POPULATE THE user_id OF THE PROJECT-USER object WITH THE USER OBJECT */ router.get('/', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot', 'subscription'])], function (req, res) { // rolequery // var role = [RoleConstants.OWNER, RoleConstants.ADMIN, RoleConstants.SUPERVISOR, RoleConstants.AGENT]; var query; if (req.query.role) { role = req.query.role; winston.debug("role", role); query = {id_project: req.projectid, role: { $in : role } }; } else { query = {id_project: req.projectid, roleType: RoleConstants.TYPE_AGENTS }; } if (!req.query.trashed || req.query.trashed === 'false' || req.query.trashed === false) { query.trashed = { $ne: true }; } // var query = {id_project: req.projectid, role: { $in : role } }; if (req.query.presencestatus) { query["presence.status"] = req.query.presencestatus; } winston.debug("query", query); if (req.query.status) { query["status"] = req.query.status; } Project_user.find(query). populate('id_user'). // lean(). exec(function (err, project_users) { if (err) { winston.error("Error gettting project_user for get users", err); return res.status(500).send({ success: false, msg: 'Error getting object.' }); } var ret = []; project_users.forEach(function(project_user) { var pu = project_user.toJSON(); pu.isBusy = ProjectUserUtil.isBusy(project_user, req.project && req.project.settings && req.project.settings.max_agent_assigned_chat); ret.push(pu); }); res.json(ret); }); }); module.exports = router;