initial commit.
This commit is contained in:
19
middlewares/404.js
Normal file
19
middlewares/404.js
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
var err = new Error('Not Found');
|
||||
if (req.accepts('text/html')) {
|
||||
res.status(404).render('not_found', {
|
||||
title: 'Page Not Found.'
|
||||
});
|
||||
} else if (req.accepts('application/json')) {
|
||||
res.status(404).json({
|
||||
"error": "not_found"
|
||||
});
|
||||
} else {
|
||||
res.status(404).send("Not Found.");
|
||||
}
|
||||
}
|
||||
10
middlewares/500.js
Normal file
10
middlewares/500.js
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = (err, req, res, next) => {
|
||||
console.error(err);
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
message: err.message,
|
||||
error: {}
|
||||
});
|
||||
}
|
||||
55
middlewares/api_helpers.js
Normal file
55
middlewares/api_helpers.js
Normal file
@@ -0,0 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
const redis = require('../helpers/redis');
|
||||
|
||||
var saveAction = (actionKey, object) => {
|
||||
if (object.constructor.modelName == "Space")
|
||||
return;
|
||||
|
||||
let attr = {
|
||||
action: actionKey,
|
||||
space: object.space_id || object.space,
|
||||
user: object.user_id || object.user,
|
||||
editor_name: object.editor_name,
|
||||
object: object.toJSON()
|
||||
};
|
||||
|
||||
let action = new Action(attr);
|
||||
action.save(function(err) {
|
||||
if (err)
|
||||
console.error("saved create action err:", err);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
res.header("Cache-Control", "no-cache");
|
||||
|
||||
req['channelId'] = req.headers['x-spacedeck-channel'];
|
||||
req['spacePassword'] = req.headers['x-spacedeck-spacepassword'];
|
||||
req['spaceAuth'] = req.query['spaceAuth'] || req.headers['x-spacedeck-space-auth'];
|
||||
|
||||
res['distributeCreate'] = function(model, object) {
|
||||
if (!object) return;
|
||||
redis.sendMessage("create", model, object.toJSON(), req.channelId);
|
||||
this.status(201).json(object.toJSON());
|
||||
saveAction("create", object);
|
||||
};
|
||||
|
||||
res['distributeUpdate'] = function(model, object) {
|
||||
if (!object) return;
|
||||
redis.sendMessage("update", model, object.toJSON(), req.channelId);
|
||||
this.status(200).json(object.toJSON());
|
||||
saveAction("update", object);
|
||||
};
|
||||
|
||||
res['distributeDelete'] = function(model, object) {
|
||||
if (!object) return;
|
||||
redis.sendMessage("delete", model, object.toJSON(), req.channelId);
|
||||
this.sendStatus(204);
|
||||
saveAction("delete", object);
|
||||
};
|
||||
|
||||
next();
|
||||
}
|
||||
22
middlewares/artifact_helpers.js
Normal file
22
middlewares/artifact_helpers.js
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
var artifactId = req.params.artifact_id;
|
||||
Artifact.findOne({
|
||||
"_id": artifactId
|
||||
}, (err, artifact) => {
|
||||
if (err) {
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
if (artifact) {
|
||||
req['artifact'] = artifact;
|
||||
next();
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
48
middlewares/cors.js
Normal file
48
middlewares/cors.js
Normal file
@@ -0,0 +1,48 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
const config = require('config');
|
||||
const url = require('url');
|
||||
|
||||
function respond(origin, req, res, next) {
|
||||
res.header('Access-Control-Allow-Origin', origin);
|
||||
res.header('Access-Control-Allow-Credentials', true);
|
||||
res.header('Access-Control-Max-Age', 60 * 60 * 24);
|
||||
res.header('Access-Control-Expose-Headers', 'Accepts, Content-Type, X-Spacedeck-Space-Role, X-Spacedeck-Channel, X-Spacedeck-Spacepassword, X-Spacedeck-Auth, X-Spacedeck-Space-Auth');
|
||||
res.header('Access-Control-Allow-Headers', 'Accepts, Accept-Language, Accept-Encoding, Accept-Language, Content-Type, X-Spacedeck-Space-Auth, X-Spacedeck-Space-Role, X-Spacedeck-Channel, X-Spacedeck-Spacepassword, X-Spacedeck-Auth');
|
||||
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
|
||||
|
||||
if (req.method == 'OPTIONS') {
|
||||
res.sendStatus(204);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
const origin = req.headers.origin;
|
||||
|
||||
if (origin) {
|
||||
const parsedUrl = url.parse(origin, true, true);
|
||||
|
||||
// FIXME
|
||||
if (parsedUrl.hostname == "cdn.spacedeck.com") {
|
||||
res.header('Cache-Control', "max-age");
|
||||
res.header('Expires', "30d");
|
||||
res.removeHeader("Pragma");
|
||||
|
||||
respond(origin, req, res, next);
|
||||
} else {
|
||||
Team.getTeamForHost(parsedUrl.hostname, (err, team, subdomain) => {
|
||||
if (team) {
|
||||
respond(origin, req, res, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
16
middlewares/error_helpers.js
Normal file
16
middlewares/error_helpers.js
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
res.bad_request = (msg) => {
|
||||
if (req.accepts('text/html')) {
|
||||
res.status(400).render('error', {
|
||||
message: msg
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({
|
||||
"error": msg
|
||||
});
|
||||
}
|
||||
}
|
||||
next();
|
||||
}
|
||||
17
middlewares/i18n.js
Normal file
17
middlewares/i18n.js
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
req.i18n.setLocale(req.i18n.prefLocale);
|
||||
|
||||
if (req.cookies.spacedeck_locale) {
|
||||
req.i18n.setLocaleFromCookie();
|
||||
}
|
||||
|
||||
if (req.user && req.user.preferences.language) {
|
||||
req.i18n.setLocale(req.user.preferences.language);
|
||||
}
|
||||
next();
|
||||
}
|
||||
38
middlewares/setuser.js
Normal file
38
middlewares/setuser.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
const token = req.cookies["sdsession"];
|
||||
if (token && token != "null" && token !== null) {
|
||||
User.findOne({
|
||||
"sessions.token": token
|
||||
}).populate('team').exec((err, user) => {
|
||||
if (!user) {
|
||||
// FIXME
|
||||
var domain = "localhost";
|
||||
res.clearCookie('sdsession', {
|
||||
domain: domain
|
||||
});
|
||||
|
||||
if (req.accepts("text/html")) {
|
||||
res.redirect("/");
|
||||
} else if (req.accepts('application/json')) {
|
||||
res.status(403).json({
|
||||
"error": "token_not_found"
|
||||
});
|
||||
} else {
|
||||
res.redirect("/");
|
||||
}
|
||||
|
||||
} else {
|
||||
req["token"] = token;
|
||||
req["user"] = user;
|
||||
next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
160
middlewares/space_helpers.js
Normal file
160
middlewares/space_helpers.js
Normal file
@@ -0,0 +1,160 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
let spaceId = req.params.id;
|
||||
|
||||
let finalizeReq = (space, role) => {
|
||||
if (role === "none") {
|
||||
res.status(403).json({
|
||||
"error": "access denied"
|
||||
});
|
||||
} else {
|
||||
req['space'] = space;
|
||||
req['spaceRole'] = role;
|
||||
res.header("x-spacedeck-space-role", req['spaceRole']);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
var rolePerUser = (originalSpace, user, cb) => {
|
||||
originalSpace.path = [];
|
||||
|
||||
if (originalSpace._id.equals(req.user.home_folder_id) || (originalSpace.creator && originalSpace.creator._id.equals(req.user._id))) {
|
||||
cb("admin");
|
||||
} else {
|
||||
var findMembershipsForSpace = function(space, allMemberships, prevRole) {
|
||||
Membership.find({
|
||||
"space": space._id
|
||||
}, function(err, parentMemberships) {
|
||||
var currentMemberships = parentMemberships.concat(allMemberships);
|
||||
|
||||
if (space.parent_space_id) {
|
||||
Space.findOne({
|
||||
"_id": space.parent_space_id
|
||||
}, function(err, parentSpace) {
|
||||
findMembershipsForSpace(parentSpace, currentMemberships, prevRole);
|
||||
});
|
||||
} else {
|
||||
// reached the top
|
||||
|
||||
var role = prevRole;
|
||||
space.memberships = currentMemberships;
|
||||
|
||||
if(role == "none"){
|
||||
if(originalSpace.access_mode == "public") {
|
||||
role = "viewer";
|
||||
}
|
||||
}
|
||||
|
||||
currentMemberships.forEach(function(m, i) {
|
||||
if (m.user && m.user.equals(user._id)) {
|
||||
role = m.role;
|
||||
}
|
||||
});
|
||||
|
||||
cb(role);
|
||||
}
|
||||
});
|
||||
};
|
||||
findMembershipsForSpace(originalSpace, [], "none");
|
||||
}
|
||||
};
|
||||
|
||||
var finalizeAnonymousLogin = function(space, spaceAuth) {
|
||||
var role = "none";
|
||||
|
||||
if (spaceAuth && (spaceAuth === space.edit_hash)) {
|
||||
role = "editor";
|
||||
} else {
|
||||
if (space.access_mode == "public") {
|
||||
role = "viewer";
|
||||
} else {
|
||||
role = "none";
|
||||
}
|
||||
}
|
||||
|
||||
if (req.user) {
|
||||
rolePerUser(space, req.user, function(newRole) {
|
||||
if (newRole == "admin" && (role == "editor" || role == "viewer")) {
|
||||
finalizeReq(space, newRole);
|
||||
} else if (newRole == "editor" && (role == "viewer")) {
|
||||
finalizeReq(space, newRole);
|
||||
} else {
|
||||
finalizeReq(space, role);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
finalizeReq(space, role);
|
||||
}
|
||||
};
|
||||
|
||||
var userMapping = {
|
||||
'_id': 1,
|
||||
'nickname': 1,
|
||||
'email': 1
|
||||
};
|
||||
|
||||
Space.findOne({
|
||||
"_id": spaceId
|
||||
}).populate("creator", userMapping).exec(function(err, space) {
|
||||
if (err) {
|
||||
res.status(400).json(err);
|
||||
} else {
|
||||
if (space) {
|
||||
|
||||
if (space.access_mode == "public") {
|
||||
|
||||
if (space.password) {
|
||||
if (req.spacePassword) {
|
||||
if (req.spacePassword === space.password) {
|
||||
finalizeAnonymousLogin(space, req["spaceAuth"]);
|
||||
} else {
|
||||
res.status(403).json({
|
||||
"error": "password_wrong"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
res.status(401).json({
|
||||
"error": "password_required"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
finalizeAnonymousLogin(space, req["spaceAuth"]);
|
||||
}
|
||||
|
||||
} else {
|
||||
// special permission for screenshot/pdf export from backend
|
||||
if (req.query['api_token'] && req.query['api_token'] == config.get('phantom_api_secret')) {
|
||||
finalizeReq(space, "viewer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.user) {
|
||||
rolePerUser(space, req.user, function(role) {
|
||||
if (role == "none") {
|
||||
finalizeAnonymousLogin(space, req["spaceAuth"]);
|
||||
} else {
|
||||
finalizeReq(space, role);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (req.spaceAuth && space.edit_hash) {
|
||||
finalizeAnonymousLogin(space, req["spaceAuth"]);
|
||||
} else {
|
||||
res.status(403).json({
|
||||
"error": "auth_required"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res.status(404).json({
|
||||
"error": "space_not_found"
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
33
middlewares/subdomain.js
Normal file
33
middlewares/subdomain.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
let host = req.headers.host;
|
||||
Team.getTeamForHost(host, (err, team, subdomain) => {
|
||||
if (subdomain) {
|
||||
if (!err && team) {
|
||||
req.subdomainTeam = team;
|
||||
req.subdomain = subdomain;
|
||||
next()
|
||||
} else {
|
||||
if (req.accepts('text/html')) {
|
||||
res.status(404).render('not_found', {
|
||||
title: 'Page Not Found.'
|
||||
});
|
||||
} else if (req.accepts('application/json')) {
|
||||
res.status(404).json({
|
||||
"error": "not_found"
|
||||
});
|
||||
} else {
|
||||
res.status(404).render('not_found', {
|
||||
title: 'Page Not Found.'
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
23
middlewares/team_helpers.js
Normal file
23
middlewares/team_helpers.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
if (req.user) {
|
||||
var isAdmin = req.user.team.admins.indexOf(req.user._id) >= 0;
|
||||
var correctMethod = req.method == "GET" || (req.method == "DELETE" || req.method == "PUT" || req.method == "POST");
|
||||
|
||||
if (correctMethod && isAdmin) {
|
||||
next();
|
||||
} else {
|
||||
res.status(403, {
|
||||
"error": "not authorized"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
res.status(403, {
|
||||
"error": "not logged in"
|
||||
});
|
||||
}
|
||||
}
|
||||
31
middlewares/templates.js
Normal file
31
middlewares/templates.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
require('../models/schema');
|
||||
var config = require('config');
|
||||
var _ = require('underscore');
|
||||
|
||||
module.exports = (req, res, next) => {
|
||||
res.oldRender = res.render;
|
||||
res.render = function(template, params) {
|
||||
|
||||
var team = req.subdomainTeam;
|
||||
if (team) {
|
||||
team = _.pick(team.toObject(), ['_id', 'name', 'subdomain', 'avatar_original_uri']);
|
||||
} else {
|
||||
team = null;
|
||||
}
|
||||
|
||||
const addParams = {
|
||||
locale: req.i18n.locale,
|
||||
config: config,
|
||||
subdomain_team: team,
|
||||
user: req.user,
|
||||
csrf_token: "",
|
||||
socket_auth: req.token
|
||||
};
|
||||
|
||||
const all = _.extend(params, addParams);
|
||||
res.oldRender(template, all);
|
||||
};
|
||||
next();
|
||||
}
|
||||
Reference in New Issue
Block a user