further porting, cleanups, artifact upload/conversion and space screenshots
This commit is contained in:
parent
c549fcf9ec
commit
8dc48a84ba
@ -27,12 +27,11 @@ Spacedeck uses the following major building blocks:
|
|||||||
- Vue.js: Frontend UI Framework (included)
|
- Vue.js: Frontend UI Framework (included)
|
||||||
- SQLite (included)
|
- SQLite (included)
|
||||||
|
|
||||||
It also has some binary dependencies for media conversion and PDF export:
|
It also has some optional binary dependencies for advanced media conversion:
|
||||||
|
|
||||||
- graphicsmagick (for image conversion)
|
- ffmpeg and ffprobe (for video/audio conversion)
|
||||||
- ffmpeg (for video/audio conversion)
|
|
||||||
- audiowaveform (for audio waveform rendering) (https://github.com/bbcrd/audiowaveform)
|
- audiowaveform (for audio waveform rendering) (https://github.com/bbcrd/audiowaveform)
|
||||||
- phantomjs (for website screenshot rendering and PDF export, included)
|
- ghostscript (gs, for PDF import)
|
||||||
|
|
||||||
By default, media files are uploaded to the ```storage``` folder.
|
By default, media files are uploaded to the ```storage``` folder.
|
||||||
|
|
||||||
|
12
app.js
12
app.js
@ -79,8 +79,6 @@ app.use(helmet.hsts({
|
|||||||
app.disable('x-powered-by');
|
app.disable('x-powered-by');
|
||||||
app.use(helmet.noSniff())
|
app.use(helmet.noSniff())
|
||||||
|
|
||||||
// CUSTOM MIDDLEWARES
|
|
||||||
|
|
||||||
//app.use(require("./middlewares/error_helpers"));
|
//app.use(require("./middlewares/error_helpers"));
|
||||||
app.use(require("./middlewares/session"));
|
app.use(require("./middlewares/session"));
|
||||||
//app.use(require("./middlewares/cors"));
|
//app.use(require("./middlewares/cors"));
|
||||||
@ -89,19 +87,17 @@ app.use("/api", require("./middlewares/api_helpers"));
|
|||||||
app.use('/api/spaces/:id', require("./middlewares/space_helpers"));
|
app.use('/api/spaces/:id', require("./middlewares/space_helpers"));
|
||||||
app.use('/api/spaces/:id/artifacts/:artifact_id', require("./middlewares/artifact_helpers"));
|
app.use('/api/spaces/:id/artifacts/:artifact_id', require("./middlewares/artifact_helpers"));
|
||||||
|
|
||||||
// REAL ROUTES
|
|
||||||
|
|
||||||
app.use('/api/users', require('./routes/api/users'));
|
app.use('/api/users', require('./routes/api/users'));
|
||||||
//app.use('/api/memberships', require('./routes/api/memberships'));
|
app.use('/api/memberships', require('./routes/api/memberships'));
|
||||||
|
|
||||||
const spaceRouter = require('./routes/api/spaces');
|
const spaceRouter = require('./routes/api/spaces');
|
||||||
app.use('/api/spaces', spaceRouter);
|
app.use('/api/spaces', spaceRouter);
|
||||||
|
|
||||||
spaceRouter.use('/:id/artifacts', require('./routes/api/space_artifacts'));
|
spaceRouter.use('/:id/artifacts', require('./routes/api/space_artifacts'));
|
||||||
spaceRouter.use('/:id/memberships', require('./routes/api/space_memberships'));
|
spaceRouter.use('/:id/memberships', require('./routes/api/space_memberships'));
|
||||||
//spaceRouter.use('/:id/messages', require('./routes/api/space_messages'));
|
spaceRouter.use('/:id/messages', require('./routes/api/space_messages'));
|
||||||
spaceRouter.use('/:id/digest', require('./routes/api/space_digest'));
|
spaceRouter.use('/:id/digest', require('./routes/api/space_digest'));
|
||||||
//spaceRouter.use('/:id', require('./routes/api/space_exports'));
|
spaceRouter.use('/:id', require('./routes/api/space_exports'));
|
||||||
|
|
||||||
app.use('/api/sessions', require('./routes/api/sessions'));
|
app.use('/api/sessions', require('./routes/api/sessions'));
|
||||||
//app.use('/api/webgrabber', require('./routes/api/webgrabber'));
|
//app.use('/api/webgrabber', require('./routes/api/webgrabber'));
|
||||||
@ -125,8 +121,6 @@ if (app.get('env') == 'development') {
|
|||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|
||||||
// CONNECT TO DATABASE
|
// CONNECT TO DATABASE
|
||||||
//const mongoHost = process.env.MONGO_PORT_27017_TCP_ADDR || config.get('mongodb_host');
|
|
||||||
//mongoose.connect('mongodb://' + mongoHost + '/spacedeck');
|
|
||||||
db.init();
|
db.init();
|
||||||
|
|
||||||
// START WEBSERVER
|
// START WEBSERVER
|
||||||
|
@ -13,47 +13,9 @@ const db = require('../models/db');
|
|||||||
const Sequelize = require('sequelize');
|
const Sequelize = require('sequelize');
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
const fileExtensionMap = {
|
const mime = require('mime-types');
|
||||||
".amr" : "audio/AMR",
|
const fileType = require('file-type');
|
||||||
".ogg" : "audio/ogg",
|
const readChunk = require('read-chunk');
|
||||||
".aac" : "audio/aac",
|
|
||||||
".mp3" : "audio/mpeg",
|
|
||||||
".mpg" : "video/mpeg",
|
|
||||||
".3ga" : "audio/3ga",
|
|
||||||
".mp4" : "video/mp4",
|
|
||||||
".wav" : "audio/wav",
|
|
||||||
".mov" : "video/quicktime",
|
|
||||||
".doc" : "application/msword",
|
|
||||||
".dot" : "application/msword",
|
|
||||||
".docx" : "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
||||||
".dotx" : "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
||||||
".docm" : "application/vnd.ms-word.document.macroEnabled.12",
|
|
||||||
".dotm" : "application/vnd.ms-word.template.macroEnabled.12",
|
|
||||||
".xls" : "application/vnd.ms-excel",
|
|
||||||
".xlt" : "application/vnd.ms-excel",
|
|
||||||
".xla" : "application/vnd.ms-excel",
|
|
||||||
".xlsx" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
||||||
".xltx" : "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
||||||
".xlsm" : "application/vnd.ms-excel.sheet.macroEnabled.12",
|
|
||||||
".xltm" : "application/vnd.ms-excel.template.macroEnabled.12",
|
|
||||||
".xlam" : "application/vnd.ms-excel.addin.macroEnabled.12",
|
|
||||||
".xlsb" : "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
|
||||||
".ppt" : "application/vnd.ms-powerpoint",
|
|
||||||
".pot" : "application/vnd.ms-powerpoint",
|
|
||||||
".pps" : "application/vnd.ms-powerpoint",
|
|
||||||
".ppa" : "application/vnd.ms-powerpoint",
|
|
||||||
".pptx" : "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
||||||
".potx" : "application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
||||||
".ppsx" : "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
|
||||||
".ppam" : "application/vnd.ms-powerpoint.addin.macroEnabled.12",
|
|
||||||
".pptm" : "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
|
||||||
".potm" : "application/vnd.ms-powerpoint.template.macroEnabled.12",
|
|
||||||
".ppsm" : "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
|
|
||||||
".key" : "application/x-iwork-keynote-sffkey",
|
|
||||||
".pages" : "application/x-iwork-pages-sffpages",
|
|
||||||
".numbers" : "application/x-iwork-numbers-sffnumbers",
|
|
||||||
".ttf" : "application/x-font-ttf"
|
|
||||||
};
|
|
||||||
|
|
||||||
const convertableImageTypes = [
|
const convertableImageTypes = [
|
||||||
"image/png",
|
"image/png",
|
||||||
@ -73,7 +35,7 @@ const convertableVideoTypes = [
|
|||||||
|
|
||||||
const convertableAudioTypes = [
|
const convertableAudioTypes = [
|
||||||
"application/ogg",
|
"application/ogg",
|
||||||
"audio/AMR",
|
"audio/amr",
|
||||||
"audio/3ga",
|
"audio/3ga",
|
||||||
"audio/wav",
|
"audio/wav",
|
||||||
"audio/3gpp",
|
"audio/3gpp",
|
||||||
@ -132,7 +94,7 @@ function createWaveform(fileName, localFilePath, callback){
|
|||||||
|
|
||||||
function convertVideo(fileName, filePath, codec, callback, progress_callback) {
|
function convertVideo(fileName, filePath, codec, callback, progress_callback) {
|
||||||
var ext = path.extname(fileName);
|
var ext = path.extname(fileName);
|
||||||
var presetMime = fileExtensionMap[ext];
|
var presetMime = mime.lookup(fileName);
|
||||||
|
|
||||||
var newExt = codec == "mp4" ? "mp4" : "ogv";
|
var newExt = codec == "mp4" ? "mp4" : "ogv";
|
||||||
var convertedPath = filePath + "." + newExt;
|
var convertedPath = filePath + "." + newExt;
|
||||||
@ -190,7 +152,7 @@ function convertVideo(fileName, filePath, codec, callback, progress_callback) {
|
|||||||
|
|
||||||
function convertAudio(fileName, filePath, codec, callback) {
|
function convertAudio(fileName, filePath, codec, callback) {
|
||||||
var ext = path.extname(fileName);
|
var ext = path.extname(fileName);
|
||||||
var presetMime = fileExtensionMap[ext];
|
var presetMime = mime.lookup(fileName);
|
||||||
|
|
||||||
var newExt = codec == "mp3" ? "mp3" : "ogg";
|
var newExt = codec == "mp3" ? "mp3" : "ogg";
|
||||||
var convertedPath = filePath + "." + newExt;
|
var convertedPath = filePath + "." + newExt;
|
||||||
@ -227,22 +189,14 @@ function createThumbnailForVideo(fileName, filePath, callback) {
|
|||||||
|
|
||||||
function getMime(fileName, filePath, callback) {
|
function getMime(fileName, filePath, callback) {
|
||||||
var ext = path.extname(fileName);
|
var ext = path.extname(fileName);
|
||||||
var presetMime = fileExtensionMap[ext];
|
var presetMime = mime.lookup(fileName);
|
||||||
|
|
||||||
if (presetMime) {
|
if (presetMime) {
|
||||||
callback(null, presetMime);
|
callback(null, presetMime);
|
||||||
} else {
|
} else {
|
||||||
exec.execFile("file", ["-b","--mime-type", filePath], {}, function(error, stdout, stderr) {
|
const buffer = readChunk.sync(filePath, 0, 4100);
|
||||||
console.log("file stdout: ",stdout);
|
var mimeType = fileType(buffer);
|
||||||
if (stderr === '' && error == null) {
|
callback(null, mimeType);
|
||||||
//filter special chars from commandline
|
|
||||||
var mime = stdout.replace(/[^a-zA-Z0-9\/\-]/g,'');
|
|
||||||
callback(null, mime);
|
|
||||||
} else {
|
|
||||||
console.log("getMime file error: ", error);
|
|
||||||
callback(error, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +230,7 @@ function resizeAndUpload(a, size, max, fileName, localFilePath, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var resizeAndUploadImage = function(a, mime, size, fileName, fileNameOrg, imageFilePath, originalFilePath, payloadCallback) {
|
var resizeAndUploadImage = function(a, mimeType, size, fileName, fileNameOrg, imageFilePath, originalFilePath, payloadCallback) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
small: function(callback){
|
small: function(callback){
|
||||||
resizeAndUpload(a, size, 320, fileName, imageFilePath, callback);
|
resizeAndUpload(a, size, 320, fileName, imageFilePath, callback);
|
||||||
@ -289,13 +243,13 @@ var resizeAndUploadImage = function(a, mime, size, fileName, fileNameOrg, imageF
|
|||||||
},
|
},
|
||||||
original: function(callback){
|
original: function(callback){
|
||||||
var s3Key = "s"+ a.space_id.toString() + "/a" + a._id + "/" + fileNameOrg;
|
var s3Key = "s"+ a.space_id.toString() + "/a" + a._id + "/" + fileNameOrg;
|
||||||
uploader.uploadFile(s3Key, mime, originalFilePath, function(err, url){
|
uploader.uploadFile(s3Key, mimeType, originalFilePath, function(err, url){
|
||||||
callback(null, url);
|
callback(null, url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, function(err, results) {
|
}, function(err, results) {
|
||||||
a.state = "idle";
|
a.state = "idle";
|
||||||
a.mime = mime;
|
a.mime = mimeType;
|
||||||
var stats = fs.statSync(originalFilePath);
|
var stats = fs.statSync(originalFilePath);
|
||||||
|
|
||||||
a.payload_size = stats["size"];
|
a.payload_size = stats["size"];
|
||||||
@ -325,21 +279,21 @@ var resizeAndUploadImage = function(a, mime, size, fileName, fileNameOrg, imageF
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
convert: function(a, fileName, localFilePath, payloadCallback, progress_callback) {
|
convert: function(a, fileName, localFilePath, payloadCallback, progress_callback) {
|
||||||
getMime(fileName, localFilePath, function(err, mime){
|
getMime(fileName, localFilePath, function(err, mimeType){
|
||||||
console.log("[convert] fn: "+fileName+" local: "+localFilePath+" mime:", mime);
|
console.log("[convert] fn: "+fileName+" local: "+localFilePath+" mimeType:", mimeType);
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (convertableImageTypes.indexOf(mime) > -1) {
|
if (convertableImageTypes.indexOf(mimeType) > -1) {
|
||||||
|
|
||||||
gm(localFilePath).size(function (err, size) {
|
gm(localFilePath).size(function (err, size) {
|
||||||
console.log("[convert] gm:", err, size);
|
console.log("[convert] gm:", err, size);
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if(mime == "application/pdf") {
|
if(mimeType == "application/pdf") {
|
||||||
var firstImagePath = localFilePath + ".jpeg";
|
var firstImagePath = localFilePath + ".jpeg";
|
||||||
exec.execFile("gs", ["-sDEVICE=jpeg","-dNOPAUSE", "-dJPEGQ=80", "-dBATCH", "-dFirstPage=1", "-dLastPage=1", "-sOutputFile=" + firstImagePath, "-r90", "-f", localFilePath], {}, function(error, stdout, stderr) {
|
exec.execFile("gs", ["-sDEVICE=jpeg","-dNOPAUSE", "-dJPEGQ=80", "-dBATCH", "-dFirstPage=1", "-dLastPage=1", "-sOutputFile=" + firstImagePath, "-r90", "-f", localFilePath], {}, function(error, stdout, stderr) {
|
||||||
if(error === null) {
|
if(error === null) {
|
||||||
resizeAndUploadImage(a, mime, size, fileName + ".jpeg", fileName, firstImagePath, localFilePath, function(err, a) {
|
resizeAndUploadImage(a, mimeType, size, fileName + ".jpeg", fileName, firstImagePath, localFilePath, function(err, a) {
|
||||||
fs.unlink(firstImagePath, function (err) {
|
fs.unlink(firstImagePath, function (err) {
|
||||||
payloadCallback(err, a);
|
payloadCallback(err, a);
|
||||||
});
|
});
|
||||||
@ -349,7 +303,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if(mime == "image/gif") {
|
} else if(mimeType == "image/gif") {
|
||||||
//gifs are buggy after convertion, so we should not convert them
|
//gifs are buggy after convertion, so we should not convert them
|
||||||
|
|
||||||
var s3Key = "s"+ a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
var s3Key = "s"+ a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
||||||
@ -361,7 +315,7 @@ module.exports = {
|
|||||||
var stats = fs.statSync(localFilePath);
|
var stats = fs.statSync(localFilePath);
|
||||||
|
|
||||||
a.state = "idle";
|
a.state = "idle";
|
||||||
a.mime = mime;
|
a.mime = mimeType;
|
||||||
|
|
||||||
a.payload_size = stats["size"];
|
a.payload_size = stats["size"];
|
||||||
a.payload_thumbnail_web_uri = url;
|
a.payload_thumbnail_web_uri = url;
|
||||||
@ -389,12 +343,12 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resizeAndUploadImage(a, mime, size, fileName, fileName, localFilePath, localFilePath, payloadCallback);
|
resizeAndUploadImage(a, mimeType, size, fileName, fileName, localFilePath, localFilePath, payloadCallback);
|
||||||
}
|
}
|
||||||
} else payloadCallback(err);
|
} else payloadCallback(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (convertableVideoTypes.indexOf(mime) > -1) {
|
} else if (convertableVideoTypes.indexOf(mimeType) > -1) {
|
||||||
async.parallel({
|
async.parallel({
|
||||||
thumbnail: function(callback) {
|
thumbnail: function(callback) {
|
||||||
createThumbnailForVideo(fileName, localFilePath, function(err, created){
|
createThumbnailForVideo(fileName, localFilePath, function(err, created){
|
||||||
@ -410,7 +364,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
ogg: function(callback) {
|
ogg: function(callback) {
|
||||||
if (mime == "video/ogg") {
|
if (mimeType == "video/ogg") {
|
||||||
callback(null, "org");
|
callback(null, "org");
|
||||||
} else {
|
} else {
|
||||||
convertVideo(fileName, localFilePath, "ogg", function(err, file) {
|
convertVideo(fileName, localFilePath, "ogg", function(err, file) {
|
||||||
@ -426,7 +380,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mp4: function(callback) {
|
mp4: function(callback) {
|
||||||
if (mime == "video/mp4") {
|
if (mimeType == "video/mp4") {
|
||||||
callback(null, "org");
|
callback(null, "org");
|
||||||
} else {
|
} else {
|
||||||
convertVideo(fileName, localFilePath, "mp4", function(err, file) {
|
convertVideo(fileName, localFilePath, "mp4", function(err, file) {
|
||||||
@ -442,7 +396,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
original: function(callback){
|
original: function(callback){
|
||||||
uploader.uploadFile(fileName, mime, localFilePath, function(err, url){
|
uploader.uploadFile(fileName, mimeType, localFilePath, function(err, url){
|
||||||
callback(null, url);
|
callback(null, url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -452,7 +406,7 @@ module.exports = {
|
|||||||
if (err) payloadCallback(err, a);
|
if (err) payloadCallback(err, a);
|
||||||
else {
|
else {
|
||||||
a.state = "idle";
|
a.state = "idle";
|
||||||
a.mime = mime;
|
a.mime = mimeType;
|
||||||
var stats = fs.statSync(localFilePath);
|
var stats = fs.statSync(localFilePath);
|
||||||
|
|
||||||
a.payload_size = stats["size"];
|
a.payload_size = stats["size"];
|
||||||
@ -461,7 +415,7 @@ module.exports = {
|
|||||||
a.payload_thumbnail_big_uri = results.thumbnail;
|
a.payload_thumbnail_big_uri = results.thumbnail;
|
||||||
a.payload_uri = results.original;
|
a.payload_uri = results.original;
|
||||||
|
|
||||||
if (mime == "video/mp4") {
|
if (mimeType == "video/mp4") {
|
||||||
a.payload_alternatives = [
|
a.payload_alternatives = [
|
||||||
{
|
{
|
||||||
mime: "video/ogg",
|
mime: "video/ogg",
|
||||||
@ -497,7 +451,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else if (convertableAudioTypes.indexOf(mime) > -1) {
|
} else if (convertableAudioTypes.indexOf(mimeType) > -1) {
|
||||||
|
|
||||||
async.parallel({
|
async.parallel({
|
||||||
ogg: function(callback) {
|
ogg: function(callback) {
|
||||||
@ -535,7 +489,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
original: function(callback) {
|
original: function(callback) {
|
||||||
var keyName = "s" + a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
var keyName = "s" + a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
||||||
uploader.uploadFile(keyName, mime, localFilePath, function(err, url){
|
uploader.uploadFile(keyName, mimeType, localFilePath, function(err, url){
|
||||||
callback(null, url);
|
callback(null, url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -546,7 +500,7 @@ module.exports = {
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
a.state = "idle";
|
a.state = "idle";
|
||||||
a.mime = mime;
|
a.mime = mimeType;
|
||||||
var stats = fs.statSync(localFilePath);
|
var stats = fs.statSync(localFilePath);
|
||||||
|
|
||||||
a.payload_size = stats["size"];
|
a.payload_size = stats["size"];
|
||||||
@ -579,12 +533,12 @@ module.exports = {
|
|||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.log("mime not matched for conversion, storing file");
|
console.log("mimeType not matched for conversion, storing file");
|
||||||
var keyName = "s" + a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
var keyName = "s" + a.space_id.toString() + "/a" + a._id.toString() + "/" + fileName;
|
||||||
uploader.uploadFile(keyName, mime, localFilePath, function(err, url) {
|
uploader.uploadFile(keyName, mimeType, localFilePath, function(err, url) {
|
||||||
|
|
||||||
a.state = "idle";
|
a.state = "idle";
|
||||||
a.mime = mime;
|
a.mime = mimeType;
|
||||||
var stats = fs.statSync(localFilePath);
|
var stats = fs.statSync(localFilePath);
|
||||||
a.payload_size = stats["size"];
|
a.payload_size = stats["size"];
|
||||||
a.payload_uri = url;
|
a.payload_uri = url;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
require('../models/db');
|
const db = require('../models/db');
|
||||||
var config = require('config');
|
const config = require('config');
|
||||||
var phantom = require('node-phantom-simple');
|
const phantom = require('node-phantom-simple');
|
||||||
|
const os = require('os');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// type = "pdf" or "png"
|
// type = "pdf" or "png"
|
||||||
@ -10,7 +11,7 @@ module.exports = {
|
|||||||
var spaceId = space._id;
|
var spaceId = space._id;
|
||||||
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
|
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
|
||||||
|
|
||||||
var export_path = "/tmp/"+spaceId+"."+type;
|
var export_path = os.tmpdir()+"/"+spaceId+"."+type;
|
||||||
|
|
||||||
var timeout = 5000;
|
var timeout = 5000;
|
||||||
if (type=="pdf") timeout = 30000;
|
if (type=="pdf") timeout = 30000;
|
||||||
@ -24,7 +25,7 @@ module.exports = {
|
|||||||
|
|
||||||
var on_exit = function(exit_code) {
|
var on_exit = function(exit_code) {
|
||||||
if (exit_code>0) {
|
if (exit_code>0) {
|
||||||
console.log("phantom abnormal exit for url "+space_url);
|
console.error("phantom abnormal exit for url "+space_url);
|
||||||
if (!on_success_called && on_error) {
|
if (!on_success_called && on_error) {
|
||||||
on_error();
|
on_error();
|
||||||
}
|
}
|
||||||
@ -33,15 +34,15 @@ module.exports = {
|
|||||||
|
|
||||||
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
|
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err);
|
console.error(err);
|
||||||
} else {
|
} else {
|
||||||
return browser.createPage(function (err, page) {
|
return browser.createPage(function (err, page) {
|
||||||
console.log("page created, opening ",space_url);
|
console.log("page created, opening ",space_url);
|
||||||
|
|
||||||
if (type=="pdf") {
|
if (type=="pdf") {
|
||||||
var psz = {
|
var psz = {
|
||||||
width: space.advanced.width+"px",
|
width: space.width+"px",
|
||||||
height: space.advanced.height+"px"
|
height: space.height+"px"
|
||||||
};
|
};
|
||||||
page.set('paperSize', psz);
|
page.set('paperSize', psz);
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ module.exports = {
|
|||||||
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Artifact: sequelize.define('message', {
|
Message: sequelize.define('message', {
|
||||||
_id: {type: Sequelize.STRING, primaryKey: true},
|
_id: {type: Sequelize.STRING, primaryKey: true},
|
||||||
space_id: Sequelize.STRING,
|
space_id: Sequelize.STRING,
|
||||||
user_id: Sequelize.STRING,
|
user_id: Sequelize.STRING,
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
"cookie-parser": "~1.4.3",
|
"cookie-parser": "~1.4.3",
|
||||||
"csurf": "1.9.0",
|
"csurf": "1.9.0",
|
||||||
"debug": "~2.6.3",
|
"debug": "~2.6.3",
|
||||||
|
"electron": "^1.8.4",
|
||||||
"execSync": "latest",
|
"execSync": "latest",
|
||||||
"express": "~4.13.0",
|
"express": "~4.13.0",
|
||||||
"extract-zip": "^1.6.6",
|
"extract-zip": "^1.6.6",
|
||||||
|
"file-type": "^7.6.0",
|
||||||
"glob": "7.1.1",
|
"glob": "7.1.1",
|
||||||
"gm": "1.23.0",
|
"gm": "1.23.0",
|
||||||
"googleapis": "18.0.0",
|
"googleapis": "18.0.0",
|
||||||
@ -40,6 +42,7 @@
|
|||||||
"lodash": "^4.3.0",
|
"lodash": "^4.3.0",
|
||||||
"log-timestamp": "latest",
|
"log-timestamp": "latest",
|
||||||
"md5": "2.2.1",
|
"md5": "2.2.1",
|
||||||
|
"mime-types": "^2.1.18",
|
||||||
"mock-aws-s3": "^2.6.0",
|
"mock-aws-s3": "^2.6.0",
|
||||||
"moment": "^2.19.3",
|
"moment": "^2.19.3",
|
||||||
"mongoose": "4.9.3",
|
"mongoose": "4.9.3",
|
||||||
@ -51,6 +54,7 @@
|
|||||||
"pm2": "latest",
|
"pm2": "latest",
|
||||||
"qr-image": "3.2.0",
|
"qr-image": "3.2.0",
|
||||||
"raven": "1.2.0",
|
"raven": "1.2.0",
|
||||||
|
"read-chunk": "^2.1.0",
|
||||||
"request": "2.81.0",
|
"request": "2.81.0",
|
||||||
"sanitize-html": "^1.11.1",
|
"sanitize-html": "^1.11.1",
|
||||||
"sequelize": "^4.37.6",
|
"sequelize": "^4.37.6",
|
||||||
|
@ -640,13 +640,10 @@ var SpacedeckSpaces = {
|
|||||||
this.download_space_as_pdf(this.active_space);
|
this.download_space_as_pdf(this.active_space);
|
||||||
} else if (e == "ZIP") {
|
} else if (e == "ZIP") {
|
||||||
this.download_space_as_zip(this.active_space);
|
this.download_space_as_zip(this.active_space);
|
||||||
}else if (e == "TXT"){
|
|
||||||
this.download_space_as_list(this.active_space);
|
|
||||||
}
|
}
|
||||||
}.bind(this), {
|
}.bind(this), {
|
||||||
button_1: "PDF",
|
button_1: "PDF",
|
||||||
button_2: "ZIP",
|
button_2: "ZIP",
|
||||||
button_3: "TXT",
|
|
||||||
button_cancel:__("cancel")
|
button_cancel:__("cancel")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
|
|
||||||
|
const os = require('os');
|
||||||
const db = require('../../models/db');
|
const db = require('../../models/db');
|
||||||
const Sequelize = require('sequelize');
|
const Sequelize = require('sequelize');
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
@ -124,8 +126,7 @@ router.post('/:artifact_id/payload', function(req, res, next) {
|
|||||||
|
|
||||||
var fileName = (req.query.filename || "upload.bin").replace(/[^a-zA-Z0-9_\-\.]/g, '');
|
var fileName = (req.query.filename || "upload.bin").replace(/[^a-zA-Z0-9_\-\.]/g, '');
|
||||||
|
|
||||||
// FIXME TODO use portable tmp dir
|
var localFilePath = os.tmpdir() + "/" + fileName;
|
||||||
var localFilePath = "/tmp/" + fileName;
|
|
||||||
var writeStream = fs.createWriteStream(localFilePath);
|
var writeStream = fs.createWriteStream(localFilePath);
|
||||||
var stream = req.pipe(writeStream);
|
var stream = req.pipe(writeStream);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
require('../../models/db');
|
const db = require('../../models/db');
|
||||||
|
|
||||||
var redis = require('../../helpers/redis');
|
var redis = require('../../helpers/redis');
|
||||||
var mailer = require('../../helpers/mailer');
|
var mailer = require('../../helpers/mailer');
|
||||||
@ -49,18 +49,10 @@ var roleMapping = {
|
|||||||
|
|
||||||
router.get('/png', function(req, res, next) {
|
router.get('/png', function(req, res, next) {
|
||||||
var triggered = new Date();
|
var triggered = new Date();
|
||||||
|
|
||||||
var s3_filename = "s" + req.space._id + "/" + "thumb_" + triggered.getTime() + ".jpg";
|
var s3_filename = "s" + req.space._id + "/" + "thumb_" + triggered.getTime() + ".jpg";
|
||||||
|
|
||||||
if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) {
|
if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) {
|
||||||
|
db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }});
|
||||||
Space.update({
|
|
||||||
"_id": req.space._id
|
|
||||||
}, {
|
|
||||||
"$set": {
|
|
||||||
thumbnail_updated_at: triggered
|
|
||||||
}
|
|
||||||
}, function(a, b, c) {});
|
|
||||||
|
|
||||||
phantom.takeScreenshot(req.space, "png",
|
phantom.takeScreenshot(req.space, "png",
|
||||||
function(local_path) {
|
function(local_path) {
|
||||||
@ -68,7 +60,7 @@ router.get('/png', function(req, res, next) {
|
|||||||
gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
|
gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error("screenshot resize error: ", err);
|
console.error("[space screenshot] resize error: ", err);
|
||||||
res.status(500).send("Error taking screenshot.");
|
res.status(500).send("Error taking screenshot.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -76,22 +68,15 @@ router.get('/png', function(req, res, next) {
|
|||||||
uploader.uploadFile(s3_filename, "image/jpeg", localResizedFilePath, function(err, thumbnailUrl) {
|
uploader.uploadFile(s3_filename, "image/jpeg", localResizedFilePath, function(err, thumbnailUrl) {
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error("screenshot s3 upload error. filename: " + s3_filename + " details: ", err);
|
console.error("[space screenshot] upload error. filename: " + s3_filename + " details: ", err);
|
||||||
res.status(500).send("Error uploading screenshot.");
|
res.status(500).send("Error uploading screenshot.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldUrl = req.space.thumbnail_url;
|
var oldUrl = req.space.thumbnail_url;
|
||||||
|
|
||||||
Space.update({
|
db.Space.update({ thumbnail_url: thumbnailUrl }, {where : {"_id": req.space._id }}).then(() => {
|
||||||
"_id": req.space._id
|
|
||||||
}, {
|
|
||||||
"$set": {
|
|
||||||
thumbnail_url: thumbnailUrl
|
|
||||||
}
|
|
||||||
}, function(a, b, c) {
|
|
||||||
res.redirect(thumbnailUrl);
|
res.redirect(thumbnailUrl);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (oldUrl) {
|
if (oldUrl) {
|
||||||
var oldPath = url.parse(oldUrl).pathname;
|
var oldPath = url.parse(oldUrl).pathname;
|
||||||
@ -125,77 +110,6 @@ function make_export_filename(space, extension) {
|
|||||||
return space.name.replace(/[^\w]/g, '') + "-" + space._id + "-" + moment().format("YYYYMMDD-HH-mm-ss") + "." + extension;
|
return space.name.replace(/[^\w]/g, '') + "-" + space._id + "-" + moment().format("YYYYMMDD-HH-mm-ss") + "." + extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
router.get('/list', function(req, res, next) {
|
|
||||||
|
|
||||||
if (req.user) {
|
|
||||||
if (req.spaceRole == "admin" || req.spaceRole == "editor") {
|
|
||||||
|
|
||||||
if (req.space.space_type == "space") {
|
|
||||||
Artifact.find({
|
|
||||||
space_id: req.space._id
|
|
||||||
}).exec(function(err, artifacts) {
|
|
||||||
async.map(artifacts, function(a, cb) {
|
|
||||||
if (a.user_id) {
|
|
||||||
User.findOne({
|
|
||||||
"_id": a.user_id
|
|
||||||
}).exec(function(err, user) {
|
|
||||||
a.user = user;
|
|
||||||
|
|
||||||
if (a.last_update_user_id) {
|
|
||||||
User.findOne({
|
|
||||||
"_id": a.last_update_user_id
|
|
||||||
}).exec(function(err, updateUser) {
|
|
||||||
a.update_user = updateUser;
|
|
||||||
cb(null, a);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cb(null, a);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
cb(null, a);
|
|
||||||
}
|
|
||||||
}, function(err, mappedArtifacts) {
|
|
||||||
|
|
||||||
req.space.artifacts = mappedArtifacts.map(function(a) {
|
|
||||||
a.description = sanitizeHtml(a.description, {
|
|
||||||
allowedTags: [],
|
|
||||||
allowedAttributes: []
|
|
||||||
});
|
|
||||||
|
|
||||||
if (a.payload_uri) {
|
|
||||||
var parsed = url.parse(a.payload_uri);
|
|
||||||
var fileName = path.basename(parsed.pathname) || "file.bin";
|
|
||||||
a.filename = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
|
||||||
});
|
|
||||||
|
|
||||||
res.render('artifact_list', {
|
|
||||||
space: req.space
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Space.getRecursiveSubspacesForSpace(req.space, (err, subspaces) => {
|
|
||||||
res.render('space_list', {
|
|
||||||
subspaces: subspaces.map((s) => {
|
|
||||||
s.ae_link = config.endpoint + '/s/' + s.edit_hash + (s.edit_slug ? ('-'+s.edit_slug) : '')
|
|
||||||
return s;
|
|
||||||
}),
|
|
||||||
space: req.space
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.sendStatus(403);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.sendStatus(403);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/pdf', function(req, res, next) {
|
router.get('/pdf', function(req, res, next) {
|
||||||
var s3_filename = make_export_filename(req.space, "pdf");
|
var s3_filename = make_export_filename(req.space, "pdf");
|
||||||
|
|
||||||
@ -329,9 +243,10 @@ router.get('/zip', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/html', function(req, res) {
|
router.get('/html', function(req, res) {
|
||||||
Artifact.find({
|
console.log("!!!!! hello ");
|
||||||
|
db.Artifact.findAll({where: {
|
||||||
space_id: req.space._id
|
space_id: req.space._id
|
||||||
}, function(err, artifacts) {
|
}}).then(function(artifacts) {
|
||||||
var space = req.space;
|
var space = req.space;
|
||||||
res.send(space_render.render_space_as_html(space, artifacts));
|
res.send(space_render.render_space_as_html(space, artifacts));
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ var config = require('config');
|
|||||||
const db = require('../../models/db');
|
const db = require('../../models/db');
|
||||||
const Sequelize = require('sequelize');
|
const Sequelize = require('sequelize');
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
const uuidv4 = require('uuid/v4');
|
||||||
|
|
||||||
var redis = require('../../helpers/redis');
|
var redis = require('../../helpers/redis');
|
||||||
var mailer = require('../../helpers/mailer');
|
var mailer = require('../../helpers/mailer');
|
||||||
@ -55,13 +56,15 @@ router.post('/', function(req, res, next) {
|
|||||||
var attrs = req.body;
|
var attrs = req.body;
|
||||||
attrs['space'] = req.space._id;
|
attrs['space'] = req.space._id;
|
||||||
attrs['state'] = "pending";
|
attrs['state'] = "pending";
|
||||||
var membership = new Membership(attrs);
|
attrs._id = uuidv4();
|
||||||
|
var membership = attrs;
|
||||||
|
|
||||||
var msg = attrs.personal_message;
|
var msg = attrs.personal_message;
|
||||||
|
|
||||||
if (membership.email_invited != req.user.email) {
|
if (membership.email_invited != req.user.email) {
|
||||||
User.findOne({
|
db.User.findOne({where:{
|
||||||
"email": membership.email_invited
|
"email": membership.email_invited
|
||||||
}, function(err, user) {
|
}}, function(user) {
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
membership.user = user;
|
membership.user = user;
|
||||||
@ -70,9 +73,7 @@ router.post('/', function(req, res, next) {
|
|||||||
membership.code = crypto.randomBytes(64).toString('hex').substring(0, 12);
|
membership.code = crypto.randomBytes(64).toString('hex').substring(0, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
membership.save(function(err) {
|
db.Membership.create(membership).then(function() {
|
||||||
if (err) res.sendStatus(400);
|
|
||||||
else {
|
|
||||||
var accept_link = config.endpoint + "/accept/" + membership._id + "?code=" + membership.code;
|
var accept_link = config.endpoint + "/accept/" + membership._id + "?code=" + membership.code;
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
@ -98,7 +99,6 @@ router.post('/', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
res.status(201).json(membership);
|
res.status(201).json(membership);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
require('../../models/db');
|
const db = require('../../models/db');
|
||||||
|
const Sequelize = require('sequelize');
|
||||||
|
const Op = Sequelize.Op;
|
||||||
|
const uuidv4 = require('uuid/v4');
|
||||||
|
|
||||||
var redis = require('../../helpers/redis');
|
var redis = require('../../helpers/redis');
|
||||||
var mailer = require('../../helpers/mailer');
|
var mailer = require('../../helpers/mailer');
|
||||||
@ -17,9 +20,7 @@ var request = require('request');
|
|||||||
var url = require("url");
|
var url = require("url");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
var qr = require('qr-image');
|
|
||||||
var glob = require('glob');
|
var glob = require('glob');
|
||||||
var gm = require('gm');
|
|
||||||
|
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var router = express.Router({mergeParams: true});
|
var router = express.Router({mergeParams: true});
|
||||||
@ -49,16 +50,18 @@ var roleMapping = {
|
|||||||
// MESSAGES
|
// MESSAGES
|
||||||
|
|
||||||
router.get('/', function(req, res, next) {
|
router.get('/', function(req, res, next) {
|
||||||
Message.find({
|
db.Message.findAll({where:{
|
||||||
space: req.space._id
|
space_id: req.space._id
|
||||||
}).populate('user', userMapping).exec(function(err, messages) {
|
}})
|
||||||
|
//.populate('user', userMapping)
|
||||||
|
.then(function(messages) {
|
||||||
res.status(200).json(messages);
|
res.status(200).json(messages);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/', function(req, res, next) {
|
router.post('/', function(req, res, next) {
|
||||||
var attrs = req.body;
|
var attrs = req.body;
|
||||||
attrs.space = req.space;
|
attrs.space_id = req.space._id;
|
||||||
|
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
attrs.user = req.user;
|
attrs.user = req.user;
|
||||||
@ -66,65 +69,24 @@ router.post('/', function(req, res, next) {
|
|||||||
attrs.user = null;
|
attrs.user = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg = new Message(attrs);
|
var msg = attrs;
|
||||||
msg.save(function(err) {
|
msg._id = uuidv4();
|
||||||
if (err) res.status(400).json(erra);
|
|
||||||
else {
|
db.Message.create(msg, function() {
|
||||||
if (msg.message.length <= 1) return;
|
if (msg.message.length <= 1) return;
|
||||||
|
// TODO reimplement notifications
|
||||||
Membership
|
|
||||||
.find({
|
|
||||||
space: req.space,
|
|
||||||
user: {
|
|
||||||
"$exists": true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.populate('user')
|
|
||||||
.exec(function(err, memberships) {
|
|
||||||
var users = memberships.map(function(m) {
|
|
||||||
return m.user;
|
|
||||||
});
|
|
||||||
users.forEach((user) => {
|
|
||||||
if (user.preferences.email_notifications) {
|
|
||||||
redis.isOnlineInSpace(user, req.space, function(err, online) {
|
|
||||||
if (!online) {
|
|
||||||
var nickname = msg.editor_name;
|
|
||||||
if (req.user) {
|
|
||||||
nickname = req.user.nickname;
|
|
||||||
}
|
|
||||||
mailer.sendMail(
|
|
||||||
user.email,
|
|
||||||
req.i18n.__("space_message_subject", req.space.name),
|
|
||||||
req.i18n.__("space_message_body", nickname, req.space.name), {
|
|
||||||
message: msg.message,
|
|
||||||
action: {
|
|
||||||
link: config.endpoint + "/spaces/" + req.space._id.toString(),
|
|
||||||
name: req.i18n.__("open")
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("not sending message to user: is online.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log("not sending message to user: is disabled notifications.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
res.distributeCreate("Message", msg);
|
res.distributeCreate("Message", msg);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.delete('/:message_id', function(req, res, next) {
|
router.delete('/:message_id', function(req, res, next) {
|
||||||
Message.findOne({
|
db.Message.findOne({where:{
|
||||||
"_id": req.params.message_id
|
"_id": req.params.message_id
|
||||||
}, function(err, msg) {
|
}}, function(msg) {
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
} else {
|
} else {
|
||||||
msg.remove(function(err) {
|
msg.destroy(function(err) {
|
||||||
if (err) res.status(400).json(err);
|
if (err) res.status(400).json(err);
|
||||||
else {
|
else {
|
||||||
if (msg) {
|
if (msg) {
|
||||||
|
@ -114,32 +114,33 @@ router.get('/', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
} else if (req.query.search) {
|
} else if (req.query.search) {
|
||||||
|
|
||||||
Membership.find({
|
db.Membership.findAll({where:{
|
||||||
user: req.user._id
|
user: req.user._id
|
||||||
}, function(err, memberships) {
|
}}).then(memberships => {
|
||||||
|
|
||||||
var validMemberships = memberships.filter(function(m) {
|
var validMemberships = memberships.filter(function(m) {
|
||||||
if (!m.space || (m.space == "undefined"))
|
if (!m.space_id || (m.space_id == "undefined"))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return mongoose.Types.ObjectId.isValid(m.space.toString());
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
var spaceIds = validMemberships.map(function(m) {
|
var spaceIds = validMemberships.map(function(m) {
|
||||||
return new mongoose.Types.ObjectId(m.space);
|
return m.space_id;
|
||||||
});
|
});
|
||||||
|
|
||||||
var q = {
|
// TODO FIXME port
|
||||||
"$or": [{"creator": req.user._id},
|
var q = { where: {
|
||||||
|
"$or": [{"creator_id": req.user._id},
|
||||||
{"_id": {"$in": spaceIds}},
|
{"_id": {"$in": spaceIds}},
|
||||||
{"parent_space_id": {"$in": spaceIds}}],
|
{"parent_space_id": {"$in": spaceIds}}],
|
||||||
name: new RegExp(req.query.search, "i")
|
name: new RegExp(req.query.search, "i")}
|
||||||
};
|
};
|
||||||
|
|
||||||
Space
|
db.Space
|
||||||
.find(q)
|
.findAll(q)
|
||||||
.populate('creator', userMapping)
|
//.populate('creator', userMapping)
|
||||||
.exec(function(err, spaces) {
|
.then(function(spaces) {
|
||||||
if (err) console.error(err);
|
if (err) console.error(err);
|
||||||
var updatedSpaces = spaces.map(function(s) {
|
var updatedSpaces = spaces.map(function(s) {
|
||||||
var spaceObj = s.toObject();
|
var spaceObj = s.toObject();
|
||||||
@ -151,15 +152,14 @@ router.get('/', function(req, res, next) {
|
|||||||
|
|
||||||
} else if (req.query.parent_space_id && req.query.parent_space_id != req.user.home_folder_id) {
|
} else if (req.query.parent_space_id && req.query.parent_space_id != req.user.home_folder_id) {
|
||||||
|
|
||||||
Space
|
db.Space
|
||||||
.findOne({
|
.findOne({where: {
|
||||||
_id: req.query.parent_space_id
|
_id: req.query.parent_space_id
|
||||||
})
|
}})
|
||||||
.populate('creator', userMapping)
|
//.populate('creator', userMapping)
|
||||||
.exec(function(err, space) {
|
.then(function(space) {
|
||||||
if (space) {
|
if (space) {
|
||||||
db.getUserRoleInSpace(space, req.user, function(role) {
|
db.getUserRoleInSpace(space, req.user, function(role) {
|
||||||
|
|
||||||
if (role == "none") {
|
if (role == "none") {
|
||||||
if(space.access_mode == "public") {
|
if(space.access_mode == "public") {
|
||||||
role = "viewer";
|
role = "viewer";
|
||||||
@ -167,12 +167,12 @@ router.get('/', function(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (role != "none") {
|
if (role != "none") {
|
||||||
Space
|
db.Space
|
||||||
.find({
|
.findAll({where:{
|
||||||
parent_space_id: req.query.parent_space_id
|
parent_space_id: req.query.parent_space_id
|
||||||
})
|
}})
|
||||||
.populate('creator', userMapping)
|
//.populate('creator', userMapping)
|
||||||
.exec(function(err, spaces) {
|
.then(function(spaces) {
|
||||||
res.status(200).json(spaces);
|
res.status(200).json(spaces);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -185,9 +185,6 @@ router.get('/', function(req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
console.log("!!!!!!!!!! spaces lookup");
|
|
||||||
|
|
||||||
db.Membership.findAll({ where: {
|
db.Membership.findAll({ where: {
|
||||||
user_id: req.user._id
|
user_id: req.user._id
|
||||||
}}).then(memberships => {
|
}}).then(memberships => {
|
||||||
@ -243,9 +240,6 @@ router.post('/', function(req, res, next) {
|
|||||||
|
|
||||||
db.Space.create(attrs).then(createdSpace => {
|
db.Space.create(attrs).then(createdSpace => {
|
||||||
//if (err) res.sendStatus(400);
|
//if (err) res.sendStatus(400);
|
||||||
|
|
||||||
console.log("!!!!!!!!!! createdSpace:",createdSpace);
|
|
||||||
|
|
||||||
var membership = {
|
var membership = {
|
||||||
_id: uuidv4(),
|
_id: uuidv4(),
|
||||||
user_id: req.user._id,
|
user_id: req.user._id,
|
||||||
@ -342,7 +336,7 @@ router.put('/:id', function(req, res) {
|
|||||||
router.post('/:id/background', function(req, res, next) {
|
router.post('/:id/background', function(req, res, next) {
|
||||||
var space = req.space;
|
var space = req.space;
|
||||||
var newDate = new Date();
|
var newDate = new Date();
|
||||||
var fileName = (req.query.filename || "upload.bin").replace(/[^a-zA-Z0-9\.]/g, '');
|
var fileName = (req.query.filename || "upload.jpg").replace(/[^a-zA-Z0-9\.]/g, '');
|
||||||
var localFilePath = "/tmp/" + fileName;
|
var localFilePath = "/tmp/" + fileName;
|
||||||
var writeStream = fs.createWriteStream(localFilePath);
|
var writeStream = fs.createWriteStream(localFilePath);
|
||||||
var stream = req.pipe(writeStream);
|
var stream = req.pipe(writeStream);
|
||||||
@ -351,29 +345,18 @@ router.post('/:id/background', function(req, res, next) {
|
|||||||
uploader.uploadFile("s" + req.space._id + "/bg_" + newDate.getTime() + "_" + fileName, "image/jpeg", localFilePath, function(err, backgroundUrl) {
|
uploader.uploadFile("s" + req.space._id + "/bg_" + newDate.getTime() + "_" + fileName, "image/jpeg", localFilePath, function(err, backgroundUrl) {
|
||||||
if (err) res.status(400).json(err);
|
if (err) res.status(400).json(err);
|
||||||
else {
|
else {
|
||||||
var adv = space.advanced;
|
if (space.background_uri) {
|
||||||
|
var oldPath = url.parse(req.space.background_uri).pathname;
|
||||||
if (adv.background_uri) {
|
|
||||||
var oldPath = url.parse(req.space.thumbnail_url).pathname;
|
|
||||||
uploader.removeFile(oldPath, function(err) {
|
uploader.removeFile(oldPath, function(err) {
|
||||||
console.error("removed old bg error:", err);
|
console.error("removed old bg error:", err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
adv.background_uri = backgroundUrl;
|
db.Space.update({
|
||||||
|
background_uri: backgroundUrl
|
||||||
Space.findOneAndUpdate({
|
|
||||||
"_id": space._id
|
|
||||||
}, {
|
}, {
|
||||||
"$set": {
|
where: { "_id": space._id }
|
||||||
advanced: adv
|
}, function(rows) {
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"new": true
|
|
||||||
}, function(err, space) {
|
|
||||||
if (err) {
|
|
||||||
res.sendStatus(400);
|
|
||||||
} else {
|
|
||||||
fs.unlink(localFilePath, function(err) {
|
fs.unlink(localFilePath, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -382,7 +365,6 @@ router.post('/:id/background', function(req, res, next) {
|
|||||||
res.status(200).json(space);
|
res.status(200).json(space);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<div id="space" class="section board active mouse-{{mouse_state}} tool-{{active_tool}}">
|
<div id="space" class="section board active mouse-{{mouse_state}} tool-{{active_tool}}">
|
||||||
|
|
||||||
<div class="space-bounds" style="width:{{active_space.advanced.width*bounds_zoom}}px;height:{{active_space.advanced.height*bounds_zoom}}px;"></div>
|
<div class="space-bounds" style="width:{{active_space.width*bounds_zoom}}px;height:{{active_space.height*bounds_zoom}}px;"></div>
|
||||||
|
|
||||||
<div class="wrapper"
|
<div class="wrapper"
|
||||||
style="transform:scale({{viewport_zoom}});transform-origin:0 0;width:{{active_space.advanced.width}}px;height:{{active_space.advanced.height}}px;background-image:url('{{active_space.advanced.background_uri}}');background-color:{{active_space.advanced.background_color}};margin-left:{{bounds_margin_horiz}}px;margin-top:{{bounds_margin_vert}}px" >
|
style="transform:scale({{viewport_zoom}});transform-origin:0 0;width:{{active_space.width}}px;height:{{active_space.height}}px;background-image:url('{{active_space.background_uri}}');background-color:{{active_space.background_color}};margin-left:{{bounds_margin_horiz}}px;margin-top:{{bounds_margin_vert}}px" >
|
||||||
|
|
||||||
<div v-repeat="a : active_space_artifacts"
|
<div v-repeat="a : active_space_artifacts"
|
||||||
v-class="text-editing:(editing_artifact_id==a._id && (a.view.major_type=='text' || a.view.major_type=='shape'))"
|
v-class="text-editing:(editing_artifact_id==a._id && (a.view.major_type=='text' || a.view.major_type=='shape'))"
|
||||||
@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tl-controls">
|
<div class="tl-controls">
|
||||||
<div class="btn btn-md btn-toggle btn-round" v-class="alt:a.player_view.state=='playing'" v-show="a.board.w>=200 || a.player_view.state!='playing'">
|
<div class="btn btn-md btn-toggle btn-round" v-class="alt:a.player_view.state=='playing'" v-show="a.w>=200 || a.player_view.state!='playing'">
|
||||||
<span class="btn-option play">
|
<span class="btn-option play">
|
||||||
<span class="icon icon-controls-play"></span>
|
<span class="icon icon-controls-play"></span>
|
||||||
</span>
|
</span>
|
||||||
@ -95,8 +95,8 @@
|
|||||||
<span class="icon icon-controls-stop"></span>
|
<span class="icon icon-controls-stop"></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="tl-title" v-show="a.board.w>=250 && a.board.h>=150">{{a.view.filename}}</span>
|
<span class="tl-title" v-show="a.w>=250 && a.h>=150">{{a.view.filename}}</span>
|
||||||
<span class="tl-times" class="btn-group" v-show="a.board.w>=400 && a.board.h>=150">
|
<span class="tl-times" class="btn-group" v-show="a.w>=400 && a.h>=150">
|
||||||
<span class="btn btn-md btn-transparent no-p set-inpoint">{{a.player_view.current_time_string}} /</span>
|
<span class="btn btn-md btn-transparent no-p set-inpoint">{{a.player_view.current_time_string}} /</span>
|
||||||
<span class="btn btn-md btn-transparent no-p set-outpoint">{{a.player_view.total_time_string}}</span>
|
<span class="btn btn-md btn-transparent no-p set-outpoint">{{a.player_view.total_time_string}}</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div id="pick-mobile" v-if="active_space" class="dialog-section" v-show="opened_dialog=='mobile'">
|
<div id="pick-mobile" v-if="active_space" class="dialog-section" v-show="opened_dialog=='mobile'">
|
||||||
<h4 class="dialog-title">Mobile Upload</h4>
|
<h4 class="dialog-title">Mobile Upload</h4>
|
||||||
|
|
||||||
<img v-if="active_space.edit_hash" v-bind:src="'/api/helper/qrcode/'+ active_space._id" />
|
<!--img v-if="active_space.edit_hash" v-bind:src="'/api/helper/qrcode/'+ active_space._id"-->
|
||||||
|
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
Install the Spacedeck App on your phone and scan this QR code to upload photos, sound, video or text.
|
Install the Spacedeck App on your phone and scan this QR code to upload photos, sound, video or text.
|
||||||
|
Loading…
Reference in New Issue
Block a user