diff --git a/cli/defaults/siteConfig.json b/cli/defaults/siteConfig.json index 7b23113e..e6366a3d 100644 --- a/cli/defaults/siteConfig.json +++ b/cli/defaults/siteConfig.json @@ -18,7 +18,8 @@ "host": "https://www.example.com", "description": "A decentralized hosting platform built on LBRY", "twitter": false, - "blockListEndpoint": "https://api.lbry.com/file/list_blocked" + "blockListEndpoint": "https://api.lbry.com/file/list_blocked", + "corsWhitelist": [] }, "publishing": { "primaryClaimAddress": null, diff --git a/package-lock.json b/package-lock.json index a9acd7eb..0d8c6e30 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3611,6 +3611,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cosmiconfig": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", @@ -8605,9 +8614,9 @@ } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", diff --git a/package.json b/package.json index 9b224229..8ad68ed5 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "body-parser": "^1.18.3", "connect-multiparty": "^2.2.0", "cookie-session": "^2.0.0-beta.3", + "cors": "^2.8.5", "express": "^4.16.4", "express-handlebars": "^3.0.0", "express-http-context": "^1.2.0", diff --git a/server/index.js b/server/index.js index 87455cea..d96ba252 100644 --- a/server/index.js +++ b/server/index.js @@ -3,6 +3,7 @@ const express = require('express'); const bodyParser = require('body-parser'); const expressHandlebars = require('express-handlebars'); const helmet = require('helmet'); +const cors = require('cors'); const cookieSession = require('cookie-session'); const http = require('http'); const logger = require('winston'); @@ -23,7 +24,7 @@ const processTrending = require('./utils/processTrending'); const { setRouteDataInContextMiddleware } = require('./middleware/httpContextMiddleware'); const { - details: { port: PORT, blockListEndpoint }, + details: { port: PORT, blockListEndpoint, corsWhitelist, host }, startup: { performChecks, performUpdates }, } = require('@config/siteConfig'); @@ -82,7 +83,37 @@ function Server() { // set HTTP headers to protect against well-known web vulnerabilties app.use(helmet()); + // open cors for site/config:host (current instance) + var originWhitelist = [ + host + ]; + // whitelist is found in site/config:details: + // enter corsWhitelist: ["*"] to allow all + // enter your domains otherwise:["https://example.com", ...] + if ( corsWhitelist && corsWhitelist.length ) { + originWhitelist = originWhitelist.concat(corsWhitelist); + } + var corsOptions = originWhitelist && originWhitelist.includes('*') + ? { + "origin": "*", + "methods": "GET,HEAD,PUT,PATCH,POST,DELETE", + "preflightContinue": false, + "optionsSuccessStatus": 204 + } + : { + origin: function(origin, callback) { + if ((origin === undefined) || originWhitelist.indexOf(origin) !== -1) { + callback(null, true); + } else { + let error = new Error(`CORS has blocked this website from access. Contact an administrator from ${host} if you feel this is in error.`); + error.code = "ECORS" + callback(error); + } + }, + }; + + app.use(cors(corsOptions)); // Support per-request http-context app.use(httpContext.middleware); @@ -148,6 +179,16 @@ function Server() { ); }); + app.use( (error, req, res, next) => { + if (error.code === 'ECORS'){ + res.status(403); + res.send({message: error}) + } else { + res.status(520); + res.send({ message: error }); + } + }) + this.app = app; }; this.createServer = () => {