diff --git a/app/assets/javascripts/web-dev-listener.js b/app/assets/javascripts/web-dev-listener.js index dc0e5f67d..1daf5269e 100644 --- a/app/assets/javascripts/web-dev-listener.js +++ b/app/assets/javascripts/web-dev-listener.js @@ -17,13 +17,9 @@ var virtualScripts; var goalStates; var allowedOrigins = [ - /https:\/\/codecombat\.com/, - /https?:\/\/cn\.codecombat\.com/, - /http:\/\/localhost:3000/, - /http:\/\/direct\.codecombat\.com/, - /http:\/\/staging\.codecombat\.com/, - /http:\/\/next\.codecombat\.com/, - /http:\/\/.*codecombat-staging-codecombat\.runnableapp\.com/, + /^https?:\/\/(.*\.)?codecombat\.com$/, + /^https?:\/\/localhost:3000$/, + /^https?:\/\/.*codecombat-staging-codecombat\.runnableapp\.com$/, ]; function receiveMessage(event) { diff --git a/app/templates/play/level/web-surface-view.jade b/app/templates/play/level/web-surface-view.jade index f2991ad44..0744afd9c 100644 --- a/app/templates/play/level/web-surface-view.jade +++ b/app/templates/play/level/web-surface-view.jade @@ -1 +1 @@ -iframe(src="/web-dev-iframe.html") +iframe(src="http://" + fullUnsafeContentHostname + "/web-dev-iframe.html") diff --git a/app/views/play/level/WebSurfaceView.coffee b/app/views/play/level/WebSurfaceView.coffee index d737a662d..819b16d82 100644 --- a/app/views/play/level/WebSurfaceView.coffee +++ b/app/views/play/level/WebSurfaceView.coffee @@ -13,6 +13,9 @@ module.exports = class WebSurfaceView extends CocoView # Consider https://www.npmjs.com/package/css-select to do this on virtualDom instead of in iframe on concreteDOM super(options) + getRenderData: -> + _.merge super(), { fullUnsafeContentHostname: serverConfig.fullUnsafeContentHostname } + afterRender: -> super() @iframe = @$('iframe')[0] @@ -81,7 +84,7 @@ module.exports = class WebSurfaceView extends CocoView onIframeMessage: (event) => origin = event.origin or event.originalEvent.origin - unless origin is window.location.origin + unless new RegExp("^https?:\/\/#{serverConfig.fullUnsafeContentHostname}$").test origin return console.log 'Ignoring message from bad origin:', origin unless event.source is @iframe.contentWindow return console.log 'Ignoring message from somewhere other than our iframe:', event.source diff --git a/server_config.coffee b/server_config.coffee index b13b4ae28..f3beb8d72 100644 --- a/server_config.coffee +++ b/server_config.coffee @@ -91,6 +91,11 @@ config.cookie_secret = process.env.COCO_COOKIE_SECRET or 'chips ahoy' config.isProduction = config.mongo.host isnt 'localhost' +# Domains (without subdomain prefix, with port number) for main hostname (usually codecombat.com) +# and unsafe web-dev iFrame content (usually codecombatprojects.com). +config.mainHostname = process.env.COCO_MAIN_HOSTNAME or 'localhost:3000' +config.unsafeContentHostname = process.env.COCO_UNSAFE_CONTENT_HOSTNAME or 'localhost:3000' + if process.env.COCO_PICOCTF config.picoCTF = true config.picoCTF_api_url = 'http://staging.picoctf.com/api' diff --git a/server_setup.coffee b/server_setup.coffee index 848f7498d..3d7b0f04a 100644 --- a/server_setup.coffee +++ b/server_setup.coffee @@ -52,6 +52,22 @@ developmentLogging = (tokens, req, res) -> s += ' (proxied)' if req.proxied return s +setupDomainFilterMiddleware = (app) -> + if config.isProduction + unsafePaths = [ + /^\/web-dev-iframe\.html$/ + /^\/javascripts\/web-dev-listener\.js$/ + ] + app.use (req, res, next) -> + domainRegex = new RegExp("(.*\.)?(#{config.mainHostname}|#{config.unsafeContentHostname})") + domainPrefix = req.host.match(domainRegex)?[1] or '' + if _.any(unsafePaths, (pathRegex) -> pathRegex.test(req.path)) and (req.host isnt domainPrefix + config.unsafeContentHostname) + res.redirect('http://' + domainPrefix + config.unsafeContentHostname + req.path) + else if not _.any(unsafePaths, (pathRegex) -> pathRegex.test(req.path)) and req.host is domainPrefix + config.unsafeContentHostname + res.redirect('http://' + domainPrefix + config.mainHostname + req.path) + else + next() + setupErrorMiddleware = (app) -> app.use (err, req, res, next) -> if err @@ -177,6 +193,7 @@ exports.setupMiddleware = (app) -> setupPerfMonMiddleware app setupCountryRedirectMiddleware app, "china", "CN", "zh", config.chinaDomain setupCountryRedirectMiddleware app, "brazil", "BR", "pt-BR", config.brazilDomain + setupDomainFilterMiddleware app setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly app setupExpressMiddleware app setupPassportMiddleware app @@ -206,6 +223,9 @@ setupFallbackRouteToIndex = (app) -> configData = _.omit mandate?.toObject() or {}, '_id' configData.picoCTF = config.picoCTF configData.production = config.isProduction + domainRegex = new RegExp("(.*\.)?(#{config.mainHostname}|#{config.unsafeContentHostname})") + domainPrefix = req.host.match(domainRegex)?[1] or '' + configData.fullUnsafeContentHostname = domainPrefix + config.unsafeContentHostname data = data.replace '"serverConfigTag"', JSON.stringify configData data = data.replace('"userObjectTag"', user) data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually))