zen 0.2.4.1 → 0.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.
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