diff --git a/services/upload/package.json b/services/upload/package.json index 1a4a2e0b..4e8a449f 100644 --- a/services/upload/package.json +++ b/services/upload/package.json @@ -11,8 +11,10 @@ "license": "ISC", "dependencies": { "body-parser": "^1.15.2", + "cookie-parser": "^1.4.4", "cors": "^2.8.4", - "express": "^4.14.0", - "multer": "^1.1.0" + "express": "^4.17.1", + "multer": "^1.1.0", + "properties-reader": "0.0.16" } } diff --git a/services/upload/properties.file b/services/upload/properties.file new file mode 100644 index 00000000..b7d0ba44 --- /dev/null +++ b/services/upload/properties.file @@ -0,0 +1,4 @@ +userInfoUrl = http://scoobydoo.di.uoa.gr:8080/dnet-openaire-users-1.0.0-SNAPSHOT/api/users/getUserInfo?accessToken= +originServer = .di.uoa.gr +post.allowed = /upload +ssl = false diff --git a/services/upload/uploadService.js b/services/upload/uploadService.js index 13cd778a..4b1da745 100644 --- a/services/upload/uploadService.js +++ b/services/upload/uploadService.js @@ -1,54 +1,227 @@ var express = require("express"); var bodyParser = require("body-parser"); +var cookieParser = require('cookie-parser'); var multer = require("multer"); +var PropertiesReader = require('properties-reader'); +var properties = PropertiesReader('./properties.file'); var app = express(); -var cors = require('cors') -app.use(cors()); +var http = null; + +if(properties.get('ssl')) { + http = require("https"); +} else { + http = require("http"); +} + + +// Properties +var auth = properties.get('userInfoUrl'); +var originServer = properties.get('originServer'); +var allowPostRequests = properties.get('post.allowed').split(','); + +var storage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, 'uploads') + }, + filename: function (req, file, cb) { + if(req.params.id) { + cb(null, req.params.id + '-' + new Date().getTime() + '.' + file.originalname.split('.').pop()); + } else { + cb(null, file.originalname); + } + } +}); + +var upload = multer({ storage: storage }) app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.urlencoded({extended: true})); +app.use(cookieParser()); -app.use(function(req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); - next(); +app.use(function (req, res, next) { + if((req.method === 'POST' || req.method === 'DELETE') && allowPostRequests.indexOf(req.url) === -1) { + if(checkCookies(req)) { + res.header('Access-Control-Allow-Origin', req.headers.origin); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, x-xsrf-token'); + res.header('Access-Control-Allow-Credentials', true); + next(); + } else { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Credentials', true); + res.header('Vary', 'Origin'); + res.status(403).send(getResponse(403, "Forbidden: You don't have permission to access. Maybe you are not registered.")); + } + } else if(req.method === 'OPTIONS' && allowPostRequests.indexOf(req.url) === -1){ + res.header('Access-Control-Allow-Origin', req.headers.origin); + res.header('Access-Control-Allow-Credentials', true); + res.header('Access-Control-Allow-Methods', 'POST, DELETE'); + res.header('Access-Control-Max-Age', 1800); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, x-xsrf-token'); + next(); + } else { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + next(); + } }); -app.post("/upload", multer({dest: "/home/argirok/projects/openaire/uoa-services-portal/trunk/services/upload/uploads/"}).array("uploads[]", 12), function(req, res) { - var filepath ="/"+req.files[0].path; - console.log(req.files[0]); - if (req.files[0].mimetype != 'text/csv') { - console.error("No proper file type"); - res.status(500).send(getResponse(500,"No proper file type")) ; - }else{ - //send file - res.sendFile(filepath); - } - var fs = require('fs'); - fs.stat(filepath, function (err, stats) { - console.log(stats);//here we got all information of file in stats variable - - if (err) { - return console.error(err); - } - - fs.unlink(filepath,function(err){ - if(err) return console.log(err); - console.log('file deleted successfully'); - }); -}); +app.post("/upload", upload.array("uploads[]", 12), function (req, res) { + var filepath = "./" + req.files[0].path; + if (req.files[0].mimetype !== 'text/csv') { + console.error("No proper file type"); + res.status(500).send(getResponse(500, "No proper file type")); + } else { + //send file + res.download(filepath); + } + deleteFile(filepath); }); -app.get('/get/d6bd36a06762e2f0da891f9670fcb2b0', function(req, res) { - res.sendFile('uploads/d6bd36a06762e2f0da891f9670fcb2b0') -}) -var server = app.listen(8000, function() { + +app.post('/upload/:id', upload.single('photo'), (req, res) => { + const token = req.headers['x-xsrf-token']; + const file = req.file; + const filepath = "./" + file.path; + if(!token) { + res.status(401).send(getResponse(401, "Unauthorized")); + deleteFile(filepath); + } + else if (!file || (file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png')) { + res.status(500).send(getResponse(500, "No image file type")); + deleteFile(filepath); + } + else { + http.get(auth+token, function (resp) { + var responseString = ""; + resp.on("data", function (data) { + responseString += data; + }); + resp.on("end", function () { + var result = JSON.parse(responseString); + if(result.error) { + res.status(401).send(getResponse(401, "Unauthorized")); + deleteFile(filepath); + } else { + // if user id contains id param or is Admin or Curator keep file and send information, else delete it. + if(result.sub.indexOf(req.params.id) !== -1 || isAdminOrCurator(result.edu_person_entitlements)) { + res.send(file); + } else { + res.status(401).send(getResponse(401, "Unauthorized")); + deleteFile(filepath); + } + } + }); + }); + } + +}); + +app.get('/download/:filename', function (req, res) { + res.download('./uploads/' + req.params.filename); +}); + +app.delete('/delete/:filename', function (req, res) { + const token = req.headers['x-xsrf-token']; + if(!token) { + res.status(401).send(getResponse(401, "Unauthorized")); + } else { + http.get(auth+token, function (resp) { + var responseString = ""; + resp.on("data", function (data) { + responseString += data; + }); + resp.on("end", function () { + var result = JSON.parse(responseString); + if(result.error) { + res.status(401).send(getResponse(401, "Unauthorized")); + } else { + // if user id is on filename or is Admin delete file else unauthorized. + if(result.sub.indexOf(req.params.filename.split('-')[0]) !== -1 || isAdminOrCurator(result.edu_person_entitlements)) { + deleteFile('./uploads/' + req.params.filename); + return res.status(200).send(getResponse(200, "File Deleted Successfully")); + } else { + res.status(401).send(getResponse(401, "Unauthorized")); + } + } + }); + }); + } +}); + +const server = app.listen(8000, function () { console.log("Listening on port %s...", server.address().port); }); -function getResponse(code, message){ - var response ={}; - response["code"]=code; - response["message"]=message; - return response; +function getResponse(code, message) { + var response = {}; + response["code"] = code; + response["message"] = message; + return response; } + +function deleteFile(filepath) { + const fs = require('fs'); + fs.stat(filepath, function (err, stats) { + console.log(stats); //here we got all information of file in stats variable + + if (err) { + return console.error(err); + } + + fs.unlink(filepath, function (err) { + if (err) return console.log(err); + console.log('file deleted successfully'); + }); + }); +} + +function isAdminOrCurator(roles) { + var isAdmin = false; + var isCurator = false; + for(var i = 0; i < roles.length; i++) { + if(roles[i] === 'urn:geant:openaire.eu:group:Portal+Administrator#aai.openaire.eu') { + isAdmin = true; + } + if(roles[i] === 'urn:geant:openaire.eu:group:Curator+-+Community#aai.openaire.eu') { + isCurator = true; + } + } + return isAdmin || isCurator; +} + +function checkCookies(request){ + var valid = true; + var cookieValue = request.cookies.AccessToken; + if(cookieValue === undefined || cookieValue === ''){ + console.log("no cookie available"); + valid = false; + } else { + const headerValue = request.headers['x-xsrf-token']; + if(headerValue === undefined || headerValue === ''){ + console.log("no header available"); + valid = false; + } else{ + if(cookieValue !== headerValue){ + console.log("no proper header or cookie"); + valid = false; + } else if(!hasValidOrigin(request.headers.origin)){ + console.log("no proper origin"); + valid = false; + } + } + } + return valid; +} + + +function hasValidOrigin(origin) { + if(origin !== undefined && origin.indexOf(originServer) !== -1) { + return true; + } else { + console.log("Not valid origin. Origin server is \"" + origin + + "\", but expected value is \"" + originServer + + "\". If the expected value is not right, check originServer variable."); + return false; + } +} +