Commit b1b3e471f1143b0b8aab231005c896c571ea7de2
Committed by
Daniela Feitosa
1 parent
f2a648b7
Exists in
master
and in
29 other branches
Multitenancy documentation and separation
(ActionItem1845)
Showing
6 changed files
with
43 additions
and
11 deletions
Show diff stats
INSTALL.multitenancy
@@ -11,7 +11,7 @@ organization works with a customized virtual application instance. | @@ -11,7 +11,7 @@ organization works with a customized virtual application instance. | ||
11 | 11 | ||
12 | Today this feature is available only for PostgreSQL databases. | 12 | Today this feature is available only for PostgreSQL databases. |
13 | 13 | ||
14 | -This document assumes that you have a fully PostgresSQL default Noosfero | 14 | +This document assumes that you have a new fully PostgresSQL default Noosfero |
15 | installation as explained at the INSTALL file. | 15 | installation as explained at the INSTALL file. |
16 | 16 | ||
17 | == Separated data | 17 | == Separated data |
@@ -121,11 +121,6 @@ Run Noosfero init file as root: | @@ -121,11 +121,6 @@ Run Noosfero init file as root: | ||
121 | It's necessary to run only one instance of ferret_server. Don't worry | 121 | It's necessary to run only one instance of ferret_server. Don't worry |
122 | about this, Noosfero initializer had already done this for you. | 122 | about this, Noosfero initializer had already done this for you. |
123 | 123 | ||
124 | -Build or rebuild the Ferret index by running the following task just | ||
125 | -for your hosting environment, do this as noosfero user: | ||
126 | - | ||
127 | -$ RAILS_ENV=production rake multitenancy:reindex | ||
128 | - | ||
129 | == Feed updater & Delayed job | 124 | == Feed updater & Delayed job |
130 | 125 | ||
131 | Just for your information, a daemon of feed-updater and delayed_job | 126 | Just for your information, a daemon of feed-updater and delayed_job |
@@ -137,3 +132,32 @@ relax. | @@ -137,3 +132,32 @@ relax. | ||
137 | When running with PostgreSQL, Noosfero uploads stuff to a folder named | 132 | When running with PostgreSQL, Noosfero uploads stuff to a folder named |
138 | the same way as the running schema. Inside the upload folder root, for | 133 | the same way as the running schema. Inside the upload folder root, for |
139 | example, will be public/image_uploads/env2 and public/image_uploads/env3. | 134 | example, will be public/image_uploads/env2 and public/image_uploads/env3. |
135 | + | ||
136 | +== Adding multitenancy support to an existing Noosfero environment | ||
137 | + | ||
138 | +If you already have a Noosfero environment, you can turn it multitenant | ||
139 | +by following the steps below in addition to the previous steps: | ||
140 | + | ||
141 | +1. Reindex your database | ||
142 | + | ||
143 | +Rebuild the Ferret index by running the following task just | ||
144 | +for your hosting environment, do this as noosfero user: | ||
145 | + | ||
146 | +$ RAILS_ENV=production rake multitenancy:reindex | ||
147 | + | ||
148 | +2. Move the uploaded files to the right place | ||
149 | + | ||
150 | +Add a directory with the same name as your schema name (by default this | ||
151 | +name is 'public') in the root of each upload directory, for example, | ||
152 | +public/articles/0000 will be moved to public/articles/public/0000. Do this | ||
153 | +with the directories public/image_uploads, public/articles and public/thumbnails. | ||
154 | + | ||
155 | +3. Fix paths on activities | ||
156 | + | ||
157 | +The profile activities store static paths to the images, so it's necessary to fix | ||
158 | +these paths. You can do this easily by setting an alias on your webserver. | ||
159 | +On Apache you can add the three rules below, where 'public' is the schema name: | ||
160 | + | ||
161 | + RewriteRule ^/articles(.+) /articles/public$1 | ||
162 | + RewriteRule ^/image_uploads(.+) /image_uploads/public$1 | ||
163 | + RewriteRule ^/thumbnails(.+) /thumbnails/public$1 |
lib/acts_as_searchable.rb
@@ -2,7 +2,7 @@ module ActsAsSearchable | @@ -2,7 +2,7 @@ module ActsAsSearchable | ||
2 | 2 | ||
3 | module ClassMethods | 3 | module ClassMethods |
4 | def acts_as_searchable(options = {}) | 4 | def acts_as_searchable(options = {}) |
5 | - if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' | 5 | + if Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql? |
6 | options[:additional_fields] ||= {} | 6 | options[:additional_fields] ||= {} |
7 | options[:additional_fields] = Hash[*options[:additional_fields].collect{ |v| [v, {}] }.flatten] if options[:additional_fields].is_a?(Array) | 7 | options[:additional_fields] = Hash[*options[:additional_fields].collect{ |v| [v, {}] }.flatten] if options[:additional_fields].is_a?(Array) |
8 | options[:additional_fields].merge!(:schema_name => { :index => :untokenized }) | 8 | options[:additional_fields].merge!(:schema_name => { :index => :untokenized }) |
@@ -35,7 +35,7 @@ module ActsAsSearchable | @@ -35,7 +35,7 @@ module ActsAsSearchable | ||
35 | 35 | ||
36 | ferret_options[:limit] = :all | 36 | ferret_options[:limit] = :all |
37 | 37 | ||
38 | - ferret_query = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' ? "+schema_name:\"#{schema_name}\" AND #{query}" : query | 38 | + ferret_query = (Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? "+schema_name:\"#{schema_name}\" AND #{query}" : query |
39 | # FIXME this is a HORRIBLE HACK | 39 | # FIXME this is a HORRIBLE HACK |
40 | ids = find_ids_with_ferret(ferret_query, ferret_options)[1][0..8000].map{|r|r[:id].to_i} | 40 | ids = find_ids_with_ferret(ferret_query, ferret_options)[1][0..8000].map{|r|r[:id].to_i} |
41 | 41 |
lib/noosfero/multi_tenancy.rb
@@ -6,7 +6,7 @@ module Noosfero | @@ -6,7 +6,7 @@ module Noosfero | ||
6 | end | 6 | end |
7 | 7 | ||
8 | def self.on? | 8 | def self.on? |
9 | - !self.mapping.blank? | 9 | + !self.mapping.blank? || self.is_hosted_environment? |
10 | end | 10 | end |
11 | 11 | ||
12 | def self.db_by_host=(host) | 12 | def self.db_by_host=(host) |
@@ -26,5 +26,11 @@ module Noosfero | @@ -26,5 +26,11 @@ module Noosfero | ||
26 | map | 26 | map |
27 | end | 27 | end |
28 | 28 | ||
29 | + def self.is_hosted_environment? | ||
30 | + db_file = File.join(RAILS_ROOT, 'config', 'database.yml') | ||
31 | + db_config = YAML.load_file(db_file) | ||
32 | + db_config.select{ |env, attr| RAILS_ENV.to_s.match(/_#{env}$/) }.any? | ||
33 | + end | ||
34 | + | ||
29 | end | 35 | end |
30 | end | 36 | end |
lib/postgresql_attachment_fu.rb
@@ -9,7 +9,7 @@ module PostgresqlAttachmentFu | @@ -9,7 +9,7 @@ module PostgresqlAttachmentFu | ||
9 | module InstanceMethods | 9 | module InstanceMethods |
10 | def full_filename(thumbnail = nil) | 10 | def full_filename(thumbnail = nil) |
11 | file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s | 11 | file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s |
12 | - file_system_path = File.join(file_system_path, ActiveRecord::Base.connection.schema_search_path) if ActiveRecord::Base.postgresql? | 12 | + file_system_path = File.join(file_system_path, ActiveRecord::Base.connection.schema_search_path) if ActiveRecord::Base.postgresql? and Noosfero::MultiTenancy.on? |
13 | File.join(RAILS_ROOT, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))) | 13 | File.join(RAILS_ROOT, file_system_path, *partitioned_path(thumbnail_name_for(thumbnail))) |
14 | end | 14 | end |
15 | end | 15 | end |
test/test_helper.rb
@@ -189,12 +189,14 @@ class Test::Unit::TestCase | @@ -189,12 +189,14 @@ class Test::Unit::TestCase | ||
189 | adapter = ActiveRecord::Base.connection.class | 189 | adapter = ActiveRecord::Base.connection.class |
190 | adapter.any_instance.stubs(:adapter_name).returns('PostgreSQL') | 190 | adapter.any_instance.stubs(:adapter_name).returns('PostgreSQL') |
191 | adapter.any_instance.stubs(:schema_search_path).returns(schema_name) | 191 | adapter.any_instance.stubs(:schema_search_path).returns(schema_name) |
192 | + Noosfero::MultiTenancy.stubs(:on?).returns(true) | ||
192 | reload_for_ferret | 193 | reload_for_ferret |
193 | end | 194 | end |
194 | 195 | ||
195 | def uses_sqlite | 196 | def uses_sqlite |
196 | adapter = ActiveRecord::Base.connection.class | 197 | adapter = ActiveRecord::Base.connection.class |
197 | adapter.any_instance.stubs(:adapter_name).returns('SQLite') | 198 | adapter.any_instance.stubs(:adapter_name).returns('SQLite') |
199 | + Noosfero::MultiTenancy.stubs(:on?).returns(false) | ||
198 | end | 200 | end |
199 | 201 | ||
200 | def reload_for_ferret | 202 | def reload_for_ferret |
vendor/plugins/acts_as_ferret/lib/acts_as_ferret.rb
@@ -204,7 +204,7 @@ module ActsAsFerret | @@ -204,7 +204,7 @@ module ActsAsFerret | ||
204 | # these properties are somewhat vital to the plugin and shouldn't | 204 | # these properties are somewhat vital to the plugin and shouldn't |
205 | # be overwritten by the user: | 205 | # be overwritten by the user: |
206 | index_definition[:ferret].update( | 206 | index_definition[:ferret].update( |
207 | - :key => (ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' ? [:id, :class_name, :schema_name] : [:id, :class_name]), | 207 | + :key => ((Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?) ? [:id, :class_name, :schema_name] : [:id, :class_name]), |
208 | :path => index_definition[:index_dir], | 208 | :path => index_definition[:index_dir], |
209 | :auto_flush => true, # slower but more secure in terms of locking problems TODO disable when running in drb mode? | 209 | :auto_flush => true, # slower but more secure in terms of locking problems TODO disable when running in drb mode? |
210 | :create_if_missing => true | 210 | :create_if_missing => true |