zena 1.2.3 → 1.2.4
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 +29 -1
- data/Rakefile +0 -1
- data/app/controllers/documents_controller.rb +1 -1
- data/app/controllers/nodes_controller.rb +34 -8
- data/app/controllers/sites_controller.rb +8 -1
- data/app/controllers/user_sessions_controller.rb +13 -3
- data/app/models/acl.rb +16 -0
- data/app/models/document.rb +33 -14
- data/app/models/idx_nodes_integer.rb +5 -0
- data/app/models/image.rb +16 -4
- data/app/models/node.rb +16 -3
- data/app/models/relation_proxy.rb +3 -3
- data/app/models/site.rb +11 -1
- data/app/models/string_hash.rb +1 -1
- data/app/models/template.rb +1 -1
- data/app/models/user.rb +6 -1
- data/app/models/virtual_class.rb +36 -1
- data/app/views/acls/_form.rhtml +5 -1
- data/app/views/acls/_li.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -0
- data/app/views/templates/document_create_tabs/_template.rhtml +1 -1
- data/app/views/users/_form.rhtml +1 -0
- data/app/views/virtual_classes/_form.erb +8 -7
- data/bricks/acls/lib/bricks/acls.rb +43 -15
- data/bricks/acls/zena/migrate/20130313110443_add_create_kpath_to_acl.rb +13 -0
- data/bricks/acls/zena/migrate/20130429073432_fix_create_kpath_default.rb +8 -0
- data/bricks/acls/zena/test/integration/acl_integration_test.rb +53 -1
- data/bricks/acls/zena/test/sites/erebus/acls.yml +21 -0
- data/bricks/acls/zena/test/unit/acl_test.rb +35 -2
- data/bricks/math/lib/bricks/math.rb +1 -1
- data/bricks/sphinx/zena/tasks.rb +1 -1
- data/bricks/spreadsheet/lib/bricks/spreadsheet.rb +1 -1
- data/bricks/worker/zena/worker +25 -0
- data/config/environment.rb +1 -1
- data/config/environments/production.rb +1 -1
- data/config/gems.yml +6 -5
- data/lib/bricks/requirements_validation.rb +1 -1
- data/lib/log_recorder/lib/log_recorder.rb +1 -1
- data/lib/tasks/zena.rake +10 -2
- data/lib/zena.rb +4 -3
- data/lib/zena/app.rb +1 -0
- data/lib/zena/deploy/httpd.rhtml +2 -2
- data/lib/zena/deploy/template.rb +15 -5
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +9 -2
- data/lib/zena/remote/connection.rb +2 -2
- data/lib/zena/remote/interface.rb +8 -2
- data/lib/zena/remote/node.rb +1 -1
- data/lib/zena/routes.rb +2 -1
- data/lib/zena/use/action.rb +8 -2
- data/lib/zena/use/ajax.rb +31 -20
- data/lib/zena/use/calendar.rb +2 -0
- data/lib/zena/use/conditional.rb +15 -14
- data/lib/zena/use/dates.rb +5 -2
- data/lib/zena/use/display.rb +3 -2
- data/lib/zena/use/forms.rb +36 -9
- data/lib/zena/use/i18n.rb +8 -2
- data/lib/zena/use/image_builder.rb +7 -0
- data/lib/zena/use/query_node.rb +24 -8
- data/lib/zena/use/relations.rb +2 -6
- data/lib/zena/use/rendering.rb +10 -6
- data/lib/zena/use/upload.rb +6 -4
- data/lib/zena/use/urls.rb +13 -5
- data/lib/zena/use/zafu_safe_definitions.rb +1 -1
- data/public/javascripts/grid.js +11 -2
- data/public/javascripts/upload-progress.js +5 -3
- data/public/javascripts/zena.js +6 -2
- data/public/stylesheets/upload-progress.css +1 -0
- data/test/fixtures/files/TestNode.zafu +2 -2
- data/test/fixtures/files/translations_fr.yml +2 -1
- data/test/functional/acls_controller_test.rb +6 -0
- data/test/functional/nodes_controller_test.rb +1 -1
- data/test/functional/sites_controller_test.rb +19 -0
- data/test/integration/navigation_test.rb +7 -0
- data/test/integration/query_node/filters.yml +10 -0
- data/test/integration/zafu_compiler/action.yml +8 -4
- data/test/integration/zafu_compiler/ajax.yml +4 -4
- data/test/integration/zafu_compiler/calendar.yml +8 -15
- data/test/integration/zafu_compiler/context.yml +1 -1
- data/test/integration/zafu_compiler/dates.yml +5 -1
- data/test/integration/zafu_compiler/display.yml +1 -2
- data/test/integration/zafu_compiler/forms.yml +37 -10
- data/test/integration/zafu_compiler/query.yml +5 -5
- data/test/integration/zafu_compiler/relations.yml +8 -8
- data/test/integration/zafu_compiler/safe_definitions.yml +7 -2
- data/test/integration/zafu_compiler/urls.yml +24 -3
- data/test/integration/zafu_compiler/zazen.yml +9 -1
- data/test/selenium/Destroy/destroy1.rsel +2 -1
- data/test/selenium/Destroy/destroy2.rsel +17 -0
- data/test/unit/document_test.rb +17 -4
- data/test/unit/relation_proxy_test.rb +19 -8
- data/test/unit/string_hash_test.rb +1 -1
- data/test/unit/template_test.rb +3 -3
- data/test/unit/virtual_class_test.rb +77 -0
- data/test/unit/zena/use/urls_test.rb +9 -1
- data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails_config.rb +1 -1
- data/zena.gemspec +60 -53
- metadata +145 -125
|
@@ -70,7 +70,7 @@ class RelationProxy < Relation
|
|
|
70
70
|
# get
|
|
71
71
|
|
|
72
72
|
def other_link
|
|
73
|
-
other_links ? other_links
|
|
73
|
+
other_links ? other_links.first : nil
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def other_id
|
|
@@ -100,9 +100,9 @@ class RelationProxy < Relation
|
|
|
100
100
|
}.merge(opts)
|
|
101
101
|
@records = secure(Node) { Node.find(:all, options) }
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
LINK_ATTRIBUTES.each do |sym|
|
|
105
|
-
define_method(sym) do
|
|
105
|
+
define_method(:"other_#{sym}") do
|
|
106
106
|
other_link ? other_link[sym] : nil
|
|
107
107
|
end
|
|
108
108
|
end
|
data/app/models/site.rb
CHANGED
|
@@ -470,9 +470,19 @@ class Site < ActiveRecord::Base
|
|
|
470
470
|
# unpublished templates).
|
|
471
471
|
def rebuild_index(nodes = nil, page = nil, page_count = nil)
|
|
472
472
|
if !page
|
|
473
|
-
Site.logger.error("\n----------------- REBUILD INDEX FOR SITE #{host} -----------------\n")
|
|
474
473
|
Zena::SiteWorker.perform(self, :rebuild_index)
|
|
475
474
|
else
|
|
475
|
+
if page == 1
|
|
476
|
+
Site.logger.error("\n----------------- REBUILD INDEX FOR SITE #{host} -----------------\n")
|
|
477
|
+
# Reset reference to cache origin to make sure it is always overwritten
|
|
478
|
+
Zena::Use::ScopeIndex::AVAILABLE_MODELS.each do |klass|
|
|
479
|
+
changes = klass.column_names.select{|n| n =~ %r{(.*)_id}}.reject {|n| %w{node_id site_id}.include?(n)}.map do |c|
|
|
480
|
+
"#{c} = NULL"
|
|
481
|
+
end.join(', ')
|
|
482
|
+
Site.logger.error("#{klass.name}: reset #{changes}\n")
|
|
483
|
+
Zena::Db.execute "UPDATE #{klass.table_name} SET #{changes} WHERE site_id = #{id}"
|
|
484
|
+
end
|
|
485
|
+
end
|
|
476
486
|
# do things
|
|
477
487
|
nodes.each do |node|
|
|
478
488
|
node.rebuild_index!
|
data/app/models/string_hash.rb
CHANGED
data/app/models/template.rb
CHANGED
data/app/models/user.rb
CHANGED
|
@@ -340,7 +340,7 @@ class User < ActiveRecord::Base
|
|
|
340
340
|
end
|
|
341
341
|
end
|
|
342
342
|
|
|
343
|
-
def find_node(path, zip, name, request)
|
|
343
|
+
def find_node(path, zip, name, request, need_write = false)
|
|
344
344
|
secure!(Node) do
|
|
345
345
|
if name =~ /^\d+$/
|
|
346
346
|
Node.find_by_zip(name)
|
|
@@ -397,6 +397,11 @@ class User < ActiveRecord::Base
|
|
|
397
397
|
if login.blank? && !is_anon?
|
|
398
398
|
self.login = name
|
|
399
399
|
end
|
|
400
|
+
|
|
401
|
+
if !is_admin?
|
|
402
|
+
# Make sure we remove dev_skin settings if user is not an admin.
|
|
403
|
+
self[:dev_skin_id] = nil
|
|
404
|
+
end
|
|
400
405
|
end
|
|
401
406
|
|
|
402
407
|
# Validates that anon user does not have a login, that other users have a password
|
data/app/models/virtual_class.rb
CHANGED
|
@@ -34,7 +34,7 @@ class VirtualClass < Role
|
|
|
34
34
|
attr_accessor :export_attributes
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
self.export_attributes = %w{auto_create_discussion icon monolingual}
|
|
37
|
+
self.export_attributes = %w{auto_create_discussion icon monolingual content_type}
|
|
38
38
|
|
|
39
39
|
attr_accessor :import_result
|
|
40
40
|
belongs_to :create_group, :class_name => 'Group', :foreign_key => 'create_group_id'
|
|
@@ -52,7 +52,10 @@ class VirtualClass < Role
|
|
|
52
52
|
include Zena::Use::ScopeIndex::VirtualClassMethods
|
|
53
53
|
|
|
54
54
|
property.boolean 'monolingual'
|
|
55
|
+
property.text 'content_type'
|
|
56
|
+
|
|
55
57
|
safe_method :monolingual? => Boolean
|
|
58
|
+
safe_method :content_type => String
|
|
56
59
|
safe_method :roles => {:class => ['Role'], :method => 'sorted_roles'}
|
|
57
60
|
safe_method :relations => {:class => ['RelationProxy'], :method => 'all_relations'}
|
|
58
61
|
safe_method [:relations, String] => {:class => ['RelationProxy'], :method => 'filtered_relations'}
|
|
@@ -68,6 +71,17 @@ class VirtualClass < Role
|
|
|
68
71
|
end
|
|
69
72
|
end
|
|
70
73
|
|
|
74
|
+
# Class path hierarchy. Example for (Post) : N, NN, NNP
|
|
75
|
+
def self.split_kpath(kpath)
|
|
76
|
+
parts = []
|
|
77
|
+
kpath.split(//).each_index { |i| parts << kpath[0..i] }
|
|
78
|
+
parts
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def split_kpath
|
|
82
|
+
@split_kpath ||= VirtualClass.split_kpath(kpath)
|
|
83
|
+
end
|
|
84
|
+
|
|
71
85
|
class Cache
|
|
72
86
|
def initialize
|
|
73
87
|
clear_cache!
|
|
@@ -240,6 +254,7 @@ class VirtualClass < Role
|
|
|
240
254
|
attribute = opts[:class_attr] || 'name'
|
|
241
255
|
|
|
242
256
|
VirtualClass.all_classes(base_kpath, opts[:without]).map do |vclass|
|
|
257
|
+
# Only insert allowed classes.
|
|
243
258
|
if vclass.create_group_id.nil? || group_ids.include?(vclass.create_group_id)
|
|
244
259
|
# white spaces are insecable spaces (not ' ')
|
|
245
260
|
a, b = vclass.kpath, vclass.name
|
|
@@ -249,6 +264,15 @@ class VirtualClass < Role
|
|
|
249
264
|
end
|
|
250
265
|
end.compact
|
|
251
266
|
end
|
|
267
|
+
|
|
268
|
+
def sub_classes
|
|
269
|
+
@sub_classes ||= VirtualClass.all_classes(self.kpath).sort {|a,b| a.name <=> b.name}
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def content_type_re
|
|
273
|
+
# if content_type is empty => match all
|
|
274
|
+
@content_type_re ||= %r{^#{content_type || ".*"}$}
|
|
275
|
+
end
|
|
252
276
|
|
|
253
277
|
# Include all roles into the this schema. By including the superclass
|
|
254
278
|
# and all roles related to this class.
|
|
@@ -579,6 +603,17 @@ class VirtualClass < Role
|
|
|
579
603
|
unless self[:real_class]
|
|
580
604
|
errors.add('superclass', 'invalid')
|
|
581
605
|
end
|
|
606
|
+
|
|
607
|
+
if content_type =~ /[^a-zA-Z\.\-\/\*\|\\]/
|
|
608
|
+
errors.add('content_type', 'invalid characters')
|
|
609
|
+
else
|
|
610
|
+
begin
|
|
611
|
+
re = %r{^#{content_type}$}
|
|
612
|
+
rescue RegexpError => err
|
|
613
|
+
errors.add('content_type', err.message)
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
582
617
|
end
|
|
583
618
|
|
|
584
619
|
def get_real_class(klass)
|
data/app/views/acls/_form.rhtml
CHANGED
|
@@ -21,7 +21,11 @@
|
|
|
21
21
|
</tr>
|
|
22
22
|
<tr>
|
|
23
23
|
<td class='label'><%= _('action')%> <%= help(_('acl_action_help')) %></td>
|
|
24
|
-
<td
|
|
24
|
+
<td>
|
|
25
|
+
<%= select('acl', 'action', Acl::ACTIONS ) %>
|
|
26
|
+
|
|
27
|
+
<%= _('create only: allow') %> <%= select('acl', 'create_kpath', Node.kpaths_for_form ) %>
|
|
28
|
+
</td>
|
|
25
29
|
</tr>
|
|
26
30
|
<tr class='priority'>
|
|
27
31
|
<td class='label'><%= _('priority')%> <%= help(_('acl_priority_help')) %></td>
|
data/app/views/acls/_li.rhtml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<tr id='acl<%= li[:id] %>'>
|
|
2
2
|
<td class="adm_icon"><%= link_to_remote( _("img_acl"), :update=>"acl#{li[:id]}", :url=>edit_acl_path(li), :method=>:get) %></td>
|
|
3
3
|
<td class='group'><%= li.group.name %></td>
|
|
4
|
-
<td class='act'><%= li.action %></td>
|
|
4
|
+
<td class='act'><%= li.action %><% if li.action == 'create' %> <span class='constant'><%= li.create_vclass_name %></span><% end %></td>
|
|
5
5
|
<td class='name'><%= li.name %></td>
|
|
6
6
|
<td class='mode'><%= li.mode %></td>
|
|
7
7
|
<td class='format'><%= li.format %></td>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<input id='title' type='text' name='node[title]'/><br/>
|
|
12
12
|
|
|
13
13
|
<label for='node_target_klass'><%= _('class scope') %></label>
|
|
14
|
-
<%= select('node', 'target_klass', Node.classes_for_form, {:include_blank => true} ) %><br/>
|
|
14
|
+
<%= select('node', 'target_klass', Node.classes_for_form, {:include_blank => true}, {} ) %><br/>
|
|
15
15
|
|
|
16
16
|
<label for='node_mode'><%= _('mode') %></label>
|
|
17
17
|
<input id='node_mode' type='text' name='node[mode]'/><br/>
|
data/app/views/users/_form.rhtml
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
<% end -%>
|
|
24
24
|
<% end -%>
|
|
25
25
|
<tr><td class='label'><%= _("status")%> </td><td><%= select('user', 'status', User::Status.reject {|k,v| v > User::Status[:admin]}.map{|k,v| [_(k.to_s),v]}.sort{|a,b| b[1] <=> a[1]}) %></td></tr>
|
|
26
|
+
<tr><td class='label'><%= _("single_access_token")%> </td><td><%= @user.single_access_token %></td></tr>
|
|
26
27
|
<tr><td class='label'><%= _('language')%> </td><td><%= select('user', 'lang', visitor.site.lang_list.map {|l| [_(l),l]}) %></td></tr>
|
|
27
28
|
<tr><td class='label'><%= _("time zone")%> </td><td><select name='user[time_zone]'><%= options_for_select([''] + TZInfo::Timezone.all_identifiers, @user[:time_zone] || '') %></select></td></tr>
|
|
28
29
|
<% unless @user.is_anon? -%>
|
|
@@ -32,16 +32,17 @@
|
|
|
32
32
|
|
|
33
33
|
<% if @virtual_class.kind_of?(VirtualClass) -%>
|
|
34
34
|
<% Zena::Use::Fulltext::FULLTEXT_FIELDS.reverse_each do |fld| -%>
|
|
35
|
-
<tr><td class='label'><%= _(fld)%></td><td><%= text_area('virtual_class', fld, :rows => 2, :cols => 30) %></td></tr>
|
|
35
|
+
<tr><td class='label'><%= _(fld) %></td><td><%= text_area('virtual_class', fld, :rows => 2, :cols => 30) %></td></tr>
|
|
36
36
|
<% end -%>
|
|
37
|
-
<tr><td class='label'><%= _('idx_class')%></td><td><%= select('virtual_class', 'idx_class', Zena::Use::ScopeIndex.models_for_form) %></td></tr>
|
|
38
|
-
<tr><td class='label'><%= _('idx_scope')%></td><td><%= text_area('virtual_class', 'idx_scope', :rows => 2, :cols => 30) %></td></tr>
|
|
39
|
-
<tr><td class='label'><%= _('idx_reverse_scope')%></td><td><%= text_area('virtual_class', 'idx_reverse_scope', :rows => 2, :cols => 30) %></td></tr>
|
|
40
|
-
<tr><td class='label'><%= _('prop eval')%></td><td><%= text_area('virtual_class', 'prop_eval', :rows => 2, :cols => 30) %></td></tr>
|
|
37
|
+
<tr><td class='label'><%= _('idx_class') %></td><td><%= select('virtual_class', 'idx_class', Zena::Use::ScopeIndex.models_for_form) %></td></tr>
|
|
38
|
+
<tr><td class='label'><%= _('idx_scope') %></td><td><%= text_area('virtual_class', 'idx_scope', :rows => 2, :cols => 30) %></td></tr>
|
|
39
|
+
<tr><td class='label'><%= _('idx_reverse_scope') %></td><td><%= text_area('virtual_class', 'idx_reverse_scope', :rows => 2, :cols => 30) %></td></tr>
|
|
40
|
+
<tr><td class='label'><%= _('prop eval') %></td><td><%= text_area('virtual_class', 'prop_eval', :rows => 2, :cols => 30) %></td></tr>
|
|
41
41
|
|
|
42
|
-
<tr><td class='label'><%= _('
|
|
42
|
+
<tr><td class='label'><%= _('edit group') %></td><td><%= select('virtual_class', 'create_group_id', visitor.all_groups.map{|g| [g.name, g.id]} ) %></td></tr>
|
|
43
43
|
<tr><td class='label'><%= _('auto create discussion')%></td><td><%= check_box('virtual_class', 'auto_create_discussion') %></td></tr>
|
|
44
|
-
<tr><td class='label'><%= _('monolingual')%></td><td><%= check_box('virtual_class', 'monolingual') %></td></tr>
|
|
44
|
+
<tr><td class='label'><%= _('monolingual') %></td><td><%= check_box('virtual_class', 'monolingual') %></td></tr>
|
|
45
|
+
<tr><td class='label'><%= _('content_type')%></td><td><%= text_field('virtual_class', 'content_type') %></td></tr>
|
|
45
46
|
<% end -%>
|
|
46
47
|
<tr><td class='label'><%= _('icon')%> </td><td><%= text_field('virtual_class', 'icon', :size=>15 ) %></td></tr>
|
|
47
48
|
<tr><td colspan='2'><p class='btn_validate'><input type='submit' value='<%= _('validate') %>'/></p></td></tr>
|
|
@@ -34,7 +34,11 @@ module Bricks
|
|
|
34
34
|
def acl_authorized?(action, params, request)
|
|
35
35
|
node = nil
|
|
36
36
|
group_ids_bak = group_ids.dup
|
|
37
|
-
|
|
37
|
+
if action == 'create'
|
|
38
|
+
klass = (params['node'] || {})['klass']
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
acls(action, params[:mode], params[:format], klass).each do |acl|
|
|
38
42
|
# Load exec_group to execute query
|
|
39
43
|
if acl.exec_group_id
|
|
40
44
|
@group_ids = group_ids_bak + [acl.exec_group_id]
|
|
@@ -56,27 +60,46 @@ module Bricks
|
|
|
56
60
|
|
|
57
61
|
# Find all acls for the visitor for a given action. The action should
|
|
58
62
|
# be one of the following: 'create', 'read', 'update', 'delete'. See
|
|
59
|
-
# Acl::ACTIONS.
|
|
60
|
-
|
|
63
|
+
# Acl::ACTIONS. If the action is 'create', we should also pass the class
|
|
64
|
+
# of the object to create.
|
|
65
|
+
def acls(action, mode, format, klass = nil)
|
|
61
66
|
mode = '' if mode.blank?
|
|
62
67
|
# Can the format be blank ?
|
|
63
68
|
format = 'html' if format.blank?
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if action == 'create'
|
|
70
|
+
return [] unless klass = VirtualClass[klass || 'Node']
|
|
71
|
+
# Can the format be blank ?
|
|
72
|
+
format = 'html' if format.blank?
|
|
73
|
+
secure(Acl) { Acl.find(:all,
|
|
74
|
+
:conditions => [
|
|
75
|
+
'group_id IN (?) AND action = ? AND (mode = ? OR mode = ?) AND (format = ? OR format = ?) AND create_kpath IN (?)',
|
|
76
|
+
group_ids, action, '*', mode, '*', format, klass.split_kpath],
|
|
77
|
+
:order => 'priority DESC'
|
|
78
|
+
)}
|
|
79
|
+
else
|
|
80
|
+
secure(Acl) { Acl.find(:all,
|
|
81
|
+
:conditions => [
|
|
82
|
+
'group_id IN (?) AND action = ? AND (mode = ? OR mode = ?) AND (format = ? OR format = ?)',
|
|
83
|
+
group_ids, action, '*', mode, '*', format],
|
|
84
|
+
:order => 'priority DESC'
|
|
85
|
+
)}
|
|
86
|
+
end || []
|
|
70
87
|
end
|
|
71
88
|
|
|
72
89
|
def get_skin_with_acls(node)
|
|
73
90
|
exec_acl ? exec_acl.exec_skin : get_skin_without_acls(node)
|
|
74
91
|
end
|
|
75
92
|
|
|
76
|
-
def find_node_with_acls(path, zip, name, request)
|
|
77
|
-
find_node_without_acls(path, zip, name, request)
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
def find_node_with_acls(path, zip, name, request, need_write = false)
|
|
94
|
+
n = find_node_without_acls(path, zip, name, request, need_write) rescue nil
|
|
95
|
+
if !n || (!n.can_write? && need_write)
|
|
96
|
+
n = find_node_force_acls(path, zip, name, request) || n
|
|
97
|
+
end
|
|
98
|
+
n
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def find_node_force_acls(path, zip, name, request)
|
|
102
|
+
raise ActiveRecord::RecordNotFound unless visitor.use_acls?
|
|
80
103
|
acl_params = request.params.dup
|
|
81
104
|
if name =~ /^\d+$/
|
|
82
105
|
acl_params[:id] = name
|
|
@@ -86,8 +109,13 @@ module Bricks
|
|
|
86
109
|
else
|
|
87
110
|
acl_params[:id] = zip
|
|
88
111
|
end
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
if request.path =~ %r{^/nodes/\d+/zafu$}
|
|
113
|
+
# This is to allow preview by using POST requests (long text in js).
|
|
114
|
+
action = 'read'
|
|
115
|
+
else
|
|
116
|
+
action = ::Acl::ACTION_FROM_METHOD[request.method]
|
|
117
|
+
end
|
|
118
|
+
visitor.acl_authorized?(action, acl_params, request)
|
|
91
119
|
end
|
|
92
120
|
end # UserMethods
|
|
93
121
|
end # Acls
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddCreateKpathToAcl < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :acls, :create_kpath, :string, :limit => 200
|
|
4
|
+
add_index :acls, ["create_kpath", "group_id", "action", "site_id"]
|
|
5
|
+
rescue
|
|
6
|
+
# Could be run twice (was in zena brick by mistake in zena 1.2.4pre)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.down
|
|
10
|
+
remove_column :groups, :auto_publish
|
|
11
|
+
remove_index :acls, :column => ["create_kpath", "group_id", "action", "site_id"]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -145,7 +145,8 @@ class AclIntegrationTest < Zena::Integration::TestCase
|
|
|
145
145
|
setup do
|
|
146
146
|
# The visitor can create objects in assigned_project as direct parent
|
|
147
147
|
Zena::Db.execute "UPDATE acls SET query = '%q{assigned_project}', action = 'create' WHERE id = #{acls_id(:rap)}"
|
|
148
|
-
@create_url = "http://erebus.host/nodes?node[parent_id]=#{nodes_zip(:queen)}&node[klass]=
|
|
148
|
+
@create_url = "http://erebus.host/nodes?node[parent_id]=#{nodes_zip(:queen)}&node[klass]=Contact&node[title]=foobar"
|
|
149
|
+
@create_bad = "http://erebus.host/nodes?node[parent_id]=#{nodes_zip(:queen)}&node[klass]=Page&node[title]=foobar"
|
|
149
150
|
end
|
|
150
151
|
|
|
151
152
|
context 'with wrong user status' do
|
|
@@ -170,6 +171,14 @@ class AclIntegrationTest < Zena::Integration::TestCase
|
|
|
170
171
|
assert_equal nodes_id(:queen), node.parent_id
|
|
171
172
|
assert_equal 'foobar', node.title
|
|
172
173
|
end
|
|
174
|
+
|
|
175
|
+
context 'with wrong klass type' do
|
|
176
|
+
should 'create item' do
|
|
177
|
+
assert_difference('Node.count', 0) do
|
|
178
|
+
post @create_bad
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
173
182
|
|
|
174
183
|
should 'not create item out of acl scope' do
|
|
175
184
|
assert_difference('Node.count', 0) do
|
|
@@ -177,6 +186,30 @@ class AclIntegrationTest < Zena::Integration::TestCase
|
|
|
177
186
|
end
|
|
178
187
|
assert_response :missing
|
|
179
188
|
end
|
|
189
|
+
|
|
190
|
+
context 'with read access' do
|
|
191
|
+
setup do
|
|
192
|
+
# We must grant read access on visitor node to avoid errors in page rendering
|
|
193
|
+
Zena::Db.execute "UPDATE nodes SET rgroup_id = #{groups_id(:site)} WHERE id IN (#{nodes_id(:queen)},#{nodes_id(:demeter)})"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
should 'read without acl' do
|
|
197
|
+
get "http://erebus.host/oo/project#{nodes_zip(:queen)}.html"
|
|
198
|
+
assert_response :success
|
|
199
|
+
assert_nil visitor.exec_acl
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
should 'load acl' do
|
|
203
|
+
assert_difference('Node.count', 1) do
|
|
204
|
+
post @create_url
|
|
205
|
+
end
|
|
206
|
+
node = assigns(:node)
|
|
207
|
+
assert visitor.exec_acl
|
|
208
|
+
assert_equal visitor.id, node.user_id
|
|
209
|
+
assert_equal nodes_id(:queen), node.parent_id
|
|
210
|
+
assert_equal 'foobar', node.title
|
|
211
|
+
end
|
|
212
|
+
end
|
|
180
213
|
|
|
181
214
|
context 'without use acl' do
|
|
182
215
|
setup do
|
|
@@ -223,6 +256,25 @@ class AclIntegrationTest < Zena::Integration::TestCase
|
|
|
223
256
|
put "http://erebus.host/nodes/#{nodes_zip(:queen)}?node[title]=foobar"
|
|
224
257
|
assert_response :missing
|
|
225
258
|
end
|
|
259
|
+
|
|
260
|
+
context 'with read access' do
|
|
261
|
+
setup do
|
|
262
|
+
# We must grant read access on visitor node to avoid errors in page rendering
|
|
263
|
+
Zena::Db.execute "UPDATE nodes SET rgroup_id = #{groups_id(:site)} WHERE id IN (#{nodes_id(:persephone)},#{nodes_id(:demeter)})"
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
should 'read without acl' do
|
|
267
|
+
get "http://erebus.host/oo/contact#{nodes_zip(:persephone)}.html"
|
|
268
|
+
assert_response :success
|
|
269
|
+
assert_nil visitor.exec_acl
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
should 'load acl' do
|
|
273
|
+
put @update_url
|
|
274
|
+
assert_equal 'foobar', nodes(:persephone).title
|
|
275
|
+
assert visitor.exec_acl
|
|
276
|
+
end
|
|
277
|
+
end
|
|
226
278
|
|
|
227
279
|
context 'without use acl' do
|
|
228
280
|
setup do
|
|
@@ -17,6 +17,27 @@ rap:
|
|
|
17
17
|
# allow any format
|
|
18
18
|
format: '*'
|
|
19
19
|
|
|
20
|
+
# Create Posts in assigned projects
|
|
21
|
+
create_rap:
|
|
22
|
+
name: create posts in assigned projects
|
|
23
|
+
# Anyone in the 'sky' group
|
|
24
|
+
group: sky
|
|
25
|
+
# can create
|
|
26
|
+
action: create
|
|
27
|
+
# in 'assigned_projects'
|
|
28
|
+
query: "%q{assigned_projects}"
|
|
29
|
+
# objects with kpath
|
|
30
|
+
create_kpath: NRC
|
|
31
|
+
# by receiving the 'erebus' access group
|
|
32
|
+
exec_group: erebus
|
|
33
|
+
# and viewing it through the 'sky' Skin.
|
|
34
|
+
exec_skin: sky
|
|
35
|
+
priority: 10
|
|
36
|
+
# allow any mode
|
|
37
|
+
mode: '*'
|
|
38
|
+
# allow any format
|
|
39
|
+
format: '*'
|
|
40
|
+
|
|
20
41
|
# Read self (this never matches)
|
|
21
42
|
self:
|
|
22
43
|
name: read assigned projects
|