cozy-proxy
Version:
Cozy Proxy redirects requests properly to the right application of the Cozy platform depending on given path. It also handles authentication to the Cozy for users and devices.
230 lines (209 loc) • 6.48 kB
JavaScript
// Generated by CoffeeScript 1.10.0
var Client, RateLimiter, clientDS, createSharing, dsHost, dsPort, getProxy, limiter, remoteAccess, request, revokeFromRecipient, revokeFromSharer, utils;
Client = require('request-json').JsonClient;
remoteAccess = require('../lib/remote_access');
request = require('request-json');
utils = require('../helpers/utils');
RateLimiter = require('limiter').RateLimiter;
getProxy = require('../lib/proxy').getProxy;
dsHost = 'localhost';
dsPort = '9101';
clientDS = new Client("http://" + dsHost + ":" + dsPort + "/");
if (process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test") {
clientDS.setBasicAuth(process.env.NAME, process.env.TOKEN);
}
limiter = new RateLimiter(200, 'day', true);
createSharing = function(sharing, callback) {
sharing.docType = "Sharing";
return clientDS.post("data/", sharing, function(err, result, docInfo) {
return callback(err, docInfo);
});
};
revokeFromSharer = function(shareID, callback) {
var path;
path = "request/sharing/byShareID";
return clientDS.post(path, {
key: shareID
}, function(err, result, body) {
var id, ref;
if ((err != null) || (body.error != null) || body.length !== 1) {
return callback(err);
} else {
id = (ref = body[0]) != null ? ref.id : void 0;
return clientDS.del("access/" + id + "/", function(err, result, body) {
if (err != null) {
return callback(err);
} else {
return clientDS.del("data/" + id + "/", function(err, result, body) {
if (err != null) {
return callback(err);
} else {
return callback(null, id);
}
});
}
});
}
});
};
revokeFromRecipient = function(doc, target, callback) {
var err, i;
i = doc.targets.map(function(t) {
return t.recipientUrl;
}).indexOf(target.recipientUrl);
if (i < 0) {
err = new Error(target.recipientUrl + " not found for this sharing");
err.status = 404;
return callback(err);
} else {
doc.targets.splice(i, 1);
return clientDS.put("data/" + doc._id, doc, function(err, result, body) {
return callback(err);
});
}
};
module.exports.rateLimiter = function(req, res, next) {
return limiter.removeTokens(1, function(err, tokens) {
if (tokens < 0) {
err = new Error("Too many requests. Please try later");
err.status = 429;
return next(err);
} else {
return next();
}
});
};
module.exports.request = function(req, res, next) {
var err;
request = req.body;
if (utils.hasEmptyField(request, ["shareID", "sharerUrl", "recipientUrl", "rules", "desc", "preToken"])) {
err = new Error("Bad request");
err.status = 400;
return next(err);
}
if (utils.hasIncorrectStructure(request.rules, ["id", "docType"])) {
err = new Error("Bad request");
err.status = 400;
return next(err);
}
return createSharing(request, function(err, doc) {
var error;
if ((err != null) || (doc._id == null)) {
error = new Error("The sharing cannot be created");
error.status = 400;
return next(error);
} else {
return res.status(200).send({
success: true
});
}
});
};
module.exports.revoke = function(req, res, next) {
var authHeader, revoke;
revoke = req.body;
authHeader = req.headers['authorization'];
return remoteAccess.isAuthenticated(authHeader, function(auth) {
var error, ref, shareID, token;
if (auth) {
ref = remoteAccess.extractCredentials(authHeader), shareID = ref[0], token = ref[1];
return revokeFromSharer(shareID, function(err, id) {
if (err != null) {
return next(err);
}
return res.status(200).send({
success: true
});
});
} else {
error = new Error("Request unauthorized");
error.status = 401;
return next(error);
}
});
};
module.exports.revokeTarget = function(req, res, next) {
var authHeader, credential, ref, revoke, shareID, token;
revoke = req.body;
authHeader = req.headers['authorization'];
ref = remoteAccess.extractCredentials(authHeader), shareID = ref[0], token = ref[1];
credential = {
shareID: shareID,
token: token
};
return remoteAccess.isTargetAuthenticated(credential, function(auth, doc, target) {
var error;
if (auth) {
return revokeFromRecipient(doc, target, function(err) {
var error;
if (err != null) {
error = new Error("Cannot revoke the recipient");
error.status = 400;
return next(error);
} else {
return res.status(200).send({
success: true
});
}
});
} else {
error = new Error("Request unauthorized");
error.status = 401;
return next(error);
}
});
};
module.exports.answer = function(req, res, next) {
var answer, authHeader, credential, err, ref, shareID, token;
answer = req.body;
if (utils.hasEmptyField(answer, ["recipientUrl", "accepted"])) {
err = new Error("Bad request");
err.status = 400;
return next(err);
}
if (answer.accepted && utils.hasEmptyField(answer, ["token"])) {
err = new Error("Bad request");
err.status = 400;
return next(err);
}
authHeader = req.headers['authorization'];
ref = remoteAccess.extractCredentials(authHeader), shareID = ref[0], token = ref[1];
credential = {
shareID: shareID,
token: token
};
return remoteAccess.isTargetAuthenticated(credential, function(auth) {
var error;
if (auth) {
answer.shareID = shareID;
answer.preToken = token;
return clientDS.post(req.url, answer, function(err, result, body) {
if (err != null) {
return next(err);
}
return res.status(200).send({
success: true
});
});
} else {
error = new Error("Request unauthorized");
error.status = 401;
return next(error);
}
});
};
module.exports.replication = function(req, res, next) {
return remoteAccess.isAuthenticated(req.headers['authorization'], function(auth) {
var error;
if (auth) {
req.url = req.url.replace('services/sharing/', '');
return getProxy().web(req, res, {
target: "http://" + dsHost + ":" + dsPort
});
} else {
error = new Error("Request unauthorized");
error.status = 401;
return next(error);
}
});
};