linagora-rse
Version:
586 lines (495 loc) • 19.9 kB
JavaScript
'use strict';
var communityModule = require('../../core/community');
var permission = communityModule.permission;
var collaborationConstants = require('../../core/collaboration/constants');
var imageModule = require('../../core/image');
var acceptedImageTypes = ['image/jpeg', 'image/gif', 'image/png'];
var escapeStringRegexp = require('escape-string-regexp');
var logger = require('../../core/logger');
var _ = require('lodash');
var async = require('async');
var mongoose = require('mongoose');
var Community = mongoose.model('Community');
var ObjectId = mongoose.Types.ObjectId;
function transform(community, user, callback) {
if (!community) {
return {};
}
var membershipRequest = communityModule.member.getMembershipRequest(community, user);
if (typeof community.toObject === 'function') {
community = community.toObject();
}
community.members_count = community.members ? community.members.length : 0;
if (membershipRequest) {
community.membershipRequest = membershipRequest.timestamp.creation.getTime();
}
communityModule.member.isMember(community, {objectType: 'user', id: user.id}, function(err, membership) {
if (membership) {
community.member_status = 'member';
} else {
community.member_status = 'none';
}
delete community.members;
delete community.membershipRequests;
return callback(community);
});
}
function ensureLoginCommunityAndUserId(req, res) {
var community = req.community;
var user = req.user;
if (!user) {
res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'You must be logged in to access this resource'}});
return false;
}
if (!req.params || !req.params.user_id) {
res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'The user_id parameter is missing'}});
return false;
}
if (!community) {
res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'Community is missing'}});
return false;
}
return true;
}
module.exports.loadDomainForCreate = function(req, res, next) {
var domains = req.body.domain_ids;
if (!domains) {
return res.status(400).json({ error: { status: 400, message: 'Bad request', details: 'Domain ids is mandatory'}});
}
if (domains.length === 0) {
return res.status(400).json({ error: { status: 400, message: 'Bad request', details: 'Domain id is mandatory'}});
}
req.params.uuid = domains[0];
var domainMiddleware = require('../middleware/domain');
return domainMiddleware.load(req, res, next);
};
function save(community, user, res) {
communityModule.save(community, function(err, saved) {
if (err) {
return res.status(500).json({ error: { status: 500, message: 'Community save error', details: err}});
}
transform(saved, user, function(result) {
return res.status(201).json(result);
});
});
}
module.exports.create = function(req, res) {
var community = {
title: req.body.title,
creator: req.user._id,
members: [
{member: {id: req.user._id, objectType: 'user'}}
]
};
if (!community.title) {
return res.status(400).json({ error: { status: 400, message: 'Bad request', details: 'Community title is mandatory'}});
}
if (!req.body.domain_ids) {
return res.status(400).json({ error: { status: 400, message: 'Bad request', details: 'Community domain is mandatory'}});
}
if (req.body.domain_ids.length === 0) {
return res.status(400).json({ error: { status: 400, message: 'Bad request', details: 'At least a domain is required'}});
}
community.domain_ids = req.body.domain_ids;
if (req.body.type) {
community.type = req.body.type;
}
if (req.body.description) {
community.description = req.body.description;
}
if (req.body.avatar) {
community.avatar = new ObjectId(req.body.avatar);
}
if (req.query.noTitleCheck) {
save(community, req.user, res);
} else {
Community.testTitleDomain(community.title, community.domain_ids, function(err, result) {
if (err) {
return res.status(500).json({error: { status: 500, message: 'Community save error : Unable to lookup title/domain', details: err}});
}
if (result) {
return res.status(403).json({error: { status: 403, message: 'Title/domain: ' + community.title + '/' + community.domain_id + ' already exist.', details: err}});
}
save(community, req.user, res);
});
}
};
module.exports.list = function(req, res) {
var query = {};
if (req.domain) {
query.domain_ids = [req.domain._id];
}
if (req.query.creator) {
query.creator = req.query.creator;
}
if (req.query.type) {
query.type = req.query.type;
}
if (req.query.title) {
var escapedString = escapeStringRegexp(req.query.title);
query.title = new RegExp('^' + escapedString + '$', 'i');
}
communityModule.query(query, function(err, response) {
if (err) {
return res.status(500).json({ error: { code: 500, message: 'Community list failed', details: err.message}});
}
async.filter(response, function(community, callback) {
permission.canFind(community, {objectType: 'user', id: req.user._id}, callback);
}, function(err, filterResults) {
async.map(filterResults, function(community, callback) {
transform(community, req.user, function(transformed) {
return callback(null, transformed);
});
}, function(err, mapResults) {
return res.status(200).json(mapResults);
});
});
});
};
module.exports.load = function(req, res, next) {
communityModule.load(req.params.id, function(err, community) {
if (err) {
return next(err);
}
if (!community) {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
req.community = community;
return next();
});
};
module.exports.get = function(req, res) {
if (req.community) {
var userTuple = {objectType: 'user', id: String(req.user._id)};
permission.canFind(req.community, userTuple, function(err, canFind) {
if (err) {
return res.status(500).json({error: 500, message: 'Server Error', details: 'Could not find community'});
}
if (canFind) {
transform(req.community, req.user, function(transformed) {
permission.canWrite(req.community, userTuple, function(err, writable) {
var result = transformed;
result.writable = writable;
return res.status(200).json(result);
});
});
} else {
return res.status(403).json({error: 403, message: 'Forbidden', details: 'Community not readable'});
}
});
} else {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
};
module.exports.delete = function(req, res) {
if (!req.community) {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
communityModule.delete(req.community, req.user)
.then(() => res.status(204).end())
.catch(err => res.status(500).json({ error: { status: 500, message: 'Error while deleting community', details: err.message }}));
};
module.exports.update = function(req, res) {
if (!req.community) {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
if (_.isEmpty(req.body)) {
return res.status(400).json({error: 400, message: 'No Parameters', details: 'No parameters send.'});
}
function updateCommunity() {
communityModule.update(req.community, req.body, function(err) {
if (err) {
return res.status(500).json({error: 500, message: 'Datastore failure', details: err.message});
}
return res.status(200).end();
});
}
return updateCommunity();
};
module.exports.uploadAvatar = function(req, res) {
if (!req.community) {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
if (!req.query.mimetype) {
return res.status(400).json({error: 400, message: 'Parameter missing', details: 'mimetype parameter is required'});
}
var mimetype = req.query.mimetype.toLowerCase();
if (acceptedImageTypes.indexOf(mimetype) < 0) {
return res.status(400).json({error: 400, message: 'Bad parameter', details: 'mimetype ' + req.query.mimetype + ' is not acceptable'});
}
if (!req.query.size) {
return res.status(400).json({error: 400, message: 'Parameter missing', details: 'size parameter is required'});
}
var size = parseInt(req.query.size, 10);
if (isNaN(size)) {
return res.status(400).json({error: 400, message: 'Bad parameter', details: 'size parameter should be an integer'});
}
var avatarId = new ObjectId();
function updateCommunityAvatar() {
communityModule.updateAvatar(req.community, avatarId, function(err) {
if (err) {
return res.status(500).json({error: 500, message: 'Datastore failure', details: err.message});
}
return res.status(200).json({_id: avatarId});
});
}
function avatarRecordResponse(err, storedBytes) {
if (err) {
if (err.code === 1) {
return res.status(500).json({error: 500, message: 'Datastore failure', details: err.message});
} else if (err.code === 2) {
return res.status(500).json({error: 500, message: 'Image processing failure', details: err.message});
} else {
return res.status(500).json({error: 500, message: 'Internal server error', details: err.message});
}
} else if (storedBytes !== size) {
return res.status(412).json({error: 412, message: 'Image size does not match', details: 'Image size given by user agent is ' + size +
' and image size returned by storage system is ' + storedBytes});
}
updateCommunityAvatar();
}
var metadata = {};
if (req.user) {
metadata.creator = {objectType: 'user', id: req.user._id};
}
return imageModule.recordAvatar(avatarId, mimetype, metadata, req, avatarRecordResponse);
};
module.exports.getAvatar = function(req, res) {
if (!req.community) {
return res.status(404).json({error: 404, message: 'Not found', details: 'Community not found'});
}
if (!req.community.avatar) {
return res.redirect('/images/community.png');
}
imageModule.getAvatar(req.community.avatar, req.query.format, function(err, fileStoreMeta, readable) {
if (err) {
logger.warn('Can not get community avatar : %s', err.message);
return res.redirect('/images/community.png');
}
if (!readable) {
logger.warn('Can not retrieve avatar stream for community %s', req.community._id);
return res.redirect('/images/community.png');
}
if (req.headers['if-modified-since'] && Number(new Date(req.headers['if-modified-since']).setMilliseconds(0)) === Number(fileStoreMeta.uploadDate.setMilliseconds(0))) {
return res.status(304).end();
} else {
res.header('Last-Modified', fileStoreMeta.uploadDate);
res.status(200);
return readable.pipe(res);
}
});
};
module.exports.getMine = function(req, res) {
var user = req.user;
if (!user) {
return res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'User is missing'}});
}
communityModule.getUserCommunities(user._id, {member: true}, function(err, communities) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
async.map(communities, function(community, callback) {
transform(community, req.user, function(transformed) {
return callback(null, transformed);
});
}, function(err, results) {
return res.status(200).json(results);
});
});
};
module.exports.getMembers = function(req, res) {
var community = req.community;
if (!community) {
return res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'Community is missing'}});
}
var query = {};
if (req.query.limit) {
var limit = parseInt(req.query.limit, 10);
if (!isNaN(limit)) {
query.limit = limit;
}
}
if (req.query.offset) {
var offset = parseInt(req.query.offset, 10);
if (!isNaN(offset)) {
query.offset = offset;
}
}
communityModule.member.getMembers(community, query, function(err, members) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
res.header('X-ESN-Items-Count', req.community.members ? req.community.members.length : 0);
var result = members.map(function(member) {
return communityModule.userToMember(member);
});
return res.status(200).json(result || []);
});
};
module.exports.getMember = function(req, res) {
var community = req.community;
if (!community) {
return res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'Community is missing'}});
}
communityModule.member.isMember(community, {objectType: 'user', id: req.params.user_id}, function(err, result) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
if (result) {
return res.status(200).end();
}
return res.status(404).end();
});
};
module.exports.join = function(req, res) {
if (!ensureLoginCommunityAndUserId(req, res)) {
return;
}
var community = req.community;
var user = req.user;
var targetUserId = req.params.user_id;
if (req.isCommunityManager) {
if (user._id.equals(targetUserId)) {
return res.status(400).json({error: {code: 400, message: 'Bad request', details: 'Community Manager can not add himself to a community'}});
}
if (!communityModule.member.getMembershipRequest(community, {_id: targetUserId})) {
return res.status(400).json({error: {code: 400, message: 'Bad request', details: 'User did not request to join community'}});
}
communityModule.join(community, user, targetUserId, 'manager', function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
communityModule.member.cleanMembershipRequest(community, targetUserId, function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
return res.status(204).end();
});
});
} else {
if (!user._id.equals(targetUserId)) {
return res.status(400).json({error: {code: 400, message: 'Bad request', details: 'Current user is not the target user'}});
}
if (req.community.type !== collaborationConstants.COLLABORATION_TYPES.OPEN) {
var membershipRequest = communityModule.member.getMembershipRequest(community, user);
if (!membershipRequest) {
return res.status(400).json({error: {code: 400, message: 'Bad request', details: 'User was not invited to join community'}});
}
communityModule.join(community, user, user, null, function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
communityModule.member.cleanMembershipRequest(community, user, function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
return res.status(204).end();
});
});
} else {
communityModule.join(community, user, targetUserId, 'user', function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
communityModule.member.cleanMembershipRequest(community, user, function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
return res.status(204).end();
});
});
}
}
};
module.exports.leave = function(req, res) {
if (!ensureLoginCommunityAndUserId(req, res)) {
return;
}
var community = req.community;
var user = req.user;
var targetUserId = req.params.user_id;
communityModule.leave(community, user, targetUserId, function(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
return res.status(204).end();
});
};
module.exports.getMembershipRequests = function(req, res) {
var community = req.community;
if (!community) {
return res.status(400).json({error: {code: 400, message: 'Bad Request', details: 'Community is missing'}});
}
if (!req.isCommunityManager) {
return res.status(403).json({error: {code: 403, message: 'Forbidden', details: 'Only community managers can get requests'}});
}
var query = {};
if (req.query.limit) {
var limit = parseInt(req.query.limit, 10);
if (!isNaN(limit)) {
query.limit = limit;
}
}
if (req.query.offset) {
var offset = parseInt(req.query.offset, 10);
if (!isNaN(offset)) {
query.offset = offset;
}
}
communityModule.member.getMembershipRequests(community, query, function(err, membershipRequests) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.details}});
}
res.header('X-ESN-Items-Count', req.community.membershipRequests ? req.community.membershipRequests.length : 0);
var result = membershipRequests.map(function(request) {
var result = communityModule.userToMember({member: request.user, timestamp: request.timestamp});
result.workflow = request.workflow;
result.timestamp = request.timestamp;
return result;
});
return res.status(200).json(result || []);
});
};
module.exports.removeMembershipRequest = function(req, res) {
if (!ensureLoginCommunityAndUserId(req, res)) {
return;
}
if (!req.isCommunityManager && !req.user._id.equals(req.params.user_id)) {
return res.status(403).json({error: {code: 403, message: 'Forbidden', details: 'Current user is not the target user'}});
}
if (!req.community.membershipRequests || !('filter' in req.community.membershipRequests)) {
return res.status(204).end();
}
var memberships = req.community.membershipRequests.filter(function(mr) {
return mr.user.equals(req.params.user_id);
});
if (!memberships.length) {
return res.status(204).end();
}
var membership = memberships[0];
function onResponse(err) {
if (err) {
return res.status(500).json({error: {code: 500, message: 'Server Error', details: err.message}});
}
res.status(204).end();
}
/*
* workflow | isCommunityManager | What does it mean ?
* -----------------------------------------------------------
* INVITATION | yes | manager cancel the invitation of the user
* INVITATION | no | attendee declines the invitation
* REQUEST | yes | manager refuses the user's request to enter the community
* REQUEST | no | user cancels her request to enter the commity
*/
if (req.isCommunityManager) {
if (membership.workflow === communityModule.MEMBERSHIP_TYPE_INVITATION) {
communityModule.member.cancelMembershipInvitation(req.community, membership, req.user, onResponse);
} else {
communityModule.member.refuseMembershipRequest(req.community, membership, req.user, onResponse);
}
} else if (membership.workflow === communityModule.member.MEMBERSHIP_TYPE_INVITATION) {
communityModule.member.declineMembershipInvitation(req.community, membership, req.user, onResponse);
} else {
communityModule.member.cancelMembershipRequest(req.community, membership, req.user, onResponse);
}
};