diff --git a/caracal.js b/caracal.js index cbb9ed6..6eb81ff 100644 --- a/caracal.js +++ b/caracal.js @@ -14,7 +14,8 @@ const fs = require('fs'); const auth = require('./handlers/authHandlers.js'); const monitor = require('./handlers/monitorHandlers.js'); const userFunction = require('./handlers/userFunction.js'); -const iipHandler = require('./handlers/iipHandler.js'); +const iipHandlers = require('./handlers/iipHandler.js'); +const pdbIipHandlers = require('./handlers/pathdbIipHandler.js'); const proxyHandler = require('./handlers/proxyHandler.js'); const permissionHandler = require('./handlers/permssionHandler.js'); const dataHandlers = require('./handlers/dataHandlers.js'); @@ -91,7 +92,13 @@ var HANDLERS = { "proxyHandler": proxyHandler, "writeFile": fileHandlers.writeFile, "iipHandler": function() { - return iipHandler; + return iipHandlers.iipHandler; + }, + "preIip": function() { + return iipHandlers.preIip; + }, + "iipCheck": function() { + return pdbIipHandlers.iipCheck; }, "markMulti": function() { return dataHandlers.Mark.multi; diff --git a/handlers/authHandlers.js b/handlers/authHandlers.js index 1e55336..26a2df8 100644 --- a/handlers/authHandlers.js +++ b/handlers/authHandlers.js @@ -301,6 +301,7 @@ auth.tokenTrade = tokenTrade; auth.filterHandler = filterHandler; auth.loginHandler = loginHandler; auth.editHandler = editHandler; +auth.getToken = getToken; auth.firstSetupUserSignupExists = firstSetupUserSignupExists; auth.loginWithHeader = loginWithHeader; auth.CLIENT = CLIENT; diff --git a/handlers/iipHandler.js b/handlers/iipHandler.js index d7cacd5..379d91f 100644 --- a/handlers/iipHandler.js +++ b/handlers/iipHandler.js @@ -2,7 +2,7 @@ var proxy = require('http-proxy-middleware'); var IIP_PATH = process.env.IIP_PATH || 'http://ca-iip/'; -iipHandler = function(req, res, next) { +preIip = function(req, res, next) { if (req.query) { if (req.query.DeepZoom) { if (req.query.DeepZoom.endsWith('.dzi')) { @@ -12,13 +12,25 @@ iipHandler = function(req, res, next) { // just in case _files is in the filename for some reason req.iipFileRequested = req.query.DeepZoom.split('_files').slice(0, -1).join('/'); } + } else if (req.query.IIIF) { + req.iipFileRequested = req.query.IIIF.split("/")[0]; } else if (req.query.FIF) { req.iipFileRequested = req.query.FIF; } else { req.iipFileRequested = false; } } + console.log(req.iipFileRequested); + next(); +}; + +function RemoveParameterFromUrl(url, parameter) { + return url + .replace(new RegExp('[?&]' + parameter + '=[^&#]*(#.*)?$'), '$1') + .replace(new RegExp('([?&])' + parameter + '=[^&]*&'), '$1'); +} +iipHandler = function(req, res, next) { proxy({ secure: false, onError(err, req, res) { @@ -29,8 +41,14 @@ iipHandler = function(req, res, next) { changeOrigin: true, target: IIP_PATH, pathRewrite: function(path, req) { + if (req.newFilepath) { + path = path.replace(req.iipFileRequested, req.newFilepath); + } + // remove token if present + path = RemoveParameterFromUrl(path, "token"); // NOTE -- this may need to change if the original url has more subdirs or so added var splitPath = path.split('/'); + console.log(path); return '/' + splitPath.slice(2, splitPath.length).join('/'); }, onProxyReq: function(proxyReq, req, res) { @@ -42,5 +60,9 @@ iipHandler = function(req, res, next) { })(req, res, next); }; +iipHandlers = {}; +iipHandlers.preIip = preIip; +iipHandlers.iipHandler = iipHandler; + -module.exports = iipHandler; +module.exports = iipHandlers; diff --git a/handlers/pathdbIipHandler.js b/handlers/pathdbIipHandler.js new file mode 100644 index 0000000..78a7eec --- /dev/null +++ b/handlers/pathdbIipHandler.js @@ -0,0 +1,60 @@ +// EXTENDS authHandlers +const proxy = require('http-proxy-middleware'); +var jwt = require('jsonwebtoken'); +var EXPIRY = process.env.EXPIRY || '1d'; +var BYPASS_IIP_CHECK = process.env.BYPASS_IIP_CHECK == "Y"; +const auth = require('./authHandlers.js'); +const fetch = require('cross-fetch'); + +// internal function to issue a new jwt +function issueToken(data, signKey) { + return jwt.sign(data, signKey, { + algorithm: 'RS256', + expiresIn: EXPIRY, + }); +} + +iipCheck = function(req, res, next) { + if (!BYPASS_IIP_CHECK) { + if (req.iipFileRequested) { + // rewrite path first + const PDB_URL = process.env.PDB_URL || 'http://quip-pathdb'; + let requestedNode = req.iipFileRequested.replace("pathdb*", ""); + let lookupUrl = PDB_URL + "/node/" + requestedNode + "?_format=json"; + console.log(lookupUrl); + let pdbReqHeaders = {"Authorization": "Bearer " + auth.getToken(req)}; + console.log(pdbReqHeaders); + fetch(lookupUrl, {headers: pdbReqHeaders}).then((x)=>x.json()).then((x)=>{ + console.log(x); + // get path + if (x && x['field_iip_path'] && x['field_iip_path'].length && x['field_iip_path'][0]['value']) { + req.newFilepath = x['field_iip_path'][0]['value']; + console.log(req.newFilepath); + next(); + } else { + let err = {}; + err.message = "unauthorized slide request"; + err.statusCode = 401; + next(err); + } + }).catch((e)=>{ + console.error(e); + next(e); + }); + } else { + // do not return + let err = {}; + err.message = "unauthorized slide request"; + err.statusCode = 401; + next(err); + } + } else { + // NOTE -- this instead uses the actual value given instead + next(); + } +}; + +let pih = {}; +pih.iipCheck = iipCheck; + +module.exports = pih; diff --git a/package-lock.json b/package-lock.json index 51cd2c0..991e9d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -284,17 +284,17 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz", + "integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==", "requires": { - "follow-redirects": "^1.14.0" + "follow-redirects": "^1.14.8" }, "dependencies": { "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" } } }, @@ -572,6 +572,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1526,6 +1534,14 @@ "debug": "4" } }, + "axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "requires": { + "follow-redirects": "^1.14.0" + } + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -1541,6 +1557,11 @@ } } }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -1960,6 +1981,40 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2589,6 +2644,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", @@ -2664,11 +2724,25 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, "webworkify": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/webworkify/-/webworkify-1.5.0.tgz", "integrity": "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g==" }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index ad5d43c..49bee32 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "ajv": "^8.6.0", "ajv-keywords": "^5.0.0", "atob": "^2.1.2", + "cross-fetch": "^3.1.5", "dotenv": "^8.6.0", "express": "^4.17.1", "helmet": "^4.6.0", diff --git a/routes.json.example b/routes.json.example index 534364a..fd8fbf8 100644 --- a/routes.json.example +++ b/routes.json.example @@ -79,6 +79,10 @@ "function": "loginHandler", "args": [] }, + { + "function": "preIip", + "args": [] + }, { "function": "iipHandler", "args": []