drg_cms 0.6.0.6 → 0.6.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -10
  3. data/app/assets/javascripts/drg_cms/drg_cms.js +281 -106
  4. data/app/assets/stylesheets/drg_cms/drg_cms.css +417 -152
  5. data/app/assets/stylesheets/drg_cms/select-multiple.css +9 -12
  6. data/app/assets/stylesheets/drg_cms_cms.css +1 -1
  7. data/app/controllers/cmsedit_controller.rb +247 -175
  8. data/app/controllers/dc_application_controller.rb +251 -173
  9. data/app/controllers/dc_common_controller.rb +81 -48
  10. data/app/controls/dc_help_control.rb +126 -0
  11. data/app/controls/dc_report.rb +223 -0
  12. data/app/forms/all_options.yml +38 -10
  13. data/app/forms/cms_menu.yml +7 -1
  14. data/app/forms/dc_big_table.yml +1 -0
  15. data/app/forms/dc_big_table_value.yml +1 -0
  16. data/app/forms/dc_category.yml +2 -1
  17. data/app/forms/dc_design.yml +1 -0
  18. data/app/forms/dc_help_1.yml +109 -0
  19. data/app/forms/dc_journal.yml +3 -1
  20. data/app/forms/dc_link.yml +1 -1
  21. data/app/forms/dc_menu.yml +2 -0
  22. data/app/forms/dc_menu_item.yml +1 -0
  23. data/app/forms/dc_page.yml +6 -0
  24. data/app/forms/dc_part.yml +1 -0
  25. data/app/forms/dc_piece.yml +1 -0
  26. data/app/forms/dc_poll.yml +15 -5
  27. data/app/forms/dc_poll_item.yml +2 -1
  28. data/app/forms/dc_poll_result.yml +9 -0
  29. data/app/forms/dc_simple_menu.yml +2 -0
  30. data/app/forms/dc_site.yml +4 -12
  31. data/app/forms/dc_user.yml +27 -11
  32. data/app/forms/dc_user_role.yml +3 -0
  33. data/app/helpers/cms_common_helper.rb +375 -0
  34. data/app/helpers/{cmsedit_edit_helper.rb → cms_edit_helper.rb} +109 -65
  35. data/app/helpers/{cmsedit_helper.rb → cms_helper.rb} +93 -48
  36. data/app/helpers/{cmsedit_index_helper.rb → cms_index_helper.rb} +240 -206
  37. data/app/helpers/dc_application_helper.rb +108 -327
  38. data/app/models/concerns/dc_page_concern.rb +14 -4
  39. data/app/models/concerns/dc_piece_concern.rb +1 -1
  40. data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
  41. data/app/models/concerns/dc_site_concern.rb +67 -44
  42. data/app/models/concerns/dc_user_concern.rb +58 -19
  43. data/app/models/dc_design.rb +29 -19
  44. data/app/models/dc_filter.rb +26 -18
  45. data/app/models/dc_key_value_store.rb +1 -0
  46. data/app/models/dc_permission.rb +49 -9
  47. data/app/models/dc_policy.rb +25 -14
  48. data/app/models/dc_policy_role.rb +22 -11
  49. data/app/models/dc_poll.rb +1 -0
  50. data/app/models/dc_poll_result.rb +4 -2
  51. data/app/models/dc_temp.rb +6 -3
  52. data/app/models/dc_user_role.rb +2 -2
  53. data/app/models/drgcms_form_fields/date_picker.rb +6 -3
  54. data/app/models/drgcms_form_fields/datetime_picker.rb +4 -3
  55. data/app/models/drgcms_form_fields/drgcms_field.rb +20 -5
  56. data/app/models/drgcms_form_fields/embedded.rb +23 -16
  57. data/app/models/drgcms_form_fields/file_field.rb +2 -2
  58. data/app/models/drgcms_form_fields/file_select.rb +2 -2
  59. data/app/models/drgcms_form_fields/hash_field.rb +11 -7
  60. data/app/models/drgcms_form_fields/hidden_field.rb +1 -1
  61. data/app/models/drgcms_form_fields/link_to.rb +2 -2
  62. data/app/models/drgcms_form_fields/method.rb +66 -0
  63. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +18 -12
  64. data/app/models/drgcms_form_fields/number_field.rb +4 -3
  65. data/app/models/drgcms_form_fields/radio.rb +10 -5
  66. data/app/models/drgcms_form_fields/readonly.rb +13 -17
  67. data/app/models/drgcms_form_fields/select.rb +58 -41
  68. data/app/models/drgcms_form_fields/text_autocomplete.rb +41 -33
  69. data/app/models/drgcms_form_fields.rb +12 -1
  70. data/app/renderers/dc_big_menu_renderer.rb +1 -0
  71. data/app/renderers/dc_gallery_renderer.rb +1 -0
  72. data/app/renderers/dc_menu_renderer.rb +1 -0
  73. data/app/renderers/dc_page_renderer.rb +8 -6
  74. data/app/renderers/dc_part_renderer.rb +1 -0
  75. data/app/renderers/dc_piece_renderer.rb +1 -1
  76. data/app/renderers/dc_poll_renderer.rb +56 -55
  77. data/app/renderers/dc_renderer.rb +1 -0
  78. data/app/renderers/dc_simple_menu_renderer.rb +1 -0
  79. data/app/views/cmsedit/_edit_stuff.html.erb +5 -2
  80. data/app/views/cmsedit/edit.html.erb +4 -1
  81. data/app/views/cmsedit/index.html.erb +3 -2
  82. data/app/views/cmsedit/new.html.erb +5 -2
  83. data/app/views/dc_common/_help.html.erb +17 -0
  84. data/app/views/layouts/models.html.erb +2 -1
  85. data/config/locales/drgcms_en.yml +17 -2
  86. data/config/locales/drgcms_sl.yml +22 -4
  87. data/config/locales/models_en.yml +16 -7
  88. data/config/locales/models_sl.yml +21 -12
  89. data/drg_cms.gemspec +16 -16
  90. data/lib/drg_cms/version.rb +1 -1
  91. data/lib/drg_cms.rb +98 -0
  92. data/lib/generators/new_drg_form/new_drg_form_generator.rb +5 -3
  93. data/lib/tasks/database.rake +6 -56
  94. metadata +39 -35
  95. data/app/helpers/application_helper.rb +0 -2
  96. data/app/models/__dc_dummy.rb +0 -102
@@ -1,4 +1,3 @@
1
- #coding: utf-8
2
1
  #--
3
2
  # Copyright (c) 2012+ Damjan Rems
4
3
  #
@@ -27,9 +26,8 @@
27
26
  # application controllers.
28
27
  ##########################################################################
29
28
  class DcApplicationController < ActionController::Base
30
- protect_from_forgery
31
-
32
- before_action :dc_reload_patches if Rails.env.development?
29
+ protect_from_forgery with: :null_session, only: Proc.new { |c| c.request.format.json? }
30
+ before_action :dc_reload_patches if Rails.env.development?
33
31
 
34
32
  ########################################################################
35
33
  # Writes anything passed as parameter to logger file.
@@ -55,9 +53,9 @@ end
55
53
  ####################################################################
56
54
  # Checks if user has required role.
57
55
  #
58
- # @param [DcPolicyRole] role can be passed as DcPolicyRole object or
59
- # @param [String] role as role name. If passed as name, dc_policy_roles is searched for appropriate role.
60
- #
56
+ # @param [DcPolicyRole or String] role can be passed as DcPolicyRole object or
57
+ # as role name. If passed as name, dc_policy_roles is searched for appropriate role.
58
+ #
61
59
  # @return [Boolean] True if user has required role added to his profile.
62
60
  #
63
61
  # @example If user has required role
@@ -66,8 +64,8 @@ end
66
64
  ####################################################################
67
65
  def dc_user_has_role(role)
68
66
  role = DcPolicyRole.get_role(role)
69
- return false if role.nil? or session[:user_roles].nil?
70
- # role is found in user_roles
67
+ return false if role.nil? || session[:user_roles].nil?
68
+ # role exists in user_roles
71
69
  session[:user_roles].include?(role._id)
72
70
  end
73
71
 
@@ -81,22 +79,28 @@ end
81
79
  # @example Returns Google analytics code from site settings
82
80
  # settings = dc_get_site.params['ga_acc']
83
81
  ####################################################################
84
- def dc_get_site()
85
- return @site if @site
82
+ def dc_get_site
83
+ return @site if @site
84
+
86
85
  uri = URI.parse(request.url)
86
+ cache_key = ['dc_site', uri.host]
87
+
88
+ @site = dc_cache_read(cache_key)
89
+ return @site if @site
90
+
87
91
  @site = DcSite.find_by(name: uri.host)
88
- # Site can be aliased
89
- if @site and !@site.alias_for.blank?
92
+ # Site can be aliased
93
+ if @site && !@site.alias_for.blank?
90
94
  @site = DcSite.find_by(name: @site.alias_for)
91
95
  end
92
- # Development environment. Check if site with name test exists and use
93
- # alias_for as pointer to real site.
94
- if @site.nil? and ENV["RAILS_ENV"] != 'production'
96
+ # Development environment. Check if site with name test exists and use
97
+ # alias_for as pointer to real site.
98
+ if @site.nil? && ENV["RAILS_ENV"] != 'production'
95
99
  @site = DcSite.find_by(name: 'test')
96
100
  @site = DcSite.find_by(name: @site.alias_for) if @site
97
- end
98
- @site = nil if @site and !@site.active # site is disabled
99
- @site
101
+ end
102
+ @site = nil if @site && !@site.active # site is disabled
103
+ dc_cache_write(cache_key, @site)
100
104
  end
101
105
 
102
106
  ##########################################################################
@@ -104,7 +108,7 @@ end
104
108
  #
105
109
  # Sets internal @page_title variable.
106
110
  ##########################################################################
107
- def set_page_title()
111
+ def set_page_title
108
112
  @page_title = @page.title.blank? ? @page.subject : @page.title
109
113
  dc_add_meta_tag(:name, 'description', @page.meta_description)
110
114
  end
@@ -115,18 +119,17 @@ end
115
119
  # @param [String] Form file name. File name can be passed as gem_name.filename. This can
116
120
  # be useful when you are extending form but want to retain same name as original form
117
121
  # For example. You are extending dc_user form from drg_cms gem and want to
118
- # retain same dc_user name. This can be done by setting drg_cms.dc_user to extend option.
122
+ # retain same dc_user name. This can be done by setting drg_cms.dc_user as extend option.
119
123
  #
120
124
  # @return [String] Form file name including path or nil if not found.
121
125
  ########################################################################
122
126
  def dc_find_form_file(form_file)
123
- form_path=nil
124
- if form_file.match(/\.|\//)
125
- form_path,form_file=form_file.split(/\.|\//)
126
- end
127
+ form_path = nil
128
+ form_path, form_file = form_file.split(/\.|\//) if form_file.match(/\.|\//)
129
+
127
130
  DrgCms.paths(:forms).reverse.each do |path|
128
131
  f = "#{path}/#{form_file}.yml"
129
- return f if File.exist?(f) and (form_path.nil? or path.to_s.match(/\/#{form_path}\//i))
132
+ return f if File.exist?(f) && (form_path.nil? || path.to_s.match(/\/#{form_path}(-|\/)/i))
130
133
  end
131
134
  raise "Exception: Form file '#{form_file}' not found!"
132
135
  end
@@ -149,7 +152,7 @@ end
149
152
  # Will write document to dc_visits collection unless visit comes from robot.
150
153
  # It also sets session[is_robot] variable to true if robot.
151
154
  ########################################################################
152
- def dc_log_visit()
155
+ def dc_log_visit
153
156
  if request.env["HTTP_USER_AGENT"] and request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
154
157
  logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
155
158
  session[:is_robot] = true
@@ -165,80 +168,94 @@ end
165
168
 
166
169
  protected
167
170
 
168
- #############################################################################
169
- # Add permissions. Subroutine of dc_user_can
170
- ############################################################################
171
- def add_permissions_for(table_name=nil) # :nodoc:
172
- perm = table_name.nil? ? DcPermission.find_by(is_default: true) : DcPermission.find_by(table_name: table_name, active: true)
173
- (perm.dc_policy_rules.each {|p1| @permissions[p1.dc_policy_role_id] = p1.permission }) if perm
174
- end
175
-
176
- ############################################################################
171
+ ###########################################################################
177
172
  # Checks if user can perform (read, create, edit, delete) document in specified
178
173
  # table (collection).
179
174
  #
180
- # @param [Integer] Required permission level
181
- # @param [String] Collection (table) name for which permission is queried. Defaults to params[table].
175
+ # @param [Integer] permission: Required permission level
176
+ # @param [String] table: Collection (table) name for which permission is queried. Defaults to params[table].
182
177
  #
183
178
  # @return [Boolean] true if user's role permits (is higher or equal then required) operation on a table (collection).
184
179
  #
185
180
  # @Example True when user has view permission on the table
186
181
  # if dc_user_can(DcPermission::CAN_VIEW, params[:table]) then ...
187
182
  ############################################################################
188
- def dc_user_can(permission, table=params[:table])
189
- if @permissions.nil?
190
- @permissions = {}
191
- add_permissions_for # default permission
192
- table_name = ''
193
- # permission can be set for table or object embedded in table. Read all possible values
194
- table.strip.downcase.split(';').each do |t|
195
- table_name << (table_name.size > 0 ? ';' : '') + t # table;embedded;another;...
196
- add_permissions_for table_name
197
- end
183
+ def dc_user_can(permission, table = params[:table])
184
+ table = table.underscore
185
+ cache_key = ['dc_permission', table, session[:user_id], dc_get_site.id]
186
+ permissions = dc_cache_read(cache_key)
187
+ if permissions.nil?
188
+ permissions = DcPermission.permissions_for_table(table)
189
+ dc_cache_write(cache_key, permissions)
198
190
  end
199
- # Return true if any of the permissions user has is higher or equal to requested permission
200
- session[:user_roles].each {|r| return true if @permissions[r] and @permissions[r] >= permission }
191
+ session[:user_roles].each { |r| return true if permissions[r] && permissions[r] >= permission }
201
192
  false
202
- end
193
+ end
194
+
195
+ ####################################################################
196
+ # Read from cache
197
+ #
198
+ # @keys [Array] Array of keys
199
+ #
200
+ # @return [Object] Data returned from cache
201
+ ####################################################################
202
+ def dc_cache_read(keys)
203
+ if redis_cache_store?
204
+ keys = keys.dup
205
+ first = keys.shift
206
+ data = redis.hget(first, keys.join(''))
207
+ data ? Marshal.load(data) : nil
208
+ else
209
+ Rails.cache.read(keys.join(''))
210
+ end
211
+ end
212
+
213
+ ####################################################################
214
+ # Write data to cache
215
+ #
216
+ # @param [Array] keys: Array of keys
217
+ # @param [Object] data: Data written to cache
218
+ #
219
+ # @return [Object] data so dc_cache_write can be used as last statement in method.
220
+ ####################################################################
221
+ def dc_cache_write(keys, data)
222
+ if redis_cache_store?
223
+ keys = keys.dup
224
+ first = keys.shift
225
+ redis.hset(first, keys.join(''), Marshal.dump(data))
226
+ else
227
+ Rails.cache.write(keys.join(''), data)
228
+ end
229
+ data
230
+ end
203
231
 
204
232
  ####################################################################
205
- # Detects if called from mobile agent according to http://detectmobilebrowsers.com/
233
+ # Detects if called from mobile agent according to http://detectmobilebrowsers.com/
206
234
  # and set session[:is_mobile]
207
- #
235
+ #
208
236
  # Detect also if caller is a robot and set session[:is_robot]
209
237
  ####################################################################
210
238
  def dc_set_is_mobile
211
239
  is_mobile = request.user_agent ? /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.match(request.user_agent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.match(request.user_agent[0..3])
212
240
  : false
213
241
  session[:is_mobile] = is_mobile ? 1 : 0
214
- #
215
- if request.env["HTTP_USER_AGENT"] and request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
242
+
243
+ if request.env["HTTP_USER_AGENT "] && request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
216
244
  logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
217
245
  session[:is_robot] = true
218
246
  end
219
247
  end
220
248
 
221
-
222
249
  ##########################################################################
223
250
  # Merge values from parameters fields (from site, page ...) into internal @options hash.
224
251
  #
225
- # @param [String] YAML string.
252
+ # @param [String] parameters: passed as YAML string.
226
253
  ##########################################################################
227
254
  def dc_set_options(parameters)
228
255
  @options ||= {}
229
256
  return if parameters.to_s.size < 3
230
- # parameters are set az YAML. This should be default in future.
231
- parms = YAML.load(parameters) rescue nil
232
- if parms.nil? # error when loadnig yaml, try the old way parsing manually
233
- parms = {}
234
- parameters.split("\n").each do |line|
235
- line.chomp.split(',').each do |parm|
236
- key, value = parm.split(':')
237
- value = value.to_s.strip.gsub(/\'|\"/,'')
238
- parms[key.strip] = (value == '/' ? nil : value)
239
- end
240
- end
241
- end
257
+ # parameters are set as YAML. This should be default in future.
258
+ parms = YAML.load(parameters) rescue {}
242
259
  @options.merge!(parms)
243
260
  end
244
261
 
@@ -252,7 +269,6 @@ end
252
269
  # @return [Boolean] true when none of documents is changed.
253
270
  ##########################################################################
254
271
  def dc_not_modified?(*documents)
255
- # request.env.each {|k,v| p k,'*',v}
256
272
  return false unless request.env.include? 'HTTP_IF_MODIFIED_SINCE'
257
273
 
258
274
  since_date = Time.parse request.env['HTTP_IF_MODIFIED_SINCE']
@@ -261,7 +277,7 @@ def dc_not_modified?(*documents)
261
277
  next unless doc.respond_to?(:updated_at)
262
278
  last_modified = doc.updated_at if doc.updated_at > last_modified
263
279
  end
264
- # p last_modified, since_date
280
+
265
281
  if last_modified >= since_date then
266
282
  render :nothing => true, :status => 304
267
283
  return true
@@ -280,16 +296,16 @@ def get_design_and_render(design_doc)
280
296
  layout = @site.site_layout.blank? ? 'content' : @site.site_layout
281
297
  site_top = '<%= dc_page_top %>'
282
298
  site_bottom = '<%= dc_page_bottom %>'
283
- # lets try the rails way
284
- if @options[:control] and @options[:action]
299
+ # lets try the rails way
300
+ if @options[:control] && @options[:action]
285
301
  controller = "#{@options[:control]}_control".classify.constantize rescue nil
286
302
  extend controller if controller
287
303
  return send @options[:action] if respond_to?(@options[:action])
288
304
  end
289
- # design doc present
305
+ # design doc present
290
306
  if design_doc
291
307
  # defined as rails view
292
- design = if design_doc.rails_view.blank? or design_doc.rails_view == 'site'
308
+ design = if design_doc.rails_view.blank? || design_doc.rails_view == 'site'
293
309
  @site.rails_view
294
310
  else
295
311
  design_doc.rails_view
@@ -300,8 +316,8 @@ def get_design_and_render(design_doc)
300
316
  design = site_top + design + site_bottom
301
317
  return render(inline: design, layout: layout) unless design.blank?
302
318
  end
303
- # Design doc not defined
304
- if @site.rails_view.blank?
319
+ # Design doc not defined
320
+ if @site.rails_view.blank?
305
321
  design = site_top + @site.design + site_bottom
306
322
  render(inline: design, layout: layout)
307
323
  else
@@ -323,34 +339,35 @@ end
323
339
  # dc_process_default_request
324
340
  # end
325
341
  ##########################################################################
326
- def dc_process_default_request()
342
+ def dc_process_default_request
327
343
  session[:edit_mode] ||= 0
328
- # Initialize parts
344
+ # Initialize parts
329
345
  @parts = nil
330
346
  @js, @css = '', ''
331
- # find domain name in sites
347
+ # find domain name in sites
332
348
  @site = dc_get_site
333
- # site not defined. render 404 error
349
+ # site not defined. render 404 error
334
350
  return dc_render_404('Site!') if @site.nil?
351
+
335
352
  dc_set_options(@site.settings)
336
- # HOMEPAGE. When no parameters is set
353
+ # HOMEPAGE. When no parameters is set
337
354
  params[:path] = @site.homepage_link if params[:id].nil? and params[:path].nil?
338
355
  @options[:path] = params[:path].to_s.downcase.split('/')
339
356
  params[:path] = @options[:path].first if @options[:path].size > 1
340
- # some other process request. It should fail if not defined
357
+ # some other process request. It should fail if not defined
341
358
  return send(@site.request_processor) unless @site.request_processor.blank?
342
359
 
343
- # Search for page
360
+ # Search for page
344
361
  pageclass = @site.page_klass
345
362
  if params[:id]
346
363
  #Page.where(id: params[:id]).or(subject_link: params[:id]).first
347
364
  @page = pageclass.find_by(:dc_site_id.in => [@site._id, nil], subject_link: params[:id], active: true)
348
365
  @page = pageclass.find(params[:id]) if @page.nil? # I think that there will be more subject_link searchers than id
349
366
  elsif params[:path]
350
- # path may point direct to page's subject_link
367
+ # path may point direct to page's subject_link
351
368
  @page = pageclass.find_by(:dc_site_id.in => [@site._id, nil], subject_link: params[:path], active: true)
352
369
  if @page.nil?
353
- # no. Find if defined in links
370
+ # no. Find if defined in links
354
371
  link = DcLink.find_by(:dc_site_id.in => [@site._id, nil], name: params[:path])
355
372
  if link
356
373
  #pageclass.find_by(alt_link: params[:path])
@@ -359,10 +376,11 @@ def dc_process_default_request()
359
376
  end
360
377
  end
361
378
  end
362
- # if @page is not found render 404 error
379
+ # if @page is not found render 404 error
363
380
  return dc_render_404('Page!') unless @page
381
+
364
382
  dc_set_is_mobile unless session[:is_mobile] # do it only once per session
365
- # find design if defined. Otherwise design MUST be declared in site
383
+ # find design if defined. Otherwise design MUST be declared in site
366
384
  if @page.dc_design_id
367
385
  @design = DcDesign.find(@page.dc_design_id)
368
386
  return dc_render_404('Design!') unless @design
@@ -370,20 +388,20 @@ def dc_process_default_request()
370
388
  dc_set_options @design.params if @design
371
389
  dc_set_options @page.params
372
390
  dc_add_json_ld(@page.get_json_ld)
373
- # Add edit menu
391
+ # Add edit menu
374
392
  if session[:edit_mode] > 0
375
393
  session[:site_id] = @site.id
376
394
  session[:site_page_class] = @site.page_class
377
395
  session[:page_id] = @page.id
378
- else
379
- # Log only visits from non-editors
396
+ else
397
+ # Log only visits from non-editors
380
398
  dc_log_visit()
381
399
  end
382
400
  set_page_title()
383
401
  get_design_and_render @design
384
402
  end
385
403
 
386
- ##########################################################################
404
+ ###########################################################################
387
405
  # Single site document kind of request handler.
388
406
  #
389
407
  # This request handler assumes that all data for the site is saved in the site document.
@@ -399,18 +417,17 @@ def dc_single_sitedoc_request
399
417
  if @site.nil?
400
418
  session[:edit_mode] ||= 0
401
419
  @site = dc_get_site
402
- # @site is not defined. render 404 error
420
+ # @site is not defined. render 404 error
403
421
  return dc_render_404('Site!') unless @site
422
+
404
423
  dc_set_options(@site.settings)
405
424
  end
406
- # HOMEPAGE. When no parameters is set
425
+ # HOMEPAGE. When no parameters is set
407
426
  params[:path] = @site.homepage_link if params[:path].nil?
408
427
  @parts = @site.dc_parts
409
428
  @part = @parts.find_by(link: params[:path])
410
429
  return dc_render_404('Part!') unless @part
411
- # Document was not modified since last visit
412
- # return if dc_not_modified?(@site, @part)
413
- #
430
+
414
431
  @page_title = "#{@site.page_title} #{@part.name}"
415
432
  @js, @css = '', ''
416
433
  get_design_and_render nil
@@ -421,56 +438,46 @@ end
421
438
  # very good with non ascii chars. Since this method is used for converting from model
422
439
  # to collection names it is very unwise to use non ascii chars for table (collection) names.
423
440
  #
424
- # @param [String] String to be converted
425
- #
441
+ # @param [Object] model_string to be converted
442
+ #
426
443
  # @example
427
444
  # decamelize_type(ModelName) # 'ModelName' => 'model_name'
428
445
  ########################################################################
429
- def decamelize_type(string)
430
- return nil unless string
431
- r = ''
432
- string.to_s.each_char do |c|
433
- r << case
434
- when r.size == 0 then c.downcase
435
- when c.downcase != c then '_' + c.downcase
436
- else c
437
- end
438
- end
439
- r
446
+ def decamelize_type(model_string)
447
+ model_string ? model_string.underscore : nil
440
448
  end
441
449
 
442
450
  ####################################################################
443
451
  # Return's error messages for the document formated for display on edit form.
444
452
  #
445
- # @param [Document] Document object which will be examined for errors.
446
- #
453
+ # @param [Document] document object which will be examined for errors.
454
+ #
447
455
  # @return [String] HTML code for displaying error on edit form.
448
456
  ####################################################################
449
457
  def dc_error_messages_for(document)
450
458
  return '' unless document.errors.any?
459
+
451
460
  msg = ''
452
- document.errors.each do |attribute, errors_array|
453
- label = t("helpers.label.#{decamelize_type(document.class)}.#{attribute}")
454
- msg << "<li>#{label} : #{errors_array}</li>"
461
+ document.errors.each do |error|
462
+ label = t("helpers.label.#{decamelize_type(document.class)}.#{error.attribute}", error.attribute)
463
+ msg << "<li>#{label} : #{error.message}</li>"
455
464
  end
456
465
 
457
- html = <<eot
466
+ %(
458
467
  <div class="dc-form-error">
459
468
  <h2>#{t('drgcms.errors_no')} #{document.errors.size}</h2>
460
469
  <ul>#{msg}</ul>
461
- </div>
462
- eot
463
- html.html_safe
470
+ </div>).html_safe
464
471
  end
465
472
 
466
473
  ####################################################################
467
- # Checks if any errors exist on document and writes debug log. It can also
474
+ # Checks if any errors exist on document and writes error log. It can also
468
475
  # crash if requested. This is mostly usefull in development for debuging
469
476
  # model errors or when saving to multiple collections and where each save must be
470
477
  # checked if succesfull.
471
478
  #
472
- # @param [Document] Document object which will be checked
473
- # @param [Boolean] If true method should end in runtime error. Default = false.
479
+ # @param [Document] document: Document object to be checked
480
+ # @param [Boolean] crash: If true method should end in runtime error. Default = false.
474
481
  #
475
482
  # @return [String] Error messages or empty string if everything is OK.
476
483
  #
@@ -482,23 +489,16 @@ end
482
489
  # end
483
490
  #
484
491
  ####################################################################
485
- def dc_check_model(document, crash=false)
486
- return nil unless document.errors.any?
487
- msg = ''
488
- document.errors.each do |attribute, errors_array|
489
- msg << "#{attribute}: #{errors_array}\n"
490
- end
491
- logger.debug(msg) if msg.size > 0
492
- crash_it if crash
493
- msg
492
+ def dc_check_model(document, crash = false)
493
+ DrgCms.model_check(document, crash)
494
494
  end
495
495
 
496
496
  ######################################################################
497
497
  # Call rake task from controller.
498
498
  #
499
- # @param [String] Rake task name
500
- # @param [Hash] Options that will be send to task as environment variables
501
- #
499
+ # @param [String] task: Rake task name
500
+ # @param [Hash] options: Options that will be send to task as environment variables
501
+ #
502
502
  # @example Call rake task from application
503
503
  # dc_call_rake('clear:all', some_parm: some_id)
504
504
  ######################################################################
@@ -513,8 +513,8 @@ end
513
513
  # made from DRG CMS form return may be quite complicated. All ajax return combinations
514
514
  # can be found in drg_cms.js file.
515
515
  #
516
- # @param [Hash] Options
517
- #
516
+ # @param [Hash] opts: Options
517
+ #
518
518
  # @return [JSON Response] Formatted to be used for ajax return.
519
519
  #
520
520
  # @example
@@ -526,7 +526,7 @@ end
526
526
  ######################################################################
527
527
  def dc_render_ajax(opts)
528
528
  result = {}
529
- if opts[:div] or opts[:class]
529
+ if opts[:div] || opts[:class]
530
530
  selector = opts[:div] ? '#' : '.' # for div . for class
531
531
  key = case
532
532
  when opts[:prepend] then "#{selector}+div"
@@ -548,7 +548,7 @@ end
548
548
  # @param [String] Table (collection) name. Could be dc_page;dc_part;... when searching for embedded document.
549
549
  # @param [String] Id of the document
550
550
  # @param [String] Ids of parent documents when document is embedded. Ids are separated by ; char.
551
- #
551
+ #
552
552
  # @return [document]. Required document or nil if not found.
553
553
  #
554
554
  # @example As used in Cmsedit_controller
@@ -593,7 +593,7 @@ def clear_login_data
593
593
  session[:edit_mode] = 0
594
594
  session[:user_id] = nil
595
595
  session[:user_name] = nil
596
- session[:user_roles] = nil
596
+ set_default_guest_user_role
597
597
  cookies.delete :remember_me
598
598
  end
599
599
 
@@ -611,32 +611,48 @@ end
611
611
  # @param [DcUser] user : User's document
612
612
  # @param [Boolean] remember_me : false by default
613
613
  ####################################################################
614
- def fill_login_data(user, remember_me=false)
615
- session[:user_id] = user.id if user
616
- session[:user_name] = user.name if user
617
- session[:edit_mode] = 0
618
- session[:user_roles] = []
619
- # Every user has guest role
620
- # guest = DcPolicyRole.find_by(system_name: 'guest')
621
- # session[:user_roles] << guest.id if guest
614
+ def fill_login_data(user, remember_me = false)
615
+ session[:user_id] = user.id if user
616
+ session[:user_name] = user.name.squish if user
617
+ session[:edit_mode] = 0
622
618
  set_default_guest_user_role
623
- return unless user and user.active
619
+ return unless user&.active
620
+
624
621
  # special for SUPERADMIN
625
622
  sa = DcPolicyRole.find_by(system_name: 'superadmin')
626
- if sa and (role = user.dc_user_roles.find_by(dc_policy_role_id: sa.id))
623
+ if sa && (role = user.dc_user_roles.find_by(dc_policy_role_id: sa.id))
627
624
  session[:user_roles] << role.dc_policy_role_id
628
- session[:edit_mode] = 2
625
+ session[:edit_mode] = 2
629
626
  return
630
627
  end
631
- # read default policy from site. Policy might be inherited
628
+ # read default policy from site. Policy might be inherited from other site
632
629
  policy_site = dc_get_site()
633
630
  policy_site = DcSite.find(policy_site.inherit_policy) if policy_site.inherit_policy
634
631
  default_policy = policy_site.dc_policies.find_by(is_default: true)
635
- # load user roles
632
+
633
+ # load user roles from groups
634
+ roles = {}
635
+ user.member.each do |group_id|
636
+ group = DcUser.find(group_id)
637
+ next unless group.active
638
+
639
+ group.dc_user_roles.each do |role|
640
+ next unless role.active?
641
+ roles[role.dc_policy_role_id] = role
642
+ end
643
+ end unless user.member.blank?
644
+
645
+ # load user roles from user
636
646
  user.dc_user_roles.each do |role|
637
- next unless role.active
638
- next if role.valid_from and role.valid_from > Time.now.end_of_day.to_date
639
- next if role.valid_to and role.valid_to < Time.now.to_date
647
+ # not active in user roles will remove role defined in groups
648
+ unless role.active?
649
+ roles.delete(role.dc_policy_role_id) if roles[role.dc_policy_role_id]
650
+ next
651
+ end
652
+ roles[role.dc_policy_role_id] = role
653
+ end
654
+ # select only roles defined in default site policy and set edit_mode
655
+ roles.each do |key, role|
640
656
  # check if role is active in this site
641
657
  policy_role = default_policy.dc_policy_rules.find_by(dc_policy_role_id: role.dc_policy_role_id)
642
658
  next unless policy_role
@@ -645,20 +661,19 @@ def fill_login_data(user, remember_me=false)
645
661
  session[:user_roles] << role.dc_policy_role_id
646
662
  end
647
663
  # Save remember me cookie if not CMS user and remember me is selected
648
- if session[:edit_mode] == 0 and remember_me
649
- cookies.signed[:remember_me] = { :value => user.id, :expires => 180.days.from_now}
664
+ if session[:edit_mode] == 0 && remember_me
665
+ cookies.signed[:remember_me] = { value: user.id, expires: 180.days.from_now }
650
666
  end
651
667
  end
652
668
 
653
669
  ##########################################################################
654
- # Will check if user's login data is stil valid and reload user roles.
670
+ # Will check if user's login data is still valid and reload user roles.
655
671
  #
656
672
  # @param [Time] repeat_after : Check is repeated after time. This is by default performed every 24 hours.
657
673
  ##########################################################################
658
- def dc_check_user_still_valid(repeat_after=1.day)
659
- # not needed
660
- return if session[:user_id].nil?
661
- # last check more than a day ago
674
+ def dc_check_user_still_valid(repeat_after = 1.day)
675
+ return if session[:user_id].nil?
676
+ # last check more than repeat_after ago
662
677
  if (session[:user_chk] ||= Time.now) < repeat_after.ago
663
678
  user_id = session[:user_id]
664
679
  clear_login_data
@@ -673,9 +688,9 @@ end
673
688
  # Evaluates Class.method in more predictable context then just calling eval
674
689
  #
675
690
  # @param [String] class_method defined as MyClass.method_name
676
- # @param [Object] optional parameters send to class_method
691
+ # @param [Object] params: optional parameters send to class_method
677
692
  ##########################################################################
678
- def dc_eval_class_method(class_method, params=nil)
693
+ def dc_eval_class_method(class_method, params = nil)
679
694
  klass, method = class_method.split('.')
680
695
  # check if class exists
681
696
  klass = klass.classify.constantize rescue nil
@@ -718,26 +733,89 @@ end
718
733
  ########################################################################
719
734
  def dc_add_meta_tag(type, name, content)
720
735
  return if content.blank?
736
+
721
737
  @meta_tags ||= {}
722
738
  key = "#{type}=\"#{name}\""
723
739
  @meta_tags[key] = content
724
740
  end
725
741
 
726
742
  ########################################################################
727
- # Will prepare flash[:update] data, which will be used for updating fields
728
- # on forms parent form fields.
729
- #
730
- # Parameters:
731
- # [field_name] String: Field name
743
+ # Will prepare flash[:update] data, which is used for updating elements
744
+ # on parent form.
745
+ #
746
+ # Parameters passed as hash:
747
+ # [field] String: Field name
748
+ # [head] String: Filed name in head of form
732
749
  # [value] String: New value
733
750
  # [readonly] Boolean: Field is readonly
734
- #
751
+ #
735
752
  ########################################################################
736
- def dc_update_form_field(field_name, value, readonly=false)
737
- key_name = (readonly ? 'td_' : '') + "record_#{field_name}"
753
+ def dc_update_form_element(field: nil, head: nil, value:, readonly: true)
754
+ key = if field
755
+ (readonly ? 'td_' : '') + "record_#{field}"
756
+ elsif head
757
+ "head-#{head}"
758
+ end
759
+ return if key.nil?
760
+
738
761
  flash[:update] ||= {}
739
- flash[:update][key_name] = value
762
+ flash[:update][key] = value
740
763
  end
741
764
 
765
+ ####################################################################
766
+ # Checks if any errors exist on document and writes error log. It can also
767
+ # crash if requested. This is mostly usefull in development for debuging
768
+ # model errors or when updating multiple collections and each save must be
769
+ # checked if succesfull.
770
+ #
771
+ # @param [Document] Document object which will be checked
772
+ # @param [Boolean] If true method should end in runtime error. Default = false.
773
+ #
774
+ # @return [String] Error messages or empty string if everything is OK.
775
+ #
776
+ # @Example Check for error when data is saved.
777
+ # model.save
778
+ # if (msg = DcApplicationController.dc_check_model(model) ).size > 0
779
+ # p msg
780
+ # error process ......
781
+ # end
782
+ #
783
+ ####################################################################
784
+ def self.dc_check_model(document, crash = false)
785
+ DrgCms.model_check(document, crash)
786
+ end
787
+
788
+ ########################################################################
789
+ # Will dump exception to rails log and console.
790
+ #
791
+ # Parameters:
792
+ # [exception] Object: Exception caught
793
+ #
794
+ ########################################################################
795
+ def dc_dump_exception(exception)
796
+ msg = [exception.message, *exception.backtrace].join($/)
797
+ pp msg
798
+ Rails.logger.error msg
799
+ end
800
+
801
+ private
802
+
803
+ ########################################################################
804
+ # Determines if redis cache store is active
805
+ #
806
+ # @return [Boolean] : True if redis cache store is active
807
+ ########################################################################
808
+ def redis_cache_store?
809
+ (Rails.application.config.cache_store.first == :redis_cache_store) rescue false
810
+ end
811
+
812
+ ########################################################################
813
+ # Returns redis object
814
+ #
815
+ # @return [Object] : Redis object
816
+ ########################################################################
817
+ def redis
818
+ Rails.cache.redis
819
+ end
742
820
 
743
821
  end