incline 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
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,121 @@
1
+ require_relative './access_group_group_member'
2
+ require_relative './access_group_user_member'
3
+
4
+ module Incline
5
+ class AccessGroup < ActiveRecord::Base
6
+
7
+ # hide the Groups<=>Users relationship association
8
+ has_many :access_group_user_members, class_name: 'Incline::AccessGroupUserMember', foreign_key: 'group_id', dependent: :delete_all
9
+ private :access_group_user_members, :access_group_user_members=
10
+
11
+ # and expose the users instead.
12
+ has_many :users, class_name: 'Incline::User', through: :access_group_user_members, source: :member
13
+
14
+ # hide the Groups<=>Groups relationship association
15
+ has_many :access_group_group_members, class_name: 'Incline::AccessGroupGroupMember', foreign_key: 'group_id', dependent: :delete_all
16
+ private :access_group_group_members, :access_group_group_members=
17
+
18
+ # and expose the groups instead.
19
+ has_many :groups, class_name: 'Incline::AccessGroup', through: :access_group_group_members, source: :member
20
+
21
+ ##
22
+ # Gets a list of memberships for this group. (Read-only)
23
+ def memberships(refresh = false)
24
+ @memberships = nil if refresh
25
+ @memberships ||= AccessGroupGroupMember.where(member_id: id).includes(:group).map{|v| v.group}.to_a.freeze
26
+ end
27
+
28
+ ##
29
+ # Gets a list of all of the member users for this group. (Read-only)
30
+ def members(refresh = false)
31
+ @members = nil if refresh
32
+ @members ||= safe_members.sort{|a,b| a.to_s <=> b.to_s}
33
+ end
34
+
35
+ validates :name,
36
+ presence: true,
37
+ length: { maximum: 100 },
38
+ uniqueness: { case_sensitive: false }
39
+
40
+ scope :sorted, ->{ order(:name) }
41
+
42
+ ##
43
+ # Determines if this group belongs to the specified group.
44
+ def belongs_to?(group)
45
+ group = AccessGroup.get(group) unless group.is_a?(::Incline::AccessGroup)
46
+ return false unless group
47
+ safe_belongs_to?(group)
48
+ end
49
+
50
+ ##
51
+ # Gets a list of all the groups this group provides effective membership to.
52
+ def effective_groups
53
+ ret = [ self ]
54
+ memberships.each do |m|
55
+ unless ret.include?(m) # prevent infinite recursion
56
+ tmp = m.effective_groups
57
+ tmp.each do |g|
58
+ ret << g unless ret.include?(g)
59
+ end
60
+ end
61
+ end
62
+ ret.sort{|a,b| a.name <=> b.name}
63
+ end
64
+
65
+ ##
66
+ # Gets the user IDs for the members of this group.
67
+ def user_ids
68
+ users.pluck(:id)
69
+ end
70
+
71
+ ##
72
+ # Gets the group IDs for the members of this group.
73
+ def group_ids
74
+ groups.pluck(:id)
75
+ end
76
+
77
+ ##
78
+ # Sets the user IDs for the members of this group.
79
+ def user_ids=(values)
80
+ values ||= []
81
+ values = [ values ] unless values.is_a?(::Array)
82
+ values = values.reject{|v| v.blank?}.map{|v| v.to_i}
83
+ self.users = Incline::User.where(id: values).to_a
84
+ end
85
+
86
+ ##
87
+ # Sets the group IDs for the members of this group.
88
+ def group_ids=(values)
89
+ values ||= []
90
+ values = [ values ] unless values.is_a?(::Array)
91
+ values = values.reject{|v| v.blank?}.map{|v| v.to_i}
92
+ self.groups = Incline::AccessGroup.where(id: values).to_a
93
+ end
94
+
95
+ protected
96
+
97
+ def safe_belongs_to?(group, already_tried = [])
98
+ return true if self == group
99
+ already_tried << self
100
+ memberships.each do |parent|
101
+ unless already_tried.include?(parent)
102
+ return true if parent.safe_belongs_to?(group, already_tried)
103
+ end
104
+ end
105
+ false
106
+ end
107
+
108
+ def safe_members(already_tried = [])
109
+ return [] if already_tried.include?(self)
110
+ already_tried << self
111
+ ret = users.to_a
112
+ groups.each do |g|
113
+ g.send(:safe_members, already_tried).each do |u|
114
+ ret << u unless ret.include?(u)
115
+ end
116
+ end
117
+ ret
118
+ end
119
+
120
+ end
121
+ end
@@ -0,0 +1,12 @@
1
+ module Incline
2
+ class AccessGroupGroupMember < ActiveRecord::Base
3
+ belongs_to :group, class_name: 'Incline::AccessGroup'
4
+ belongs_to :member, class_name: 'Incline::AccessGroup'
5
+
6
+ validates :group_id, presence: true
7
+ validates :member_id, presence: true, uniqueness: { scope: :group_id }
8
+
9
+ # member_id should not equal group_id or cause infinite recursion.
10
+ # these two issues are addressed in the AccessGroup model.
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Incline
2
+ class AccessGroupUserMember < ActiveRecord::Base
3
+
4
+ belongs_to :group, class_name: 'Incline::AccessGroup'
5
+ belongs_to :member, class_name: 'Incline::User'
6
+
7
+ validates :group_id, presence: true
8
+ validates :member_id, presence: true, uniqueness: { scope: :group_id }
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './access_group'
2
+
3
+ module Incline
4
+ class ActionGroup < ActiveRecord::Base
5
+ belongs_to :action_security
6
+ belongs_to :access_group
7
+
8
+ validates :action_security, presence: true
9
+ validates :access_group, presence: true, uniqueness: { scope: :action_security }
10
+
11
+ end
12
+ end
@@ -0,0 +1,222 @@
1
+ require_relative './action_group'
2
+
3
+ module Incline
4
+ class ActionSecurity < ActiveRecord::Base
5
+
6
+ SHORT_PERMITTED_FILTERS = {
7
+ '- Editable -' => 'users|custom',
8
+ 'Admins' => 'admins',
9
+ 'Anon' => 'anon',
10
+ 'Custom' => 'custom',
11
+ 'Everyone' => 'everyone',
12
+ 'Users' => 'users'
13
+ }.freeze
14
+
15
+ has_many :action_groups
16
+ private :action_groups, :action_groups=
17
+
18
+ has_many :groups, through: :action_groups, class_name: 'Incline::AccessGroup', source: :access_group
19
+
20
+ validates :controller_name, presence: true, length: { maximum: 200 }
21
+ validates :action_name, presence: true, length: { maximum: 200 }, uniqueness: { scope: :controller_name, case_sensitive: false }
22
+ validates :path, presence: true
23
+
24
+ before_save :downcase_names
25
+
26
+ scope :visible, ->{ where(visible: true) }
27
+
28
+ ##
29
+ # Updates the flags based on the controller configuration.
30
+ def update_flags
31
+ self.allow_anon = self.require_anon = self.require_admin = self.unknown_controller = self.non_standard = false
32
+
33
+ self.unknown_controller = true
34
+ klass =
35
+ begin
36
+ (controller_name + '_controller').classify.constantize
37
+ rescue NameError
38
+ nil
39
+ end
40
+
41
+ unless klass
42
+ options =
43
+ if controller_name.include?('/')
44
+ ns = controller_name.rpartition('/')[0]
45
+ ctrl = controller_name.rpartition('/')[2]
46
+ options = [
47
+ "#{ns}/app/controllers/#{ns}/#{ctrl}_controller",
48
+ "app/controllers/#{ns}/#{ctrl}_controller",
49
+ "#{ns}/app/controllers/#{ctrl}_controller",
50
+ "#{ns}/#{ctrl}_controller"
51
+ ]
52
+ else
53
+ options = [
54
+ "app/controllers/#{controller_name}_controller",
55
+ "#{controller_name}_controller"
56
+ ]
57
+ end
58
+
59
+ while (file = options.shift)
60
+ begin
61
+ require file
62
+ klass = (controller_name + '_controller').classify.constantize
63
+ break
64
+ rescue LoadError, NameError
65
+ # just preventing the error from bubbling up.
66
+ end
67
+ end
68
+ end
69
+
70
+ if klass
71
+ self.unknown_controller = false
72
+ if klass.require_admin_for?(action_name)
73
+ self.require_admin = true
74
+ elsif klass.require_anon_for?(action_name)
75
+ self.require_anon = true
76
+ elsif klass.allow_anon_for?(action_name)
77
+ self.allow_anon = true
78
+ end
79
+
80
+ # if the authentication methods are overridden, set a flag to alert the user that standard security may not be honored.
81
+ unless klass.instance_method(:valid_user?).owner == Incline::Extensions::ActionControllerBase &&
82
+ klass.instance_method(:authorize!).owner == Incline::Extensions::ActionControllerBase
83
+ self.non_standard = true
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
90
+ ##
91
+ # Determines if the action allows custom security settings.
92
+ def allow_custom?
93
+ !(require_admin? || require_anon? || allow_anon?)
94
+ end
95
+
96
+ ##
97
+ # Generates a list of security items related to all of the current routes in the application.
98
+ #
99
+ # If "refresh" is true, the list will be rebuilt.
100
+ # If "update_flags" is true, the individual controllers will be loaded to regenerate the flags for the security.
101
+ #
102
+ # The returned list can be indexed two ways. The normal way with a numeric index and also by specifying the
103
+ # controller_name and action_name.
104
+ #
105
+ # Incline::ActionSecurity.valid_items[0]
106
+ # Incline::ActionSecurity.valid_items['incline/welcome','home']
107
+ #
108
+ def self.valid_items(refresh = false, update_flags = true)
109
+ @valid_items = nil if refresh
110
+ @valid_items ||=
111
+ begin
112
+ Incline::ActionSecurity.update_all(visible: false)
113
+
114
+ ret = Incline
115
+ .route_list
116
+ .reject{|r| r[:action] == 'api'}
117
+ .map do |r|
118
+ item = ActionSecurity.find_or_initialize_by(controller_name: r[:controller], action_name: r[:action])
119
+ item.path = "#{r[:path]} [#{r[:verb]}]"
120
+ item.visible = true
121
+ item.update_flags if update_flags
122
+ item.save!
123
+ item
124
+ end
125
+ .sort{|a,b| a.controller_name == b.controller_name ? a.action_name <=> b.action_name : a.controller_name <=> b.controller_name}
126
+
127
+ def ret.[](*args)
128
+ if args.length == 2
129
+ controller = args[0].to_s
130
+ action = args[1].to_s
131
+ find{|item| item.controller_name == controller && item.action_name == action}
132
+ else
133
+ super(*args)
134
+ end
135
+ end
136
+
137
+ ret.freeze
138
+ end
139
+ end
140
+
141
+ ##
142
+ # Gets a string describing who is permitted to execute the action.
143
+ def permitted(refresh = false)
144
+ @permitted = nil if refresh
145
+ @permitted ||=
146
+ if require_admin?
147
+ 'Administrators Only'
148
+ elsif require_anon?
149
+ 'Anonymous Only'
150
+ elsif allow_anon?
151
+ 'Everyone'
152
+ elsif groups.any?
153
+ names = groups.pluck(:name).map{|v| "\"#{v}\""}
154
+ 'Members of ' +
155
+ if names.count == 1
156
+ names.first
157
+ elsif names.count == 2
158
+ names.join(' or ')
159
+ else
160
+ names[0...-1].join(', ') + ', or ' + names.last
161
+ end
162
+ else
163
+ 'All Users'
164
+ end +
165
+ if non_standard
166
+ ' (Non-Standard)'
167
+ else
168
+ ''
169
+ end
170
+ end
171
+
172
+ ##
173
+ # Gets a short string describing who is permitted to execute the action.
174
+ def short_permitted
175
+ if require_admin?
176
+ 'Admins'
177
+ elsif require_anon?
178
+ 'Anon'
179
+ elsif allow_anon?
180
+ 'Everyone'
181
+ elsif groups.any?
182
+ 'Custom'
183
+ else
184
+ 'Users'
185
+ end +
186
+ if non_standard
187
+ '*'
188
+ else
189
+ ''
190
+ end
191
+ end
192
+
193
+ ##
194
+ # Description of action.
195
+ def to_s
196
+ @to_s ||= "#{controller_name}:#{action_name} [#{permitted}]"
197
+ end
198
+
199
+ ##
200
+ # Gets the group IDs accepted by this action.
201
+ def group_ids
202
+ groups.pluck(:id)
203
+ end
204
+
205
+ ##
206
+ # Sets the group IDs accepted by this action.
207
+ def group_ids=(values)
208
+ values ||= []
209
+ values = [ values ] unless values.is_a?(::Array)
210
+ values = values.reject{|v| v.blank?}.map{|v| v.to_i}
211
+ self.groups = Incline::AccessGroup.where(id: values).to_a
212
+ end
213
+
214
+ private
215
+
216
+ def downcase_names
217
+ controller_name.downcase!
218
+ action_name.downcase!
219
+ end
220
+
221
+ end
222
+ end
@@ -0,0 +1,37 @@
1
+ module Incline
2
+ ##
3
+ # Defines the message generated by the generic contact form.
4
+ class ContactMessage
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :your_name, :your_email, :related_to, :subject, :body, :remote_ip, :recaptcha
9
+
10
+ validates :your_name, presence: true
11
+ validates :your_email, presence: true, 'incline/email' => true
12
+ validates :related_to, presence: true
13
+ validates :subject, presence: true, if: :need_subject?
14
+ validates :body, presence: true
15
+ validates :recaptcha, presence: true, 'incline/recaptcha' => true
16
+
17
+ ##
18
+ # Gets the full subject for the message.
19
+ def full_subject
20
+ return related_to if subject.blank?
21
+ "#{related_to}: #{subject}"
22
+ end
23
+
24
+ ##
25
+ # Sends the message.
26
+ def send_message
27
+ Incline::ContactForm.contact(self).deliver_now
28
+ end
29
+
30
+ private
31
+
32
+ def need_subject?
33
+ related_to.to_s.downcase == 'other'
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ module Incline
2
+ ##
3
+ # This model is used to disable a user with a reason for the disabling.
4
+ class DisableInfo
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :reason, :user
9
+
10
+ validates :reason, presence: true
11
+ validate do
12
+ if user && user.is_a?(::Incline::User)
13
+ errors.add(:user, 'must be enabled') unless user.enabled?
14
+ else
15
+ errors.add(:user, 'must be provided')
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Incline
2
+ class PasswordReset
3
+ include ActiveModel::Model
4
+ include ActiveModel::Validations
5
+
6
+ attr_accessor :password
7
+ attr_accessor :recaptcha
8
+
9
+ validates :password, presence: true, length: { minimum: 8 }, confirmation: true
10
+ validates :password_confirmation, presence: true
11
+ validates :recaptcha, presence: true, 'incline/recaptcha' => true
12
+
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module Incline
3
+ class PasswordResetRequest
4
+ include ActiveModel::Model
5
+ include ActiveModel::Validations
6
+
7
+ attr_accessor :email
8
+ attr_accessor :recaptcha
9
+
10
+ validates :email, presence: true, 'incline/email' => true
11
+ validates :recaptcha, presence: true, 'incline/recaptcha' => true
12
+ end
13
+
14
+ end