incline 0.1.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 (303) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +186 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +208 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/incline/.keep +0 -0
  9. data/app/assets/images/incline/.keep +0 -0
  10. data/app/assets/images/incline/barcode-B.svg +181 -0
  11. data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
  12. data/app/assets/javascripts/incline/application.js +30 -0
  13. data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
  14. data/app/assets/javascripts/incline/datatables.js +22193 -0
  15. data/app/assets/javascripts/incline/escapeHtml.js +10 -0
  16. data/app/assets/javascripts/incline/inline_actions.js +479 -0
  17. data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
  18. data/app/assets/javascripts/incline/jquery.number.js +764 -0
  19. data/app/assets/javascripts/incline/regexMask.js +27 -0
  20. data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
  21. data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
  22. data/app/assets/stylesheets/incline/application.css +18 -0
  23. data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
  24. data/app/assets/stylesheets/incline/custom.scss +279 -0
  25. data/app/assets/stylesheets/incline/datatables.css +494 -0
  26. data/app/assets/stylesheets/incline/datepicker3.css +790 -0
  27. data/app/assets/stylesheets/incline/select2.css +484 -0
  28. data/app/controllers/incline/access_groups_controller.rb +127 -0
  29. data/app/controllers/incline/access_test_controller.rb +30 -0
  30. data/app/controllers/incline/account_activations_controller.rb +28 -0
  31. data/app/controllers/incline/application_controller.rb +11 -0
  32. data/app/controllers/incline/contact_controller.rb +34 -0
  33. data/app/controllers/incline/password_resets_controller.rb +113 -0
  34. data/app/controllers/incline/security_controller.rb +100 -0
  35. data/app/controllers/incline/sessions_controller.rb +50 -0
  36. data/app/controllers/incline/users_controller.rb +304 -0
  37. data/app/controllers/incline/welcome_controller.rb +19 -0
  38. data/app/helpers/incline/.keep +0 -0
  39. data/app/mailers/incline/application_mailer_base.rb +11 -0
  40. data/app/mailers/incline/contact_form.rb +19 -0
  41. data/app/mailers/incline/user_mailer.rb +45 -0
  42. data/app/models/incline/access_group.rb +121 -0
  43. data/app/models/incline/access_group_group_member.rb +12 -0
  44. data/app/models/incline/access_group_user_member.rb +10 -0
  45. data/app/models/incline/action_group.rb +12 -0
  46. data/app/models/incline/action_security.rb +222 -0
  47. data/app/models/incline/contact_message.rb +37 -0
  48. data/app/models/incline/disable_info.rb +20 -0
  49. data/app/models/incline/password_reset.rb +14 -0
  50. data/app/models/incline/password_reset_request.rb +14 -0
  51. data/app/models/incline/user.rb +437 -0
  52. data/app/models/incline/user_login_history.rb +30 -0
  53. data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
  54. data/app/views/incline/access_groups/_form.html.erb +19 -0
  55. data/app/views/incline/access_groups/_list.html.erb +60 -0
  56. data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
  57. data/app/views/incline/access_groups/edit.html.erb +2 -0
  58. data/app/views/incline/access_groups/index.html.erb +6 -0
  59. data/app/views/incline/access_groups/index.json.jbuilder +16 -0
  60. data/app/views/incline/access_groups/new.html.erb +2 -0
  61. data/app/views/incline/access_groups/show.html.erb +9 -0
  62. data/app/views/incline/access_groups/show.json.jbuilder +11 -0
  63. data/app/views/incline/contact/new.html.erb +22 -0
  64. data/app/views/incline/contact_form/contact.html.erb +16 -0
  65. data/app/views/incline/contact_form/contact.text.erb +13 -0
  66. data/app/views/incline/password_resets/edit.html.erb +16 -0
  67. data/app/views/incline/password_resets/new.html.erb +12 -0
  68. data/app/views/incline/security/_details.json.jbuilder +7 -0
  69. data/app/views/incline/security/_form.html.erb +20 -0
  70. data/app/views/incline/security/_list.html.erb +89 -0
  71. data/app/views/incline/security/_messages.json.jbuilder +6 -0
  72. data/app/views/incline/security/edit.html.erb +2 -0
  73. data/app/views/incline/security/index.html.erb +6 -0
  74. data/app/views/incline/security/index.json.jbuilder +16 -0
  75. data/app/views/incline/security/show.html.erb +31 -0
  76. data/app/views/incline/security/show.json.jbuilder +11 -0
  77. data/app/views/incline/sessions/new.html.erb +26 -0
  78. data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
  79. data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
  80. data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
  81. data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
  82. data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
  83. data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
  84. data/app/views/incline/users/_details.json.jbuilder +32 -0
  85. data/app/views/incline/users/_form.html.erb +21 -0
  86. data/app/views/incline/users/_list.html.erb +102 -0
  87. data/app/views/incline/users/_messages.json.jbuilder +6 -0
  88. data/app/views/incline/users/disable_confirm.html.erb +19 -0
  89. data/app/views/incline/users/edit.html.erb +5 -0
  90. data/app/views/incline/users/index.html.erb +6 -0
  91. data/app/views/incline/users/index.json.jbuilder +16 -0
  92. data/app/views/incline/users/new.html.erb +5 -0
  93. data/app/views/incline/users/show.html.erb +12 -0
  94. data/app/views/incline/users/show.json.jbuilder +11 -0
  95. data/app/views/incline/welcome/home.html.erb +5 -0
  96. data/app/views/layouts/application.html.erb +1 -0
  97. data/app/views/layouts/incline/_account_menu.html.erb +18 -0
  98. data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  99. data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  100. data/app/views/layouts/incline/_footer.html.erb +13 -0
  101. data/app/views/layouts/incline/_header.html.erb +21 -0
  102. data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
  103. data/app/views/layouts/incline/_incline_app.html.erb +25 -0
  104. data/app/views/layouts/incline/_messages.html.erb +3 -0
  105. data/app/views/layouts/incline/_shim.html.erb +3 -0
  106. data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
  107. data/app/views/layouts/incline/application.html.erb +1 -0
  108. data/app/views/layouts/mailer.html.erb +2 -0
  109. data/app/views/layouts/mailer.text.erb +2 -0
  110. data/bin/rails +12 -0
  111. data/bin/test_scaffold.sh +10 -0
  112. data/config/routes.rb +61 -0
  113. data/db/migrate/20170511230126_create_incline_users.rb +26 -0
  114. data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
  115. data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
  116. data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
  117. data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
  118. data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
  119. data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
  120. data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
  121. data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
  122. data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
  123. data/db/seeds.rb +81 -0
  124. data/exe/new_incline_app +42 -0
  125. data/lib/generators/incline/install_generator.rb +259 -0
  126. data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
  127. data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
  128. data/lib/generators/incline/templates/incline_application.css +17 -0
  129. data/lib/generators/incline/templates/incline_application.html.erb +1 -0
  130. data/lib/generators/incline/templates/incline_application.js +12 -0
  131. data/lib/generators/incline/templates/incline_database.yml +25 -0
  132. data/lib/generators/incline/templates/incline_email.yml +20 -0
  133. data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
  134. data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
  135. data/lib/generators/incline/templates/incline_users.yml +64 -0
  136. data/lib/generators/incline/templates/incline_version.rb +3 -0
  137. data/lib/incline/auth_engine_base.rb +52 -0
  138. data/lib/incline/data_tables_request.rb +336 -0
  139. data/lib/incline/date_time_formats.rb +6 -0
  140. data/lib/incline/engine.rb +212 -0
  141. data/lib/incline/errors.rb +15 -0
  142. data/lib/incline/extensions/action_controller_base.rb +526 -0
  143. data/lib/incline/extensions/action_mailer_base.rb +66 -0
  144. data/lib/incline/extensions/action_view_base.rb +489 -0
  145. data/lib/incline/extensions/active_record_base.rb +308 -0
  146. data/lib/incline/extensions/application.rb +137 -0
  147. data/lib/incline/extensions/application_configuration.rb +50 -0
  148. data/lib/incline/extensions/connection_adapter.rb +55 -0
  149. data/lib/incline/extensions/date_time_value.rb +123 -0
  150. data/lib/incline/extensions/date_value.rb +77 -0
  151. data/lib/incline/extensions/decimal_value.rb +55 -0
  152. data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
  153. data/lib/incline/extensions/float_value.rb +59 -0
  154. data/lib/incline/extensions/form_builder.rb +617 -0
  155. data/lib/incline/extensions/integer_value.rb +54 -0
  156. data/lib/incline/extensions/jbuilder_generator.rb +38 -0
  157. data/lib/incline/extensions/jbuilder_template.rb +39 -0
  158. data/lib/incline/extensions/main_app.rb +40 -0
  159. data/lib/incline/extensions/numeric.rb +63 -0
  160. data/lib/incline/extensions/object.rb +31 -0
  161. data/lib/incline/extensions/resource_route_generator.rb +53 -0
  162. data/lib/incline/extensions/session.rb +113 -0
  163. data/lib/incline/extensions/string.rb +50 -0
  164. data/lib/incline/extensions/test_case.rb +764 -0
  165. data/lib/incline/extensions/time_zone_converter.rb +40 -0
  166. data/lib/incline/global_status.rb +236 -0
  167. data/lib/incline/helpers/route_hash_formatter.rb +46 -0
  168. data/lib/incline/json_log_formatter.rb +96 -0
  169. data/lib/incline/json_logger.rb +17 -0
  170. data/lib/incline/log.rb +153 -0
  171. data/lib/incline/number_formats.rb +17 -0
  172. data/lib/incline/recaptcha.rb +346 -0
  173. data/lib/incline/user_manager.rb +212 -0
  174. data/lib/incline/validators/email_validator.rb +45 -0
  175. data/lib/incline/validators/ip_address_validator.rb +32 -0
  176. data/lib/incline/validators/recaptcha_validator.rb +37 -0
  177. data/lib/incline/validators/safe_name_validator.rb +31 -0
  178. data/lib/incline/version.rb +3 -0
  179. data/lib/incline/work_path.rb +75 -0
  180. data/lib/incline.rb +197 -0
  181. data/lib/tasks/incline_tasks.rake +4 -0
  182. data/lib/templates/erb/scaffold/_form.html.erb +43 -0
  183. data/lib/templates/erb/scaffold/_list.html.erb +81 -0
  184. data/lib/templates/erb/scaffold/edit.html.erb +1 -0
  185. data/lib/templates/erb/scaffold/index.html.erb +6 -0
  186. data/lib/templates/erb/scaffold/new.html.erb +1 -0
  187. data/lib/templates/erb/scaffold/show.html.erb +34 -0
  188. data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
  189. data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
  190. data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
  191. data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
  192. data/test/controllers/incline/access_groups_controller_test.rb +65 -0
  193. data/test/controllers/incline/access_test_controller_test.rb +53 -0
  194. data/test/controllers/incline/contact_controller_test.rb +32 -0
  195. data/test/controllers/incline/security_controller_test.rb +39 -0
  196. data/test/controllers/incline/welcome_controller_test.rb +16 -0
  197. data/test/dummy/README.rdoc +28 -0
  198. data/test/dummy/Rakefile +6 -0
  199. data/test/dummy/app/assets/images/.keep +0 -0
  200. data/test/dummy/app/assets/javascripts/application.js +12 -0
  201. data/test/dummy/app/assets/stylesheets/application.css +17 -0
  202. data/test/dummy/app/controllers/application_controller.rb +5 -0
  203. data/test/dummy/app/controllers/concerns/.keep +0 -0
  204. data/test/dummy/app/helpers/application_helper.rb +2 -0
  205. data/test/dummy/app/mailers/.keep +0 -0
  206. data/test/dummy/app/models/.keep +0 -0
  207. data/test/dummy/app/models/concerns/.keep +0 -0
  208. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  209. data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  210. data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  211. data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
  212. data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
  213. data/test/dummy/bin/bundle +3 -0
  214. data/test/dummy/bin/rails +4 -0
  215. data/test/dummy/bin/rake +4 -0
  216. data/test/dummy/bin/setup +29 -0
  217. data/test/dummy/config/application.rb +38 -0
  218. data/test/dummy/config/boot.rb +5 -0
  219. data/test/dummy/config/database.yml +34 -0
  220. data/test/dummy/config/email.yml +24 -0
  221. data/test/dummy/config/environment.rb +5 -0
  222. data/test/dummy/config/environments/development.rb +45 -0
  223. data/test/dummy/config/environments/production.rb +85 -0
  224. data/test/dummy/config/environments/test.rb +44 -0
  225. data/test/dummy/config/initializers/assets.rb +11 -0
  226. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  227. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  228. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  229. data/test/dummy/config/initializers/inflections.rb +16 -0
  230. data/test/dummy/config/initializers/mime_types.rb +4 -0
  231. data/test/dummy/config/initializers/session_store.rb +3 -0
  232. data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  233. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  234. data/test/dummy/config/locales/en.yml +23 -0
  235. data/test/dummy/config/routes.rb +6 -0
  236. data/test/dummy/config.ru +4 -0
  237. data/test/dummy/db/schema.rb +108 -0
  238. data/test/dummy/lib/assets/.keep +0 -0
  239. data/test/dummy/log/.keep +0 -0
  240. data/test/dummy/public/404.html +67 -0
  241. data/test/dummy/public/422.html +67 -0
  242. data/test/dummy/public/500.html +66 -0
  243. data/test/dummy/public/favicon.ico +0 -0
  244. data/test/extensions/action_controller_base_extensions_test.rb +21 -0
  245. data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
  246. data/test/extensions/action_view_base_extensions_test.rb +267 -0
  247. data/test/extensions/active_record_extensions_test.rb +173 -0
  248. data/test/extensions/application_configuration_extensions_test.rb +46 -0
  249. data/test/extensions/application_extensions_test.rb +23 -0
  250. data/test/extensions/connection_adapter_extensions_test.rb +54 -0
  251. data/test/extensions/date_time_value_extensions_test.rb +104 -0
  252. data/test/extensions/date_value_extensions_test.rb +102 -0
  253. data/test/extensions/decimal_value_extensions_test.rb +85 -0
  254. data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
  255. data/test/extensions/float_value_extensions_test.rb +78 -0
  256. data/test/extensions/form_builder_extensions_test.rb +28 -0
  257. data/test/extensions/integer_value_extensions_test.rb +78 -0
  258. data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
  259. data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
  260. data/test/extensions/main_app_extensions_test.rb +55 -0
  261. data/test/extensions/numeric_extensions_test.rb +76 -0
  262. data/test/extensions/object_extensions_test.rb +104 -0
  263. data/test/extensions/session_extensions_test.rb +69 -0
  264. data/test/extensions/string_extensions_test.rb +32 -0
  265. data/test/extensions/test_case_extensions_test.rb +538 -0
  266. data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
  267. data/test/fixtures/incline/access_group_group_members.yml +1 -0
  268. data/test/fixtures/incline/access_group_user_members.yml +1 -0
  269. data/test/fixtures/incline/access_groups.yml +13 -0
  270. data/test/fixtures/incline/action_groups.yml +6 -0
  271. data/test/fixtures/incline/action_securities.yml +18 -0
  272. data/test/fixtures/incline/user_login_histories.yml +1 -0
  273. data/test/fixtures/incline/users.yml +64 -0
  274. data/test/incline_test.rb +63 -0
  275. data/test/integration/incline/users_edit_test.rb +180 -0
  276. data/test/integration/incline/users_login_test.rb +105 -0
  277. data/test/integration/incline/users_signup_test.rb +147 -0
  278. data/test/integration/navigation_test.rb +11 -0
  279. data/test/lib/data_tables_request_test.rb +245 -0
  280. data/test/lib/date_time_formats_test.rb +111 -0
  281. data/test/lib/global_status_test.rb +89 -0
  282. data/test/lib/json_log_formatter_test.rb +43 -0
  283. data/test/lib/log_test.rb +36 -0
  284. data/test/lib/recaptcha_test.rb +75 -0
  285. data/test/lib/user_manager_test.rb +47 -0
  286. data/test/lib/work_path_test.rb +18 -0
  287. data/test/models/incline/access_group_group_member_test.rb +30 -0
  288. data/test/models/incline/access_group_test.rb +60 -0
  289. data/test/models/incline/access_group_user_member_test.rb +29 -0
  290. data/test/models/incline/action_group_test.rb +27 -0
  291. data/test/models/incline/action_security_test.rb +176 -0
  292. data/test/models/incline/contact_message_test.rb +66 -0
  293. data/test/models/incline/disable_info_test.rb +29 -0
  294. data/test/models/incline/password_reset_request_test.rb +35 -0
  295. data/test/models/incline/password_reset_test.rb +51 -0
  296. data/test/models/incline/user_login_history_test.rb +31 -0
  297. data/test/models/incline/user_test.rb +91 -0
  298. data/test/test_helper.rb +42 -0
  299. data/test/validators/email_validator_test.rb +102 -0
  300. data/test/validators/ip_address_validator_test.rb +107 -0
  301. data/test/validators/recaptcha_validator_test.rb +57 -0
  302. data/test/validators/safe_name_validator_test.rb +101 -0
  303. metadata +584 -0
@@ -0,0 +1,526 @@
1
+ require 'action_controller'
2
+
3
+ module Incline::Extensions
4
+
5
+ ##
6
+ # Adds some extra functionality to the base controller definition.
7
+ module ActionControllerBase
8
+
9
+ ##
10
+ # Adds some class methods to the base action controller.
11
+ module ClassMethods
12
+
13
+ ##
14
+ # Turn on auto API for the controller.
15
+ def enable_auto_api
16
+ @enable_auto_api = true
17
+ end
18
+
19
+ ##
20
+ # Turn off auto API for the controller.
21
+ def disable_auto_api
22
+ @enable_auto_api = false
23
+ end
24
+
25
+ ##
26
+ # Determines if the controller is configured for auto API.
27
+ def auto_api?
28
+ @enable_auto_api ||= false
29
+ end
30
+
31
+ ##
32
+ # Enables or disables HTTP (non-SSL) for actions.
33
+ #
34
+ # Pass +false+ to disable HTTP for all actions(default).
35
+ # Pass +true+ to enable HTTP for all actions.
36
+ # Pass action names to enable HTTP for specific actions.
37
+ #
38
+ # With no arguments, the current setting is returned.
39
+ #
40
+ # allow_non_ssl false
41
+ # allow_non_ssl true
42
+ # allow_non_ssl :home, :about
43
+ #
44
+ def allow_non_ssl(*args)
45
+ if args.blank?
46
+ @allow_non_ssl ||= false
47
+ else
48
+ @allow_non_ssl = setting_value(args)
49
+ end
50
+ end
51
+
52
+ ##
53
+ # Enables anonymous access for actions.
54
+ #
55
+ # Pass +false+ to disable anonymous access for all actions(default).
56
+ # Pass +true+ to allow anonymous access for all actions.
57
+ # Pass action names to enable anonymous access for specific actions.
58
+ #
59
+ # With no arguments, the current setting is returned.
60
+ #
61
+ # allow_anon false
62
+ # allow_anon true
63
+ # allow_anon :home, :about
64
+ #
65
+ def allow_anon(*args)
66
+ if args.blank?
67
+ @allow_anon ||= false
68
+ else
69
+ @allow_anon = setting_value(args)
70
+ end
71
+ end
72
+
73
+ ##
74
+ # Enables requiring a system administrator for actions.
75
+ #
76
+ # Pass +false+ to allow non-system administrators access for all actions(default).
77
+ # Pass +true+ to require system administrators for all actions.
78
+ # Pass action names to require system administrators for specific actions.
79
+ #
80
+ # With no arguments, the current setting is returned.
81
+ #
82
+ # require_admin false
83
+ # require_admin true
84
+ # require_admin :new, :edit, :create, :update, :destroy
85
+ #
86
+ def require_admin(*args)
87
+ if args.blank?
88
+ @require_admin ||= false
89
+ else
90
+ @require_admin = setting_value(args)
91
+ end
92
+ end
93
+
94
+ ##
95
+ # Enables requiring an anonymous user for actions.
96
+ #
97
+ # Pass +false+ to allow logged in users access for all actions(default).
98
+ # Pass +true+ to require anonymous users for all actions.
99
+ # Pass action names to require anonymous for specific actions.
100
+ #
101
+ # With no arguments, the current setting is returned.
102
+ #
103
+ # require_anon false
104
+ # require_anon true
105
+ # require_anon :new, :edit, :create, :update, :destroy
106
+ #
107
+ def require_anon(*args)
108
+ if args.blank?
109
+ @require_anon ||= false
110
+ else
111
+ @require_anon = setting_value(args)
112
+ end
113
+ end
114
+
115
+ ##
116
+ # Determines if the current request can be allowed with an anonymous user.
117
+ #
118
+ # Overridden by require_admin_for_request?
119
+ # Implied by require_anon_for_request?
120
+ def allow_anon_for?(action)
121
+ require_anon_for?(action) || setting_for_action(allow_anon, action)
122
+ end
123
+
124
+ ##
125
+ # Determines if the current request requires a system administrator.
126
+ #
127
+ # Overrides all other access requirements.
128
+ def require_admin_for?(action)
129
+ setting_for_action require_admin, action
130
+ end
131
+
132
+ ##
133
+ # Determines if the current request requires an anonymous user.
134
+ #
135
+ # Overridden by require_admin_for_request?
136
+ # Implies allow_anon_for_request?
137
+ def require_anon_for?(action)
138
+ setting_for_action require_anon, action
139
+ end
140
+
141
+ private
142
+
143
+ def setting_value(args)
144
+ if args.include?(false)
145
+ false
146
+ elsif args.include?(true)
147
+ true
148
+ else
149
+ args.map{|v| v.is_a?(::Symbol) ? v : v.to_s.to_sym }
150
+ end
151
+ end
152
+
153
+ def setting_for_action(setting, action)
154
+ return false unless setting
155
+ if setting.is_a?(::Array)
156
+ return false unless setting.include?(action.to_sym)
157
+ end
158
+ true
159
+ end
160
+
161
+ end
162
+
163
+ ##
164
+ # Enforces SSL and catches Incline::NotLoggedIn exceptions.
165
+ def self.included(base)
166
+ base.extend ClassMethods
167
+ base.class_eval do
168
+
169
+ # Force SSL under production environments unless allow_http_for_request returns true.
170
+ if Rails.env.production?
171
+ force_ssl unless: :allow_http_for_request?
172
+ end
173
+
174
+ # Process user authorization for all actions except the GET/POST api actions.
175
+ # These get to be authorized once the actual action is selected.
176
+ before_action :valid_user?, except: [ :api ]
177
+
178
+ undef process_action
179
+
180
+ ##
181
+ # Override the default to enable auto-api behavior if desired.
182
+ def process_action(method_name, *args) #:nodoc:
183
+ if self.class.auto_api?
184
+ unless process_api_action(false, nil)
185
+ super method_name, *args
186
+ end
187
+ else
188
+ super method_name, *args
189
+ end
190
+ end
191
+
192
+ rescue_from ::Incline::NotLoggedIn do |exception|
193
+ flash[:info] = exception.message
194
+ store_location
195
+ redirect_to(incline.login_url)
196
+ end
197
+
198
+ end
199
+ end
200
+
201
+ ##
202
+ # Renders the view as a CSV file.
203
+ #
204
+ # Set the +filename+ you would like to provide to the client, or leave it nil to use the action name.
205
+ # Set the +view_name+ you would like to render, or leave it nil to use the action name.
206
+ def render_csv(filename = nil, view_name = nil)
207
+
208
+ filename ||= params[:action]
209
+ view_name ||= params[:action]
210
+ filename.downcase!
211
+ filename += '.csv' unless filename[-4..-1] == '.csv'
212
+
213
+ headers['Content-Type'] = 'text/csv'
214
+ headers['Content-Disposition'] = "attachment; filename=\"#{filename}\""
215
+
216
+ render view_name, layout: false
217
+ end
218
+
219
+ ##
220
+ # A redirects to a previously stored location or to the default location.
221
+ #
222
+ # Usually this will be used to return to an action after a user logs in.
223
+ def redirect_back_or(default)
224
+ redirect_to session[:forwarding_url] || default
225
+ session.delete :forwarding_url
226
+ end
227
+
228
+ ##
229
+ # Stores the current URL to be used with #redirect_back_or.
230
+ def store_location
231
+ session[:forwarding_url] = request.url if request.get?
232
+ end
233
+
234
+
235
+
236
+
237
+ protected
238
+
239
+ ##
240
+ # This method maps the requested action into the actual action performed.
241
+ #
242
+ # By default, the requested action is returned. If for some reason you want to use a different
243
+ # action in your API, override this method in your controller and map the actions as appropriate.
244
+ #
245
+ # The actions you can expect to translate are 'index', 'new', 'show', and 'edit' for GET requests, and
246
+ # 'create', 'update', and 'destroy' for POST requests. They will be string values or nil, they will not be
247
+ # symbols.
248
+ #
249
+ # The default behavior causes the API to "fall through" to your standard controller methods.
250
+ #
251
+ # The API is accessed by either a POST or a GET request that specifies an `action` parameter. The action
252
+ # gets translated to the acceptable actions listed above and then run through this method for translation.
253
+ #
254
+ def map_api_action(requested_action) #:doc:
255
+ requested_action
256
+ end
257
+
258
+
259
+ ##
260
+ # Authorizes access for the action.
261
+ #
262
+ # * With no arguments, this will validate that a user is currently logged in, but does not check their permission.
263
+ # * With an argument of true, this will validate that the user currently logged in is an administrator.
264
+ # * With one or more strings, this will validate that the user currently logged in has at least one or more
265
+ # of the named permissions.
266
+ #
267
+ # authorize!
268
+ # authorize! true
269
+ # authorize! "Safety Manager", "HR Manager"
270
+ #
271
+ # If no user is logged in, then the user will be redirected to the login page and the method will return false.
272
+ # If a user is logged in, but is not authorized, then the user will be redirected to the home page and the method
273
+ # will return false.
274
+ # If the user is authorized, the method will return true.
275
+ def authorize!(*accepted_groups) #:doc:
276
+ begin
277
+
278
+ # an authenticated user must exist.
279
+ unless logged_in?
280
+ store_location
281
+
282
+ raise_not_logged_in "You need to login to access '#{request.fullpath}'.",
283
+ 'nobody is logged in'
284
+ end
285
+
286
+ if system_admin?
287
+ log_authorize_success 'user is system admin'
288
+ else
289
+ # clean up the group list.
290
+ accepted_groups ||= []
291
+ accepted_groups.flatten!
292
+ accepted_groups.delete false
293
+ accepted_groups.delete ''
294
+
295
+ if accepted_groups.include?(true)
296
+ # group_list contains "true" so only a system admin may continue.
297
+ raise_authorize_failure "Your are not authorized to access '#{request.fullpath}'.",
298
+ 'requires system administrator'
299
+
300
+ elsif accepted_groups.blank?
301
+ # group_list is empty or contained nothing but empty strings and boolean false.
302
+ # everyone can continue.
303
+ log_authorize_success 'only requires authenticated user'
304
+
305
+ else
306
+ # the group list contains one or more authorized groups.
307
+ # we want them to all be uppercase strings.
308
+ accepted_groups = accepted_groups.map{|v| v.to_s.upcase}.sort
309
+ result = current_user.has_any_group?(*accepted_groups)
310
+ unless result
311
+ raise_authorize_failure "You are not authorized to access '#{request.fullpath}'.",
312
+ "requires one of: #{accepted_groups.inspect}"
313
+ end
314
+ log_authorize_success "user has #{result.inspect}"
315
+ end
316
+ end
317
+
318
+ rescue ::Incline::NotAuthorized => err
319
+
320
+ flash[:danger] = err.message
321
+ redirect_to root_url and return false
322
+ end
323
+ true
324
+
325
+ end
326
+
327
+ ##
328
+ # Is the current request for JSON data?
329
+ #
330
+ # Redirects are generally bad when JSON data is requested.
331
+ # For instance a `create` request in JSON format should return data, not redirect to `show`.
332
+ def json_request? #:doc:
333
+ request.format.to_s.downcase == 'json'
334
+ end
335
+
336
+ ##
337
+ # Is the current request an inline request?
338
+ #
339
+ # JSON requests are always considered inline, otherwise we check to see if the "inline" parameter is set to a true value.
340
+ #
341
+ # Primarily this would be used to strip the layour from rendered content.
342
+ def inline_request?
343
+ json_request? || params[:inline].to_bool
344
+ end
345
+
346
+ ##
347
+ # Determines if the current request can be allowed via HTTP (non-SSL).
348
+ def allow_http_for_request? #:doc:
349
+ self.class.setting_for_action self.class.allow_non_ssl, params[:action]
350
+ end
351
+
352
+ ##
353
+ # Determines if the current request can be allowed with an anonymous user.
354
+ #
355
+ # Overridden by require_admin_for_request?
356
+ # Implied by require_anon_for_request?
357
+ def allow_anon_for_request? #:doc:
358
+ self.class.allow_anon_for? params[:action]
359
+ end
360
+
361
+ ##
362
+ # Determines if the current request requires a system administrator.
363
+ #
364
+ # Overrides all other access requirements.
365
+ def require_admin_for_request? #:doc:
366
+ self.class.require_admin_for? params[:action]
367
+ end
368
+
369
+ ##
370
+ # Determines if the current request requires an anonymous user.
371
+ #
372
+ # Overridden by require_admin_for_request?
373
+ # Implies allow_anon_for_request?
374
+ def require_anon_for_request? #:doc:
375
+ self.class.require_anon_for? params[:action]
376
+ end
377
+
378
+
379
+ private
380
+
381
+ ##
382
+ # Validates that the current user is authorized for the current request.
383
+ #
384
+ # This method is called for every action except the :api action.
385
+ # For the :api action, this method will not be called until the actual requested action is performed.
386
+ #
387
+ # One of four scenarios are possible:
388
+ # 1. If the +require_admin+ method applies to the current action, then a system administrator must be logged in.
389
+ # 1. If a nobody is logged in, then the user will be redirected to the login url.
390
+ # 2. If a system administrator is logged in, then access is granted.
391
+ # 3. Non-system administrators will be redirected to the root url.
392
+ # 2. If the +require_anon+ method applies to the current action, then a user cannot be logged in.
393
+ # 1. If a user is logged in, a warning message is set and the user is redirected to their account.
394
+ # 2. If no user is logged in, then access is granted.
395
+ # 3. If the +allow_anon+ method applies to the current action, then access is granted.
396
+ # 4. The action doesn't require a system administrator, but does require a valid user to be logged in.
397
+ # 1. If nobody is logged in, then the user will be redirected to the login url.
398
+ # 2. If a system administrator is logged in, then access is granted.
399
+ # 3. If the action doesn't have any required permissions, then access is granted to any logged in user.
400
+ # 4. If the action has required permissions and the logged in user shares at least one, then access is granted.
401
+ # 5. Users without at least one required permission are redirected to the root url.
402
+ #
403
+ # Two of the scenarios are configured at design time. If you use +require_admin+ or +allow_anon+,
404
+ # they cannot be changed at runtime. The idea is that anything that allows anonymous access will always allow
405
+ # anonymous access during runtime and anything that requires admin access will always require admin access during
406
+ # runtime.
407
+ #
408
+ # The third scenario is what would be used by most actions. Using the +admin+ controller, which requires admin
409
+ # access, you can customize the permissions required for each available route. Using the +users+ controller,
410
+ # admins can assign permissions to other users.
411
+ #
412
+ def valid_user? #:doc:
413
+ if require_admin_for_request?
414
+ authorize! true
415
+ elsif require_anon_for_request?
416
+ if logged_in?
417
+ flash[:warning] = 'The specified action cannot be performed while logged in.'
418
+ redirect_to current_user
419
+ end
420
+ elsif allow_anon_for_request?
421
+ true
422
+ else
423
+ action = Incline::ActionSecurity.valid_items[self.class.controller_path, params[:action]]
424
+ if action && action.groups.count > 0
425
+ authorize! action.groups.pluck(:name)
426
+ else
427
+ authorize!
428
+ end
429
+ end
430
+ end
431
+
432
+
433
+ def process_api_action(raise_on_invalid_action = true, default_get_action = 'index')
434
+ api_action =
435
+ map_api_action(
436
+ if request.post?
437
+ # A post request can create, update, or destroy.
438
+ # In addition we allow index to post since DataTables can send quite a bit of data with server-side
439
+ # processing.
440
+ # The post action can be provided as a query parameter or a form parameter with the form parameter
441
+ # taking priority.
442
+ {
443
+ nil => 'index',
444
+ 'list' => 'index',
445
+ 'index' => 'index',
446
+ 'new' => 'create',
447
+ 'create' => 'create',
448
+ 'edit' => 'update',
449
+ 'update' => 'update',
450
+ 'remove' => 'destroy',
451
+ 'destroy' => 'destroy'
452
+ }[request.request_parameters.delete('action') || request.query_parameters.delete('action')]
453
+ elsif request.get?
454
+ # For the most part, these shouldn't be used except for maybe index and show.
455
+ # The new and edit actions could be used if for some reason you need to supply data to the ajax form
456
+ # calling these actions, e.g. - a list of locations.
457
+ # Datatables Editor does not use any of them.
458
+ # Datatables will simple be requesting the index action in JSON format.
459
+ # To remain consistent though, you can use '?action=list' to perform the same feat.
460
+ {
461
+ 'list' => 'index',
462
+ 'index' => 'index',
463
+ 'new' => 'new',
464
+ 'show' => 'show',
465
+ 'edit' => 'edit'
466
+ }[request.query_parameters.delete('action')] || default_get_action
467
+ else
468
+ nil
469
+ end
470
+ )
471
+
472
+ if api_action
473
+ # Datatables Editor sends the 'data' in the 'data' parameter.
474
+ # We simple want to move that up a level so `params[:data][:user][:name]` becomes `params[:user][:name]`.
475
+ data = request.params.delete('data')
476
+ unless data.blank?
477
+ # get the first entry in the hash.
478
+ id, item = data.first
479
+
480
+ # if the id is in AAAAA_NNN format, then we can extract the ID from it.
481
+ if id.include?('_')
482
+ params[:id] = id.split('_').last.to_i
483
+ end
484
+
485
+ # merge the item data into the params array.
486
+ params.merge! item
487
+ end
488
+
489
+ # since we are processing for an API request, we should return JSON.
490
+ request.format = :json
491
+
492
+ # finally, we'll start over on processing the stack.
493
+ # This should ensure the appropriate `before_action` filters are called for the new action.
494
+ process api_action
495
+ else
496
+ # raise an error.
497
+ raise Incline::InvalidApiCall, 'Invalid API Action' if raise_on_invalid_action
498
+ nil
499
+ end
500
+ end
501
+
502
+ def raise_authorize_failure(message, log_message = nil)
503
+ log_authorize_failure message, log_message
504
+ raise Incline::NotAuthorized.new(message)
505
+ end
506
+
507
+ def raise_not_logged_in(message, log_message = nil)
508
+ log_authorize_failure message, log_message
509
+ raise Incline::NotLoggedIn.new(message)
510
+ end
511
+
512
+ def log_authorize_failure(message, log_message = nil)
513
+ log_message ||= message
514
+ Incline::Log::info "AUTH(FAILURE): #{request.fullpath}, #{current_user}, #{log_message}"
515
+ end
516
+
517
+ def log_authorize_success(message)
518
+ Incline::Log::info "AUTH(SUCCESS): #{request.fullpath}, #{current_user}, #{message}"
519
+ end
520
+
521
+ end
522
+
523
+ end
524
+
525
+ ActionController::Base.include Incline::Extensions::ActionControllerBase
526
+
@@ -0,0 +1,66 @@
1
+ require 'action_mailer'
2
+
3
+ module Incline::Extensions
4
+
5
+ ##
6
+ # Adds the default_hostname, default_sender, and default_recipient methods to the ApplicationMailer::Base class.
7
+ module ActionMailerBase
8
+
9
+ ##
10
+ # Adds the extra class methods to the ApplicationMailer::Base class.
11
+ module ClassMethods
12
+ ##
13
+ # Gets the default hostname for messages.
14
+ def default_hostname
15
+ @default_hostname ||= Incline::email_config[:default_hostname]
16
+ end
17
+
18
+ ##
19
+ # Gets the default sender for messages.
20
+ def default_sender
21
+ @default_sender ||= Incline::email_config[:sender]
22
+ end
23
+
24
+ ##
25
+ # Gets the default recipient for messages.
26
+ def default_recipient
27
+ @default_recipient ||= Incline::email_config[:default_recipient]
28
+ end
29
+ end
30
+
31
+ ##
32
+ # Sets the default from and to address according to the configuration.
33
+ def self.included(base)
34
+ base.extend ClassMethods
35
+
36
+ class << self
37
+
38
+ private
39
+
40
+ if method_defined?(:inherited)
41
+ alias_method :incline_original_inherited, :inherited
42
+ else
43
+ def incline_original_inherited(subclass)
44
+ # Do nothing.
45
+ end
46
+ end
47
+
48
+ def inherited(subclass)
49
+ incline_original_inherited subclass
50
+
51
+ default(
52
+ {
53
+ from: default_sender,
54
+ to: default_recipient
55
+ }
56
+ )
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ ActionMailer::Base.include Incline::Extensions::ActionMailerBase