zen 0.2.4.1 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. data/MANIFEST +42 -33
  2. data/README.md +14 -27
  3. data/ROADMAP.md +20 -2
  4. data/{Thorfile → Rakefile} +2 -3
  5. data/bin/zen +27 -5
  6. data/lib/zen.rb +70 -52
  7. data/lib/zen/asset.rb +258 -0
  8. data/lib/zen/bin/app.rb +42 -0
  9. data/lib/zen/controller/admin_controller.rb +53 -36
  10. data/lib/zen/controller/base_controller.rb +13 -8
  11. data/lib/zen/controller/frontend_controller.rb +4 -3
  12. data/lib/zen/controller/main_controller.rb +17 -33
  13. data/lib/zen/error/validation_error.rb +10 -0
  14. data/lib/zen/ext/string.rb +185 -0
  15. data/lib/zen/helper/acl.rb +120 -92
  16. data/lib/zen/helper/common.rb +1 -3
  17. data/lib/zen/helper/theme.rb +73 -0
  18. data/lib/zen/language.rb +66 -57
  19. data/lib/zen/layout/admin.xhtml +5 -48
  20. data/lib/zen/layout/login.xhtml +4 -44
  21. data/lib/zen/model/methods.rb +1 -1
  22. data/lib/zen/model/settings.rb +0 -3
  23. data/lib/zen/package.rb +101 -83
  24. data/lib/zen/package/base.rb +62 -0
  25. data/lib/zen/package/categories/lib/categories.rb +29 -10
  26. data/lib/zen/package/categories/lib/categories/controller/categories.rb +4 -5
  27. data/lib/zen/package/categories/lib/categories/controller/category_groups.rb +4 -5
  28. data/lib/zen/package/categories/lib/categories/language/en/category_groups.yml +4 -3
  29. data/lib/zen/package/categories/lib/categories/model/category.rb +2 -2
  30. data/lib/zen/package/categories/lib/categories/model/category_group.rb +3 -3
  31. data/lib/zen/package/categories/lib/categories/plugin/categories.rb +130 -0
  32. data/lib/zen/package/categories/lib/categories/view/admin/categories/form.xhtml +1 -1
  33. data/lib/zen/package/categories/lib/categories/view/admin/categories/index.xhtml +2 -2
  34. data/lib/zen/package/categories/lib/categories/view/admin/category-groups/index.xhtml +11 -6
  35. data/lib/zen/package/comments/lib/comments.rb +23 -13
  36. data/lib/zen/package/comments/lib/comments/controller/comments.rb +4 -5
  37. data/lib/zen/package/comments/lib/comments/controller/comments_form.rb +7 -8
  38. data/lib/zen/package/comments/lib/comments/model/comment.rb +4 -4
  39. data/lib/zen/package/comments/lib/comments/plugin/comments.rb +111 -0
  40. data/lib/zen/package/comments/lib/comments/view/admin/comments/form.xhtml +2 -2
  41. data/lib/zen/package/comments/lib/comments/view/admin/comments/index.xhtml +3 -3
  42. data/lib/zen/package/custom_fields/lib/custom_fields.rb +18 -11
  43. data/lib/zen/package/custom_fields/lib/custom_fields/controller/custom_field_groups.rb +4 -5
  44. data/lib/zen/package/custom_fields/lib/custom_fields/controller/custom_fields.rb +4 -5
  45. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field.rb +2 -2
  46. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field_group.rb +3 -3
  47. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field_value.rb +3 -3
  48. data/lib/zen/package/custom_fields/lib/custom_fields/view/admin/custom-field-groups/index.xhtml +9 -5
  49. data/lib/zen/package/custom_fields/lib/custom_fields/view/admin/custom-fields/form.xhtml +1 -1
  50. data/lib/zen/package/custom_fields/lib/custom_fields/view/admin/custom-fields/index.xhtml +3 -3
  51. data/lib/zen/package/menus/lib/menus.rb +25 -43
  52. data/lib/zen/package/menus/lib/menus/controller/menu_items.rb +5 -6
  53. data/lib/zen/package/menus/lib/menus/controller/menus.rb +9 -5
  54. data/lib/zen/package/menus/lib/menus/helper/menu_item.rb +4 -4
  55. data/lib/zen/package/menus/lib/menus/model/menu.rb +2 -2
  56. data/lib/zen/package/menus/lib/menus/model/menu_item.rb +4 -1
  57. data/lib/zen/package/menus/lib/menus/plugin/menus.rb +152 -0
  58. data/lib/zen/package/menus/lib/menus/view/admin/menu-items/form.xhtml +1 -1
  59. data/lib/zen/package/menus/lib/menus/view/admin/menu-items/index.xhtml +3 -3
  60. data/lib/zen/package/menus/lib/menus/view/admin/menus/index.xhtml +7 -7
  61. data/lib/zen/package/sections/lib/sections.rb +32 -16
  62. data/lib/zen/package/sections/lib/sections/controller/section_entries.rb +9 -18
  63. data/lib/zen/package/sections/lib/sections/controller/sections.rb +8 -9
  64. data/lib/zen/package/sections/lib/sections/language/en/section_entries.yml +1 -1
  65. data/lib/zen/package/sections/lib/sections/model/section.rb +4 -4
  66. data/lib/zen/package/sections/lib/sections/model/section_entry.rb +9 -10
  67. data/lib/zen/package/sections/lib/sections/plugin/section_entries.rb +224 -0
  68. data/lib/zen/package/sections/lib/sections/plugin/sections.rb +85 -0
  69. data/lib/zen/package/sections/lib/sections/view/admin/form.xhtml +1 -1
  70. data/lib/zen/package/sections/lib/sections/view/admin/index.xhtml +9 -5
  71. data/lib/zen/package/sections/lib/sections/view/admin/section-entries/index.xhtml +2 -2
  72. data/lib/zen/package/settings/lib/settings.rb +145 -10
  73. data/lib/zen/package/settings/lib/settings/controller/settings.rb +28 -24
  74. data/lib/zen/package/settings/lib/settings/language/en/settings.yml +10 -0
  75. data/lib/zen/package/settings/lib/settings/model/setting.rb +3 -64
  76. data/lib/zen/package/settings/lib/settings/plugin/group_base.rb +40 -0
  77. data/lib/zen/package/settings/lib/settings/plugin/setting_base.rb +76 -0
  78. data/lib/zen/package/settings/lib/settings/plugin/settings.rb +236 -0
  79. data/lib/zen/package/settings/lib/settings/view/admin/settings/index.xhtml +20 -49
  80. data/lib/zen/package/settings/migrations/1295597111_create_schema.rb +0 -12
  81. data/lib/zen/package/settings/migrations/1303196915_settings_plugin.rb +31 -0
  82. data/lib/zen/package/users/lib/users.rb +18 -15
  83. data/lib/zen/package/users/lib/users/controller/access_rules.rb +44 -8
  84. data/lib/zen/package/users/lib/users/controller/user_groups.rb +4 -5
  85. data/lib/zen/package/users/lib/users/controller/users.rb +5 -6
  86. data/lib/zen/package/users/lib/users/language/en/access_rules.yml +11 -9
  87. data/lib/zen/package/users/lib/users/model/access_rule.rb +7 -6
  88. data/lib/zen/package/users/lib/users/model/user.rb +4 -4
  89. data/lib/zen/package/users/lib/users/model/user_group.rb +3 -3
  90. data/lib/zen/package/users/lib/users/public/admin/js/users/access_rules.js +50 -0
  91. data/lib/zen/package/users/lib/users/view/admin/access-rules/form.xhtml +32 -29
  92. data/lib/zen/package/users/lib/users/view/admin/access-rules/index.xhtml +8 -6
  93. data/lib/zen/package/users/lib/users/view/admin/user-groups/index.xhtml +3 -3
  94. data/lib/zen/package/users/lib/users/view/admin/users/index.xhtml +2 -2
  95. data/lib/zen/package/users/migrations/1303510943_class_rules.rb +13 -0
  96. data/lib/zen/plugin.rb +110 -104
  97. data/lib/zen/plugin/base.rb +46 -0
  98. data/lib/zen/{liquid/controller_behavior.rb → plugin/controller.rb} +9 -7
  99. data/lib/zen/plugin/helper.rb +47 -0
  100. data/lib/zen/plugin/markup/lib/markup.rb +14 -0
  101. data/lib/zen/plugin/markup/lib/markup/language/en/markup.yml +6 -0
  102. data/lib/zen/plugin/markup/lib/markup/markup.rb +154 -0
  103. data/lib/zen/public/admin/css/forms.css +4 -0
  104. data/lib/zen/public/admin/css/general.css +15 -15
  105. data/lib/zen/public/admin/css/layout.css +10 -10
  106. data/lib/zen/public/admin/css/reset.css +123 -0
  107. data/lib/zen/public/admin/images/icons/accept.png +0 -0
  108. data/lib/zen/public/admin/images/icons/add.png +0 -0
  109. data/lib/zen/public/admin/images/icons/back.png +0 -0
  110. data/lib/zen/public/admin/images/icons/bold.png +0 -0
  111. data/lib/zen/public/admin/images/icons/close.png +0 -0
  112. data/lib/zen/public/admin/images/icons/delete.png +0 -0
  113. data/lib/zen/public/admin/images/icons/edit.png +0 -0
  114. data/lib/zen/public/admin/images/icons/error.png +0 -0
  115. data/lib/zen/public/admin/images/icons/help.png +0 -0
  116. data/lib/zen/public/admin/images/icons/info.png +0 -0
  117. data/lib/zen/public/admin/images/icons/italic.png +0 -0
  118. data/lib/zen/public/admin/images/icons/large/error.png +0 -0
  119. data/lib/zen/public/admin/images/icons/large/notice.png +0 -0
  120. data/lib/zen/public/admin/images/icons/large/success.png +0 -0
  121. data/lib/zen/public/admin/images/icons/link.png +0 -0
  122. data/lib/zen/public/admin/images/icons/logout.png +0 -0
  123. data/lib/zen/public/admin/images/icons/ol.png +0 -0
  124. data/lib/zen/public/admin/images/icons/pdf.png +0 -0
  125. data/lib/zen/public/admin/images/icons/ul.png +0 -0
  126. data/lib/zen/public/admin/images/icons/user.png +0 -0
  127. data/lib/zen/public/admin/images/icons/view.png +0 -0
  128. data/lib/zen/public/admin/js/mootools/core.js +384 -333
  129. data/lib/zen/public/admin/js/mootools/more.js +256 -231
  130. data/lib/zen/public/admin/js/vendor/{datepicker/Picker.Date.js → datepicker.js} +447 -0
  131. data/lib/zen/public/admin/js/vendor/yepnope.js +1 -0
  132. data/lib/zen/public/admin/js/zen/editor/base.js +8 -1
  133. data/lib/zen/public/admin/js/zen/init.js +89 -26
  134. data/lib/zen/public/favicon.ico +0 -0
  135. data/lib/zen/task.rb +7 -0
  136. data/lib/zen/task/build.rake +60 -0
  137. data/lib/zen/task/clean.rake +27 -0
  138. data/lib/zen/task/db.rake +111 -0
  139. data/lib/zen/task/package.rake +67 -0
  140. data/lib/zen/task/plugin.rake +24 -0
  141. data/lib/zen/task/proto.rake +95 -0
  142. data/lib/zen/task/theme.rake +68 -0
  143. data/lib/zen/theme.rb +28 -55
  144. data/lib/zen/theme/base.rb +64 -0
  145. data/lib/zen/validation.rb +149 -0
  146. data/lib/zen/version.rb +1 -1
  147. data/lib/zen/view/bottom.xhtml +6 -0
  148. data/lib/zen/view/main.xhtml +32 -0
  149. data/proto/app/Rakefile +12 -0
  150. data/proto/app/app.rb +6 -6
  151. data/proto/app/config/config.rb +7 -14
  152. data/proto/app/config/database.rb +0 -20
  153. data/proto/app/start.rb +0 -1
  154. data/proto/app/{vendor/themes → task}/.gitkeep +0 -0
  155. data/proto/app/vendor/theme/.gitkeep +0 -0
  156. data/proto/package/lib/package.rb +8 -17
  157. data/proto/package/lib/package/controller/controllers.rb +4 -4
  158. data/proto/package/lib/package/language/en/languages.yml +3 -3
  159. data/proto/package/lib/package/model/model.rb +1 -1
  160. metadata +73 -73
  161. data/lib/zen/bin/base.rb +0 -109
  162. data/lib/zen/helper/asset.rb +0 -106
  163. data/lib/zen/liquid/general.rb +0 -94
  164. data/lib/zen/liquid/redirect.rb +0 -70
  165. data/lib/zen/liquid/strip.rb +0 -60
  166. data/lib/zen/package/categories/lib/categories/liquid/categories.rb +0 -16
  167. data/lib/zen/package/comments/lib/comments/liquid/comment_form.rb +0 -127
  168. data/lib/zen/package/comments/lib/comments/liquid/comments.rb +0 -115
  169. data/lib/zen/package/menus/lib/menus/liquid/menus.rb +0 -152
  170. data/lib/zen/package/sections/lib/sections/liquid/section_entries.rb +0 -228
  171. data/lib/zen/package/sections/lib/sections/liquid/sections.rb +0 -77
  172. data/lib/zen/package/settings/lib/settings/liquid/setting.rb +0 -58
  173. data/lib/zen/package/users/lib/users/liquid/user.rb +0 -77
  174. data/lib/zen/package/users/lib/users/liquid/users.rb +0 -82
  175. data/lib/zen/plugin/markup.rb +0 -30
  176. data/lib/zen/public/admin/css/boilerplate.css +0 -176
  177. data/lib/zen/public/admin/images/general/noise.jpg +0 -0
  178. data/lib/zen/public/admin/js/vendor/datepicker/Picker.Attach.js +0 -137
  179. data/lib/zen/public/admin/js/vendor/datepicker/Picker.js +0 -291
  180. data/lib/zen/public/admin/js/vendor/datepicker/README.md +0 -325
  181. data/lib/zen/public/admin/js/vendor/datepicker/locale.js +0 -16
  182. data/lib/zen/strict_struct.rb +0 -36
  183. data/lib/zen/task/build.rb +0 -123
  184. data/lib/zen/task/clean.rb +0 -46
  185. data/lib/zen/task/db.rb +0 -130
  186. data/lib/zen/task/package.rb +0 -87
  187. data/lib/zen/task/proto.rb +0 -116
  188. data/lib/zen/task/theme.rb +0 -88
  189. data/proto/app/Thorfile +0 -4
@@ -1,7 +1,7 @@
1
1
  #:nodoc:
2
2
  module Zen
3
3
  #:nodoc:
4
- module Controllers
4
+ module Controller
5
5
  ##
6
6
  # Controller that should be extended by other controllers that can be accessed from
7
7
  # the web without having to log in. Frontend controllers don't have a layout and
@@ -10,9 +10,10 @@ module Zen
10
10
  # @author Yorick Peterse
11
11
  # @since 0.1
12
12
  #
13
- class FrontendController < Zen::Controllers::BaseController
14
- engine :liquid
13
+ class FrontendController < Zen::Controller::BaseController
14
+ engine :etanni
15
15
  layout :none
16
+ helper :theme, :common
16
17
  end
17
18
  end
18
19
  end
@@ -1,7 +1,7 @@
1
1
  #:nodoc:
2
2
  module Zen
3
3
  #:nodoc:
4
- module Controllers
4
+ module Controller
5
5
  ##
6
6
  # The MainController controller is used to load the correct template files based
7
7
  # on the current URI. If no section is specified the default section will be retrieved
@@ -10,7 +10,7 @@ module Zen
10
10
  # @author Yorick Peterse
11
11
  # @since 0.1
12
12
  #
13
- class MainController < Zen::Controllers::FrontendController
13
+ class MainController < Zen::Controller::FrontendController
14
14
  map '/'
15
15
 
16
16
  ##
@@ -25,52 +25,36 @@ module Zen
25
25
  # @param [Array] uri Array containing all arguments (thus the URI).
26
26
  #
27
27
  def index(*uri)
28
- @uri = []
28
+ @request_uri = []
29
29
 
30
30
  # Clean the URI of nasty input
31
- uri.each { |v| @uri.push(h(v)) }
31
+ uri.each { |v| @request_uri.push(h(v)) }
32
32
 
33
- if !@uri[0] or @uri[0].empty?
34
- @uri[0] = settings[:default_section]
33
+ if !@request_uri[0] or @request_uri[0].empty?
34
+ @request_uri[0] = ::Zen::Settings[:default_section]
35
35
  end
36
36
 
37
- if !@uri[1] or @uri[1].empty?
38
- @uri[1] = 'index'
37
+ if !@request_uri[1] or @request_uri[1].empty?
38
+ @request_uri[1] = 'index'
39
39
  end
40
40
 
41
41
  # A theme is always required
42
- if @settings[:theme].nil? or @settings[:theme].empty?
42
+ if ::Zen::Settings[:theme].nil? or ::Zen::Settings[:theme].empty?
43
43
  respond(lang('zen_general.errors.no_theme'))
44
44
  end
45
45
 
46
- theme = ::Zen::Theme[@settings[:theme]]
47
- group = @uri[0]
48
- template = @uri[1]
49
-
50
- # Pre-create a few Liquid variables
51
- @flash = {}
52
- @current_user = {}
53
- flash.each { |k, v| @flash[k.to_s] = v }
54
-
55
- if !session[:user].nil?
56
- session[:user].values.each { |k, v| @current_user[k.to_s] = v }
57
- end
46
+ theme = ::Zen::Theme[::Zen::Settings[:theme]]
47
+ group = @request_uri[0]
48
+ template = @request_uri[1]
58
49
 
59
50
  # Create the group, template and partial paths
60
51
  theme_path = theme.template_dir
61
- group_path = theme_path + "/#{group}"
62
- template_path = theme_path + "/#{group}/#{template}.liquid"
63
-
64
- # Register our partial path
65
- if theme.respond_to?(:partial_dir) and !theme.partial_dir.nil?
66
- ::Liquid::Template.file_system = ::Liquid::LocalFileSystem.new(
67
- theme.partial_dir
68
- )
69
- end
52
+ group_path = File.join(theme_path, group)
53
+ template_path = File.join(theme_path, group, "#{template}.xhtml")
70
54
 
71
55
  # Is the website down?
72
- if @settings[:website_enabled] == '0'
73
- offline_path = theme_path + "/offline.liquid"
56
+ if ::Zen::Settings[:website_enabled] == '0'
57
+ offline_path = File.join(theme_path, 'offline.xhtml')
74
58
 
75
59
  if File.exist?(offline_path)
76
60
  render_file(offline_path)
@@ -82,7 +66,7 @@ module Zen
82
66
  if File.directory?(group_path) and File.exists?(template_path)
83
67
  render_file(template_path)
84
68
  else
85
- not_found = theme_path + "/404.liquid"
69
+ not_found = File.join(theme_path, '404.xhtml')
86
70
 
87
71
  if File.exist?(not_found)
88
72
  render_file(not_found)
@@ -0,0 +1,10 @@
1
+ #:nodoc:
2
+ module Zen
3
+ ##
4
+ # Error class used by Zen::Validation.
5
+ #
6
+ # @author Yorick Peterse
7
+ # @since 0.2.5
8
+ #
9
+ class ValidationError < StandardError; end
10
+ end
@@ -0,0 +1,185 @@
1
+ ##
2
+ # Extension to the string class provided by Ruby that provides the following 2 methods:
3
+ #
4
+ # * String.pluralize
5
+ # * String.singularize
6
+ #
7
+ # Note that these methods only work for English words, other languages such as Japanese
8
+ # or French aren't supported at this time (January, 2011). This snippet also doesn't cover
9
+ # every single english word, patches are welcome!
10
+ #
11
+ # @author Yorick Peterse, Michael Fellinger
12
+ # @since 1.0
13
+ #
14
+ class String
15
+ ##
16
+ # Constant containing all regular expressions for singular strings (that will be pluralized)
17
+ # and their replacements.
18
+ #
19
+ # @since 1.0
20
+ #
21
+ SingularToPlural = {
22
+ /ss$/ => 'sses',
23
+ /se$/ => 'ses',
24
+ /sh$/ => 'shes',
25
+ /ge$/ => 'ges',
26
+ /ch$/ => 'ches',
27
+ /ge$/ => 'ges',
28
+ /g$/ => 'gs',
29
+
30
+ # When the singular form ends in a voiceless consonant (other than a sibilant).
31
+ #
32
+ # lap => laps
33
+ # cat => cats
34
+ # clock => clocks
35
+ # cuff => cuffs
36
+ # death => deaths
37
+ /ap$/ => 'aps',
38
+ /at$/ => 'ats',
39
+ /ck$/ => 'cks',
40
+ /ff$/ => 'ffs',
41
+ /th$/ => 'ths',
42
+
43
+ # Most nouns ending in o preceded by a consonant also form their plurals by adding -es
44
+ #
45
+ # hero => heroes
46
+ # potato => potatoes
47
+ # volcano => volcanoes or volcanos
48
+ /o$/ => 'oes',
49
+
50
+ # nouns ending in a y preceded by a consonant usually drop the y and add -ies
51
+ #
52
+ # cherry => cherries
53
+ # lady => ladies
54
+ # ywzxvtsrqpnmlkjhgfdcb
55
+ #
56
+ /([bcdfghjklmnpqrstvxzwy]+)y$/ => "\\1ies",
57
+
58
+ # For all other words (i.e. words ending in vowels or voiced non-sibilants).
59
+ #
60
+ # boy => boys
61
+ # girl => girls
62
+ # chair => chairs
63
+ # quiz => quizes
64
+ /z$/ => 'zes',
65
+ /y$/ => 'ys',
66
+ /l$/ => 'ls',
67
+ /r$/ => 'rs'
68
+ }
69
+
70
+ ##
71
+ # Constant containing all regular expressions used to convert plural words to
72
+ # singular words.
73
+ #
74
+ # @since 1.0
75
+ #
76
+ PluralToSingular = {
77
+ /sses$/ => 'ss',
78
+ /ses$/ => 'se',
79
+ /shes$/ => 'sh',
80
+ /ges$/ => 'ges',
81
+ /ches$/ => 'ches',
82
+ /ges$/ => 'ges',
83
+ /aps$/ => 'ap',
84
+ /ats$/ => 'at',
85
+ /cks$/ => 'ck',
86
+ /ffs$/ => 'ff',
87
+ /ths$/ => 'th',
88
+ /oes$/ => 'o',
89
+ /ies$/ => 'y',
90
+ /zes$/ => 'z',
91
+ /ys$/ => 'y',
92
+ /l$/ => 'ls',
93
+ /r$/ => 'rs',
94
+ /s$/ => ''
95
+ }
96
+
97
+ ##
98
+ # Tries to convert a string to it's pluralized version. For example, "user" would
99
+ # result in "users" and "quiz" will result in "quizes". This method will return
100
+ # the pluralized string, use pluralize! to overwrite the current (singular) version
101
+ # of the string with the pluralized one.
102
+ #
103
+ # @example
104
+ #
105
+ # "user".pluralize # => users
106
+ # "baby".pluralize # => babies
107
+ #
108
+ # @author Yorick Peterse, Michael Fellinger
109
+ # @return [String] The pluralized version of the string.
110
+ # @since 1.0
111
+ #
112
+ def pluralize
113
+ string = self.dup
114
+
115
+ SingularToPlural.each do |regex, replace|
116
+ new_string = string.gsub(regex, replace)
117
+
118
+ if new_string != string
119
+ return new_string
120
+ end
121
+ end
122
+
123
+ return string
124
+ end
125
+
126
+ ##
127
+ # Converts the current string into a pluralized form and
128
+ # overwrites the old value rather than returning it.
129
+ #
130
+ # @example
131
+ #
132
+ # word = "user"
133
+ # word.pluralize! # => nil
134
+ #
135
+ # puts word # => users
136
+ #
137
+ # @since 1.0
138
+ #
139
+ def pluralize!
140
+ self.replace(self.pluralize)
141
+ end
142
+
143
+ ##
144
+ # Tries to convert the current string into a singular version.
145
+ #
146
+ # @example
147
+ #
148
+ # "users".singularize # => user
149
+ # "babies".singularize # => baby
150
+ #
151
+ # @author Yorick Peterse
152
+ # @return [String] a singular form of the string
153
+ # @since 1.0
154
+ #
155
+ def singularize
156
+ string = self.dup
157
+
158
+ PluralToSingular.each do |regex, replace|
159
+ new_string = string.gsub(regex, replace)
160
+
161
+ if new_string != string
162
+ return new_string
163
+ end
164
+ end
165
+
166
+ return string
167
+ end
168
+
169
+ ##
170
+ # Converts a plural string to it's singular form and replaces
171
+ # the current value of the string with this singular version.
172
+ #
173
+ # @example
174
+ #
175
+ # word = "users"
176
+ # word.singularize! # => nil
177
+ #
178
+ # puts word # => user
179
+ #
180
+ # @since 1.0
181
+ #
182
+ def singularize!
183
+ self.replace(self.singularize)
184
+ end
185
+ end
@@ -3,132 +3,160 @@ module Ramaze
3
3
  #:nodoc:
4
4
  module Helper
5
5
  ##
6
- # This helper provides an easy way of working with the ACL system that
7
- # ships with Zen. Using this helper you can restrict access to methods,
8
- # view elements and pretty much everything else based on the user's
9
- # permissions.
6
+ # This helper provides an easy way of working with the ACL system that ships with Zen.
7
+ # Using this helper you can restrict access to methods, view elements and pretty much
8
+ # everything else based on the user's permissions.
10
9
  #
11
- # In order to use the ACL helper you'll need to define a trait named
12
- # "extension_identifier" in your classes. Once this trait have been set you
13
- # can use the "user_authorized?" method to verify the permissions of the current user.
14
- # The first parameter is an array of required permissions,
15
- # the second a boolean that indicates if either all or just a single permission must
16
- # be set.
10
+ # In order to restrict certain actions to only those with the correct permissions you
11
+ # can use the method "user_authorized?". This method takes a list of required
12
+ # permissions and when the user has the correct permissions it will return true:
17
13
  #
18
- # For more information about the ACL system you should read the documentation
19
- # in the ACL controller, Users::Controllers::AccessRules().
14
+ # user_authorized?([:read]) # => true
15
+ #
16
+ # The method has 3 parameters: a list of permissions, a boolean that indicates whether
17
+ # all of them or just a single one is required and a third argument that can be used
18
+ # to manually specify the controller to validate against rather than the current node.
19
+ #
20
+ # user_authorized?([:read], true 'FoobarController')
20
21
  #
21
22
  # @author Yorick Peterse
22
23
  # @since 0.1
23
- # @see Users::Controllers::AccessRules()
24
+ # @see Users::Controller::AccessRules()
24
25
  #
25
26
  module ACL
27
+
26
28
  ##
27
- # Retrieves all permissions for the current user
28
- # along with the permissions set for all groups the user
29
- # belongs to. Rather than loading a new instance of the User model
30
- # we'll retrieve the model from the session variable set by the
31
- # User helper provided by Ramaze. Doing this saves us a few queries.
29
+ # Builds a hash containing the permissions for all controllers. First all group
30
+ # based rules will be retrieved. If the user is in a super group he'll gain full
31
+ # access. However, if there's a user specific rule it will overwrite the rules set
32
+ # for the group. This means that if a group allows something but a user rule doesn't
33
+ # the user won't be able to gain access to the resource.
32
34
  #
33
35
  # @author Yorick Peterse
34
36
  # @since 0.1
35
- # @return [Mixed] returns a hash containing all rules per identifier along
36
- # with a boolean that indicates if the user is in a super group.
37
+ # @return [Hash]
37
38
  #
38
39
  def extension_permissions
39
- m = session[:user]
40
- user_groups = m.user_groups
41
- super_group = false
42
- rules = []
43
- ordered_rules = {}
44
-
45
- user_groups.each do |group|
46
- rules += group.access_rules
47
-
48
- if group.super_group == true
49
- super_group = true
50
- end
51
- end
52
-
53
- m.access_rules.each do |rule|
54
- rules.push(rule)
40
+ if session[:access_rules]
41
+ return session[:access_rules]
55
42
  end
56
-
57
- rules.each do |rule|
58
- if !ordered_rules.key?(rule.extension)
59
- ordered_rules[rule.extension] = []
60
- end
61
-
62
- [:create_access, :read_access, :update_access, :delete_access].each do |perm|
63
- if rule.send(perm) === true or super_group == true
64
- perm = perm.to_s.gsub!('_access', '').to_sym
65
-
66
- if !ordered_rules[rule.extension].include?(perm)
67
- ordered_rules[rule.extension].push(perm)
68
- end
43
+
44
+ user = session[:user]
45
+ user_groups = user.user_groups
46
+ @used_rules = {}
47
+ available_rules = [:create_access, :read_access, :update_access, :delete_access]
48
+
49
+ # First all group rules should be built
50
+ user_groups.each do |group|
51
+ # If it's a super group we'll add all rules
52
+ if group.super_group === true
53
+ ::Zen::Package::Controllers.each do |controller|
54
+ @used_rules[controller.to_s] = [:create, :read, :update, :delete]
69
55
  end
70
56
  end
57
+
58
+ group.access_rules.each do |rule|
59
+ process_permissions(rule, available_rules)
60
+ end
61
+ end
62
+
63
+ # Process all user specific rules
64
+ user.access_rules.each do |rule|
65
+ process_permissions(rule, available_rules)
71
66
  end
72
-
73
- return ordered_rules, super_group
67
+
68
+ # Store the rules in the user's session so that they don't have to be re-processed
69
+ # every time this method is called.
70
+ session[:access_rules] = @used_rules
71
+
72
+ return @used_rules
74
73
  end
75
74
 
76
75
  ##
77
- # Checks if the user has the specified permissions for the current
78
- # extension that was called. Returns true if this is the case and false
79
- # otherwise.
76
+ # Checks if the user has the specified permissions for the current extension that
77
+ # was called. Returns true if this is the case and false otherwise.
80
78
  #
81
79
  # @author Yorick Peterse
82
- # @param [Array] reqs Array of permissions that are required.
83
- # @param [Boolean] require_all Boolean that specifies that the user
84
- # should have ALL specified permissios. Setting this to false causes
85
- # this method to return true if any of the permissions are set for the
86
- # current user.
87
- # @param [String] identifier A custom identifier to use for validating the user's
88
- # permissions instead of using a class trait.
89
- # @return [Boolean]
80
+ # @param [Array] required Array of permissions that are required.
81
+ # @param [Boolean] require_all Boolean that specifies that the user should have
82
+ # ALL specified permissios. Setting this to false causes this method to return true
83
+ # if any of the permissions are set for the current user.
84
+ # @param [String] controller When set this will overwrite the controller name of
85
+ # action.node. This is useful when you want to check the permissions of a different
86
+ # controller than the current one.
87
+ # @return [TrueClass]
90
88
  #
91
- def user_authorized?(reqs, require_all = true, identifier = nil)
92
- # Retrieve the identifier from the class trait if we didn't already have one
93
- if identifier.nil?
94
- identifier = ancestral_trait.values_at(:extension_identifier)
95
- identifier = identifier[0]
96
- end
97
-
98
- # Still don't have an identifier?
99
- if identifier.nil?
100
- raise "You need to specify an extension identifier"
101
- end
102
-
89
+ def user_authorized?(required, require_all = true, controller = nil)
103
90
  # Get the ACL list
104
- rules = self.extension_permissions
105
- super_group = rules[1]
106
- rules = rules[0]
107
-
108
- # Super groups have full access
109
- if super_group == true
110
- return true
91
+ rules = extension_permissions
92
+
93
+ if !controller
94
+ controller = action.node.to_s
111
95
  end
112
-
113
- # Deny access if the identifier is not found
114
- if !rules.key?(identifier)
96
+
97
+ if !rules.key?(controller)
115
98
  return false
116
99
  end
117
-
118
- # Verify the permissions
119
- perms = rules[identifier]
120
-
121
- reqs.each do |req|
122
- if require_all == false and perms.include?(req)
100
+
101
+ required.each do |req|
102
+ if require_all === false and rules[controller].include?(req)
123
103
  return true
124
- elsif !perms.include?(req)
104
+ elsif !rules[controller].include?(req)
125
105
  return false
126
106
  end
127
107
  end
128
-
108
+
129
109
  return true
130
110
  end
131
111
 
112
+ private
113
+
114
+ ##
115
+ # Extracts and stores all the permissions from a given rule.
116
+ #
117
+ # @author Yorick Peterse
118
+ # @since 0.2.5
119
+ # @param [Users::Model::AccessRule] rule Database record containing the details of
120
+ # a single rule.
121
+ # @param [Array] available_rules All the available rules that can be used.
122
+ #
123
+ def process_permissions(rule, available_rules)
124
+ available_rules.each do |available_rule|
125
+ # Add the rule to the list
126
+ if rule.send(available_rule) === true
127
+ method = :push
128
+ # Remove the rule
129
+ else
130
+ method = :delete
131
+ end
132
+
133
+ available_rule = available_rule.to_s.gsub('_access', '').to_sym
134
+ controllers = []
135
+
136
+ # Process all controllers
137
+ if rule.controller === '*'
138
+ ::Zen::Package[rule.package].controllers.each do |name, controller|
139
+ controllers.push(controller.to_s)
140
+ end
141
+ # Process a single controller
142
+ else
143
+ controllers.push(rule.controller)
144
+ end
145
+
146
+ # Add the rules for all the controllers
147
+ controllers.each do |c|
148
+ @used_rules[c] ||= []
149
+
150
+ if method === :push and @used_rules[c].include?(available_rule)
151
+ next
152
+ end
153
+
154
+ # Add or remove the permission
155
+ @used_rules[c].send(method, available_rule)
156
+ end
157
+ end
158
+ end
159
+
132
160
  end
133
161
  end
134
162
  end