spacedeck-open/routes/api/spaces.js
2020-04-09 17:56:37 +02:00

340 lines
8.9 KiB
JavaScript

"use strict";
var config = require('config');
const os = require('os');
const db = require('../../models/db');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
const uuidv4 = require('uuid/v4');
var redis = require('../../helpers/redis');
var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader');
var space_render = require('../../helpers/space-render');
var phantom = require('../../helpers/phantom');
var payloadConverter = require('../../helpers/artifact_converter');
var slug = require('slug');
var fs = require('fs');
var async = require('async');
var _ = require("underscore");
var request = require('request');
var url = require("url");
var path = require("path");
var crypto = require('crypto');
var glob = require('glob');
var gm = require('gm');
const exec = require('child_process');
var express = require('express');
var router = express.Router();
// JSON MAPPINGS
var userMapping = {
_id: 1,
nickname: 1,
email: 1,
avatar_thumb_uri: 1
};
var spaceMapping = {
_id: 1,
name: 1,
thumbnail_url: 1
};
router.get('/', function(req, res, next) {
if (!req.user) {
res.status(403).json({
error: "auth required"
});
} else {
if (req.query.search) {
db.Membership.findAll({where:{
user_id: req.user._id
}}).then(memberships => {
// search for spaces
var validMemberships = memberships.filter(function(m) {
if (!m.space_id || (m.space_id == "undefined"))
return false;
else
return true;
});
var spaceIds = validMemberships.map(function(m) {
return m.space_id;
});
// TODO FIXME port
var q = { where: {
[Op.or]: [{"creator_id": req.user._id},
{"_id": {[Op.in]: spaceIds}},
{"parent_space_id": {[Op.in]: spaceIds}}],
name: {[Op.like]: "%"+req.query.search+"%"}
}, include: ['creator']};
db.Space
.findAll(q)
.then(function(spaces) {
res.status(200).json(spaces);
});
});
} else if (req.query.parent_space_id && req.query.parent_space_id != req.user.home_folder_id) {
// list spaces in a folder
db.Space
.findOne({where: {
_id: req.query.parent_space_id
}})
//.populate('creator', userMapping)
.then(function(space) {
if (space) {
db.getUserRoleInSpace(space, req.user, function(role) {
if (role == "none") {
if (space.access_mode == "public") {
role = "viewer";
}
}
if (role != "none") {
db.Space
.findAll({where:{
parent_space_id: req.query.parent_space_id
}, include:['creator']})
.then(function(spaces) {
res.status(200).json(spaces);
});
} else {
res.status(403).json({"error": "no authorized"});
}
});
} else {
res.status(404).json({"error": "space not found"});
}
});
} else {
// list home folder and spaces/folders that the user is a member of
db.Membership.findAll({ where: {
user_id: req.user._id
}}).then(memberships => {
if (!memberships) memberships = [];
var validMemberships = memberships.filter(function(m) {
if (!m.space_id || (m.space_id == "undefined"))
return false;
return true;
});
var spaceIds = validMemberships.map(function(m) {
return m.space_id;
});
var q = {
[Op.or]: [{
"creator_id": req.user._id,
"parent_space_id": req.user.home_folder_id
}, {
"_id": {
[Op.in]: spaceIds
},
"creator_id": {
[Op.ne]: req.user._id
}
}]
};
db.Space
.findAll({where: q, include: ['creator']})
.then(function(spaces) {
var updatedSpaces = spaces.map(function(s) {
var spaceObj = db.spaceToObject(s);
return spaceObj;
});
res.status(200).json(spaces);
});
});
}
}
});
// create a space
router.post('/', function(req, res, next) {
if (req.user) {
var attrs = req.body;
var createSpace = () => {
attrs._id = uuidv4();
attrs.creator_id = req.user._id;
attrs.edit_hash = crypto.randomBytes(64).toString('hex').substring(0, 7);
attrs.edit_slug = slug(attrs.name);
attrs.access_mode = "private";
db.Space.create(attrs).then(createdSpace => {
res.status(201).json(createdSpace);
// create initial admin membership
var membership = {
_id: uuidv4(),
user_id: req.user._id,
space_id: attrs._id,
role: "admin",
state: "active"
};
db.Membership.create(membership).then(() => {
res.status(201).json(createdSpace);
});
});
}
if (attrs.parent_space_id) {
db.Space.findOne({ where: {
"_id": attrs.parent_space_id
}}).then(parentSpace => {
if (parentSpace) {
db.getUserRoleInSpace(parentSpace, req.user, (role) => {
if ((role == "editor") || (role == "admin")) {
createSpace();
} else {
res.status(403).json({
"error": "not editor in parent Space. role: "+role
});
}
});
} else {
res.status(404).json({
"error": "parent Space not found"
});
}
});
} else {
createSpace();
}
} else {
res.sendStatus(403);
}
});
router.get('/:id', function(req, res, next) {
res.status(200).json(req.space);
});
router.get('/:id/path', (req, res) => {
// build up a breadcrumb trail (path)
var path = [];
var buildPath = (space) => {
if (space.parent_space_id) {
db.Space.findOne({ where: {
"_id": space.parent_space_id
}}).then(parentSpace => {
if (space._id == parentSpace._id) {
console.error("error: circular parent reference for space " + space._id);
res.send("error: circular reference");
} else {
path.push(parentSpace);
buildPath(parentSpace);
}
});
} else {
// reached the top
res.json(path.reverse());
}
}
buildPath(req.space);
});
router.put('/:id', function(req, res) {
var space = req.space;
var newAttr = req.body;
if (req['spaceRole'] != "editor" && req['spaceRole'] != "admin") {
res.sendStatus(403);
return;
}
newAttr.updated_at = new Date();
newAttr.edit_slug = slug(newAttr['name']);
delete newAttr['_id'];
delete newAttr['creator'];
delete newAttr['creator_id'];
delete newAttr['space_type'];
if (req['spaceRole'] != "admin") {
delete newAttr['access_mode']
delete newAttr['password']
delete newAttr['edit_hash']
delete newAttr['edit_slug']
delete newAttr['editors_locking']
}
db.Space.update(newAttr, {where: {
"_id": space._id
}}).then(space => {
res.distributeUpdate("Space", space);
});
});
router.post('/:id/background', function(req, res, next) {
var space = req.space;
var newDate = new Date();
var fileName = (req.query.filename || "upload.jpg").replace(/[^a-zA-Z0-9\.]/g, '');
var localFilePath = "/tmp/" + fileName;
var writeStream = fs.createWriteStream(localFilePath);
var stream = req.pipe(writeStream);
req.on('end', function() {
uploader.uploadFile("s" + req.space._id + "/bg_" + newDate.getTime() + "_" + fileName, "image/jpeg", localFilePath, function(err, backgroundUrl) {
if (err) res.status(400).json(err);
else {
if (space.background_uri) {
var oldPath = url.parse(req.space.background_uri).pathname;
uploader.removeFile(oldPath, function(err) {
console.error("removed old bg error:", err);
});
}
db.Space.update({
background_uri: backgroundUrl
}, {
where: { "_id": space._id }
}, function(rows) {
fs.unlink(localFilePath, function(err) {
if (err) {
console.error(err);
res.status(400).json(err);
} else {
res.status(200).json(space);
}
});
});
}
});
});
});
router.delete('/:id', function(req, res, next) {
if (req.user) {
const space = req.space;
if (req.spaceRole == "admin") {
const attrs = req.body;
space.destroy().then(function() {
res.distributeDelete("Space", space);
});
} else {
res.status(403).json({
"error": "requires admin role"
});
}
} else {
res.sendStatus(403);
}
});
module.exports = router;