mirror of
https://github.com/spacedeck/spacedeck-open.git
synced 2025-12-15 17:37:30 +01:00
Port Backend to SQLite/Sequelize (removes MongoDB), Support Electron (#14)
* The MongoDB/Mongoose data storage is removed in favor of Sequelize. This abstracts over SQLite or RDBMs like PostgreSQL and MSSQL. The default is SQLite, which significantly simplifies deployments in end-user environments. * As Spacedeck now has no more mandatory server dependencies, we can wrap it in Electron and ship it as a desktop application. * Removes docker-compose.yml * First version of import UI
This commit is contained in:
@@ -1,56 +1,40 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var async = require('async');
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
var userMapping = { '_id': 1, 'nickname': 1, 'email': 1};
|
||||
var spaceMapping = { '_id': 1, name: 1};
|
||||
const db = require('../../models/db');
|
||||
const Sequelize = require('sequelize');
|
||||
const Op = Sequelize.Op;
|
||||
const uuidv4 = require('uuid/v4');
|
||||
|
||||
router.get('/:membership_id/accept', function(req, res, next) {
|
||||
if (req.user) {
|
||||
Membership.findOne({
|
||||
db.Membership.findOne({where:{
|
||||
_id: req.params.membership_id,
|
||||
state: "pending",
|
||||
code: req.query.code,
|
||||
user: { "$exists": false }
|
||||
}).populate('space').exec((err,mem) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
if (mem) {
|
||||
if(!mem.user) {
|
||||
mem.code = null;
|
||||
mem.state = "active";
|
||||
mem.user = req.user;
|
||||
|
||||
mem.save(function(err){
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
console.log(mem);
|
||||
res.status(200).json(mem);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({"error": "already_used"});
|
||||
}
|
||||
code: req.query.code
|
||||
}, include: ['space']}).then((mem) => {
|
||||
if (mem) {
|
||||
if (!mem.user) {
|
||||
mem.state = "active";
|
||||
mem.user_id = req.user._id;
|
||||
|
||||
mem.save().then(function() {
|
||||
res.status(200).json(mem);
|
||||
});
|
||||
} else {
|
||||
res.status(404).json({"error": "not found"});
|
||||
res.status(200).json(mem);
|
||||
}
|
||||
} else {
|
||||
res.status(404).json({"error": "not found"});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
const db = require('../../models/db');
|
||||
|
||||
var bcrypt = require('bcryptjs');
|
||||
var crypo = require('crypto');
|
||||
var crypto = require('crypto');
|
||||
var URL = require('url').URL;
|
||||
|
||||
var express = require('express');
|
||||
@@ -12,68 +12,64 @@ var router = express.Router();
|
||||
|
||||
router.post('/', function(req, res) {
|
||||
var data = req.body;
|
||||
if (data.email && data.password) {
|
||||
var email = req.body.email.toLowerCase();
|
||||
var password = req.body["password"];
|
||||
|
||||
User.find({email: email, account_type: "email"}, (function (err, users) {
|
||||
if (err) {
|
||||
res.status(400).json({"error":"session.users"});
|
||||
} else {
|
||||
|
||||
if (users.length == 1) {
|
||||
var user = users[0];
|
||||
|
||||
if (bcrypt.compareSync(password, user.password_hash)) {
|
||||
crypo.randomBytes(48, function(ex, buf) {
|
||||
var token = buf.toString('hex');
|
||||
|
||||
var session = {
|
||||
token: token,
|
||||
ip: req.ip,
|
||||
device: "web",
|
||||
created_at: new Date()
|
||||
};
|
||||
|
||||
if (!user.sessions)
|
||||
user.sessions = [];
|
||||
|
||||
user.sessions.push(session);
|
||||
|
||||
user.save(function(err, result) {
|
||||
if (err) console.error("Error saving user:",err);
|
||||
|
||||
var domain = (process.env.NODE_ENV == "production") ? new URL(config.get('endpoint')).hostname : "localhost";
|
||||
|
||||
res.cookie('sdsession', token, { domain: domain, httpOnly: true });
|
||||
res.status(201).json(session);
|
||||
});
|
||||
});
|
||||
}else{
|
||||
res.sendStatus(403);
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
if (!data.email || !data.password) {
|
||||
res.status(400).json({});
|
||||
return;
|
||||
}
|
||||
|
||||
var email = req.body.email.toLowerCase();
|
||||
var password = req.body["password"];
|
||||
|
||||
db.User.findOne({where: {email: email}})
|
||||
.error(err => {
|
||||
res.sendStatus(404);
|
||||
//res.status(400).json({"error":"session.users"});
|
||||
})
|
||||
.then(user => {
|
||||
console.log("!!! user: ",user.password_hash);
|
||||
|
||||
if (bcrypt.compareSync(password, user.password_hash)) {
|
||||
crypto.randomBytes(48, function(ex, buf) {
|
||||
var token = buf.toString('hex');
|
||||
console.log("!!! token: ",token);
|
||||
|
||||
var session = {
|
||||
user_id: user._id,
|
||||
token: token,
|
||||
ip: req.ip,
|
||||
device: "web",
|
||||
created_at: new Date()
|
||||
};
|
||||
|
||||
db.Session.create(session)
|
||||
.error(err => {
|
||||
console.error("Error creating Session:",err);
|
||||
res.sendStatus(500);
|
||||
})
|
||||
.then(() => {
|
||||
var domain = (process.env.NODE_ENV == "production") ? new URL(config.get('endpoint')).hostname : "localhost";
|
||||
res.cookie('sdsession', token, { domain: domain, httpOnly: true });
|
||||
res.status(201).json(session);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/current', function(req, res, next) {
|
||||
if (req.user) {
|
||||
var user = req.user;
|
||||
/*var user = req.user;
|
||||
var newSessions = user.sessions.filter( function(session){
|
||||
return session.token != req.token;
|
||||
});
|
||||
user.sessions = newSessions;
|
||||
user.save(function(err, result) {
|
||||
});*/
|
||||
//user.sessions = newSessions;
|
||||
//user.save(function(err, result) {
|
||||
var domain = new URL(config.get('endpoint')).hostname;
|
||||
res.clearCookie('sdsession', { domain: domain });
|
||||
res.sendStatus(204);
|
||||
});
|
||||
//});
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
|
||||
const os = require('os');
|
||||
const db = require('../../models/db');
|
||||
const Sequelize = require('sequelize');
|
||||
const Op = Sequelize.Op;
|
||||
const uuidv4 = require('uuid/v4');
|
||||
|
||||
var payloadConverter = require('../../helpers/artifact_converter');
|
||||
var redis = require('../../helpers/redis');
|
||||
@@ -9,13 +14,11 @@ var redis = require('../../helpers/redis');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
|
||||
@@ -46,15 +49,24 @@ var roleMapping = {
|
||||
// ARTIFACTS
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
Artifact.find({
|
||||
db.Artifact.findAll({where: {
|
||||
space_id: req.space._id
|
||||
}).exec((err, artifacts) => {
|
||||
}}).then(artifacts => {
|
||||
async.map(artifacts, (a, cb) => {
|
||||
a = a.toObject();
|
||||
//a = a.toObject(); TODO
|
||||
|
||||
if (a.control_points) {
|
||||
a.control_points = JSON.parse(a.control_points);
|
||||
}
|
||||
if (a.payload_alternatives) {
|
||||
a.payload_alternatives = JSON.parse(a.payload_alternatives);
|
||||
}
|
||||
|
||||
if (a.user_id) {
|
||||
User.findOne({
|
||||
// FIXME JOIN
|
||||
/*User.findOne({where: {
|
||||
"_id": a.user_id
|
||||
}).select({
|
||||
}}).select({
|
||||
"_id": 1,
|
||||
"nickname": 1,
|
||||
"email": 1
|
||||
@@ -63,7 +75,8 @@ router.get('/', (req, res) => {
|
||||
a['user'] = user.toObject();
|
||||
}
|
||||
cb(err, a);
|
||||
});
|
||||
});*/
|
||||
cb(null, a);
|
||||
} else {
|
||||
cb(null, a);
|
||||
}
|
||||
@@ -81,9 +94,8 @@ router.post('/', function(req, res, next) {
|
||||
|
||||
attrs['space_id'] = req.space._id;
|
||||
|
||||
var artifact = new Artifact(attrs);
|
||||
|
||||
artifact.created_from_ip = req['real_ip'];
|
||||
var artifact = attrs;
|
||||
artifact._id = uuidv4();
|
||||
|
||||
if (req.user) {
|
||||
artifact.user_id = req.user._id;
|
||||
@@ -92,23 +104,18 @@ router.post('/', function(req, res, next) {
|
||||
artifact.last_update_editor_name = req.editor_name;
|
||||
}
|
||||
|
||||
if (req.spaceRole == "editor" || req.spaceRole == "admin") {
|
||||
artifact.save(function(err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
Space.update({
|
||||
_id: req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
updated_at: new Date()
|
||||
}
|
||||
});
|
||||
res.distributeCreate("Artifact", artifact);
|
||||
}
|
||||
db.packArtifact(artifact);
|
||||
|
||||
if (req.spaceRole == "editor" || req.spaceRole == "admin") {
|
||||
db.Artifact.create(artifact).then(() => {
|
||||
//if (err) res.status(400).json(err);
|
||||
db.unpackArtifact(artifact);
|
||||
db.Space.update({ updated_at: new Date() }, {where: {_id: req.space._id}});
|
||||
res.distributeCreate("Artifact", artifact);
|
||||
});
|
||||
} else {
|
||||
res.status(401).json({
|
||||
"error": "no access"
|
||||
"error": "Access denied"
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -118,7 +125,8 @@ router.post('/:artifact_id/payload', function(req, res, next) {
|
||||
var a = req.artifact;
|
||||
|
||||
var fileName = (req.query.filename || "upload.bin").replace(/[^a-zA-Z0-9_\-\.]/g, '');
|
||||
var localFilePath = "/tmp/" + fileName;
|
||||
|
||||
var localFilePath = os.tmpdir() + "/" + fileName;
|
||||
var writeStream = fs.createWriteStream(localFilePath);
|
||||
var stream = req.pipe(writeStream);
|
||||
|
||||
@@ -132,13 +140,7 @@ router.post('/:artifact_id/payload', function(req, res, next) {
|
||||
payloadConverter.convert(a, fileName, localFilePath, function(error, artifact) {
|
||||
if (error) res.status(400).json(error);
|
||||
else {
|
||||
Space.update({
|
||||
_id: req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
updated_at: new Date()
|
||||
}
|
||||
});
|
||||
db.Space.update({ updated_at: new Date() }, {where: {_id: req.space._id}});
|
||||
res.distributeUpdate("Artifact", artifact);
|
||||
}
|
||||
}, progress_callback);
|
||||
@@ -161,42 +163,23 @@ router.put('/:artifact_id', function(req, res, next) {
|
||||
} else {
|
||||
newAttr.last_update_editor_name = req.editor_name;
|
||||
}
|
||||
|
||||
db.packArtifact(newAttr);
|
||||
|
||||
Artifact.findOneAndUpdate({
|
||||
db.Artifact.update(newAttr, { where: {
|
||||
"_id": a._id
|
||||
}, {
|
||||
"$set": newAttr
|
||||
}, {
|
||||
"new": true
|
||||
}, function(err, artifact) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
Space.update({
|
||||
_id: req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
updated_at: new Date()
|
||||
}
|
||||
});
|
||||
res.distributeUpdate("Artifact", artifact);
|
||||
}
|
||||
}}).then(rows => {
|
||||
db.unpackArtifact(newAttr);
|
||||
db.Space.update({ updated_at: new Date() }, {where: {_id: req.space._id} });
|
||||
res.distributeUpdate("Artifact", newAttr);
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/:artifact_id', function(req, res, next) {
|
||||
var artifact = req.artifact;
|
||||
artifact.remove(function(err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
Space.update({
|
||||
_id: req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
updated_at: new Date()
|
||||
}
|
||||
});
|
||||
res.distributeDelete("Artifact", artifact);
|
||||
}
|
||||
db.Artifact.destroy({where: { "_id": artifact._id}}).then(() => {
|
||||
db.Space.update({ updated_at: new Date() }, {where: {_id: req.space._id} });
|
||||
res.distributeDelete("Artifact", artifact);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
require('../../models/db');
|
||||
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
|
||||
@@ -40,6 +38,12 @@ var roleMapping = {
|
||||
};
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
|
||||
res.status(200).json([]);
|
||||
return;
|
||||
|
||||
// FIXME TODO
|
||||
|
||||
var showActionForSpaces = function(err, spaceIds) {
|
||||
var userMapping = {
|
||||
'_id': 1,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
"use strict";
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
const db = require('../../models/db');
|
||||
|
||||
var redis = require('../../helpers/redis');
|
||||
var mailer = require('../../helpers/mailer');
|
||||
var uploader = require('../../helpers/uploader');
|
||||
var space_render = require('../../helpers/space-render');
|
||||
@@ -12,13 +11,11 @@ var async = require('async');
|
||||
var moment = require('moment');
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
var sanitizeHtml = require('sanitize-html');
|
||||
@@ -49,26 +46,18 @@ var roleMapping = {
|
||||
|
||||
router.get('/png', function(req, res, next) {
|
||||
var triggered = new Date();
|
||||
|
||||
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) {
|
||||
|
||||
Space.update({
|
||||
"_id": req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
thumbnail_updated_at: triggered
|
||||
}
|
||||
}, function(a, b, c) {});
|
||||
|
||||
db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }});
|
||||
|
||||
phantom.takeScreenshot(req.space, "png",
|
||||
function(local_path) {
|
||||
var localResizedFilePath = local_path + ".thumb.jpg";
|
||||
gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
|
||||
|
||||
if (err) {
|
||||
console.error("screenshot resize error: ", err);
|
||||
console.error("[space screenshot] resize error: ", err);
|
||||
res.status(500).send("Error taking screenshot.");
|
||||
return;
|
||||
}
|
||||
@@ -76,22 +65,15 @@ router.get('/png', function(req, res, next) {
|
||||
uploader.uploadFile(s3_filename, "image/jpeg", localResizedFilePath, function(err, thumbnailUrl) {
|
||||
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
|
||||
var oldUrl = req.space.thumbnail_url;
|
||||
|
||||
Space.update({
|
||||
"_id": req.space._id
|
||||
}, {
|
||||
"$set": {
|
||||
thumbnail_url: thumbnailUrl
|
||||
}
|
||||
}, function(a, b, c) {
|
||||
db.Space.update({ thumbnail_url: thumbnailUrl }, {where : {"_id": req.space._id }}).then(() => {
|
||||
res.redirect(thumbnailUrl);
|
||||
|
||||
try {
|
||||
if (oldUrl) {
|
||||
var oldPath = url.parse(oldUrl).pathname;
|
||||
@@ -125,77 +107,6 @@ function make_export_filename(space, 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) {
|
||||
var s3_filename = make_export_filename(req.space, "pdf");
|
||||
|
||||
@@ -329,36 +240,14 @@ router.get('/zip', function(req, res, next) {
|
||||
});
|
||||
|
||||
router.get('/html', function(req, res) {
|
||||
Artifact.find({
|
||||
console.log("!!!!! hello ");
|
||||
db.Artifact.findAll({where: {
|
||||
space_id: req.space._id
|
||||
}, function(err, artifacts) {
|
||||
}}).then(function(artifacts) {
|
||||
var space = req.space;
|
||||
res.send(space_render.render_space_as_html(space, artifacts));
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/path', (req, res) => {
|
||||
// build up a breadcrumb trail (path)
|
||||
var path = [];
|
||||
var buildPath = (space) => {
|
||||
if (space.parent_space_id) {
|
||||
Space.findOne({
|
||||
"_id": space.parent_space_id
|
||||
}, (err, parentSpace) => {
|
||||
if (space._id == parentSpace._id) {
|
||||
console.log("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);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
||||
@@ -1,57 +1,31 @@
|
||||
"use strict";
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
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 async = require('async');
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
var crypto = require('crypto');
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router({mergeParams: true});
|
||||
|
||||
// JSON MAPPINGS
|
||||
var userMapping = {
|
||||
_id: 1,
|
||||
nickname: 1,
|
||||
email: 1,
|
||||
avatar_thumb_uri: 1
|
||||
};
|
||||
|
||||
var spaceMapping = {
|
||||
_id: 1,
|
||||
name: 1,
|
||||
thumbnail_url: 1
|
||||
};
|
||||
|
||||
var roleMapping = {
|
||||
"none": 0,
|
||||
"viewer": 1,
|
||||
"editor": 2,
|
||||
"admin": 3
|
||||
}
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
Membership
|
||||
.find({
|
||||
space: req.space._id
|
||||
})
|
||||
.populate("user")
|
||||
.exec(function(err, memberships) {
|
||||
db.Membership
|
||||
.findAll({where: {
|
||||
space_id: req.space._id
|
||||
}, include: ['user']})
|
||||
.then(memberships => {
|
||||
res.status(200).json(memberships);
|
||||
});
|
||||
});
|
||||
@@ -59,52 +33,51 @@ router.get('/', function(req, res, next) {
|
||||
router.post('/', function(req, res, next) {
|
||||
if (req.spaceRole == "admin") {
|
||||
var attrs = req.body;
|
||||
attrs['space'] = req.space._id;
|
||||
attrs['state'] = "pending";
|
||||
var membership = new Membership(attrs);
|
||||
attrs.space_id = req.space._id;
|
||||
attrs.state = "pending";
|
||||
attrs._id = uuidv4();
|
||||
var membership = attrs;
|
||||
|
||||
var msg = attrs.personal_message;
|
||||
|
||||
if (membership.email_invited != req.user.email) {
|
||||
User.findOne({
|
||||
db.User.findOne({where:{
|
||||
"email": membership.email_invited
|
||||
}, function(err, user) {
|
||||
}}).then(function(user) {
|
||||
|
||||
if (user) {
|
||||
membership.user = user;
|
||||
membership.user_id = user._id;
|
||||
membership.state = "active";
|
||||
} else {
|
||||
membership.code = crypto.randomBytes(64).toString('hex').substring(0, 12);
|
||||
}
|
||||
|
||||
membership.save(function(err) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
var accept_link = config.endpoint + "/accept/" + membership._id + "?code=" + membership.code;
|
||||
db.Membership.create(membership).then(function() {
|
||||
var accept_link = config.endpoint + "/accept/" + membership._id + "?code=" + membership.code;
|
||||
|
||||
if (user) {
|
||||
accept_link = config.endpoint + "/" + req.space.space_type + "s/" + req.space._id;
|
||||
}
|
||||
|
||||
var openText = req.i18n.__("space_invite_membership_action");
|
||||
if (user) {
|
||||
req.i18n.__("open");
|
||||
}
|
||||
|
||||
const name = req.user.nickname || req.user.email
|
||||
const subject = (req.space.space_type == "space") ? req.i18n.__("space_invite_membership_subject", name, req.space.name) : req.i18n.__("folder_invite_membership_subject", req.user.nickname, req.space.name)
|
||||
const body = (req.space.space_type == "space") ? req.i18n.__("space_invite_membership_body", name, req.space.name) : req.i18n.__("folder_invite_membership_body", req.user.nickname, req.space.name)
|
||||
|
||||
mailer.sendMail(
|
||||
membership.email_invited, subject, body, {
|
||||
messsage: msg,
|
||||
action: {
|
||||
link: accept_link,
|
||||
name: openText
|
||||
}
|
||||
});
|
||||
|
||||
res.status(201).json(membership);
|
||||
if (user) {
|
||||
accept_link = config.endpoint + "/" + req.space.space_type + "s/" + req.space._id;
|
||||
}
|
||||
|
||||
var openText = req.i18n.__("space_invite_membership_action");
|
||||
if (user) {
|
||||
req.i18n.__("open");
|
||||
}
|
||||
|
||||
const name = req.user.nickname || req.user.email
|
||||
const subject = (req.space.space_type == "space") ? req.i18n.__("space_invite_membership_subject", name, req.space.name) : req.i18n.__("folder_invite_membership_subject", req.user.nickname, req.space.name)
|
||||
const body = (req.space.space_type == "space") ? req.i18n.__("space_invite_membership_body", name, req.space.name) : req.i18n.__("folder_invite_membership_body", req.user.nickname, req.space.name)
|
||||
|
||||
mailer.sendMail(
|
||||
membership.email_invited, subject, body, {
|
||||
messsage: msg,
|
||||
action: {
|
||||
link: accept_link,
|
||||
name: openText
|
||||
}
|
||||
});
|
||||
|
||||
res.status(201).json(membership);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -125,21 +98,15 @@ router.post('/', function(req, res, next) {
|
||||
router.put('/:membership_id', function(req, res, next) {
|
||||
if (req.user) {
|
||||
if (req.spaceRole == "admin") {
|
||||
Membership.findOne({
|
||||
db.Membership.findOne({ where: {
|
||||
_id: req.params.membership_id
|
||||
}, function(err, mem) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
if (mem) {
|
||||
var attrs = req.body;
|
||||
mem.role = attrs.role;
|
||||
mem.save(function(err) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
res.status(201).json(mem);
|
||||
}
|
||||
});
|
||||
}
|
||||
}}).then(function(mem) {
|
||||
if (mem) {
|
||||
var attrs = req.body;
|
||||
mem.role = attrs.role;
|
||||
mem.save(function() {
|
||||
res.status(201).json(mem);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -152,20 +119,12 @@ router.put('/:membership_id', function(req, res, next) {
|
||||
|
||||
router.delete('/:membership_id', function(req, res, next) {
|
||||
if (req.user) {
|
||||
Membership.findOne({
|
||||
db.Membership.findOne({ where: {
|
||||
_id: req.params.membership_id
|
||||
}, function(err, mem) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
mem.remove(function(err) {
|
||||
if (err) {
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
// FIXME might need to delete the user?
|
||||
res.sendStatus(204);
|
||||
}
|
||||
});
|
||||
}
|
||||
}}).then(function(mem) {
|
||||
mem.destroy().then(function() {
|
||||
res.sendStatus(204);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"use strict";
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
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');
|
||||
@@ -11,15 +14,12 @@ var phantom = require('../../helpers/phantom');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router({mergeParams: true});
|
||||
@@ -49,90 +49,44 @@ var roleMapping = {
|
||||
// MESSAGES
|
||||
|
||||
router.get('/', function(req, res, next) {
|
||||
Message.find({
|
||||
space: req.space._id
|
||||
}).populate('user', userMapping).exec(function(err, messages) {
|
||||
res.status(200).json(messages);
|
||||
});
|
||||
db.Message.findAll({where:{
|
||||
space_id: req.space._id
|
||||
}, include: ['user']})
|
||||
.then(function(messages) {
|
||||
res.status(200).json(messages);
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/', function(req, res, next) {
|
||||
var attrs = req.body;
|
||||
attrs.space = req.space;
|
||||
attrs.space_id = req.space._id;
|
||||
|
||||
if (req.user) {
|
||||
attrs.user = req.user;
|
||||
attrs.user_id = req.user._id;
|
||||
} else {
|
||||
attrs.user = null;
|
||||
}
|
||||
|
||||
var msg = new Message(attrs);
|
||||
msg.save(function(err) {
|
||||
if (err) res.status(400).json(erra);
|
||||
else {
|
||||
if (msg.message.length <= 1) return;
|
||||
var msg = attrs;
|
||||
msg._id = uuidv4();
|
||||
|
||||
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);
|
||||
}
|
||||
db.Message.create(msg).then(function() {
|
||||
if (msg.message.length <= 1) return;
|
||||
// TODO reimplement notifications
|
||||
res.distributeCreate("Message", msg);
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/:message_id', function(req, res, next) {
|
||||
Message.findOne({
|
||||
db.Message.findOne({where:{
|
||||
"_id": req.params.message_id
|
||||
}, function(err, msg) {
|
||||
}}).then(function(msg) {
|
||||
if (!msg) {
|
||||
res.sendStatus(404);
|
||||
} else {
|
||||
msg.remove(function(err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
if (msg) {
|
||||
res.distributeDelete("Message", msg);
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
}
|
||||
msg.destroy().then(function() {
|
||||
res.distributeDelete("Message", msg);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"use strict";
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
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');
|
||||
@@ -14,13 +17,10 @@ var slug = require('slug');
|
||||
var fs = require('fs');
|
||||
var async = require('async');
|
||||
var _ = require("underscore");
|
||||
var mongoose = require("mongoose");
|
||||
var archiver = require('archiver');
|
||||
var request = require('request');
|
||||
var url = require("url");
|
||||
var path = require("path");
|
||||
var crypto = require('crypto');
|
||||
var qr = require('qr-image');
|
||||
var glob = require('glob');
|
||||
var gm = require('gm');
|
||||
const exec = require('child_process');
|
||||
@@ -48,15 +48,14 @@ router.get('/', function(req, res, next) {
|
||||
});
|
||||
} else {
|
||||
if (req.query.writablefolders) {
|
||||
Membership.find({
|
||||
user: req.user._id
|
||||
}, (err, memberships) => {
|
||||
db.Membership.find({where: {
|
||||
user_id: req.user._id
|
||||
}}, (memberships) => {
|
||||
|
||||
var validMemberships = memberships.filter((m) => {
|
||||
if (!m.space || (m.space == "undefined"))
|
||||
if (!m.space_id || (m.space_id == "undefined"))
|
||||
return false;
|
||||
else
|
||||
return mongoose.Types.ObjectId.isValid(m.space.toString());
|
||||
return true;
|
||||
});
|
||||
|
||||
var editorMemberships = validMemberships.filter((m) => {
|
||||
@@ -64,9 +63,10 @@ router.get('/', function(req, res, next) {
|
||||
});
|
||||
|
||||
var spaceIds = editorMemberships.map(function(m) {
|
||||
return new mongoose.Types.ObjectId(m.space);
|
||||
return m.space_id;
|
||||
});
|
||||
|
||||
// TODO port
|
||||
var q = {
|
||||
"space_type": "folder",
|
||||
"$or": [{
|
||||
@@ -81,13 +81,11 @@ router.get('/', function(req, res, next) {
|
||||
}]
|
||||
};
|
||||
|
||||
Space
|
||||
.find(q)
|
||||
.populate('creator', userMapping)
|
||||
.exec(function(err, spaces) {
|
||||
if (err) console.error(err);
|
||||
db.Space
|
||||
.findAll({where: q})
|
||||
.then(function(spaces) {
|
||||
var updatedSpaces = spaces.map(function(s) {
|
||||
var spaceObj = s.toObject();
|
||||
var spaceObj = s; //.toObject();
|
||||
return spaceObj;
|
||||
});
|
||||
|
||||
@@ -104,75 +102,67 @@ router.get('/', function(req, res, next) {
|
||||
return s.space_type == "folder";
|
||||
})
|
||||
var uniqueFolders = _.unique(onlyFolders, (s) => {
|
||||
return s._id.toString();
|
||||
return s._id;
|
||||
})
|
||||
|
||||
res.status(200).json(uniqueFolders);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
} else if (req.query.search) {
|
||||
|
||||
Membership.find({
|
||||
user: req.user._id
|
||||
}, function(err, memberships) {
|
||||
db.Membership.findAll({where:{
|
||||
user_id: req.user._id
|
||||
}}).then(memberships => {
|
||||
|
||||
var validMemberships = memberships.filter(function(m) {
|
||||
if (!m.space || (m.space == "undefined"))
|
||||
if (!m.space_id || (m.space_id == "undefined"))
|
||||
return false;
|
||||
else
|
||||
return mongoose.Types.ObjectId.isValid(m.space.toString());
|
||||
return true;
|
||||
});
|
||||
|
||||
var spaceIds = validMemberships.map(function(m) {
|
||||
return new mongoose.Types.ObjectId(m.space);
|
||||
return m.space_id;
|
||||
});
|
||||
|
||||
var q = {
|
||||
"$or": [{"creator": req.user._id},
|
||||
{"_id": {"$in": spaceIds}},
|
||||
{"parent_space_id": {"$in": spaceIds}}],
|
||||
name: new RegExp(req.query.search, "i")
|
||||
};
|
||||
// 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']};
|
||||
|
||||
Space
|
||||
.find(q)
|
||||
.populate('creator', userMapping)
|
||||
.exec(function(err, spaces) {
|
||||
if (err) console.error(err);
|
||||
var updatedSpaces = spaces.map(function(s) {
|
||||
var spaceObj = s.toObject();
|
||||
return spaceObj;
|
||||
});
|
||||
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) {
|
||||
|
||||
Space
|
||||
.findOne({
|
||||
db.Space
|
||||
.findOne({where: {
|
||||
_id: req.query.parent_space_id
|
||||
})
|
||||
.populate('creator', userMapping)
|
||||
.exec(function(err, space) {
|
||||
}})
|
||||
//.populate('creator', userMapping)
|
||||
.then(function(space) {
|
||||
if (space) {
|
||||
Space.roleInSpace(space, req.user, function(err, role) {
|
||||
|
||||
db.getUserRoleInSpace(space, req.user, function(role) {
|
||||
if (role == "none") {
|
||||
if(space.access_mode == "public") {
|
||||
if (space.access_mode == "public") {
|
||||
role = "viewer";
|
||||
}
|
||||
}
|
||||
|
||||
if (role != "none") {
|
||||
Space
|
||||
.find({
|
||||
db.Space
|
||||
.findAll({where:{
|
||||
parent_space_id: req.query.parent_space_id
|
||||
})
|
||||
.populate('creator', userMapping)
|
||||
.exec(function(err, spaces) {
|
||||
}, include:['creator']})
|
||||
.then(function(spaces) {
|
||||
res.status(200).json(spaces);
|
||||
});
|
||||
} else {
|
||||
@@ -185,41 +175,39 @@ router.get('/', function(req, res, next) {
|
||||
});
|
||||
|
||||
} else {
|
||||
Membership.find({
|
||||
user: req.user._id
|
||||
}, function(err, memberships) {
|
||||
db.Membership.findAll({ where: {
|
||||
user_id: req.user._id
|
||||
}}).then(memberships => {
|
||||
if (!memberships) memberships = [];
|
||||
|
||||
var validMemberships = memberships.filter(function(m) {
|
||||
if (!m.space || (m.space == "undefined"))
|
||||
if (!m.space_id || (m.space_id == "undefined"))
|
||||
return false;
|
||||
else
|
||||
return mongoose.Types.ObjectId.isValid(m.space.toString());
|
||||
});
|
||||
|
||||
var spaceIds = validMemberships.map(function(m) {
|
||||
return new mongoose.Types.ObjectId(m.space);
|
||||
return m.space_id;
|
||||
});
|
||||
|
||||
var q = {
|
||||
"$or": [{
|
||||
"creator": req.user._id,
|
||||
[Op.or]: [{
|
||||
"creator_id": req.user._id,
|
||||
"parent_space_id": req.user.home_folder_id
|
||||
}, {
|
||||
"_id": {
|
||||
"$in": spaceIds
|
||||
[Op.in]: spaceIds
|
||||
},
|
||||
"creator": {
|
||||
"$ne": req.user._id
|
||||
"creator_id": {
|
||||
[Op.ne]: req.user._id
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
Space
|
||||
.find(q)
|
||||
.populate('creator', userMapping)
|
||||
.exec(function(err, spaces) {
|
||||
if (err) console.error(err);
|
||||
db.Space
|
||||
.findAll({where: q, include: ['creator']})
|
||||
.then(function(spaces) {
|
||||
var updatedSpaces = spaces.map(function(s) {
|
||||
var spaceObj = s.toObject();
|
||||
var spaceObj = db.spaceToObject(s);
|
||||
return spaceObj;
|
||||
});
|
||||
res.status(200).json(spaces);
|
||||
@@ -229,47 +217,43 @@ router.get('/', function(req, res, next) {
|
||||
}
|
||||
});
|
||||
|
||||
// create a space
|
||||
router.post('/', function(req, res, next) {
|
||||
if (req.user) {
|
||||
var attrs = req.body;
|
||||
|
||||
var createSpace = () => {
|
||||
|
||||
attrs.creator = req.user;
|
||||
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);
|
||||
|
||||
var space = new Space(attrs);
|
||||
space.save(function(err, createdSpace) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
var membership = new Membership({
|
||||
user: req.user,
|
||||
space: createdSpace,
|
||||
role: "admin"
|
||||
});
|
||||
membership.save(function(err, createdTeam) {
|
||||
if (err) {
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
res.status(201).json(createdSpace);
|
||||
}
|
||||
});
|
||||
}
|
||||
db.Space.create(attrs).then(createdSpace => {
|
||||
//if (err) res.sendStatus(400);
|
||||
var membership = {
|
||||
_id: uuidv4(),
|
||||
user_id: req.user._id,
|
||||
space_id: attrs._id,
|
||||
role: "admin"
|
||||
};
|
||||
|
||||
db.Membership.create(membership).then(() => {
|
||||
res.status(201).json(createdSpace);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (attrs.parent_space_id) {
|
||||
Space.findOne({
|
||||
db.Space.findOne({ where: {
|
||||
"_id": attrs.parent_space_id
|
||||
}).populate('creator', userMapping).exec((err, parentSpace) => {
|
||||
}}).then(parentSpace => {
|
||||
if (parentSpace) {
|
||||
Space.roleInSpace(parentSpace, req.user, (err, role) => {
|
||||
db.getUserRoleInSpace(parentSpace, req.user, (role) => {
|
||||
if ((role == "editor") || (role == "admin")) {
|
||||
createSpace();
|
||||
} else {
|
||||
res.status(403).json({
|
||||
"error": "not editor in parent Space"
|
||||
"error": "not editor in parent Space. role: "+role
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -292,6 +276,30 @@ 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;
|
||||
@@ -308,24 +316,17 @@ router.put('/:id', function(req, res) {
|
||||
delete newAttr['editor_name'];
|
||||
delete newAttr['creator'];
|
||||
|
||||
Space.findOneAndUpdate({
|
||||
db.Space.update(newAttr, {where: {
|
||||
"_id": space._id
|
||||
}, {
|
||||
"$set": newAttr
|
||||
}, {
|
||||
"new": true
|
||||
}, function(err, space) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
res.distributeUpdate("Space", space);
|
||||
}
|
||||
}}).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.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 writeStream = fs.createWriteStream(localFilePath);
|
||||
var stream = req.pipe(writeStream);
|
||||
@@ -334,38 +335,26 @@ router.post('/:id/background', function(req, res, next) {
|
||||
uploader.uploadFile("s" + req.space._id + "/bg_" + newDate.getTime() + "_" + fileName, "image/jpeg", localFilePath, function(err, backgroundUrl) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
var adv = space.advanced;
|
||||
|
||||
if (adv.background_uri) {
|
||||
var oldPath = url.parse(req.space.thumbnail_url).pathname;
|
||||
if (space.background_uri) {
|
||||
var oldPath = url.parse(req.space.background_uri).pathname;
|
||||
uploader.removeFile(oldPath, function(err) {
|
||||
console.log("removed old bg error:", err);
|
||||
console.error("removed old bg error:", err);
|
||||
});
|
||||
}
|
||||
|
||||
adv.background_uri = backgroundUrl;
|
||||
|
||||
Space.findOneAndUpdate({
|
||||
"_id": space._id
|
||||
db.Space.update({
|
||||
background_uri: backgroundUrl
|
||||
}, {
|
||||
"$set": {
|
||||
advanced: adv
|
||||
}
|
||||
}, {
|
||||
"new": true
|
||||
}, function(err, space) {
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
fs.unlink(localFilePath, function(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
res.status(200).json(space);
|
||||
}
|
||||
});
|
||||
}
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -390,10 +379,10 @@ router.post('/:id/duplicate', (req, res, next) => {
|
||||
}).populate('creator', userMapping).exec((err, parentSpace) => {
|
||||
if (!parentSpace) {
|
||||
res.status(404).json({
|
||||
"error": "parent space not found for dupicate"
|
||||
"error": "parent space not found for duplicate"
|
||||
});
|
||||
} else {
|
||||
Space.roleInSpace(parentSpace, req.user, (err, role) => {
|
||||
db.getUserRoleInSpace(parentSpace, req.user, (role) => {
|
||||
if (role == "admin" || role == "editor") {
|
||||
handleDuplicateSpaceRequest(req, res, parentSpace);
|
||||
} else {
|
||||
@@ -415,15 +404,12 @@ router.delete('/:id', function(req, res, next) {
|
||||
|
||||
if (req.spaceRole == "admin") {
|
||||
const attrs = req.body;
|
||||
Space.recursiveDelete(space, function(err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
res.distributeDelete("Space", space);
|
||||
}
|
||||
space.destroy().then(function() {
|
||||
res.distributeDelete("Space", space);
|
||||
});
|
||||
} else {
|
||||
res.status(403).json({
|
||||
"error": "requires admin status"
|
||||
"error": "requires admin role"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -449,6 +435,7 @@ router.post('/:id/artifacts-pdf', function(req, res, next) {
|
||||
fs.mkdir(outputFolder, function(db) {
|
||||
var images = outputFolder + "/" + rawName + "-page-%03d.jpeg";
|
||||
|
||||
// FIXME not portable
|
||||
exec.execFile("gs", ["-sDEVICE=jpeg", "-dDownScaleFactor=4", "-dDOINTERPOLATE", "-dNOPAUSE", "-dJPEGQ=80", "-dBATCH", "-sOutputFile=" + images, "-r250", "-f", localFilePath], {}, function(error, stdout, stderr) {
|
||||
if (error === null) {
|
||||
|
||||
@@ -532,6 +519,7 @@ router.post('/:id/artifacts-pdf', function(req, res, next) {
|
||||
|
||||
}, function(err, artifacts) {
|
||||
|
||||
// FIXME not portable
|
||||
exec.execFile("rm", ["-r", outputFolder], function(err) {
|
||||
res.status(201).json(_.flatten(artifacts));
|
||||
|
||||
@@ -551,6 +539,7 @@ router.post('/:id/artifacts-pdf', function(req, res, next) {
|
||||
});
|
||||
} else {
|
||||
console.error("error:", error);
|
||||
// FIXME not portable
|
||||
exec.execFile("rm", ["-r", outputFolder], function(err) {
|
||||
fs.unlink(localFilePath);
|
||||
res.status(400).json({});
|
||||
|
||||
@@ -1,265 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
|
||||
var redis = require('../../helpers/redis');
|
||||
var mailer = require('../../helpers/mailer');
|
||||
|
||||
var fs = require('fs');
|
||||
var _ = require('underscore');
|
||||
var crypto = require('crypto');
|
||||
var bcrypt = require('bcryptjs');
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
var userMapping = { '_id': 1, 'nickname': 1, 'email': 1};
|
||||
|
||||
router.get('/:id', (req, res) => {
|
||||
res.status(200).json(req.user.team);
|
||||
});
|
||||
|
||||
router.put('/:id', (req, res) => {
|
||||
var team = req.user.team;
|
||||
if (!team) {
|
||||
res.status(400).json({"error": "user in no team"});
|
||||
} else {
|
||||
var newAttr = req.body;
|
||||
newAttr.updated_at = new Date();
|
||||
delete newAttr['_id'];
|
||||
|
||||
if(newAttr['subdomain']) {
|
||||
newAttr['subdomain'] = newAttr['subdomain'].toLowerCase();
|
||||
}
|
||||
const new_subdomain = newAttr['subdomain'];
|
||||
var forbidden_subdomains = [];
|
||||
|
||||
function updateTeam() {
|
||||
Team.findOneAndUpdate({"_id": team._id}, {"$set": newAttr}, {"new": true}, (err, team) => {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
res.status(200).json(team);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var isForbidden = forbidden_subdomains.indexOf(new_subdomain) > -1;
|
||||
if (isForbidden) {
|
||||
res.bad_request("subdomain not valid");
|
||||
} else {
|
||||
if (new_subdomain) {
|
||||
Team.findOne({"domain": new_subdomain}).exec((err, team) => {
|
||||
if(team) {
|
||||
res.bad_request("subdomain already used");
|
||||
} else {
|
||||
updateTeam()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
updateTeam()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/:id/memberships', (req, res) => {
|
||||
User
|
||||
.find({team: req.user.team})
|
||||
.populate("team")
|
||||
.exec(function(err, users){
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
res.status(200).json(users);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/:id/memberships', (req, res, next) => {
|
||||
if (req.body.email) {
|
||||
const email = req.body.email.toLowerCase();
|
||||
const team = req.user.team;
|
||||
|
||||
User.findOne({"email": email}).populate('team').exec((err, user) => {
|
||||
if (user) {
|
||||
const code = crypto.randomBytes(64).toString('hex').substring(0,7);
|
||||
team.invitation_codes.push(code);
|
||||
team.save((err) => {
|
||||
if (err){ res.status(400).json(err); }
|
||||
else {
|
||||
mailer.sendMail(email, req.i18n.__("team_invite_membership_subject", team.name), req.i18n.__("team_invite_membership_body", team.name), { action: {
|
||||
link: config.endpoint + "/teams/" + req.user.team._id + "/join?code=" + code,
|
||||
name: req.i18n.__("team_invite_membership_action"),
|
||||
teamname: team.name
|
||||
}});
|
||||
|
||||
res.status(201).json(user);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// complete new user
|
||||
const password = crypto.randomBytes(64).toString('hex').substring(0,7);
|
||||
const confirmation_token = crypto.randomBytes(64).toString('hex').substring(0,7);
|
||||
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(password, salt, (err, hash) => {
|
||||
crypto.randomBytes(16, (ex, buf) => {
|
||||
const token = buf.toString('hex');
|
||||
|
||||
var u = new User({
|
||||
email: email,
|
||||
account_type: "email",
|
||||
nickname: email,
|
||||
team: team._id,
|
||||
password_hash: hash,
|
||||
payment_plan_key: team.payment_plan_key,
|
||||
confirmation_token: confirmation_token,
|
||||
preferences: {
|
||||
language: req.i18n.locale
|
||||
}
|
||||
});
|
||||
|
||||
u.save((err) => {
|
||||
if(err) res.sendStatus(400);
|
||||
else {
|
||||
var homeSpace = new Space({
|
||||
name: req.i18n.__("home"),
|
||||
space_type: "folder",
|
||||
creator: u
|
||||
});
|
||||
|
||||
homeSpace.save((err, homeSpace) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
u.home_folder_id = homeSpace._id;
|
||||
u.save((err) => {
|
||||
|
||||
User.find({"_id": {"$in": team.admins }}).exec((err, admins) => {
|
||||
admins.forEach((admin) => {
|
||||
var i18n = req.i18n;
|
||||
if(admin.preferences && admin.preferences.language){
|
||||
i18n.setLocale(admin.preferences.language || "en");
|
||||
}
|
||||
mailer.sendMail(admin.email, i18n.__("team_invite_membership_subject", team.name), i18n.__("team_invite_admin_body", email, team.name, password), { teamname: team.name });
|
||||
});
|
||||
});
|
||||
|
||||
mailer.sendMail(email, req.i18n.__("team_invite_membership_subject", team.name), req.i18n.__("team_invite_user_body", team.name, password), { action: {
|
||||
link: config.endpoint + "/users/byteam/" + req.user.team._id + "/join?confirmation_token=" + confirmation_token,
|
||||
name: req.i18n.__("team_invite_membership_action")
|
||||
}, teamname: team.name });
|
||||
|
||||
if (err) res.status(400).json(err);
|
||||
else{
|
||||
res.status(201).json(u)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({"error": "email missing"});
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/:id/memberships/:user_id', (req, res) => {
|
||||
User.findOne({_id: req.params.user_id}, (err,mem) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
if(user.team._id == req.user.team._id){
|
||||
user['team'] = req.user.team._id;
|
||||
user.save((err) => {
|
||||
res.sendStatus(204);
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/:id/memberships/:user_id/promote', (req, res) => {
|
||||
User.findOne({_id: req.params.user_id}, (err,user) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
if (user.team.toString() == req.user.team._id.toString()) {
|
||||
var team = req.user.team;
|
||||
var adminIndex = team.admins.indexOf(user._id);
|
||||
|
||||
if (adminIndex == -1) {
|
||||
team.admins.push(user._id);
|
||||
team.save((err, team) => {
|
||||
res.status(204).json(team);
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({"error": "already admin"});
|
||||
}
|
||||
} else {
|
||||
res.status(403).json({"error": "team id not correct"});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/:id/memberships/:user_id/demote', (req, res, next) => {
|
||||
User.findOne({_id: req.params.user_id}, (err,user) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
if (user.team.toString() == req.user.team._id.toString()) {
|
||||
const team = req.user.team;
|
||||
const adminIndex = team.admins.indexOf(user._id);
|
||||
|
||||
if(adminIndex > -1) {
|
||||
team.admins.splice(adminIndex,1);
|
||||
team.save((err, team) => {
|
||||
res.status(204).json(team);
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/:id/memberships/:user_id', (req, res) => {
|
||||
User.findOne({_id: req.params.user_id}).populate('team').exec((err,user) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
const currentUserId = req.user._id.toString();
|
||||
const team = req.user.team;
|
||||
|
||||
const isAdmin = (req.user.team.admins.filter( mem => {
|
||||
return mem == currentUserId;
|
||||
}).length == 1)
|
||||
|
||||
if (isAdmin) {
|
||||
user.team = null;
|
||||
user.payment_plan_key = "free";
|
||||
user.save( err => {
|
||||
const adminIndex = team.admins.indexOf(user._id);
|
||||
if(adminIndex > -1) {
|
||||
team.admins.splice(adminIndex,1);
|
||||
team.save((err, team) => {
|
||||
console.log("admin removed");
|
||||
});
|
||||
}
|
||||
|
||||
res.sendStatus(204);
|
||||
});
|
||||
} else {
|
||||
res.status(403).json({"error": "not admin"});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,14 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
const db = require('../../models/db');
|
||||
const uuidv4 = require('uuid/v4');
|
||||
|
||||
var mailer = require('../../helpers/mailer');
|
||||
var uploader = require('../../helpers/uploader');
|
||||
var importer = require('../../helpers/importer');
|
||||
|
||||
var bcrypt = require('bcryptjs');
|
||||
var crypo = require('crypto');
|
||||
var crypto = require('crypto');
|
||||
var swig = require('swig');
|
||||
var async = require('async');
|
||||
var _ = require('underscore');
|
||||
@@ -20,6 +21,7 @@ var URL = require('url').URL;
|
||||
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
var glob = require('glob');
|
||||
|
||||
router.get('/current', function(req, res, next) {
|
||||
if (req.user) {
|
||||
@@ -30,231 +32,95 @@ router.get('/current', function(req, res, next) {
|
||||
}
|
||||
});
|
||||
|
||||
// create user
|
||||
router.post('/', function(req, res) {
|
||||
if (req.body["email"] && req.body["password"]) {
|
||||
|
||||
var email = req.body["email"].toLowerCase();
|
||||
var nickname = req.body["nickname"];
|
||||
var password = req.body["password"];
|
||||
var password_confirmation = req.body["password_confirmation"];
|
||||
|
||||
if (password_confirmation == password) {
|
||||
if (validator.isEmail(email)) {
|
||||
|
||||
var createUser = function() {
|
||||
bcrypt.genSalt(10, function(err, salt) {
|
||||
bcrypt.hash(password, salt, function(err, hash) {
|
||||
|
||||
crypo.randomBytes(16, function(ex, buf) {
|
||||
var token = buf.toString('hex');
|
||||
|
||||
var u = new User({
|
||||
email: email,
|
||||
account_type: "email",
|
||||
nickname: nickname,
|
||||
password_hash: hash,
|
||||
preferences: {
|
||||
language: req.i18n.locale
|
||||
},
|
||||
confirmation_token: token
|
||||
});
|
||||
|
||||
u.save(function (err) {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
var homeSpace = new Space({
|
||||
name: req.i18n.__("home"),
|
||||
space_type: "folder",
|
||||
creator: u
|
||||
});
|
||||
|
||||
homeSpace.save((err, homeSpace) => {
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
u.home_folder_id = homeSpace._id;
|
||||
u.save((err) => {
|
||||
|
||||
mailer.sendMail(u.email, req.i18n.__("confirm_subject"), req.i18n.__("confirm_body"), {
|
||||
action: {
|
||||
link: config.endpoint + "/confirm/" + u.confirmation_token,
|
||||
name: req.i18n.__("confirm_action")
|
||||
}
|
||||
});
|
||||
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
res.status(201).json({});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
User.find({email: email}, (function (err, users) {
|
||||
if (err) {
|
||||
res.status(400).json({"error":"password_confirmation"});
|
||||
} else {
|
||||
|
||||
if (users.length === 0) {
|
||||
var domain = email.slice(email.lastIndexOf('@')+1);
|
||||
|
||||
Domain.findOne({domain: domain}, function(err, domain) {
|
||||
if(domain){
|
||||
if(domain.edu) {
|
||||
createUser();
|
||||
} else {
|
||||
res.status(400).json({"error":"domain_blocked"});
|
||||
}
|
||||
} else {
|
||||
createUser();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({"error":"user_email_already_used"});
|
||||
}
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
res.status(400).json({"error":"email_invalid"});
|
||||
}
|
||||
} else {
|
||||
res.status(400).json({"error":"password_confirmation"});
|
||||
}
|
||||
} else {
|
||||
if (!req.body["email"] || !req.body["password"]) {
|
||||
res.status(400).json({"error":"email or password missing"});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
var email = req.body["email"].toLowerCase();
|
||||
var nickname = req.body["nickname"];
|
||||
var password = req.body["password"];
|
||||
var password_confirmation = req.body["password_confirmation"];
|
||||
|
||||
router.get('/oauth2callback/url', function(req, res) {
|
||||
var google = require('googleapis');
|
||||
var OAuth2 = google.auth.OAuth2;
|
||||
if (password_confirmation != password) {
|
||||
res.status(400).json({"error":"password_confirmation"});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validator.isEmail(email)) {
|
||||
res.status(400).json({"error":"email_invalid"});
|
||||
return;
|
||||
}
|
||||
|
||||
var createUser = function() {
|
||||
bcrypt.genSalt(10, function(err, salt) {
|
||||
bcrypt.hash(password, salt, function(err, hash) {
|
||||
crypto.randomBytes(16, function(ex, buf) {
|
||||
var token = buf.toString('hex');
|
||||
|
||||
var oauth2Client = new OAuth2(
|
||||
config.google_access,
|
||||
config.google_secret,
|
||||
config.endpoint + "/login"
|
||||
);
|
||||
var u = {
|
||||
_id: uuidv4(),
|
||||
email: email,
|
||||
account_type: "email",
|
||||
nickname: nickname,
|
||||
password_hash: hash,
|
||||
prefs_language: req.i18n.locale,
|
||||
confirmation_token: token
|
||||
};
|
||||
|
||||
var url = oauth2Client.generateAuthUrl({
|
||||
access_type: 'online',
|
||||
scope: "email"
|
||||
});
|
||||
|
||||
res.status(200).json({"url":url});
|
||||
});
|
||||
|
||||
router.get('/loginorsignupviagoogle', function(req, res) {
|
||||
var google = require('googleapis');
|
||||
var OAuth2 = google.auth.OAuth2;
|
||||
var plus = google.plus('v1');
|
||||
|
||||
var oauth2Client = new OAuth2(
|
||||
config.google_access,
|
||||
config.google_secret,
|
||||
config.endpoint + "/login"
|
||||
);
|
||||
|
||||
var loginUser = function(user, cb) {
|
||||
crypo.randomBytes(48, function(ex, buf) {
|
||||
var token = buf.toString('hex');
|
||||
var session = {
|
||||
token: token,
|
||||
created_at: new Date()
|
||||
};
|
||||
if(!user.sessions)
|
||||
user.sessions = [];
|
||||
user.sessions.push(session);
|
||||
user.save(function(err, user) {
|
||||
cb(session);
|
||||
db.User.create(u)
|
||||
.error(err => {
|
||||
res.sendStatus(400);
|
||||
})
|
||||
.then(u => {
|
||||
var homeSpace = {
|
||||
_id: uuidv4(),
|
||||
name: req.i18n.__("home"),
|
||||
space_type: "folder",
|
||||
creator_id: u._id
|
||||
};
|
||||
db.Space.create(homeSpace)
|
||||
.error(err => {
|
||||
res.sendStatus(400);
|
||||
})
|
||||
.then(homeSpace => {
|
||||
u.home_folder_id = homeSpace._id;
|
||||
u.save()
|
||||
.then(() => {
|
||||
res.status(201).json({});
|
||||
|
||||
mailer.sendMail(u.email, req.i18n.__("confirm_subject"), req.i18n.__("confirm_body"), {
|
||||
action: {
|
||||
link: config.endpoint + "/confirm/" + u.confirmation_token,
|
||||
name: req.i18n.__("confirm_action")
|
||||
}
|
||||
});
|
||||
})
|
||||
.error(err => {
|
||||
res.status(400).json(err);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var code = req.query.code;
|
||||
oauth2Client.getToken(code, function(err, tokens) {
|
||||
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
var apiUrl = "https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=" + tokens.access_token;
|
||||
|
||||
var finalizeLogin = function(session){
|
||||
res.cookie('sdsession', session.token, { httpOnly: true });
|
||||
res.status(201).json(session);
|
||||
};
|
||||
|
||||
request.get(apiUrl, function(error, response, body) {
|
||||
if (error) res.status(400).json(error);
|
||||
else {
|
||||
const data = JSON.parse(body);
|
||||
const email = data.email;
|
||||
const name = data.name;
|
||||
|
||||
User.findOne({email: email}, function (err, user) {
|
||||
if (user) {
|
||||
// login new google user
|
||||
if (user.account_type == "google") {
|
||||
// just login
|
||||
loginUser(user, (session) => {
|
||||
finalizeLogin(session);
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({"error":"user_email_already_used"});
|
||||
}
|
||||
} else {
|
||||
const u = new User({
|
||||
email: email,
|
||||
account_type: "google",
|
||||
nickname: name,
|
||||
avatar_thumb_uri: body.picture,
|
||||
preferences: {
|
||||
language: req.i18n.locale
|
||||
},
|
||||
confirmed_at: new Date()
|
||||
});
|
||||
|
||||
u.save(function (err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
var homeSpace = new Space({
|
||||
name: req.i18n.__("home"),
|
||||
space_type: "folder",
|
||||
creator: u
|
||||
});
|
||||
|
||||
homeSpace.save(function(err, homeSpace) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
u.home_folder_id = homeSpace._id;
|
||||
u.save(function(err){
|
||||
if (err) res.sendStatus(400);
|
||||
else {
|
||||
|
||||
mailer.sendMail(u.email, req.i18n.__("welcome_subject"), req.i18n.__("welcome_body"), {});
|
||||
loginUser(u, function(session) {
|
||||
finalizeLogin(session);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
db.User.findAll({where: {email: email}})
|
||||
.then(users => {
|
||||
if (users.length == 0) {
|
||||
//var domain = email.slice(email.lastIndexOf('@')+1);
|
||||
createUser();
|
||||
} else {
|
||||
res.status(400).json({"error":"user_email_already_used"});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
router.get('/ ', function(req, res, next) {
|
||||
router.get('/current', function(req, res, next) {
|
||||
if (req.user) {
|
||||
console.log(req.user.team);
|
||||
res.status(200).json(req.user);
|
||||
} else {
|
||||
res.status(401).json({"error":"user_not_found"});
|
||||
@@ -262,19 +128,15 @@ router.get('/ ', function(req, res, next) {
|
||||
});
|
||||
|
||||
router.put('/:id', function(req, res, next) {
|
||||
// TODO explicit whitelisting
|
||||
var user = req.user;
|
||||
console.log(req.params.id, user._id);
|
||||
if (user._id == req.params.id) {
|
||||
var newAttr = req.body;
|
||||
newAttr.updated_at = new Date();
|
||||
delete newAttr['_id'];
|
||||
|
||||
User.findOneAndUpdate({"_id": user._id}, {"$set": newAttr}, function(err, updatedUser) {
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
res.status(200).json(updatedUser);
|
||||
}
|
||||
db.User.update(newAttr, {where: {"_id": user._id}}).then(function(updatedUser) {
|
||||
res.status(200).json(newAttr);
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
@@ -292,12 +154,8 @@ router.post('/:id/password', function(req, res, next) {
|
||||
bcrypt.genSalt(10, function(err, salt) {
|
||||
bcrypt.hash(pass, salt, function(err, hash) {
|
||||
user.password_hash = hash;
|
||||
user.save(function(err){
|
||||
if(err){
|
||||
res.status(400).json(err);
|
||||
}else{
|
||||
res.sendStatus(204);
|
||||
}
|
||||
user.save().then(function() {
|
||||
res.sendStatus(204);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -326,7 +184,7 @@ router.delete('/:id', (req, res, next) => {
|
||||
}
|
||||
} else {
|
||||
user.remove((err) => {
|
||||
if(err)res.status(400).json(err);
|
||||
if (err) res.status(400).json(err);
|
||||
else res.sendStatus(204);
|
||||
});
|
||||
}
|
||||
@@ -370,19 +228,15 @@ router.post('/:user_id/avatar', (req, res, next) => {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
user.avatar_thumb_uri = url;
|
||||
user.save((err, updatedUser) => {
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
fs.unlink(localResizedFilePath, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
res.status(200).json(updatedUser);
|
||||
}
|
||||
});
|
||||
}
|
||||
user.save().then(() => {
|
||||
fs.unlink(localResizedFilePath, (err) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
res.status(200).json(user);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -400,31 +254,20 @@ router.post('/feedback', function(req, res, next) {
|
||||
|
||||
router.post('/password_reset_requests', (req, res, next) => {
|
||||
const email = req.query.email;
|
||||
User.findOne({"email": email}).exec((err, user) => {
|
||||
if (err) {
|
||||
res.status(400).json(err);
|
||||
db.User.findOne({where: {"email": email}}).then((user) => {
|
||||
if (user) {
|
||||
crypto.randomBytes(16, (ex, buf) => {
|
||||
user.password_reset_token = buf.toString('hex');
|
||||
user.save().then(updatedUser => {
|
||||
mailer.sendMail(email, req.i18n.__("password_reset_subject"), req.i18n.__("password_reset_body"), {action: {
|
||||
link: config.endpoint + "/password-confirm/" + user.password_reset_token,
|
||||
name: req.i18n.__("password_reset_action")
|
||||
}});
|
||||
res.status(201).json({});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (user) {
|
||||
if(user.account_type == "email") {
|
||||
crypo.randomBytes(16, (ex, buf) => {
|
||||
user.password_reset_token = buf.toString('hex');
|
||||
user.save((err, updatedUser) => {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
mailer.sendMail(email, req.i18n.__("password_reset_subject"), req.i18n.__("password_reset_body"), {action: {
|
||||
link: config.endpoint + "/password-confirm/" + user.password_reset_token,
|
||||
name: req.i18n.__("password_reset_action")
|
||||
}});
|
||||
res.status(201).json({});
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.status(404).json({"error": "error_unknown_email"});
|
||||
}
|
||||
} else {
|
||||
res.status(404).json({"error": "error_unknown_email"});
|
||||
}
|
||||
res.status(404).json({"error": "error_unknown_email"});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -433,29 +276,25 @@ router.post('/password_reset_requests/:confirm_token/confirm', function(req, res
|
||||
var password = req.body.password;
|
||||
|
||||
User
|
||||
.findOne({"password_reset_token": req.params.confirm_token})
|
||||
.exec((err, user) => {
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
if(user) {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(password, salt, function(err, hash) {
|
||||
.findOne({where: {"password_reset_token": req.params.confirm_token}})
|
||||
.then((user) => {
|
||||
if (user) {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(password, salt, function(err, hash) {
|
||||
|
||||
user.password_hash = hash;
|
||||
user.password_token = null;
|
||||
user.save(function(err, updatedUser){
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
res.sendStatus(201);
|
||||
}
|
||||
});
|
||||
user.password_hash = hash;
|
||||
user.password_token = null;
|
||||
user.save(function(err, updatedUser){
|
||||
if (err) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
res.sendStatus(201);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -468,6 +307,12 @@ router.post('/:user_id/confirm', function(req, res, next) {
|
||||
res.sendStatus(201);
|
||||
});
|
||||
|
||||
router.get('/:user_id/importables', function(req, res, next) {
|
||||
glob('*.zip', function(err, files) {
|
||||
res.status(200).json(files);
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/:user_id/import', function(req, res, next) {
|
||||
if (req.query.zip) {
|
||||
res.send("importing");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var config = require('config');
|
||||
require('../../models/schema');
|
||||
require('../../models/db');
|
||||
|
||||
var fs = require('fs');
|
||||
var phantom = require('node-phantom-simple');
|
||||
|
||||
108
routes/root.js
108
routes/root.js
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const config = require('config');
|
||||
require('../models/schema');
|
||||
require('../models/db');
|
||||
|
||||
const redis = require('../helpers/redis');
|
||||
const express = require('express');
|
||||
@@ -9,7 +9,6 @@ const crypto = require('crypto');
|
||||
const router = express.Router();
|
||||
const mailer = require('../helpers/mailer');
|
||||
const _ = require('underscore');
|
||||
const qr = require('qr-image');
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.render('index', { title: 'Spaces' });
|
||||
@@ -95,10 +94,6 @@ router.get('/logout', (req, res) => {
|
||||
res.render('spacedeck');
|
||||
});
|
||||
|
||||
router.get('/users/oauth2callback', (req, res) => {
|
||||
res.render('spacedeck');
|
||||
});
|
||||
|
||||
router.get('/contact', (req, res) => {
|
||||
res.render('public/contact');
|
||||
});
|
||||
@@ -185,107 +180,6 @@ router.get('/spaces/:id', (req, res) => {
|
||||
} else res.render('spacedeck', { title: 'Space' });
|
||||
});
|
||||
|
||||
router.get('/users/byteam/:team_id/join', (req, res) => {
|
||||
if (!req.user) {
|
||||
const q = {confirmation_token: req.query.confirmation_token, account_type: "email", team: req.params.team_id};
|
||||
User.findOne(q, (err, user) => {
|
||||
if (err) {
|
||||
res.status(400).json({"error":"session.users"});
|
||||
} else {
|
||||
if (user) {
|
||||
crypto.randomBytes(48, function(ex, buf) {
|
||||
const token = buf.toString('hex');
|
||||
|
||||
var session = {
|
||||
token: token,
|
||||
ip: req.ip,
|
||||
device: "web",
|
||||
created_at: new Date()
|
||||
};
|
||||
|
||||
if (!user.sessions)
|
||||
user.sessions = [];
|
||||
|
||||
user.sessions.push(session);
|
||||
user.confirmed_at = new Date();
|
||||
user.confirmation_token = null;
|
||||
|
||||
user.save(function(err, result) {
|
||||
// FIXME
|
||||
const secure = process.env.NODE_ENV == "production" || process.env.NODE_ENV == "staging";
|
||||
const domain = (process.env.NODE_ENV == "production") ? ".spacedeck.com" : ".spacedecklocal.de";
|
||||
|
||||
res.cookie('sdsession', token, { domain: domain, httpOnly: true, secure: secure});
|
||||
res.redirect("/spaces");
|
||||
});
|
||||
});
|
||||
} else {
|
||||
res.status(404).json({"error": "not found"});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
res.redirect("/spaces");
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/teams/:id/join', function(req, res, next) {
|
||||
if (req.user) {
|
||||
if (!req.user.team) {
|
||||
Team.findOne({"_id": req.params.id}, function(err, team) {
|
||||
if (team) {
|
||||
const idx = team.invitation_codes.indexOf(req.query.code);
|
||||
if (idx >= 0) {
|
||||
const u = req.user;
|
||||
u.team = team;
|
||||
|
||||
if(!u.confirmed_at) {
|
||||
u.confirmed_at = new Date();
|
||||
}
|
||||
|
||||
u.payment_plan_key = team.payment_plan_key;
|
||||
u.save(function(err) {
|
||||
if (err) res.status(400).json(err);
|
||||
else {
|
||||
team.invitation_condes = team.invitation_codes.slice(idx);
|
||||
team.save(function(err) {
|
||||
team.invitation_codes = null;
|
||||
|
||||
var finish = function(team, users) {
|
||||
User.find({"_id": {"$in": team.admins}}).exec((err, admins) => {
|
||||
if(admins) {
|
||||
admins.forEach((admin) => {
|
||||
mailer.sendMail(
|
||||
admin.email,
|
||||
req.i18n.__("team_new_member_subject", team.name),
|
||||
req.i18n.__("team_new_member_body", u.email, team.name)
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
User.find({team: team}, function(err, users) {
|
||||
finish(team, users);
|
||||
res.redirect("/spaces");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.redirect("/spaces?error=team_code_notfound");
|
||||
}
|
||||
} else {
|
||||
res.redirect("/spaces?error=team_notfound");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.redirect("/spaces?error=team_already");
|
||||
}
|
||||
} else res.redirect("/login");
|
||||
});
|
||||
|
||||
router.get('/qrcode/:id', function(req, res) {
|
||||
Space.findOne({"_id": req.params.id}).exec(function(err, space) {
|
||||
if (space) {
|
||||
|
||||
Reference in New Issue
Block a user