UNPKG

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.

402 lines (376 loc) 10.8 kB
// Generated by CoffeeScript 1.10.0 var Client, appManager, checkLogin, clientDS, createDevice, defaultPermissions, deviceExists, getCredentialsHeader, getProxy, initAuth, log, passport, randomString, remoteAccess, removeDevice, updateDevice, urlHelper; Client = require('request-json').JsonClient; passport = require('passport'); urlHelper = require('cozy-url-sdk'); remoteAccess = require('../lib/remote_access'); appManager = require('../lib/app_manager'); getProxy = require('../lib/proxy').getProxy; log = require('printit')({ date: false, prefix: 'controllers:devices' }); clientDS = new Client(urlHelper.dataSystem.url()); if (process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test") { clientDS.setBasicAuth(process.env.NAME, process.env.TOKEN); } defaultPermissions = { 'File': { 'description': 'Usefull to synchronize your files' }, 'Folder': { 'description': 'Usefull to synchronize your folder' }, 'Binary': { 'description': 'Usefull to synchronize the content of your files' }, 'Notification': { 'description': 'Usefull to synchronize cozy notifications' } }; randomString = function(length) { var string; string = ""; while (string.length < length) { string = string + Math.random().toString(36).substr(2); } return string.substr(0, length); }; getCredentialsHeader = function() { var basicCredentials, credentials; credentials = process.env.NAME + ":" + process.env.TOKEN; basicCredentials = new Buffer(credentials).toString('base64'); return "Basic " + basicCredentials; }; deviceExists = function(login, cb) { return clientDS.post("request/device/byLogin/", { key: login }, function(err, result, body) { var ref; if (err) { return cb(err); } else if (body.length === 0) { return cb(null, false); } else { return cb(null, (ref = body[0]) != null ? ref.value : void 0); } }); }; checkLogin = function(login, wantExist, cb) { var error; if (login == null) { error = new Error("Name isn't defined in req.body.login"); error.status = 400; return cb(error); } else { return deviceExists(login, function(err, device) { if (err) { return next(err); } else if (device) { if (wantExist) { return cb(null, device); } else { error = new Error("This name is already used"); error.status = 400; return cb(error); } } else { if (wantExist) { error = new Error("This device doesn't exist"); error.status = 400; return cb(error); } else { return cb(); } } }); } }; initAuth = function(req, cb) { var authHeader, password, ref, user, username; authHeader = req.headers['authorization']; ref = remoteAccess.extractCredentials(authHeader), username = ref[0], password = ref[1]; user = {}; user.body = { username: username, password: password }; req.headers['authorization'] = void 0; return cb(user); }; createDevice = function(device, cb) { var access; device.docType = "Device"; access = { login: device.login, password: randomString(32), permissions: device.permissions || defaultPermissions }; delete device.permissions; return clientDS.post("data/", device, function(err, result, docInfo) { if (err != null) { return cb(err); } access.app = docInfo._id; return clientDS.post('access/', access, function(err, result, body) { var data; if (err != null) { return cb(err); } data = { password: access.password, login: device.login, permissions: access.permissions }; return cb(null, data); }); }); }; updateDevice = function(oldDevice, device, callback) { var path; path = "request/access/byApp/"; return clientDS.post(path, { key: oldDevice._id }, function(err, result, accesses) { var access, error, oldAccess; if (err) { return callback(err); } if (accesses.length === 0) { error = new Error("No access to this app."); return callback(error); } oldAccess = accesses[0].value; access = { login: oldAccess.login, password: oldAccess.token, app: oldAccess.app, permissions: device.permissions || oldAccess.permissions }; path = "access/" + access.app + "/"; return clientDS.put(path, access, function(err, result, body) { if (err) { return callback(err); } oldDevice.login = device.login; delete oldDevice.permissions; path = "data/" + oldDevice._id; return clientDS.put(path, oldDevice, function(err, result, body) { var data; data = { login: access.login, password: access.password, permissions: access.permissions }; return callback(err, data); }); }); }); }; removeDevice = function(device, cb) { var id; id = device._id; return clientDS.del("access/" + id + "/", function(err, result, body) { var error; if (err != null) { error = new Error(err); error.status = 400; return cb(error); } else { return clientDS.del("data/" + id + "/", function(err, result, body) { if (err != null) { error = new Error(err); error.status = 400; return cb(error); } else { return cb(null); } }); } }); }; module.exports.create = function(req, res, next) { var authenticator; authenticator = passport.authenticate('local', function(err, user) { var device, error; if (err) { log.warn(err); return next(err); } else if (user === void 0 || !user) { error = new Error("Bad credentials"); error.status = 401; return next(error); } else { device = req.body; return checkLogin(device.login, false, function(err) { if (err != null) { return next(err); } device.docType = "Device"; return createDevice(device, function(err, data) { if (err != null) { return next(err); } else { return res.status(201).send(data); } }); }); } }); return initAuth(req, function(user) { return authenticator(user, res); }); }; module.exports.update = function(req, res, next) { var authenticator; authenticator = passport.authenticate('local', function(err, user) { var device, error, login; if (err) { console.log(err); return next(err); } else if (user === void 0 || !user) { error = new Error("Bad credentials"); error.status = 401; return next(error); } else { login = req.params.login; device = req.body; return checkLogin(login, true, function(err, oldDevice) { if (err != null) { return next(err); } device.docType = "Device"; return updateDevice(oldDevice, device, function(err, data) { if (err != null) { return next(err); } else { return res.status(200).send(data); } }); }); } }); return initAuth(req, function(user) { return authenticator(user, res); }); }; module.exports.remove = function(req, res, next) { var authHeader, authenticator, deviceName, password, ref, remove, username; authHeader = req.headers['authorization']; ref = remoteAccess.extractCredentials(authHeader), username = ref[0], password = ref[1]; deviceName = req.params.login; remove = function() { return checkLogin(deviceName, true, function(err, device) { if (err != null) { return next(err); } return removeDevice(device, function(err) { if (err != null) { return next(err); } else { return res.sendStatus(204); } }); }); }; if (deviceName === username) { return remoteAccess.isAuthenticated(authHeader, function(auth) { var error; if (auth) { return remove(); } else { error = new Error("Request unauthorized"); error.status = 401; return next(error); } }); } else { authenticator = passport.authenticate('local', function(err, user) { var error; if (err) { console.log(err); return next(err); } else if (user === void 0 || !user) { error = new Error("Bad credentials"); error.status = 401; return next(error); } else { return remove(); } }); return initAuth(req, function(user) { return authenticator(user, res); }); } }; module.exports.replication = function(req, res, next) { return remoteAccess.isAuthenticated(req.headers['authorization'], function(auth) { var error; if (auth) { return getProxy().web(req, res, { target: urlHelper.dataSystem.url() }); } else { error = new Error("Request unauthorized"); error.status = 401; return next(error); } }); }; module.exports.dsApi = function(req, res, next) { var authHeader; authHeader = req.headers['authorization'] || req.query.authorization; return remoteAccess.isAuthenticated(authHeader, function(auth) { var error; if (auth) { req.url = req.url.replace('ds-api/', ''); return getProxy().web(req, res, { target: urlHelper.dataSystem.url() }); } else { error = new Error("Request unauthorized"); error.status = 401; return next(error); } }); }; module.exports.getVersions = function(req, res, next) { return remoteAccess.isAuthenticated(req.headers['authorization'], function(auth) { var error; if (auth) { return appManager.versions(function(err, apps) { var error; if (err != null) { error = new Error(err); error.status = 400; return next(error); } else { return res.status(200).send(apps); } }); } else { error = new Error("Request unauthorized"); error.status = 401; return next(error); } }); }; module.exports.oldReplication = function(req, res, next) { return remoteAccess.isAuthenticated(req.headers['authorization'], function(auth) { var error; if (auth) { if (process.env.NODE_ENV === "production") { req.headers['authorization'] = getCredentialsHeader(); } else { req.headers['authorization'] = null; } return getProxy().web(req, res, { target: urlHelper.couch.url() }); } else { error = new Error("Request unauthorized"); error.status = 401; return next(error); } }); };