barkest_core 1.5.3.0

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 (308) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +22 -0
  4. data/Gemfile.lock +254 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +364 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/barkest_core/ArchivoNarrow-Bold.ttf +0 -0
  9. data/app/assets/fonts/barkest_core/ArchivoNarrow-BoldItalic.ttf +0 -0
  10. data/app/assets/fonts/barkest_core/ArchivoNarrow-Italic.ttf +0 -0
  11. data/app/assets/fonts/barkest_core/ArchivoNarrow-Regular.ttf +0 -0
  12. data/app/assets/images/barkest_core/.keep +0 -0
  13. data/app/assets/images/barkest_core/barcode-B.svg +181 -0
  14. data/app/assets/javascripts/barkest_core/.keep +0 -0
  15. data/app/assets/javascripts/barkest_core/application.js +22 -0
  16. data/app/assets/javascripts/barkest_core/bootstrap-datepicker.js +1800 -0
  17. data/app/assets/javascripts/barkest_core/field_init.js +7 -0
  18. data/app/assets/javascripts/barkest_core/jquery.doubleScroll.js +112 -0
  19. data/app/assets/javascripts/barkest_core/masked_edit.js +25 -0
  20. data/app/assets/javascripts/barkest_core/system_status.js.erb +201 -0
  21. data/app/assets/stylesheets/barkest_core/.keep +0 -0
  22. data/app/assets/stylesheets/barkest_core/application.css +17 -0
  23. data/app/assets/stylesheets/barkest_core/custom.css.scss +264 -0
  24. data/app/assets/stylesheets/barkest_core/datepicker3.css +790 -0
  25. data/app/controllers/.keep +0 -0
  26. data/app/controllers/access_groups_controller.rb +74 -0
  27. data/app/controllers/account_activations_controller.rb +29 -0
  28. data/app/controllers/application_controller.rb +5 -0
  29. data/app/controllers/barkest_core/application_controller_base.rb +113 -0
  30. data/app/controllers/barkest_core/engine_controller_base.rb +15 -0
  31. data/app/controllers/barkest_core/testsub_controller.rb +21 -0
  32. data/app/controllers/contact_controller.rb +32 -0
  33. data/app/controllers/log_view_controller.rb +31 -0
  34. data/app/controllers/password_resets_controller.rb +126 -0
  35. data/app/controllers/sessions_controller.rb +64 -0
  36. data/app/controllers/status_controller.rb +150 -0
  37. data/app/controllers/system_config_controller.rb +238 -0
  38. data/app/controllers/system_update_controller.rb +164 -0
  39. data/app/controllers/test_access_controller.rb +44 -0
  40. data/app/controllers/test_report_controller.rb +75 -0
  41. data/app/controllers/users_controller.rb +218 -0
  42. data/app/helpers/.keep +0 -0
  43. data/app/helpers/barkest_core/application_helper.rb +134 -0
  44. data/app/helpers/barkest_core/form_helper.rb +469 -0
  45. data/app/helpers/barkest_core/html_helper.rb +70 -0
  46. data/app/helpers/barkest_core/misc_helper.rb +68 -0
  47. data/app/helpers/barkest_core/pdf_helper.rb +180 -0
  48. data/app/helpers/barkest_core/recaptcha_helper.rb +115 -0
  49. data/app/helpers/barkest_core/sessions_helper.rb +94 -0
  50. data/app/helpers/barkest_core/status_helper.rb +118 -0
  51. data/app/helpers/barkest_core/users_helper.rb +32 -0
  52. data/app/mailers/.keep +0 -0
  53. data/app/mailers/application_mailer.rb +5 -0
  54. data/app/mailers/barkest_core/application_mailer_base.rb +30 -0
  55. data/app/mailers/barkest_core/contact_form.rb +20 -0
  56. data/app/mailers/barkest_core/user_mailer.rb +44 -0
  57. data/app/models/.keep +0 -0
  58. data/app/models/access_group.rb +121 -0
  59. data/app/models/access_group_group_member.rb +13 -0
  60. data/app/models/access_group_user_member.rb +11 -0
  61. data/app/models/barkest_core/auth_config.rb +95 -0
  62. data/app/models/barkest_core/authorize_failure.rb +7 -0
  63. data/app/models/barkest_core/contact_message.rb +37 -0
  64. data/app/models/barkest_core/database_config.rb +223 -0
  65. data/app/models/barkest_core/db_table.rb +21 -0
  66. data/app/models/barkest_core/email_config.rb +132 -0
  67. data/app/models/barkest_core/global_status.rb +267 -0
  68. data/app/models/barkest_core/log_entry.rb +101 -0
  69. data/app/models/barkest_core/log_view_options.rb +51 -0
  70. data/app/models/barkest_core/ms_sql_db_definition.rb +441 -0
  71. data/app/models/barkest_core/ms_sql_definition.rb +221 -0
  72. data/app/models/barkest_core/ms_sql_function.rb +423 -0
  73. data/app/models/barkest_core/not_logged_in.rb +7 -0
  74. data/app/models/barkest_core/pdf_table_builder.rb +407 -0
  75. data/app/models/barkest_core/self_update_config.rb +37 -0
  76. data/app/models/barkest_core/user_alert.rb +29 -0
  77. data/app/models/barkest_core/user_alert_generators.rb +58 -0
  78. data/app/models/barkest_core/user_manager.rb +404 -0
  79. data/app/models/barkest_core/work_path.rb +74 -0
  80. data/app/models/disable_user.rb +18 -0
  81. data/app/models/ldap_access_group.rb +15 -0
  82. data/app/models/system_config.rb +99 -0
  83. data/app/models/user.rb +405 -0
  84. data/app/models/user_login_history.rb +11 -0
  85. data/app/views/.keep +0 -0
  86. data/app/views/access_groups/_form.html.erb +19 -0
  87. data/app/views/access_groups/edit.html.erb +2 -0
  88. data/app/views/access_groups/index.html.erb +32 -0
  89. data/app/views/access_groups/new.html.erb +2 -0
  90. data/app/views/access_groups/show.html.erb +4 -0
  91. data/app/views/barkest_core/contact_form/contact.html.erb +16 -0
  92. data/app/views/barkest_core/contact_form/contact.text.erb +13 -0
  93. data/app/views/barkest_core/testsub/_links.html.erb +5 -0
  94. data/app/views/barkest_core/testsub/page1.html.erb +3 -0
  95. data/app/views/barkest_core/testsub/page2.html.erb +2 -0
  96. data/app/views/barkest_core/testsub/page3.html.erb +2 -0
  97. data/app/views/barkest_core/user_mailer/account_activation.html.erb +7 -0
  98. data/app/views/barkest_core/user_mailer/account_activation.text.erb +6 -0
  99. data/app/views/barkest_core/user_mailer/invalid_password_reset.html.erb +3 -0
  100. data/app/views/barkest_core/user_mailer/invalid_password_reset.text.erb +5 -0
  101. data/app/views/barkest_core/user_mailer/password_reset.html.erb +8 -0
  102. data/app/views/barkest_core/user_mailer/password_reset.text.erb +7 -0
  103. data/app/views/contact/index.html.erb +24 -0
  104. data/app/views/layouts/_footer_copyright.html.erb +1 -0
  105. data/app/views/layouts/_menu_admin.html.erb +5 -0
  106. data/app/views/layouts/_menu_anon.html.erb +0 -0
  107. data/app/views/layouts/_menu_auth.html.erb +3 -0
  108. data/app/views/layouts/_menu_footer.html.erb +1 -0
  109. data/app/views/layouts/_nav_logo.html.erb +1 -0
  110. data/app/views/layouts/application.html.erb +2 -0
  111. data/app/views/layouts/barkest_core/_application.html.erb +24 -0
  112. data/app/views/layouts/barkest_core/_footer.html.erb +18 -0
  113. data/app/views/layouts/barkest_core/_header.html.erb +38 -0
  114. data/app/views/layouts/barkest_core/_html_mailer.html.erb +11 -0
  115. data/app/views/layouts/barkest_core/_menu_account.html.erb +14 -0
  116. data/app/views/layouts/barkest_core/_menu_sample.html.erb +1 -0
  117. data/app/views/layouts/barkest_core/_messages.html.erb +4 -0
  118. data/app/views/layouts/barkest_core/_shim.html.erb +4 -0
  119. data/app/views/layouts/barkest_core/_subheader.html.erb +1 -0
  120. data/app/views/layouts/barkest_core/_text_mailer.text.erb +4 -0
  121. data/app/views/layouts/mailer.html.erb +1 -0
  122. data/app/views/layouts/mailer.text.erb +1 -0
  123. data/app/views/log_view/index.html.erb +100 -0
  124. data/app/views/password_resets/edit.html.erb +20 -0
  125. data/app/views/password_resets/new.html.erb +14 -0
  126. data/app/views/sessions/new.html.erb +27 -0
  127. data/app/views/shared/_error_messages.html.erb +29 -0
  128. data/app/views/shared/_generic_user_alert.html.erb +4 -0
  129. data/app/views/status/current.html.erb +34 -0
  130. data/app/views/status/test.html.erb +50 -0
  131. data/app/views/system_config/index.html.erb +25 -0
  132. data/app/views/system_config/show_auth.html.erb +28 -0
  133. data/app/views/system_config/show_database.html.erb +36 -0
  134. data/app/views/system_config/show_email.html.erb +21 -0
  135. data/app/views/system_config/show_self_update.html.erb +13 -0
  136. data/app/views/system_update/index.html.erb +31 -0
  137. data/app/views/system_update/new.html.erb +2 -0
  138. data/app/views/test_access/allow_anon.html.erb +2 -0
  139. data/app/views/test_access/require_admin.html.erb +2 -0
  140. data/app/views/test_access/require_group_x.html.erb +2 -0
  141. data/app/views/test_access/require_user.html.erb +2 -0
  142. data/app/views/test_report/index.csv.csvrb +23 -0
  143. data/app/views/test_report/index.html.erb +6 -0
  144. data/app/views/test_report/index.pdf.prawn +50 -0
  145. data/app/views/test_report/index.xlsx.axlsx +28 -0
  146. data/app/views/users/_user.html.erb +57 -0
  147. data/app/views/users/_user_details.html.erb +15 -0
  148. data/app/views/users/_user_details_for_list.html.erb +1 -0
  149. data/app/views/users/_user_form.html.erb +13 -0
  150. data/app/views/users/disable_confirm.html.erb +19 -0
  151. data/app/views/users/edit.html.erb +15 -0
  152. data/app/views/users/index.html.erb +9 -0
  153. data/app/views/users/new.html.erb +10 -0
  154. data/app/views/users/show.html.erb +46 -0
  155. data/bin/rails +12 -0
  156. data/config/routes.rb +3 -0
  157. data/db/migrate/20160617172539_create_access_groups.rb +10 -0
  158. data/db/migrate/20160617172725_create_users.rb +26 -0
  159. data/db/migrate/20160617172833_create_user_login_histories.rb +12 -0
  160. data/db/migrate/20160622151720_create_access_group_user_members.rb +9 -0
  161. data/db/migrate/20160622151925_create_access_group_group_members.rb +9 -0
  162. data/db/migrate/20160701005706_create_ldap_access_groups.rb +11 -0
  163. data/db/migrate/20161108155029_create_system_configs.rb +11 -0
  164. data/db/seeds/barkest_core_01_create_users.rb +42 -0
  165. data/db/seeds.rb +53 -0
  166. data/lib/barkest_core/concerns/association_with_defaults.rb +55 -0
  167. data/lib/barkest_core/concerns/boolean_parser.rb +88 -0
  168. data/lib/barkest_core/concerns/date_parser.rb +181 -0
  169. data/lib/barkest_core/concerns/email_tester.rb +55 -0
  170. data/lib/barkest_core/concerns/encrypted_fields.rb +156 -0
  171. data/lib/barkest_core/concerns/named_model.rb +73 -0
  172. data/lib/barkest_core/concerns/number_parser.rb +145 -0
  173. data/lib/barkest_core/concerns/utc_conversion.rb +60 -0
  174. data/lib/barkest_core/engine.rb +105 -0
  175. data/lib/barkest_core/extensions/active_record_extensions.rb +120 -0
  176. data/lib/barkest_core/extensions/application_configuration_extensions.rb +38 -0
  177. data/lib/barkest_core/extensions/application_extensions.rb +50 -0
  178. data/lib/barkest_core/extensions/axlsx_extenstions.rb +157 -0
  179. data/lib/barkest_core/extensions/fixture_set_extensions.rb +107 -0
  180. data/lib/barkest_core/extensions/generator_extensions.rb +271 -0
  181. data/lib/barkest_core/extensions/main_app_extensions.rb +35 -0
  182. data/lib/barkest_core/extensions/prawn_document_extensions.rb +367 -0
  183. data/lib/barkest_core/extensions/prawn_table_extensions.rb +131 -0
  184. data/lib/barkest_core/extensions/router_extensions.rb +106 -0
  185. data/lib/barkest_core/extensions/simple_formatter_extensions.rb +66 -0
  186. data/lib/barkest_core/extensions/test_case_extensions.rb +348 -0
  187. data/lib/barkest_core/extensions/time_extensions.rb +164 -0
  188. data/lib/barkest_core/handlers/csv_handler.rb +30 -0
  189. data/lib/barkest_core/version.rb +3 -0
  190. data/lib/barkest_core.rb +324 -0
  191. data/lib/generators/barkest/install_generator.rb +102 -0
  192. data/lib/generators/barkest_core/actions/01_patch_application_controller.rb +55 -0
  193. data/lib/generators/barkest_core/actions/02_patch_application_mailer.rb +56 -0
  194. data/lib/generators/barkest_core/actions/03_patch_assets.rb +62 -0
  195. data/lib/generators/barkest_core/actions/04_patch_layouts.rb +36 -0
  196. data/lib/generators/barkest_core/actions/05_patch_routes.rb +93 -0
  197. data/lib/generators/barkest_core/actions/06_patch_seeds.rb +60 -0
  198. data/lib/generators/barkest_core/actions/07_copy_migrations.rb +51 -0
  199. data/lib/generators/barkest_core/actions/08_configure_database.rb +52 -0
  200. data/lib/generators/barkest_core/actions/09_configure_secrets.rb +29 -0
  201. data/lib/generators/barkest_core/actions/99_patch_gitignore.rb +57 -0
  202. data/lib/generators/barkest_core/install_generator.rb +17 -0
  203. data/test/barkest_core_test.rb +83 -0
  204. data/test/controllers/access_groups_controller_test.rb +53 -0
  205. data/test/controllers/contact_controller_test.rb +10 -0
  206. data/test/controllers/sessions_controller_test.rb +10 -0
  207. data/test/controllers/users_controller_test.rb +10 -0
  208. data/test/dummy/.gitignore +10 -0
  209. data/test/dummy/README.rdoc +28 -0
  210. data/test/dummy/Rakefile +6 -0
  211. data/test/dummy/app/assets/images/.keep +0 -0
  212. data/test/dummy/app/assets/javascripts/application.js +14 -0
  213. data/test/dummy/app/assets/stylesheets/application.css +16 -0
  214. data/test/dummy/app/controllers/application_controller.rb +5 -0
  215. data/test/dummy/app/controllers/concerns/.keep +0 -0
  216. data/test/dummy/app/helpers/application_helper.rb +2 -0
  217. data/test/dummy/app/mailers/.keep +0 -0
  218. data/test/dummy/app/mailers/application_mailer.rb +3 -0
  219. data/test/dummy/app/models/.keep +0 -0
  220. data/test/dummy/app/models/concerns/.keep +0 -0
  221. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  222. data/test/dummy/app/views/layouts/mailer.html.erb +1 -0
  223. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  224. data/test/dummy/app/views/system_config/show_fake.html.erb +3 -0
  225. data/test/dummy/bin/bundle +3 -0
  226. data/test/dummy/bin/rails +4 -0
  227. data/test/dummy/bin/rake +4 -0
  228. data/test/dummy/bin/setup +29 -0
  229. data/test/dummy/config/application.rb +27 -0
  230. data/test/dummy/config/boot.rb +5 -0
  231. data/test/dummy/config/environment.rb +5 -0
  232. data/test/dummy/config/environments/development.rb +47 -0
  233. data/test/dummy/config/environments/production.rb +79 -0
  234. data/test/dummy/config/environments/test.rb +44 -0
  235. data/test/dummy/config/initializers/assets.rb +11 -0
  236. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  237. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  238. data/test/dummy/config/initializers/db_updater_ext.rb +33 -0
  239. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  240. data/test/dummy/config/initializers/inflections.rb +16 -0
  241. data/test/dummy/config/initializers/mime_types.rb +4 -0
  242. data/test/dummy/config/initializers/session_store.rb +3 -0
  243. data/test/dummy/config/initializers/sys_config_ext.rb +12 -0
  244. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  245. data/test/dummy/config/locales/en.yml +23 -0
  246. data/test/dummy/config/routes.rb +60 -0
  247. data/test/dummy/config.ru +4 -0
  248. data/test/dummy/db/schema.rb +95 -0
  249. data/test/dummy/db/seeds/barkest_core_01_create_users.rb +42 -0
  250. data/test/dummy/db/seeds.rb +51 -0
  251. data/test/dummy/lib/assets/.keep +0 -0
  252. data/test/dummy/log/.keep +0 -0
  253. data/test/dummy/public/404.html +67 -0
  254. data/test/dummy/public/422.html +67 -0
  255. data/test/dummy/public/500.html +66 -0
  256. data/test/dummy/public/favicon.ico +0 -0
  257. data/test/dummy/sql/my_test_view.sql +3 -0
  258. data/test/fixtures/access_groups.yml +21 -0
  259. data/test/fixtures/users.yml +71 -0
  260. data/test/helpers/barkest_core/sessions_helper_test.rb +22 -0
  261. data/test/integration/access_group_mgmt_test.rb +33 -0
  262. data/test/integration/access_test.rb +24 -0
  263. data/test/integration/account_activations_access_test.rb +12 -0
  264. data/test/integration/contact_test.rb +98 -0
  265. data/test/integration/extra_partial_test.rb +41 -0
  266. data/test/integration/log_view_access_test.rb +12 -0
  267. data/test/integration/password_resets_test.rb +101 -0
  268. data/test/integration/reports_test.rb +53 -0
  269. data/test/integration/status_access_test.rb +27 -0
  270. data/test/integration/system_config_access_test.rb +24 -0
  271. data/test/integration/system_update_access_test.rb +19 -0
  272. data/test/integration/users_access_test.rb +34 -0
  273. data/test/integration/users_edit_test.rb +178 -0
  274. data/test/integration/users_index_test.rb +62 -0
  275. data/test/integration/users_login_test.rb +67 -0
  276. data/test/integration/users_signup_test.rb +54 -0
  277. data/test/mailers/.keep +0 -0
  278. data/test/mailers/barkest_core/contact_form_test.rb +28 -0
  279. data/test/mailers/barkest_core/user_mailer_test.rb +43 -0
  280. data/test/mailers/previews/barkest_core/contact_form_preview.rb +17 -0
  281. data/test/mailers/previews/barkest_core/user_mailer_preview.rb +26 -0
  282. data/test/models/access_group_group_member_test.rb +28 -0
  283. data/test/models/access_group_test.rb +114 -0
  284. data/test/models/access_group_user_member_test.rb +28 -0
  285. data/test/models/barkest_core/auth_config_test.rb +57 -0
  286. data/test/models/barkest_core/bool_parser_test.rb +28 -0
  287. data/test/models/barkest_core/contact_message_test.rb +61 -0
  288. data/test/models/barkest_core/database_config_test.rb +33 -0
  289. data/test/models/barkest_core/date_parser_test.rb +110 -0
  290. data/test/models/barkest_core/email_config_test.rb +57 -0
  291. data/test/models/barkest_core/global_status_test.rb +50 -0
  292. data/test/models/barkest_core/ms_sql_db_updater_test.rb +115 -0
  293. data/test/models/barkest_core/ms_sql_definition_test.rb +102 -0
  294. data/test/models/barkest_core/ms_sql_function_test.rb +131 -0
  295. data/test/models/barkest_core/number_parser_test.rb +29 -0
  296. data/test/models/barkest_core/self_update_config_test.rb +29 -0
  297. data/test/models/barkest_core/user_alert_test.rb +19 -0
  298. data/test/models/barkest_core/user_manager_test.rb +34 -0
  299. data/test/models/barkest_core/work_path_test.rb +26 -0
  300. data/test/models/disable_user_test.rb +27 -0
  301. data/test/models/generic_time_test.rb +66 -0
  302. data/test/models/ldap_access_group_test.rb +31 -0
  303. data/test/models/pdf_table_builder_test.rb +6 -0
  304. data/test/models/system_config_test.rb +78 -0
  305. data/test/models/user_login_history_test.rb +37 -0
  306. data/test/models/user_test.rb +130 -0
  307. data/test/test_helper.rb +63 -0
  308. metadata +798 -0
@@ -0,0 +1,74 @@
1
+ require 'tmpdir'
2
+
3
+ module BarkestCore
4
+ ##
5
+ # This class simply locates a temporary working directory for the application.
6
+ #
7
+ # By default we shoot for shared memory such as /run/shm or /dev/shm. If those
8
+ # fail, we look to /tmp.
9
+ #
10
+ class WorkPath
11
+
12
+ ##
13
+ # Gets the temporary working directory location for the application.
14
+ #
15
+ def self.location
16
+ @location ||=
17
+ begin
18
+ retval = nil
19
+ %w(/run/shm /var/run/shm /dev/shm /tmp).each do |root|
20
+ if Dir.exist?(root)
21
+ retval = try_path(root)
22
+ break if retval
23
+ end
24
+ end
25
+ retval || try_path(Dir.tmpdir)
26
+ end
27
+ end
28
+
29
+ ##
30
+ # Gets a path for a specific temporary file.
31
+ #
32
+ def self.path_for(filename)
33
+ raise StandardError.new('Cannot determine location.') unless location
34
+ location + '/' + filename
35
+ end
36
+
37
+ ##
38
+ # Gets the path to the system status file.
39
+ #
40
+ # This file is used by long running processes to log their progress.
41
+ #
42
+ def self.system_status_file
43
+ @system_status_file ||= path_for('system_status')
44
+ end
45
+
46
+ private
47
+
48
+ def self.app_name
49
+ @app_name ||=
50
+ if Rails.application.respond_to?(:app_name)
51
+ Rails.application.app_name.underscore
52
+ else
53
+ Rails.application.class.name.underscore
54
+ end.gsub('/','-')
55
+ end
56
+
57
+ def self.try_path(path)
58
+ return nil if path.blank?
59
+ path = path.gsub('\\', '/')
60
+ path = path[0...-1] if path[-1] == '/'
61
+ path += '/barkest_' + app_name
62
+ return nil unless (Dir.exist?(path) || Dir.mkdir(path))
63
+ begin
64
+ test_file = path + '/test.file'
65
+ File.write(test_file, app_name)
66
+ File.delete(test_file)
67
+ rescue
68
+ return nil
69
+ end
70
+ path
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,18 @@
1
+ ##
2
+ # This model is used to disable a user with a reason for the disabling.
3
+ class DisableUser
4
+ include ActiveModel::Model
5
+ include ActiveModel::Validations
6
+
7
+ attr_accessor :reason, :user
8
+
9
+ validates :reason, presence: true
10
+ validate do
11
+ if user && user.is_a?(User)
12
+ errors.add(:user, 'must be enabled') unless user.enabled?
13
+ else
14
+ errors.add(:user, 'must be provided')
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,15 @@
1
+ ##
2
+ # Defines an LDAP group that belongs to an Access Group.
3
+ class LdapAccessGroup < ::BarkestCore::DbTable
4
+
5
+ belongs_to :group, class_name: 'AccessGroup'
6
+
7
+ validates :group,
8
+ presence: true
9
+
10
+ validates :name,
11
+ presence: true,
12
+ length: { maximum: 200 },
13
+ uniqueness: { case_sensitive: false, scope: :group_id }
14
+
15
+ end
@@ -0,0 +1,99 @@
1
+ require 'encrypted_strings'
2
+
3
+ ##
4
+ # Defines a mechanism to store and retrieve configurations using the core database.
5
+ #
6
+ # The +get+ and +set+ methods allow values to be stored in an encrypted fashion as well.
7
+ #
8
+ # The encryption will use the +encrypted_config_key+ value or the +secret_key_base+ value from
9
+ # +secrets.yml+. Ideally, use +encrypted_config_key+ to allow +secret_key_base+ to change if
10
+ # necessary.
11
+ class SystemConfig < ::BarkestCore::DbTable
12
+
13
+ validates :key,
14
+ presence: true,
15
+ length: { maximum: 128 },
16
+ uniqueness: { case_sensitive: false }
17
+
18
+ before_save :downcase_key
19
+
20
+ ##
21
+ # Sets the value storing it as a YAML string.
22
+ def value=(new_value)
23
+ val = new_value.nil? ? nil : new_value.to_yaml
24
+ write_attribute :value, val
25
+ end
26
+
27
+ ##
28
+ # Gets the value loading it from a YAML string.
29
+ def value
30
+ val = read_attribute(:value).to_s
31
+ return nil if val.empty?
32
+ YAML.load val
33
+ end
34
+
35
+ ##
36
+ # Gets a value from the database.
37
+ #
38
+ # If the value was stored encrypted, it will be decrypted before being returned.
39
+ #
40
+ # As a feature during testing +config/key_name.yml+ will be used if it exists and the database
41
+ # value is missing.
42
+ #
43
+ def self.get(key_name)
44
+ begin
45
+ record = where(key: key_name.to_s.downcase).first
46
+
47
+ if record
48
+ value = record.value
49
+ if value.is_a?(Hash) && value.keys.include?(:encrypted_value)
50
+ value = value[:encrypted_value]
51
+ unless value.nil? || value == ''
52
+ value = YAML.load(crypto_cipher.decrypt(value)) rescue nil
53
+ end
54
+ end
55
+ elsif Rails.env.test?
56
+ yml_file = "#{BarkestCore.app_root}/config/#{key_name}.yml"
57
+ value = File.exist?(yml_file) ? YAML.load_file(yml_file) : nil
58
+ else
59
+ value = nil
60
+ end
61
+
62
+ value
63
+ rescue
64
+ nil # if 'system_configs' table has not been created, return nil.
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Stores a value to the database.
70
+ #
71
+ # All values are converted into YAML strings before storage.
72
+ #
73
+ # If +encrypt+ is set to true, then the value will be encrypted before being stored.
74
+ def self.set(key_name, value, encrypt = false)
75
+ key_name = key_name.to_s.downcase
76
+ if encrypt
77
+ value = crypto_cipher.encrypt(value.to_yaml) unless value.nil? || value == ''
78
+ value = { encrypted_value: value }
79
+ end
80
+ record = find_or_initialize_by(key: key_name)
81
+ record.value = value
82
+ record.save
83
+ end
84
+
85
+ private
86
+
87
+ def self.crypto_password
88
+ @crypto_password ||= Rails.application.secrets[:encrypted_config_key] || Rails.application.secrets[:secret_key_base]
89
+ end
90
+
91
+ def self.crypto_cipher
92
+ @crypto_cipher ||= EncryptedStrings::SymmetricCipher.new(password: crypto_password)
93
+ end
94
+
95
+ def downcase_key
96
+ key.downcase!
97
+ end
98
+
99
+ end
@@ -0,0 +1,405 @@
1
+ ##
2
+ # The user class defines the individual users in the application.
3
+ #
4
+ # Each user can login with their email address, if the domain portion of their
5
+ # email address happens to match an LdapSource, then that LdapSource will be
6
+ # used to authenticate them, otherwise the +password_digest+ stored in the
7
+ # database will be used to authenticate them.
8
+ class User < ::BarkestCore::DbTable
9
+
10
+ ANONYMOUS_EMAIL = 'anonymous@local.server'
11
+
12
+ UNIQUE_STRING_FIELD = :email
13
+ include BarkestCore::NamedModel
14
+ include BarkestCore::EmailTester
15
+
16
+ has_many :access_group_user_members, class_name: 'AccessGroupUserMember', foreign_key: 'member_id'
17
+ private :access_group_user_members, :access_group_user_members=
18
+
19
+ has_many :groups, class_name: 'AccessGroup', through: :access_group_user_members
20
+
21
+ has_many :login_histories, :class_name => 'UserLoginHistory'
22
+
23
+ belongs_to :disabled_by, class_name: 'User'
24
+
25
+ before_save :downcase_email
26
+ before_create :create_activation_digest
27
+
28
+ ##
29
+ # Gets the temporary token used to remember this user.
30
+ attr_accessor :remember_token
31
+
32
+ ##
33
+ # Gets the temporary token used to activate this user.
34
+ attr_accessor :activation_token
35
+
36
+ ##
37
+ # Gets the temporary token used to reset this user's password.
38
+ attr_accessor :reset_token
39
+
40
+ has_secure_password
41
+
42
+ validates :name,
43
+ presence: true,
44
+ length: { maximum: 100 }
45
+
46
+ validates :email,
47
+ presence: true,
48
+ length: { maximum: 255 },
49
+ uniqueness: { case_sensitive: false },
50
+ format: { with: VALID_EMAIL_REGEX }
51
+
52
+ validates :disabled_reason,
53
+ length: { maximum: 200 }
54
+
55
+ validates :last_ip,
56
+ length: { maximum: 64 }
57
+
58
+ validates :password,
59
+ presence: true,
60
+ length: { minimum: 6 },
61
+ allow_nil: true
62
+
63
+
64
+ ##
65
+ # Gets the email address in a partially obfuscated fashion.
66
+ def partial_email
67
+ uid,_,domain = email.partition('@')
68
+ if uid.length < 4
69
+ uid = '*' * uid.length
70
+ elsif uid.length < 8
71
+ uid = uid[0..2] + ('*' * (uid.length - 3))
72
+ else
73
+ uid = uid[0..2] + ('*' * (uid.length - 6)) + uid[-3..-1]
74
+ end
75
+ "#{uid}@#{domain}"
76
+ end
77
+
78
+ ##
79
+ # Is the user a system administrator?
80
+ def system_admin?
81
+ enabled && system_admin
82
+ end
83
+
84
+ ##
85
+ # Gets the effective group membership of this user.
86
+ def effective_groups(refresh = false)
87
+ @effective_groups = nil if refresh
88
+ @effective_groups ||= if system_admin?
89
+ AccessGroup.all.map{ |g| g.to_s.upcase }
90
+ else
91
+ groups
92
+ .collect{ |g| g.effective_groups }
93
+ .flatten
94
+ .inject([]){ |memo,item| memo << item unless memo.include?(item); memo }
95
+ end
96
+ .map{ |g| g.to_s.upcase }
97
+ .sort
98
+ end
99
+
100
+ ##
101
+ # Does this user have the equivalent of one or more of these groups?
102
+ def has_any_group?(*group_list)
103
+ return true if system_admin?
104
+
105
+ group_list.each do |group|
106
+ group = group.to_s.upcase
107
+ return true if effective_groups.include?(group)
108
+ end
109
+
110
+ false
111
+ end
112
+
113
+ ##
114
+ # Generates a remember token and saves the digest to the user model.
115
+ def remember
116
+ self.remember_token = User.new_token
117
+ update_attribute(:remember_digest, User.digest(self.remember_token))
118
+ end
119
+
120
+ ##
121
+ # Removes the remember digest from the user model.
122
+ def forget
123
+ update_attribute(:remember_digest, nil)
124
+ end
125
+
126
+ ##
127
+ # Determines if the supplied token digests to the stored digest in the user model.
128
+ def authenticated?(attribute, token)
129
+ return false unless respond_to?("#{attribute}_digest")
130
+ digest = send("#{attribute}_digest")
131
+ return false if digest.blank?
132
+ BCrypt::Password.new(digest).is_password?(token)
133
+ end
134
+
135
+ ##
136
+ # Disables the user.
137
+ #
138
+ # The +other_user+ is required, cannot be the current user, and must be a system administrator.
139
+ # The +reason+ is technically optional, but should be provided.
140
+ def disable(other_user, reason)
141
+ return false unless other_user && other_user.system_admin?
142
+ return false if other_user == self
143
+
144
+ update_columns(
145
+ disabled_by_id: other_user.id,
146
+ disabled_at: Time.zone.now,
147
+ disabled_reason: reason,
148
+ enabled: false
149
+ )
150
+ end
151
+
152
+ ##
153
+ # Enables the user and removes any previous disable information.
154
+ def enable
155
+ update_columns(
156
+ disabled_by_id: nil,
157
+ disabled_at: nil,
158
+ disabled_reason: nil,
159
+ enabled: true
160
+ )
161
+ end
162
+
163
+
164
+ ##
165
+ # Marks the user as activated and removes the activation digest from the user model.
166
+ def activate
167
+ update_columns(
168
+ activated: true,
169
+ activated_at: Time.zone.now,
170
+ activation_digest: nil
171
+ )
172
+ end
173
+
174
+ ##
175
+ # Sends the activation email to the user.
176
+ def send_activation_email(client_ip = '0.0.0.0')
177
+ BarkestCore::UserMailer.account_activation(user: self, client_ip: client_ip).deliver_now
178
+ end
179
+
180
+ ##
181
+ # Creates a reset token and stores the digest to the user model.
182
+ def create_reset_digest
183
+ self.reset_token = User.new_token
184
+ update_columns(
185
+ reset_digest: User.digest(reset_token),
186
+ reset_sent_at: Time.zone.now
187
+ )
188
+ end
189
+
190
+ ##
191
+ # Was the password reset requested more than 2 hours ago?
192
+ def password_reset_expired?
193
+ reset_sent_at.nil? || reset_sent_at < 2.hours.ago
194
+ end
195
+
196
+ ##
197
+ # Is this the anonymous user?
198
+ def anonymous?
199
+ email == ANONYMOUS_EMAIL
200
+ end
201
+
202
+ ##
203
+ # Gets the last successful login for this user.
204
+ def last_successful_login
205
+ @last_successful_login ||= login_histories.where(successful: true).order(created_at: :desc).first
206
+ end
207
+
208
+ ##
209
+ # Gets the last failed login for this user.
210
+ def last_failed_login
211
+ @last_failed_login ||= login_histories.where.not(successful: true).order(created_at: :desc).first
212
+ end
213
+
214
+ ##
215
+ # Gets the failed logins for a user since the last successful login.
216
+ def failed_login_streak
217
+ @failed_login_streak ||=
218
+ begin
219
+ results = login_histories.where.not(successful: true)
220
+ if last_successful_login
221
+ results = results.where('created_at > ?', last_successful_login.created_at)
222
+ end
223
+ results.order(created_at: :desc)
224
+ end
225
+ end
226
+
227
+ def settings(reload = false)
228
+ @settings = nil if reload
229
+ @settings ||=
230
+ begin
231
+ h = SystemConfig.get("user_#{id}") || {}
232
+ h.instance_variable_set :@user_id, id
233
+
234
+ def h.save
235
+ SystemConfig.set "user_#{@user_id}", self
236
+ end
237
+
238
+ def h.method_missing(m,*a,&b)
239
+ x = (/^([A-Z][A-Z0-9_]*)(=)?$/i).match(m.to_s)
240
+ if x
241
+ key = x[1].to_sym
242
+ if x[2] == '='
243
+ val = a ? a.first : nil
244
+ self[key] = val
245
+ return val
246
+ else
247
+ return self[key]
248
+ end
249
+ end
250
+ super m, *a, &b
251
+ end
252
+
253
+ def h.[](key)
254
+ super key.to_sym
255
+ end
256
+
257
+ def h.[]=(key, value)
258
+ super key.to_sym, value
259
+ end
260
+
261
+ h
262
+ end
263
+ end
264
+
265
+ ##
266
+ # Sends the password reset email to the user.
267
+ def send_password_reset_email(client_ip = '0.0.0.0')
268
+ BarkestCore::UserMailer.password_reset(user: self, client_ip: client_ip).deliver_now
269
+ end
270
+
271
+ ##
272
+ # Sends a missing account message when a user requests a password reset.
273
+ def self.send_missing_reset_email(email, client_ip = '0.0.0.0')
274
+ BarkestCore::UserMailer::invalid_password_reset(email: email, client_ip: client_ip).deliver_now
275
+ end
276
+
277
+ ##
278
+ # Sends a disabled account message when a user requests a password reset.
279
+ def self.send_disabled_reset_email(email, client_ip = '0.0.0.0')
280
+ BarkestCore::UserMailer::invalid_password_reset(email: email, message: 'The account attached to this email address has been disabled.', client_ip: client_ip).deliver_now
281
+ end
282
+
283
+ ##
284
+ # Sends a non-activated account message when a user requests a password reset.
285
+ def self.send_inactive_reset_email(email, client_ip = '0.0.0.0')
286
+ BarkestCore::UserMailer::invalid_password_reset(email: email, message: 'The account attached to this email has not yet been activated.', client_ip: client_ip).deliver_now
287
+ end
288
+
289
+ ##
290
+ # Sends a message informing the user we cannot change LDAP passwords.
291
+ def self.send_ldap_reset_email(email, client_ip = '0.0.0.0')
292
+ BarkestCore::UserMailer::invalid_password_reset(email: email, message: 'The account attached to this email is an LDAP account. This application cannot change passwords on an LDAP account.', client_ip: client_ip).deliver_now
293
+ end
294
+
295
+ ##
296
+ # Returns a hash digest of the given string.
297
+ def self.digest(string)
298
+ cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
299
+ BCrypt::Password.create(string, cost: cost)
300
+ end
301
+
302
+ ##
303
+ # Generates a new random token in (url safe) base64.
304
+ def self.new_token
305
+ SecureRandom.urlsafe_base64(32)
306
+ end
307
+
308
+ ##
309
+ # Gets all known users.
310
+ def self.known
311
+ where.not(email: ANONYMOUS_EMAIL)
312
+ end
313
+
314
+ ##
315
+ # Gets all of the currently enabled users.
316
+ def self.enabled
317
+ where(enabled: true, activated: true)
318
+ end
319
+
320
+ ##
321
+ # Sorts the users by name.
322
+ def self.sorted
323
+ order(name: :asc)
324
+ end
325
+
326
+ ##
327
+ # Generates the necessary system administrator account.
328
+ #
329
+ # When the database is initially seeded, the only user is the system administrator.
330
+ # The system administrator is **admin@barkerest.com** and the password is initially **Password1**.
331
+ # You should change this immediately once the app is running. You will most likely want to create
332
+ # a completely new admin account and disable the **admin@barkerest.com** account.
333
+ def self.ensure_admin_exists!
334
+ unless where(system_admin: true, enabled: true).count > 0
335
+
336
+ msg = "Creating/reactivating default administrator...\n"
337
+ if Rails.application.running?
338
+ Rails.logger.info msg
339
+ else
340
+ print msg
341
+ end
342
+
343
+ def_adm_email = 'admin@barkerest.com'
344
+ def_adm_pass = 'Password1'
345
+
346
+ user = User
347
+ .where(
348
+ email: def_adm_email
349
+ )
350
+ .first_or_create!(
351
+ name: 'Default Administrator',
352
+ email: def_adm_email,
353
+ password: def_adm_pass,
354
+ password_confirmation: def_adm_pass,
355
+ enabled: true,
356
+ system_admin: true,
357
+ activated: true,
358
+ activated_at: Time.zone.now
359
+ )
360
+
361
+ unless user.enabled? && user.system_admin?
362
+ user.password = def_adm_pass
363
+ user.password_confirmation = def_adm_pass
364
+ user.enabled = true
365
+ user.system_admin = true
366
+ user.activated = true
367
+ user.activated_at = Time.zone.now
368
+ user.save!
369
+ end
370
+ end
371
+ end
372
+
373
+ ##
374
+ # Gets a generic anonymous user.
375
+ def self.anonymous
376
+ @anonymous = nil if Rails.env.test?
377
+ @anonymous ||=
378
+ begin
379
+ pwd = new_token
380
+ where(email: ANONYMOUS_EMAIL)
381
+ .first_or_create(
382
+ email: ANONYMOUS_EMAIL,
383
+ name: 'Anonymous',
384
+ enabled: false,
385
+ activated: true,
386
+ activated_at: Time.zone.now,
387
+ password: pwd,
388
+ password_confirmation: pwd
389
+ )
390
+ end
391
+ end
392
+
393
+
394
+ private
395
+
396
+ def downcase_email
397
+ email.downcase!
398
+ end
399
+
400
+ def create_activation_digest
401
+ self.activation_token = User.new_token
402
+ self.activation_digest = User.digest(activation_token)
403
+ end
404
+
405
+ end