Commit 528fc939ada3802df4ded58fb3b1c71f10a1da71
Exists in
staging
and in
2 other branches
Merge branch 'fix_multitenancy' into staging
Conflicts: config/application.rb
Showing
10 changed files
with
94 additions
and
52 deletions
Show diff stats
Gemfile
@@ -81,7 +81,7 @@ group :cucumber do | @@ -81,7 +81,7 @@ group :cucumber do | ||
81 | gem 'cucumber' | 81 | gem 'cucumber' |
82 | gem 'cucumber-rails', '~> 1.4.2', :require => false | 82 | gem 'cucumber-rails', '~> 1.4.2', :require => false |
83 | gem 'database_cleaner', '~> 1.3' | 83 | gem 'database_cleaner', '~> 1.3' |
84 | - gem 'selenium-webdriver' | 84 | + gem 'selenium-webdriver', '>= 2.50' |
85 | end | 85 | end |
86 | 86 | ||
87 | # Requires custom dependencies | 87 | # Requires custom dependencies |
app/controllers/application_controller.rb
@@ -3,7 +3,6 @@ require 'noosfero/multi_tenancy' | @@ -3,7 +3,6 @@ require 'noosfero/multi_tenancy' | ||
3 | class ApplicationController < ActionController::Base | 3 | class ApplicationController < ActionController::Base |
4 | #protect_from_forgery | 4 | #protect_from_forgery |
5 | 5 | ||
6 | - before_filter :setup_multitenancy | ||
7 | before_filter :detect_stuff_by_domain | 6 | before_filter :detect_stuff_by_domain |
8 | before_filter :init_noosfero_plugins | 7 | before_filter :init_noosfero_plugins |
9 | before_filter :allow_cross_domain_access | 8 | before_filter :allow_cross_domain_access |
@@ -111,10 +110,6 @@ class ApplicationController < ActionController::Base | @@ -111,10 +110,6 @@ class ApplicationController < ActionController::Base | ||
111 | #super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN']) | 110 | #super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN']) |
112 | end | 111 | end |
113 | 112 | ||
114 | - def setup_multitenancy | ||
115 | - Noosfero::MultiTenancy.setup!(request.host) | ||
116 | - end | ||
117 | - | ||
118 | def boxes_editor? | 113 | def boxes_editor? |
119 | false | 114 | false |
120 | end | 115 | end |
@@ -137,12 +132,11 @@ class ApplicationController < ActionController::Base | @@ -137,12 +132,11 @@ class ApplicationController < ActionController::Base | ||
137 | @domain = Domain.find_by_name(request.host) | 132 | @domain = Domain.find_by_name(request.host) |
138 | if @domain.nil? | 133 | if @domain.nil? |
139 | @environment = Environment.default | 134 | @environment = Environment.default |
140 | - if @environment.nil? && Rails.env.development? | ||
141 | - # This should only happen in development ... | 135 | + # Avoid crashes on test and development setups |
136 | + if @environment.nil? && !Rails.env.production? | ||
142 | @environment = Environment.new | 137 | @environment = Environment.new |
143 | @environment.name = "Noosfero" | 138 | @environment.name = "Noosfero" |
144 | @environment.is_default = true | 139 | @environment.is_default = true |
145 | - @environment.save! | ||
146 | end | 140 | end |
147 | else | 141 | else |
148 | @environment = @domain.environment | 142 | @environment = @domain.environment |
config/application.rb
@@ -15,6 +15,9 @@ module Noosfero | @@ -15,6 +15,9 @@ module Noosfero | ||
15 | 15 | ||
16 | require 'noosfero/plugin' | 16 | require 'noosfero/plugin' |
17 | 17 | ||
18 | + require 'noosfero/multi_tenancy' | ||
19 | + config.middleware.use Noosfero::MultiTenancy::Middleware | ||
20 | + | ||
18 | # Adds custom attributes to the Set of allowed html attributes for the #sanitize helper | 21 | # Adds custom attributes to the Set of allowed html attributes for the #sanitize helper |
19 | config.action_view.sanitized_allowed_attributes = 'align', 'border', 'alt', 'vspace', 'hspace', 'width', 'heigth', 'value', 'type', 'data', 'style', 'target', 'codebase', 'archive', 'classid', 'code', 'flashvars', 'scrolling', 'frameborder', 'controls', 'autoplay', 'colspan', 'rowspan', 'usemap', 'shape', 'coords' | 22 | config.action_view.sanitized_allowed_attributes = 'align', 'border', 'alt', 'vspace', 'hspace', 'width', 'heigth', 'value', 'type', 'data', 'style', 'target', 'codebase', 'archive', 'classid', 'code', 'flashvars', 'scrolling', 'frameborder', 'controls', 'autoplay', 'colspan', 'rowspan', 'usemap', 'shape', 'coords' |
20 | 23 |
features/edit_article.feature
@@ -90,7 +90,7 @@ Feature: edit article | @@ -90,7 +90,7 @@ Feature: edit article | ||
90 | And I fill in "Title" with "My Folder" | 90 | And I fill in "Title" with "My Folder" |
91 | And I choose "article_published_false" | 91 | And I choose "article_published_false" |
92 | And I uncheck "article_show_to_followers" | 92 | And I uncheck "article_show_to_followers" |
93 | - Then I should see "Fill in the search field to add the exception users to see this content" | 93 | + Then I should see "Allow only community members entered below to view this content" |
94 | 94 | ||
95 | @selenium | 95 | @selenium |
96 | Scenario: allowed user should see the content of a folder | 96 | Scenario: allowed user should see the content of a folder |
features/forum.feature
@@ -79,7 +79,7 @@ Feature: forum | @@ -79,7 +79,7 @@ Feature: forum | ||
79 | | joaosilva | Forum One | | 79 | | joaosilva | Forum One | |
80 | And I go to /joaosilva/forum-one | 80 | And I go to /joaosilva/forum-one |
81 | When I follow "Configure forum" | 81 | When I follow "Configure forum" |
82 | - And I fill in "Description" with "My description" | 82 | + And I fill in tinyMCE "article_body" with "My description" |
83 | And I check "Has terms of use:" | 83 | And I check "Has terms of use:" |
84 | And I press "Save" | 84 | And I press "Save" |
85 | Then I should see "Forum One" | 85 | Then I should see "Forum One" |
@@ -95,7 +95,7 @@ Feature: forum | @@ -95,7 +95,7 @@ Feature: forum | ||
95 | | mariasilva | Maria Silva | | 95 | | mariasilva | Maria Silva | |
96 | And I go to /joaosilva/forum-one | 96 | And I go to /joaosilva/forum-one |
97 | When I follow "Configure forum" | 97 | When I follow "Configure forum" |
98 | - And I fill in "Description" with "My description" | 98 | + And I fill in tinyMCE "article_body" with "My description" |
99 | And I check "Has terms of use:" | 99 | And I check "Has terms of use:" |
100 | And I press "Save" | 100 | And I press "Save" |
101 | When I follow "New discussion topic" | 101 | When I follow "New discussion topic" |
@@ -118,7 +118,7 @@ Feature: forum | @@ -118,7 +118,7 @@ Feature: forum | ||
118 | | mariasilva | Maria Silva | | 118 | | mariasilva | Maria Silva | |
119 | And I go to /joaosilva/forum-one | 119 | And I go to /joaosilva/forum-one |
120 | When I follow "Configure forum" | 120 | When I follow "Configure forum" |
121 | - And I fill in "Description" with "My description" | 121 | + And I fill in tinyMCE "article_body" with "My description" |
122 | And I check "Has terms of use:" | 122 | And I check "Has terms of use:" |
123 | And I press "Save" | 123 | And I press "Save" |
124 | When I follow "Logout" | 124 | When I follow "Logout" |
@@ -135,7 +135,7 @@ Feature: forum | @@ -135,7 +135,7 @@ Feature: forum | ||
135 | | joaosilva | Forum One | | 135 | | joaosilva | Forum One | |
136 | And I go to /joaosilva/forum-one | 136 | And I go to /joaosilva/forum-one |
137 | When I follow "Configure forum" | 137 | When I follow "Configure forum" |
138 | - And I fill in "Description" with "My description" | 138 | + And I fill in tinyMCE "article_body" with "My description" |
139 | And I check "Has terms of use:" | 139 | And I check "Has terms of use:" |
140 | And I press "Save" | 140 | And I press "Save" |
141 | When I follow "Logout" | 141 | When I follow "Logout" |
features/media_panel_upload_files.feature
@@ -94,20 +94,17 @@ Feature: uploads items on media panel | @@ -94,20 +94,17 @@ Feature: uploads items on media panel | ||
94 | 94 | ||
95 | @selenium | 95 | @selenium |
96 | Scenario: select type when create new folder | 96 | Scenario: select type when create new folder |
97 | - When I follow "Show/Hide" | ||
98 | - And I follow "New folder" | ||
99 | - And I choose "Folder" within "#new-folder-dialog" | ||
100 | - And I fill in "Name" with "Main new folder" within "#new-folder-dialog" | ||
101 | - And I press "Create" | 97 | + Given I follow "Show/Hide" |
98 | + And I follow "New folder" | ||
99 | + And I choose "Folder" within "#new-folder-dialog" | ||
100 | + And I fill in "Name" with "Main new folder" within "#new-folder-dialog" | ||
101 | + When I press "Create" | ||
102 | Then I should see "joaosilva/Gallery/Main new folder" within "#parent_id" | 102 | Then I should see "joaosilva/Gallery/Main new folder" within "#parent_id" |
103 | - When I follow "New folder" | ||
104 | - And I choose "Gallery" within "#new-folder-dialog" | ||
105 | - And I fill in "Name" with "Gallery new folder" within "#new-folder-dialog" | ||
106 | - And I press "Create" | ||
107 | - And I go to joaosilva's cms | ||
108 | - And I follow "Gallery" | ||
109 | - Then I should see "Folder" within "tr[title='Main new folder'] td.article-mime" | ||
110 | - And I should see "Gallery" within "tr[title='Gallery new folder'] td.article-mime" | 103 | + Given I follow "New folder" |
104 | + And I choose "Gallery" within "#new-folder-dialog" | ||
105 | + And I fill in "Name" with "Gallery new folder" within "#new-folder-dialog" | ||
106 | + When I press "Create" | ||
107 | + Then I should see "joaosilva/Gallery/Gallery new folder" within "#parent_id" | ||
111 | 108 | ||
112 | @selenium | 109 | @selenium |
113 | Scenario: hide and show upload list | 110 | Scenario: hide and show upload list |
features/step_definitions/web_steps.rb
@@ -39,7 +39,22 @@ end | @@ -39,7 +39,22 @@ end | ||
39 | 39 | ||
40 | When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| | 40 | When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector| |
41 | with_scope(selector) do | 41 | with_scope(selector) do |
42 | - click_link(link, :match => :prefer_exact) | 42 | + begin |
43 | + click_link(link, :match => :prefer_exact) | ||
44 | + rescue Selenium::WebDriver::Error::UnknownError => selenium_error | ||
45 | + if selenium_error.message.start_with? 'Element is not clickable at point' | ||
46 | + href = find_link(link)[:href] | ||
47 | + | ||
48 | + warn "#{selenium_error.message}\n\n"\ | ||
49 | + "Trying to overcome this by redirecting you to the link's href:\n"\ | ||
50 | + "\t'#{href}'\n\n"\ | ||
51 | + "Good luck and be careful that this may produce hidden links to work on tests!\n" | ||
52 | + | ||
53 | + visit href | ||
54 | + else | ||
55 | + raise selenium_error | ||
56 | + end | ||
57 | + end | ||
43 | end | 58 | end |
44 | end | 59 | end |
45 | 60 | ||
@@ -107,6 +122,7 @@ When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"(?: within "([^"]*)")?$/ do | @@ -107,6 +122,7 @@ When /^(?:|I )attach the file "([^"]*)" to "([^"]*)"(?: within "([^"]*)")?$/ do | ||
107 | with_scope(selector) do | 122 | with_scope(selector) do |
108 | attach_file(field, path) | 123 | attach_file(field, path) |
109 | end | 124 | end |
125 | + sleep 1 | ||
110 | end | 126 | end |
111 | 127 | ||
112 | Then /^(?:|I )should see JSON:$/ do |expected_json| | 128 | Then /^(?:|I )should see JSON:$/ do |expected_json| |
@@ -260,6 +276,10 @@ Then /^display "([^\"]*)"$/ do |element| | @@ -260,6 +276,10 @@ Then /^display "([^\"]*)"$/ do |element| | ||
260 | evaluate_script("jQuery('#{element}').show() && false;") | 276 | evaluate_script("jQuery('#{element}').show() && false;") |
261 | end | 277 | end |
262 | 278 | ||
279 | +Then /^I fill in tinyMCE "(.*?)" with "(.*?)"$/ do |field, content| | ||
280 | + execute_script("$(tinymce.editors['#{field}'].setContent('#{content}'))") | ||
281 | +end | ||
282 | + | ||
263 | Then /^there should be a div with class "([^"]*)"$/ do |klass| | 283 | Then /^there should be a div with class "([^"]*)"$/ do |klass| |
264 | should have_selector("div.#{klass}") | 284 | should have_selector("div.#{klass}") |
265 | end | 285 | end |
lib/noosfero/multi_tenancy.rb
@@ -22,6 +22,18 @@ module Noosfero | @@ -22,6 +22,18 @@ module Noosfero | ||
22 | end | 22 | end |
23 | end | 23 | end |
24 | 24 | ||
25 | + class Middleware | ||
26 | + def initialize(app) | ||
27 | + @app = app | ||
28 | + end | ||
29 | + | ||
30 | + def call(env) | ||
31 | + request = Rack::Request.new(env) | ||
32 | + Noosfero::MultiTenancy.setup!(request.host) | ||
33 | + @app.call(env) | ||
34 | + end | ||
35 | + end | ||
36 | + | ||
25 | private | 37 | private |
26 | 38 | ||
27 | def self.load_map | 39 | def self.load_map |
test/functional/application_controller_test.rb
@@ -478,30 +478,6 @@ class ApplicationControllerTest < ActionController::TestCase | @@ -478,30 +478,6 @@ class ApplicationControllerTest < ActionController::TestCase | ||
478 | assert_response :forbidden | 478 | assert_response :forbidden |
479 | end | 479 | end |
480 | 480 | ||
481 | - if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' | ||
482 | - | ||
483 | - should 'change postgresql schema' do | ||
484 | - uses_host 'schema1.com' | ||
485 | - Noosfero::MultiTenancy.expects(:on?).returns(true) | ||
486 | - Noosfero::MultiTenancy.expects(:mapping).returns({ 'schema1.com' => 'schema1' }).at_least_once | ||
487 | - exception = assert_raise(ActiveRecord::StatementInvalid) { get :index } | ||
488 | - | ||
489 | - # we have switched to a new database schema; depending on the PostgreSQL | ||
490 | - # version, we will receive either an error message because the schema | ||
491 | - # does not exist, or an error saying that whatever table we need can't be | ||
492 | - # found. | ||
493 | - assert_match /(SET search_path TO schema1|PG::UndefinedTable)/, exception.message | ||
494 | - end | ||
495 | - | ||
496 | - should 'not change postgresql schema if multitenancy is off' do | ||
497 | - uses_host 'schema1.com' | ||
498 | - Noosfero::MultiTenancy.stubs(:on?).returns(false) | ||
499 | - Noosfero::MultiTenancy.stubs(:mapping).returns({ 'schema1.com' => 'schema1' }) | ||
500 | - assert_nothing_raised(ActiveRecord::StatementInvalid) { get :index } | ||
501 | - end | ||
502 | - | ||
503 | - end | ||
504 | - | ||
505 | should 'register search_term occurrence on find_by_contents' do | 481 | should 'register search_term occurrence on find_by_contents' do |
506 | controller = ApplicationController.new | 482 | controller = ApplicationController.new |
507 | controller.stubs(:environment).returns(Environment.default) | 483 | controller.stubs(:environment).returns(Environment.default) |
@@ -0,0 +1,40 @@ | @@ -0,0 +1,40 @@ | ||
1 | +require_relative "../test_helper" | ||
2 | + | ||
3 | +class MultiTenancyTest < ActionDispatch::IntegrationTest | ||
4 | + | ||
5 | + should 'change postgresql schema' do | ||
6 | + host! 'schema1.com' | ||
7 | + Noosfero::MultiTenancy.expects(:on?).at_least_once.returns(true) | ||
8 | + Noosfero::MultiTenancy.expects(:mapping).returns({ 'schema1.com' => 'schema1' }).at_least_once | ||
9 | + exception = assert_raise(ActiveRecord::StatementInvalid) { get '/' } | ||
10 | + | ||
11 | + # we have switched to a new database schema; depending on the PostgreSQL | ||
12 | + # version, we will receive either an error message because the schema | ||
13 | + # does not exist, or an error saying that whatever table we need can't be | ||
14 | + # found. | ||
15 | + assert_match /(SET search_path TO schema1|PG::UndefinedTable)/, exception.message | ||
16 | + end | ||
17 | + | ||
18 | + should 'not change postgresql schema if multitenancy is off' do | ||
19 | + host! 'schema1.com' | ||
20 | + Noosfero::MultiTenancy.stubs(:on?).returns(false) | ||
21 | + Noosfero::MultiTenancy.stubs(:mapping).returns({ 'schema1.com' => 'schema1' }) | ||
22 | + assert_nothing_raised(ActiveRecord::StatementInvalid) { get '/' } | ||
23 | + end | ||
24 | + | ||
25 | + should 'find session from the correct database schema' do | ||
26 | + Noosfero::MultiTenancy.expects(:on?).at_least_once.returns(true) | ||
27 | + Noosfero::MultiTenancy.expects(:mapping).returns({ 'schema2.com' => 'public', 'schema1.com' => 'schema1' }).at_least_once | ||
28 | + | ||
29 | + user = create_user | ||
30 | + session_obj = create(Session, user_id: user.id, session_id: 'some_id', data: {}) | ||
31 | + person_identifier = user.person.identifier | ||
32 | + | ||
33 | + Noosfero::MultiTenancy.setup!('schema1.com') | ||
34 | + host! 'schema2.com' | ||
35 | + cookies[:_noosfero_session] = session_obj.session_id | ||
36 | + assert_nothing_raised { get "/myprofile/#{person_identifier}" } | ||
37 | + assert_equal 'public', ActiveRecord::Base.connection.schema_search_path | ||
38 | + end | ||
39 | + | ||
40 | +end |