Commit 528fc939ada3802df4ded58fb3b1c71f10a1da71

Authored by Victor Costa
2 parents fa1fe7cf 79d84c01

Merge branch 'fix_multitenancy' into staging

Conflicts:
	config/application.rb
Gemfile
... ... @@ -81,7 +81,7 @@ group :cucumber do
81 81 gem 'cucumber'
82 82 gem 'cucumber-rails', '~> 1.4.2', :require => false
83 83 gem 'database_cleaner', '~> 1.3'
84   - gem 'selenium-webdriver'
  84 + gem 'selenium-webdriver', '>= 2.50'
85 85 end
86 86  
87 87 # Requires custom dependencies
... ...
app/controllers/application_controller.rb
... ... @@ -3,7 +3,6 @@ require 'noosfero/multi_tenancy'
3 3 class ApplicationController < ActionController::Base
4 4 #protect_from_forgery
5 5  
6   - before_filter :setup_multitenancy
7 6 before_filter :detect_stuff_by_domain
8 7 before_filter :init_noosfero_plugins
9 8 before_filter :allow_cross_domain_access
... ... @@ -111,10 +110,6 @@ class ApplicationController &lt; ActionController::Base
111 110 #super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
112 111 end
113 112  
114   - def setup_multitenancy
115   - Noosfero::MultiTenancy.setup!(request.host)
116   - end
117   -
118 113 def boxes_editor?
119 114 false
120 115 end
... ... @@ -137,12 +132,11 @@ class ApplicationController &lt; ActionController::Base
137 132 @domain = Domain.find_by_name(request.host)
138 133 if @domain.nil?
139 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 137 @environment = Environment.new
143 138 @environment.name = "Noosfero"
144 139 @environment.is_default = true
145   - @environment.save!
146 140 end
147 141 else
148 142 @environment = @domain.environment
... ...
config/application.rb
... ... @@ -15,6 +15,9 @@ module Noosfero
15 15  
16 16 require 'noosfero/plugin'
17 17  
  18 + require 'noosfero/multi_tenancy'
  19 + config.middleware.use Noosfero::MultiTenancy::Middleware
  20 +
18 21 # Adds custom attributes to the Set of allowed html attributes for the #sanitize helper
19 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 90 And I fill in "Title" with "My Folder"
91 91 And I choose "article_published_false"
92 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 95 @selenium
96 96 Scenario: allowed user should see the content of a folder
... ...
features/forum.feature
... ... @@ -79,7 +79,7 @@ Feature: forum
79 79 | joaosilva | Forum One |
80 80 And I go to /joaosilva/forum-one
81 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 83 And I check "Has terms of use:"
84 84 And I press "Save"
85 85 Then I should see "Forum One"
... ... @@ -95,7 +95,7 @@ Feature: forum
95 95 | mariasilva | Maria Silva |
96 96 And I go to /joaosilva/forum-one
97 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 99 And I check "Has terms of use:"
100 100 And I press "Save"
101 101 When I follow "New discussion topic"
... ... @@ -118,7 +118,7 @@ Feature: forum
118 118 | mariasilva | Maria Silva |
119 119 And I go to /joaosilva/forum-one
120 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 122 And I check "Has terms of use:"
123 123 And I press "Save"
124 124 When I follow "Logout"
... ... @@ -135,7 +135,7 @@ Feature: forum
135 135 | joaosilva | Forum One |
136 136 And I go to /joaosilva/forum-one
137 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 139 And I check "Has terms of use:"
140 140 And I press "Save"
141 141 When I follow "Logout"
... ...
features/media_panel_upload_files.feature
... ... @@ -94,20 +94,17 @@ Feature: uploads items on media panel
94 94  
95 95 @selenium
96 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 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 109 @selenium
113 110 Scenario: hide and show upload list
... ...
features/step_definitions/web_steps.rb
... ... @@ -39,7 +39,22 @@ end
39 39  
40 40 When /^(?:|I )follow "([^"]*)"(?: within "([^"]*)")?$/ do |link, selector|
41 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 58 end
44 59 end
45 60  
... ... @@ -107,6 +122,7 @@ When /^(?:|I )attach the file &quot;([^&quot;]*)&quot; to &quot;([^&quot;]*)&quot;(?: within &quot;([^&quot;]*)&quot;)?$/ do
107 122 with_scope(selector) do
108 123 attach_file(field, path)
109 124 end
  125 + sleep 1
110 126 end
111 127  
112 128 Then /^(?:|I )should see JSON:$/ do |expected_json|
... ... @@ -260,6 +276,10 @@ Then /^display &quot;([^\&quot;]*)&quot;$/ do |element|
260 276 evaluate_script("jQuery('#{element}').show() && false;")
261 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 283 Then /^there should be a div with class "([^"]*)"$/ do |klass|
264 284 should have_selector("div.#{klass}")
265 285 end
... ...
lib/noosfero/multi_tenancy.rb
... ... @@ -22,6 +22,18 @@ module Noosfero
22 22 end
23 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 37 private
26 38  
27 39 def self.load_map
... ...
test/functional/application_controller_test.rb
... ... @@ -478,30 +478,6 @@ class ApplicationControllerTest &lt; ActionController::TestCase
478 478 assert_response :forbidden
479 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 481 should 'register search_term occurrence on find_by_contents' do
506 482 controller = ApplicationController.new
507 483 controller.stubs(:environment).returns(Environment.default)
... ...
test/integration/multi_tenancy_test.rb 0 → 100644
... ... @@ -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
... ...