require 'multi_json' module Scrivito class EditingContextMiddleware ENVKEY = 'SCRIVITO_EDITING_CONTEXT' def self.from_request(request) request.env[ENVKEY] || EditingContext.new end def initialize(app) @app = app end def call(env) request = Rack::Request.new(env) url_params = parse_url_params(request) header_params = parse_header_params(env) cookie_params = parse_cookie_params(request) display_mode = url_params['display_mode'] || header_params['display_mode'] || cookie_params['display_mode'] workspace_id = url_params['workspace_id'] || header_params['workspace_id'] || cookie_params['workspace_id'] if cookie_params['workspace_id'] workspace_changed = workspace_id != cookie_params['workspace_id'] end env[ENVKEY] = EditingContext.new( display_mode: display_mode, editor: editor_proc(env), selected_workspace_id: workspace_id, workspace_changed: workspace_changed ) @app.call(env) end private def editor_proc(env) if editing_auth_callback = Configuration.editing_auth_callback -> { editing_auth_callback.call(env) } else Rails.logger.warn(%{ WARNING! Application is running in "#{Rails.env}" environment, but authentication is not configured. For security reasons the in-place editing is disabled. Please see https://scrivito.com/permissions for details. }) nil end end def parse_url_params(request) { 'display_mode' => request.params['_scrivito_display_mode'], 'workspace_id' => request.params['_scrivito_workspace_id'], } end def parse_header_params(env) parse_json_params(env['HTTP_SCRIVITO_EDITING_CONTEXT']) end def parse_cookie_params(request) parse_json_params(request.cookies['scrivito_editing_context']) end def parse_json_params(json_params) MultiJson.decode(json_params) rescue MultiJson::ParseError {} end end end