diff --git a/app/controllers/cors_controller.rb b/app/controllers/cors_controller.rb index 943c5e3..ad30298 100644 --- a/app/controllers/cors_controller.rb +++ b/app/controllers/cors_controller.rb @@ -2,10 +2,19 @@ class CorsController < ApplicationController skip_before_filter :session_expiration, :user_setup, :check_if_login_required, :set_localization def preflight - headers['Access-Control-Allow-Origin'] = Setting.plugin_redmine_cors["cors_domain"].to_s - headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT' - headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version, Content-Type, X-Redmine-API-Key' - headers['Access-Control-Max-Age'] = '1728000' + allowed_origins = Setting.plugin_redmine_cors["cors_domain"].to_s.downcase.split(/[ ,]/).reject { |c| c.empty? } + if not request.headers["Origin"].nil? + if allowed_origins.include?("*") || allowed_origins.include?(request.headers["Origin"].to_s.downcase) + headers['Access-Control-Allow-Origin'] = request.headers["Origin"].to_s + headers['Access-Control-Allow-Methods'] = Setting.plugin_redmine_cors["cors_methods"] + headers['Access-Control-Allow-Headers'] = Setting.plugin_redmine_cors["cors_headers"] + headers['Access-Control-Max-Age'] = Setting.plugin_redmine_cors["cors_maxage"] + if (Setting.plugin_redmine_cors["cors_credentials"] == '1') + headers['Access-Control-Allow-Credentials'] = 'true' + end + end + end + headers['Vary'] = 'Origin' render :text => '', :content_type => 'text/plain' end end diff --git a/app/views/settings/_cors_settings.erb b/app/views/settings/_cors_settings.erb index 0464d78..7b206de 100644 --- a/app/views/settings/_cors_settings.erb +++ b/app/views/settings/_cors_settings.erb @@ -5,3 +5,34 @@
<%= l(:description_cors_domain) %>

+

+ <%=content_tag(:label, l(:label_cors_headers) + ":") %> + <%=text_field_tag "settings[cors_headers]", @settings["cors_headers"], :size => 100 %>
+ (<%=l(:label_default)%>: 0) +
+ <%= l(:description_cors_headers) %> +

+ +

+ <%=content_tag(:label, l(:label_cors_methods) + ":") %> + <%=text_field_tag "settings[cors_methods]", @settings["cors_methods"], :size => 100 %>
+ (<%=l(:label_default)%>: 0) +
+ <%= l(:description_cors_methods) %> +

+ +

+ <%=content_tag(:label, l(:label_cors_maxage) + ":") %> + <%=text_field_tag "settings[cors_maxage]", @settings["cors_maxage"], :size => 100 %>
+ (<%=l(:label_default)%>: 0) +
+ <%= l(:description_cors_maxage) %> +

+ +

+ <%=content_tag(:label, l(:label_cors_credentials) + ":") %> + <%=check_box_tag "settings[cors_credentials]", '1', @settings["cors_credentials"] %>
+ (<%=l(:label_default)%>: 0) +
+ <%= l(:description_cors_credentials) %> +

diff --git a/config/locales/en.yml b/config/locales/en.yml index a6b020a..89cc95e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,3 +1,11 @@ en: - label_cors_domain: Domain - description_cors_domain: Define domain allowed in CORS + label_cors_domain: Domain(s) + description_cors_domain: Define origins(s) (comma or space separated) allowed in CORS, you should include http(s):// + label_cors_headers: Allowed Headers + description_cors_headers: Define headers (comma separated) allowed in CORS requests + label_cors_methods: Allowed Methods + description_cors_methods: Define methods (comma separated) allowed in CORS requests + label_cors_maxage: Max age + description_cors_maxage: Define max age (in seconds) that browsers will cache CORS headers + label_cors_credentials: Allow Credentials + description_cors_credentials: Whether to allow credentials to be sent by browser (use of Authorization header) diff --git a/config/routes.rb b/config/routes.rb index 69d0b05..06243aa 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,3 @@ RedmineApp::Application.routes.draw do - match '*path', :to => 'cors#preflight', :constraints => {:method => 'OPTIONS'} + match '*path', :to => 'cors#preflight', via: [:options] end diff --git a/init.rb b/init.rb index 876f196..c0f3f0c 100644 --- a/init.rb +++ b/init.rb @@ -25,6 +25,10 @@ settings :partial => 'settings/cors_settings', :default => { - "cors_domain" => "*", + "cors_domain" => "", + "cors_headers" => "X-Requested-With, X-Prototype-Version, Content-Type, X-Redmine-API-Key, accept, authorization", + "cors_methods" => "POST, GET, OPTIONS, PUT", + "cors_maxage" => "1728000", + "cors_credentials" => '1' } end diff --git a/lib/redmine_cors/patches/application_controller.rb b/lib/redmine_cors/patches/application_controller.rb index 78c074d..93d6a02 100644 --- a/lib/redmine_cors/patches/application_controller.rb +++ b/lib/redmine_cors/patches/application_controller.rb @@ -11,9 +11,16 @@ def self.included(base) # :nodoc: module InstanceMethods def cors_set_access_control_headers - headers['Access-Control-Allow-Origin'] = Setting.plugin_redmine_cors["cors_domain"].to_s - headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT' - headers['Access-Control-Max-Age'] = "1728000" + allowed_origins = Setting.plugin_redmine_cors["cors_domain"].to_s.downcase.split(/[ ,]/).reject { |c| c.empty? } + if not request.headers["Origin"].nil? + if allowed_origins.include?("*") || allowed_origins.include?(request.headers["Origin"].to_s.downcase) + headers['Access-Control-Allow-Origin'] = request.headers["Origin"].to_s + if (Setting.plugin_redmine_cors["cors_credentials"] == '1') + headers['Access-Control-Allow-Credentials'] = 'true' + end + end + headers['Vary'] = 'Origin' + end end end end