zena 1.2.4 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +18 -0
- data/app/controllers/nodes_controller.rb +11 -6
- data/app/controllers/sites_controller.rb +3 -2
- data/app/controllers/user_sessions_controller.rb +1 -1
- data/app/controllers/virtual_classes_controller.rb +3 -2
- data/app/models/document.rb +2 -2
- data/app/models/node.rb +6 -1
- data/app/models/note.rb +3 -27
- data/app/models/role.rb +11 -5
- data/app/models/site.rb +140 -43
- data/app/models/string_hash.rb +2 -0
- data/app/models/user.rb +9 -4
- data/app/models/user_session.rb +1 -1
- data/app/models/virtual_class.rb +49 -18
- data/app/views/sites/_form.erb +7 -4
- data/app/views/sites/_li.erb +15 -9
- data/app/views/users/_li.rhtml +3 -0
- data/app/views/users/index.rhtml +1 -1
- data/app/views/virtual_classes/_form.erb +1 -1
- data/bricks/acls/zena/init.rb +1 -2
- data/bricks/acls/zena/test/sites/erebus/roles.yml +4 -0
- data/bricks/activity/lib/bricks/activity.rb +24 -0
- data/bricks/activity/zena/migrate/20130711135905_add_activity_to_user.rb +9 -0
- data/bricks/activity/zena/test/integration/activity_integration_test.rb +29 -0
- data/bricks/captcha/zena/init.rb +0 -3
- data/bricks/fs_skin/lib/bricks/fs_skin.rb +3 -3
- data/bricks/fs_skin/zena/skins/blog/Node.zafu +1 -1
- data/bricks/fs_skin/zena/tasks.rb +2 -2
- data/bricks/fs_skin/zena/test/integration/fs_skin_integration_test.rb +2 -2
- data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +1 -1
- data/bricks/math/zena/init.rb +0 -3
- data/bricks/pdf/zena/init.rb +1 -5
- data/bricks/worker/zena/init.rb +0 -2
- data/bricks/zena/zena/migrate/20130617164527_add_master_id_to_site.rb +13 -0
- data/bricks/zena/zena/migrate/20130712081512_alter_login_users.rb +9 -0
- data/config/bricks.yml +4 -1
- data/lib/bricks/loader.rb +17 -9
- data/lib/tasks/zena.rake +40 -5
- data/lib/zafu/process/ruby_less_processing.rb +3 -5
- data/lib/zena.rb +2 -0
- data/lib/zena/acts/secure.rb +11 -2
- data/lib/zena/console.rb +5 -4
- data/lib/zena/core_ext/string.rb +2 -2
- data/lib/zena/deploy.rb +22 -6
- data/lib/zena/deploy/logrotate_app.rhtml +10 -7
- data/lib/zena/deploy/logrotate_host.rhtml +21 -26
- data/lib/zena/deploy/vhost.rhtml +3 -3
- data/lib/zena/foxy_parser.rb +1 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/site_worker.rb +2 -2
- data/lib/zena/use.rb +0 -1
- data/lib/zena/use/ancestry.rb +1 -1
- data/lib/zena/use/authlogic.rb +2 -1
- data/lib/zena/use/display.rb +6 -0
- data/lib/zena/use/query_builder.rb +1 -1
- data/lib/zena/use/query_node.rb +3 -3
- data/lib/zena/use/rendering.rb +47 -13
- data/lib/zena/use/test_helper.rb +1 -1
- data/lib/zena/use/urls.rb +6 -104
- data/lib/zena/use/zafu_safe_definitions.rb +9 -4
- data/lib/zena/use/zafu_templates.rb +1 -0
- data/locale/app.pot +4 -0
- data/locale/de/LC_MESSAGES/zena.mo +0 -0
- data/locale/de/zena.po +6 -2
- data/locale/en/LC_MESSAGES/zena.mo +0 -0
- data/locale/en/zena.po +6 -2
- data/locale/fr/LC_MESSAGES/zena.mo +0 -0
- data/locale/fr/zena.po +5 -1
- data/locale/it/LC_MESSAGES/zena.mo +0 -0
- data/locale/it/zena.po +6 -2
- data/locale/zena.pot +4 -0
- data/test/functional/nodes_controller_test.rb +2 -133
- data/test/functional/sites_controller_test.rb +1 -1
- data/test/integration/multiple_hosts_test.rb +2 -1
- data/test/integration/navigation_test.rb +37 -0
- data/test/integration/query_node/basic.yml +1 -1
- data/test/integration/zafu_compiler/ajax.yml +7 -0
- data/test/integration/zafu_compiler/comments.yml +2 -2
- data/test/integration/zafu_compiler/context.yml +6 -2
- data/test/integration/zafu_compiler/display.yml +16 -4
- data/test/integration/zafu_compiler/forms.yml +1 -0
- data/test/integration/zafu_compiler/query.yml +7 -1
- data/test/integration/zafu_compiler/relations.yml +12 -7
- data/test/integration/zafu_compiler/roles.yml +3 -3
- data/test/integration/zafu_compiler/rubyless.yml +1 -2
- data/test/integration/zafu_compiler/safe_definitions.yml +5 -0
- data/test/sites/complex/roles.yml +1 -1
- data/test/sites/ocean/roles.yml +4 -0
- data/test/sites/zena/columns.yml +3 -1
- data/test/sites/zena/roles.yml +5 -1
- data/test/sites/zena/sites.yml +22 -0
- data/test/unit/document_test.rb +14 -0
- data/test/unit/node_test.rb +14 -0
- data/test/unit/role_test.rb +19 -4
- data/test/unit/site_test.rb +67 -0
- data/test/unit/user_test.rb +20 -0
- data/test/unit/virtual_class_test.rb +116 -11
- data/test/unit/zena/use/rendering_test.rb +1 -1
- data/zena.gemspec +67 -66
- metadata +126 -125
- data/bricks/fs_skin/zena/init.rb +0 -1
- data/bricks/grid/zena/init.rb +0 -4
- data/bricks/single/zena/init.rb +0 -1
- data/bricks/spreadsheet/zena/init.rb +0 -3
data/History.txt
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
== 1.2.5 2013-07-15
|
|
2
|
+
|
|
3
|
+
* Major changes
|
|
4
|
+
* To support video streaming: redirect on first document cache. WARNING: This
|
|
5
|
+
implies changes to vhost files !
|
|
6
|
+
* WARN: Properties in list context do not resolve with first element anymore. "first" prefix needed.
|
|
7
|
+
* Enable VirtualClass on native classes !
|
|
8
|
+
* Added 'activity' brick which records visitor's last "seen_at" date. <== TODO: Document
|
|
9
|
+
|
|
10
|
+
* Minor changes
|
|
11
|
+
* Fixed encode_params in Ajax requests.
|
|
12
|
+
* Fixed cached path in vhost file.
|
|
13
|
+
* Added "uuid" method (generates a unique id). <== TODO: Document
|
|
14
|
+
* Added support for JSON String in [string_hash] <== TODO: Document
|
|
15
|
+
* Added 'login_info' to Node.
|
|
16
|
+
* Added 'group_names' to User class.
|
|
17
|
+
* Fixed [headers] when 'Status' is set (change to redirect on 300).
|
|
18
|
+
|
|
1
19
|
== 1.2.4 2013-06-13
|
|
2
20
|
|
|
3
21
|
* Major changes
|
|
@@ -203,14 +203,19 @@ class NodesController < ApplicationController
|
|
|
203
203
|
else
|
|
204
204
|
content_path = @node.filepath
|
|
205
205
|
end
|
|
206
|
-
|
|
206
|
+
|
|
207
|
+
# content_path is used to cache by creating a symlink
|
|
208
|
+
cache_ok = cache_page(:content_path => content_path, :authenticated => @node.v_public?)
|
|
209
|
+
|
|
207
210
|
if content_path
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
if @node.v_public? && cache_ok
|
|
212
|
+
# This is the simplest working solution to save cached version and use apache for serving (all xsendfile and such do not work with video streaming).
|
|
213
|
+
redirect_to data_path(@node, :mode => params[:mode]) + "?1"
|
|
214
|
+
else
|
|
215
|
+
# FIXME RAILS: remove 'stream => false' when rails streaming is fixed
|
|
216
|
+
send_file(content_path, :filename => @node.filename, :type => @node.content_type, :disposition => 'inline', :stream => false, :x_sendfile => ENABLE_XSENDFILE)
|
|
217
|
+
end
|
|
210
218
|
end
|
|
211
|
-
|
|
212
|
-
# content_path is used to cache by creating a symlink
|
|
213
|
-
cache_page(:content_path => content_path, :authenticated => @node.v_public?)
|
|
214
219
|
else
|
|
215
220
|
render_and_cache
|
|
216
221
|
# FIXME: redirect to document format should occur in render_and_cache
|
|
@@ -58,7 +58,7 @@ class UserSessionsController < ApplicationController
|
|
|
58
58
|
raise ActiveRecord::RecordNotFound.new("host not found #{request.host}")
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
setup_visitor(anonymous_visitor(site), site)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def redirect_after_login
|
|
@@ -10,11 +10,12 @@ class VirtualClassesController < ApplicationController
|
|
|
10
10
|
secure(::Role) do
|
|
11
11
|
@virtual_classes = ::Role.paginate(:all, :order => 'kpath', :per_page => 200, :page => params[:page])
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
list = @virtual_classes.map(&:name)
|
|
14
15
|
if last = @virtual_classes.last
|
|
15
16
|
last_kpath = last.kpath
|
|
16
17
|
Node.native_classes.each do |kpath, klass|
|
|
17
|
-
if kpath < last_kpath
|
|
18
|
+
if kpath < last_kpath && !list.include?(klass.name)
|
|
18
19
|
@virtual_classes << klass
|
|
19
20
|
end
|
|
20
21
|
end
|
data/app/models/document.rb
CHANGED
|
@@ -124,7 +124,7 @@ class Document < Node
|
|
|
124
124
|
# Try to find a virtual sub-class accepting the content type
|
|
125
125
|
vclass = nil
|
|
126
126
|
VirtualClass[base.to_s].sub_classes.each do |v|
|
|
127
|
-
next if v.real_class
|
|
127
|
+
next if v.real_class != base
|
|
128
128
|
|
|
129
129
|
if content_type =~ v.content_type_re
|
|
130
130
|
vclass = v
|
|
@@ -207,7 +207,7 @@ class Document < Node
|
|
|
207
207
|
end
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
-
# Make sure the new file
|
|
210
|
+
# Make sure the new file is OK with current class.
|
|
211
211
|
def valid_content_type
|
|
212
212
|
return true unless prop.content_type_changed?
|
|
213
213
|
|
data/app/models/node.rb
CHANGED
|
@@ -225,7 +225,8 @@ class Node < ActiveRecord::Base
|
|
|
225
225
|
:data_b => {:class => ['DataEntry'], :zafu => {:data_root => 'node_b'}},
|
|
226
226
|
:data_c => {:class => ['DataEntry'], :zafu => {:data_root => 'node_c'}},
|
|
227
227
|
:data_d => {:class => ['DataEntry'], :zafu => {:data_root => 'node_d'}},
|
|
228
|
-
:traductions => ['Version'], :discussion => 'Discussion'
|
|
228
|
+
:traductions => ['Version'], :discussion => 'Discussion',
|
|
229
|
+
:login_info => 'User'
|
|
229
230
|
|
|
230
231
|
# we use safe_method because the columns can be null, but the values are never null
|
|
231
232
|
safe_method :kpath => String, :user_zip => Number, :user_id => Number,
|
|
@@ -1205,6 +1206,10 @@ class Node < ActiveRecord::Base
|
|
|
1205
1206
|
def user
|
|
1206
1207
|
secure!(User) { o_user }
|
|
1207
1208
|
end
|
|
1209
|
+
|
|
1210
|
+
def login_info
|
|
1211
|
+
secure(User) { User.find(:first, :conditions => {:node_id => self.id})}
|
|
1212
|
+
end
|
|
1208
1213
|
|
|
1209
1214
|
# Find all data entries linked to the current node
|
|
1210
1215
|
def data
|
data/app/models/note.rb
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
=begin rdoc
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
=== dates
|
|
5
|
-
|
|
6
|
-
On top of the Node's dates (+created_at+, +updated_at+, +publish_from+), a note uses the following:
|
|
7
|
-
|
|
8
|
-
log_at:: used to sort/display blog entries
|
|
9
|
-
event_at:: used in calendars
|
|
10
|
-
|
|
11
|
-
These two dates enable you to announce an event in the blog list a couple of days before it actually occurs (event_at). All dates are stored internally as 'utc' and are converted to/from the visitor's current timezone.
|
|
12
|
-
|
|
13
|
-
=== links
|
|
14
|
-
|
|
15
|
-
Default links for Notes are:
|
|
16
|
-
|
|
17
|
-
calendars:: make this note appear in the given calendar (there is one calendar per project). By default the note is not included in its project's calendar.
|
|
18
|
-
projects:: make this note appear in the blog of the given project. A note always appear in its project.
|
|
19
|
-
|
|
20
|
-
=== subclasses
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
=== subclasses to implement before 1.0
|
|
24
|
-
Task:: manage things to be done (parent = Note = Todo). The parent provides the 'due date'.
|
|
25
|
-
Letter:: like the name says...
|
|
26
|
-
Request:: subclass of Todo. Manage user/client requests.
|
|
27
|
-
Bug:: (the class we most need!). subclass of Request.
|
|
28
|
-
Milestone:: special event used when choosing a Request/Bug's parent.
|
|
2
|
+
This class is not really useful anymore since 'event_at' and 'log_at' are obsolete. This class is really used for
|
|
3
|
+
testing having a virtual class 'Note' with a real ruby class of the same Name.
|
|
29
4
|
=end
|
|
30
5
|
class Note < Node
|
|
6
|
+
|
|
31
7
|
class << self
|
|
32
8
|
|
|
33
9
|
def select_classes
|
data/app/models/role.rb
CHANGED
|
@@ -271,12 +271,18 @@ class Role < ActiveRecord::Base
|
|
|
271
271
|
|
|
272
272
|
def validate_role
|
|
273
273
|
errors.add('base', 'You do not have the rights to change roles.') unless visitor.is_admin?
|
|
274
|
-
if new_record?
|
|
275
|
-
errors.add('superclass', 'invalid') unless @superclass.kind_of?(VirtualClass) && @superclass.kpath
|
|
276
|
-
end
|
|
277
274
|
|
|
278
|
-
if
|
|
279
|
-
self.kpath =
|
|
275
|
+
if name == 'Node'
|
|
276
|
+
self.kpath = 'N'
|
|
277
|
+
errors.add('base', 'cannot create role of name "Node"') if self.class == ::Role
|
|
278
|
+
else
|
|
279
|
+
if new_record?
|
|
280
|
+
errors.add('superclass', 'invalid') unless @superclass.kind_of?(VirtualClass) && @superclass.kpath
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
if @superclass && self.class == ::Role
|
|
284
|
+
self.kpath = @superclass.kpath
|
|
285
|
+
end
|
|
280
286
|
end
|
|
281
287
|
end
|
|
282
288
|
|
data/app/models/site.rb
CHANGED
|
@@ -6,7 +6,8 @@ A zena installation supports many sites. Each site is uniquely identified by it'
|
|
|
6
6
|
The #Site model holds configuration information for a site:
|
|
7
7
|
|
|
8
8
|
+host+:: Unique host name. (teti.ch, zenadmin.org, dev.example.org, ...)
|
|
9
|
-
+
|
|
9
|
+
+orphan_id+:: Site seed node id. This is the only node in the site without a parent.
|
|
10
|
+
+root_id+:: This is the apparent root of the site.
|
|
10
11
|
+anon_id+:: Anonymous user id. This user is the 'public' user of the site. Even if +authorize+ is set to true, this user is needed to configure the defaults for all newly created users.
|
|
11
12
|
+public_group_id+:: Id of the 'public' group. Every user of the site (with 'anonymous user') belongs to this group.
|
|
12
13
|
+site_group_id+:: Id of the 'site' group. Every user except anonymous are part of this group. This group can be seen as the 'logged in users' group.
|
|
@@ -16,6 +17,7 @@ The #Site model holds configuration information for a site:
|
|
|
16
17
|
+default_lang+:: The default language of the site.
|
|
17
18
|
=end
|
|
18
19
|
class Site < ActiveRecord::Base
|
|
20
|
+
attr_accessor :alias # = site alias (different settings + domain)
|
|
19
21
|
CLEANUP_SQL = [
|
|
20
22
|
['attachments' , 'site_id = ?'],
|
|
21
23
|
['cached_pages' , 'site_id = ?'],
|
|
@@ -54,12 +56,13 @@ class Site < ActiveRecord::Base
|
|
|
54
56
|
CACHE_PATH = Bricks.raw_config['cache_path'] || '/public'
|
|
55
57
|
|
|
56
58
|
include RubyLess
|
|
57
|
-
safe_method :host
|
|
58
|
-
safe_method :root
|
|
59
|
+
safe_method :host => String, :lang_list => [String], :default_lang => String, :master_host => String
|
|
60
|
+
safe_method :root => Proc.new {|h, r, s| {:method => 'root_node', :class => VirtualClass['Project'], :nil => true}}
|
|
61
|
+
safe_method :orphan => Proc.new {|h, r, s| {:method => 'orphan_node', :class => VirtualClass['Project'], :nil => true}}
|
|
59
62
|
|
|
60
63
|
validate :valid_site
|
|
61
64
|
validates_uniqueness_of :host
|
|
62
|
-
attr_accessible :name, :languages, :default_lang, :authentication, :http_auth, :ssl_on_auth, :auto_publish, :redit_time, :api_group_id
|
|
65
|
+
attr_accessible :name, :languages, :default_lang, :authentication, :http_auth, :ssl_on_auth, :auto_publish, :redit_time, :api_group_id, :root_zip
|
|
63
66
|
has_many :groups, :order => "name"
|
|
64
67
|
has_many :nodes
|
|
65
68
|
has_many :users
|
|
@@ -74,7 +77,12 @@ class Site < ActiveRecord::Base
|
|
|
74
77
|
|
|
75
78
|
@@attributes_for_form = {
|
|
76
79
|
:bool => %w{authentication http_auth auto_publish ssl_on_auth},
|
|
77
|
-
:text => %w{
|
|
80
|
+
:text => %w{languages default_lang},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@@alias_attributes_for_form = {
|
|
84
|
+
:bool => %w{authentication auto_publish ssl_on_auth},
|
|
85
|
+
:text => %w{},
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
class << self
|
|
@@ -117,7 +125,7 @@ class Site < ActiveRecord::Base
|
|
|
117
125
|
:lang => site.default_lang, :status => User::Status[:admin])
|
|
118
126
|
admin_user.site = site
|
|
119
127
|
|
|
120
|
-
|
|
128
|
+
setup_visitor(admin_user, site)
|
|
121
129
|
|
|
122
130
|
unless admin_user.save
|
|
123
131
|
# rollback
|
|
@@ -174,6 +182,8 @@ class Site < ActiveRecord::Base
|
|
|
174
182
|
raise Exception.new("Could not publish root node for site [#{host}] (site#{site[:id]})\n#{root.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") unless (root.v_status == Zena::Status::Pub || root.publish)
|
|
175
183
|
|
|
176
184
|
site.root_id = root[:id]
|
|
185
|
+
site.orphan_id = root[:id]
|
|
186
|
+
|
|
177
187
|
# Make sure safe definitions on Time/Array/String are available on prop_eval validation.
|
|
178
188
|
Zena::Use::ZafuSafeDefinitions
|
|
179
189
|
# Should not be needed since we load PropEval in Node, but it does not work
|
|
@@ -210,15 +220,27 @@ class Site < ActiveRecord::Base
|
|
|
210
220
|
site.instance_variable_set(:@being_created, false)
|
|
211
221
|
site
|
|
212
222
|
end
|
|
223
|
+
|
|
224
|
+
def master_sites
|
|
225
|
+
Site.all(:conditions => ['master_id is NULL'])
|
|
226
|
+
end
|
|
213
227
|
|
|
214
228
|
def find_by_host(host)
|
|
215
229
|
host = $1 if host =~ /^(.*)\.$/
|
|
216
|
-
self.find(:first, :conditions => ['host = ?', host]) rescue nil
|
|
230
|
+
if site = self.find(:first, :conditions => ['host = ?', host]) rescue nil
|
|
231
|
+
if id = site.master_id
|
|
232
|
+
# The loaded site is an alias, load master site.
|
|
233
|
+
master = self.find(:first, :conditions => ['id = ?', id])
|
|
234
|
+
master.alias = site
|
|
235
|
+
site = master
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
site
|
|
217
239
|
end
|
|
218
240
|
|
|
219
241
|
# List of attributes that can be configured in the admin form
|
|
220
|
-
def attributes_for_form
|
|
221
|
-
@@attributes_for_form
|
|
242
|
+
def attributes_for_form(is_alias = false)
|
|
243
|
+
is_alias ? @@alias_attributes_for_form : @@attributes_for_form
|
|
222
244
|
end
|
|
223
245
|
end
|
|
224
246
|
|
|
@@ -229,31 +251,31 @@ class Site < ActiveRecord::Base
|
|
|
229
251
|
Site.attributes_for_form[:text] << 'usr_prototype_attributes'
|
|
230
252
|
Site.attributes_for_form[:bool] << 'expire_in_dev'
|
|
231
253
|
attr_accessible :usr_prototype_attributes, :expire_in_dev
|
|
232
|
-
|
|
254
|
+
|
|
233
255
|
# Return path for static/cached content served by proxy: RAILS_ROOT/sites/_host_/public
|
|
234
256
|
# If you need to serve from another directory, we do not store the path into the sites table
|
|
235
257
|
# for security reasons. The easiest way around this limitation is to symlink the 'public' directory.
|
|
236
258
|
def public_path
|
|
237
|
-
"/#{
|
|
259
|
+
"/#{host}#{PUBLIC_PATH}"
|
|
238
260
|
end
|
|
239
261
|
|
|
240
262
|
# This is the place where cached files should be stored in case we do not want
|
|
241
263
|
# to store the cached file inside the public directory.
|
|
242
264
|
def cache_path
|
|
243
|
-
"/#{
|
|
265
|
+
"/#{host}#{CACHE_PATH}"
|
|
244
266
|
end
|
|
245
267
|
|
|
246
268
|
# Return path for documents data: RAILS_ROOT/sites/_host_/data
|
|
247
269
|
# You can symlink the 'data' directory if you need to keep the data in some other place.
|
|
248
270
|
def data_path
|
|
249
|
-
"/#{
|
|
271
|
+
"/#{master_host}/data"
|
|
250
272
|
end
|
|
251
273
|
|
|
252
274
|
# Return the path for zafu rendered templates: RAILS_ROOT/sites/_host_/zafu
|
|
253
275
|
def zafu_path
|
|
254
|
-
"/#{
|
|
276
|
+
"/#{master_host}/zafu"
|
|
255
277
|
end
|
|
256
|
-
|
|
278
|
+
|
|
257
279
|
# Return the anonymous user, the one used by anonymous visitors to visit the public part
|
|
258
280
|
# of the site.
|
|
259
281
|
def anon
|
|
@@ -268,8 +290,12 @@ class Site < ActiveRecord::Base
|
|
|
268
290
|
# Return the root node or a dummy if the visitor cannot view root
|
|
269
291
|
# node (such as during a 404 or login rendering).
|
|
270
292
|
def root_node
|
|
271
|
-
@root ||= secure(Node) { Node.find(
|
|
272
|
-
|
|
293
|
+
@root ||= secure(Node) { Node.find(root_id) } || Node.new(:title => host)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Return the orphan node.
|
|
297
|
+
def orphan_node
|
|
298
|
+
@orphan ||= secure(Node) { Node.find(orphan_id) } || Node.new(:title => host)
|
|
273
299
|
end
|
|
274
300
|
|
|
275
301
|
# Return the public group: the one in which every visitor belongs.
|
|
@@ -298,16 +324,6 @@ class Site < ActiveRecord::Base
|
|
|
298
324
|
@admin_user_ids ||= secure!(User) { User.find(:all, :conditions => "status >= #{User::Status[:admin]}") }.map {|r| r[:id]}
|
|
299
325
|
end
|
|
300
326
|
|
|
301
|
-
# Return true if the site is configured to force authentication
|
|
302
|
-
def authentication?
|
|
303
|
-
self[:authentication]
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
# Return true if the site is configured to automatically publish redactions
|
|
307
|
-
def auto_publish?
|
|
308
|
-
self[:auto_publish]
|
|
309
|
-
end
|
|
310
|
-
|
|
311
327
|
# Set redit time from a string of the form "1d 4h 5s" or "4 days"
|
|
312
328
|
def redit_time=(val)
|
|
313
329
|
if val.kind_of?(String)
|
|
@@ -337,6 +353,64 @@ class Site < ActiveRecord::Base
|
|
|
337
353
|
def lang_list
|
|
338
354
|
(self[:languages] || "").split(',').map(&:strip)
|
|
339
355
|
end
|
|
356
|
+
|
|
357
|
+
###### Alias handling
|
|
358
|
+
def is_alias?
|
|
359
|
+
!self[:master_id].blank?
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# This is the host of the master site.
|
|
363
|
+
def master_host
|
|
364
|
+
self[:host]
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# Host with aliasing (returns alias host if alias is loaded)
|
|
368
|
+
def host
|
|
369
|
+
@alias && @alias.host || master_host
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def ssl_on_auth
|
|
373
|
+
@alias && @alias.prop['ssl_on_auth'] || self.prop['ssl_on_auth']
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Return true if the site is configured to automatically publish redactions
|
|
377
|
+
def auto_publish?
|
|
378
|
+
@alias && @alias[:auto_publish] || self[:auto_publish]
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# Return true if the site is configured to force authentication
|
|
382
|
+
def authentication?
|
|
383
|
+
@alias && @alias[:authentication] || self[:authentication]
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def root_id
|
|
387
|
+
@root_id ||= @alias && @alias[:root_id] || self[:root_id]
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def root_zip
|
|
391
|
+
root_node.zip
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def root_zip=(zip)
|
|
395
|
+
if id = secure(Node) { Node.translate_pseudo_id(zip) }
|
|
396
|
+
self[:root_id] = id
|
|
397
|
+
else
|
|
398
|
+
@root_zip_error = _('could not be found')
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def create_alias(hostname)
|
|
403
|
+
raise "Hostname '#{hostname}' already exists" if Site.find_by_host(hostname)
|
|
404
|
+
ali = Site.new(self.attributes)
|
|
405
|
+
ali.host = hostname
|
|
406
|
+
ali.master_id = self.id
|
|
407
|
+
ali.orphan_id = self.orphan_id
|
|
408
|
+
ali.root_id = self.root_id
|
|
409
|
+
ali.prop = self.prop
|
|
410
|
+
ali.save
|
|
411
|
+
ali
|
|
412
|
+
end
|
|
413
|
+
######
|
|
340
414
|
|
|
341
415
|
def being_created?
|
|
342
416
|
@being_created
|
|
@@ -383,24 +457,36 @@ class Site < ActiveRecord::Base
|
|
|
383
457
|
end
|
|
384
458
|
|
|
385
459
|
def clear_cache(clear_zafu = true)
|
|
386
|
-
|
|
387
|
-
Site.
|
|
460
|
+
paths = ["#{SITES_ROOT}#{self.cache_path}"]
|
|
461
|
+
aliases = Site.all(:conditions => {:master_id => self.id})
|
|
462
|
+
aliases.each do |site|
|
|
463
|
+
paths << "#{SITES_ROOT}#{site.cache_path}"
|
|
464
|
+
end
|
|
465
|
+
Site.logger.error("\n-----------------\nCLEAR CACHE FOR SITE #{host} (#{aliases.map(&:host).join(', ')})\n-----------------\n")
|
|
388
466
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
467
|
+
paths.each do |path|
|
|
468
|
+
if File.exist?(path)
|
|
469
|
+
Dir.foreach(path) do |elem|
|
|
470
|
+
next unless elem =~ /^(\w\w\.html|\w\w|login\.html)$/
|
|
471
|
+
FileUtils.rmtree(File.join(path, elem))
|
|
472
|
+
end
|
|
394
473
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
474
|
+
Zena::Db.execute "DELETE FROM caches WHERE site_id = #{self[:id]}"
|
|
475
|
+
Zena::Db.execute "DELETE FROM cached_pages_nodes WHERE cached_pages_nodes.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.site_id = #{self[:id]})"
|
|
476
|
+
Zena::Db.execute "DELETE FROM cached_pages WHERE site_id = #{self[:id]}"
|
|
477
|
+
end
|
|
398
478
|
end
|
|
399
|
-
|
|
479
|
+
|
|
480
|
+
# Clear zafu
|
|
400
481
|
if clear_zafu
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
482
|
+
paths = ["#{SITES_ROOT}#{self.zafu_path}"]
|
|
483
|
+
aliases.each do |site|
|
|
484
|
+
paths << "#{SITES_ROOT}#{site.cache_path}"
|
|
485
|
+
end
|
|
486
|
+
paths.each do |path|
|
|
487
|
+
if File.exist?(path)
|
|
488
|
+
FileUtils.rmtree(path)
|
|
489
|
+
end
|
|
404
490
|
end
|
|
405
491
|
end
|
|
406
492
|
|
|
@@ -510,8 +596,19 @@ class Site < ActiveRecord::Base
|
|
|
510
596
|
private
|
|
511
597
|
def valid_site
|
|
512
598
|
errors.add(:host, 'invalid') if self[:host].nil? || (self[:host] =~ /^\./) || (self[:host] =~ /[^\w\.\-]/)
|
|
513
|
-
|
|
514
|
-
|
|
599
|
+
|
|
600
|
+
if !is_alias?
|
|
601
|
+
errors.add(:languages, 'invalid') unless self[:languages].split(',').inject(true){|i,l| (i && l =~ /^\w\w$/)}
|
|
602
|
+
errors.add(:default_lang, 'invalid') unless self[:languages].split(',').include?(self[:default_lang])
|
|
603
|
+
else
|
|
604
|
+
self[:languages] = nil
|
|
605
|
+
self[:default_lang] = nil
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
if @root_zip_error
|
|
609
|
+
errors.add('root_id', @root_zip_error)
|
|
610
|
+
@root_zip_error = nil
|
|
611
|
+
end
|
|
515
612
|
end
|
|
516
613
|
|
|
517
614
|
end
|