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,29 @@
1
+ module BarkestCore
2
+ ##
3
+ # This model provides informational alerts to the user.
4
+ class UserAlert
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :message, :model
9
+
10
+ validates :message, presence: true
11
+
12
+ def type
13
+ @type || :info
14
+ end
15
+
16
+ def type=(value)
17
+ @type = value ? value.to_s.to_sym : nil
18
+ end
19
+
20
+ def view
21
+ @view || 'generic_user_alert'
22
+ end
23
+
24
+ def view=(value)
25
+ @view = value.blank? ? nil : value.to_s
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,58 @@
1
+ module BarkestCore
2
+ ##
3
+ # A repository for user alert generators.
4
+ #
5
+ # Register any alert generators that you want to give the user automatically at login.
6
+ #
7
+ class UserAlertGenerators
8
+
9
+ ##
10
+ # Enumerates all of the generators that have been registered.
11
+ #
12
+ # Yields the +type+ and +generator+.
13
+ def self.each(&block)
14
+ return unless block_given?
15
+ list.each do |type,generators|
16
+ generators.each do |generator|
17
+ yield type, generator
18
+ end
19
+ end
20
+ end
21
+
22
+ ##
23
+ # Gets all of the generators that have been registered.
24
+ #
25
+ # This list does not include the type.
26
+ def self.all
27
+ list.values.flatten.freeze
28
+ end
29
+
30
+ ##
31
+ # Gets a subset of the generators that have been registered.
32
+ #
33
+ # Provide the type of generators you would like to return.
34
+ def self.[](type)
35
+ type ||= :info
36
+ type = type.to_sym
37
+ (list[type] || []).freeze
38
+ end
39
+
40
+ ##
41
+ # Registers an alert generator.
42
+ #
43
+ # The generator shold be designed to take a User model as an argument.
44
+ def self.register(type = nil, &block)
45
+ type ||= :info
46
+ type = type.to_sym
47
+ list[type] ||= []
48
+ list[type] << block
49
+ end
50
+
51
+ private
52
+
53
+ def self.list
54
+ @list ||= {}
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,404 @@
1
+ require 'net-ldap'
2
+
3
+ module BarkestCore
4
+ ##
5
+ # Handles login requests, group mapping, and password changing for both the DB and LDAP sources.
6
+ #
7
+ class UserManager
8
+
9
+ ##
10
+ # Creates a new user manager.
11
+ def initialize(options = {})
12
+ @options = (options || {}).symbolize_keys
13
+ if @options[:enable_ldap_auth]
14
+ @ldap = get_ldap_connection
15
+ raise ArgumentError.new('Failed to connect to LDAP host using supplied arguments.') unless @ldap.bind
16
+ end
17
+ @options[:enable_db_auth] = true unless @options[:enable_ldap_auth]
18
+ User.ensure_admin_exists!
19
+ end
20
+
21
+ ##
22
+ # Is this user manager using ldap?
23
+ def using_ldap?
24
+ @options[:enable_ldap_auth]
25
+ end
26
+
27
+ ##
28
+ # Is the user manager using ldap?
29
+ def self.using_ldap?
30
+ default.using_ldap?
31
+ end
32
+
33
+ ##
34
+ # Is this user manager using the db?
35
+ def using_db?
36
+ @options[:enable_db_auth]
37
+ end
38
+
39
+ ##
40
+ # Is the user manager using the db?
41
+ def self.using_db?
42
+ default.using_db?
43
+ end
44
+
45
+ ##
46
+ # Gets the first authentication source for this user manager.
47
+ def primary_source
48
+ return :ldap if using_ldap? && !using_db?
49
+ return :db if using_db? && !using_ldap?
50
+
51
+ source = @options[:primary_source]
52
+ source = source.to_sym if source.is_a?(String)
53
+
54
+ return source if [:ldap, :db].include?(source)
55
+
56
+ return :ldap if using_ldap?
57
+
58
+ :db
59
+ end
60
+
61
+ ##
62
+ # Gets the first authentication source for the user manager.
63
+ def self.primary_source
64
+ default.primary_source
65
+ end
66
+
67
+ ##
68
+ # Attempts to authenticate the user and returns the model on success.
69
+ def authenticate(email, password, client_ip)
70
+ return nil unless email && BarkestCore::EmailTester.valid_email?(email, false)
71
+
72
+ email = email.downcase
73
+
74
+ sources.each do |source|
75
+ if source == :ldap
76
+ entry = @ldap.search(filter: "(&(objectClass=user)(mail=#{email}))")
77
+ if entry && entry.count == 1 # we found a match.
78
+ user = User.find_by(email: email, ldap: true)
79
+
80
+ # make sure it authenticates correctly.
81
+ entry = @ldap.bind_as(filter: "(&(objectClass=user)(mail=#{email}))", password: password)
82
+
83
+ # do not allow authenticating against the DB now.
84
+ unless entry && entry.count == 1
85
+ add_failure_to user || email, '(LDAP) failed to authenticate', client_ip
86
+ return nil
87
+ end
88
+
89
+ # load the user and return.
90
+ user = load_ldap_user(entry.first, true, client_ip)
91
+ unless user.enabled?
92
+ add_failure_to user, '(LDAP) account disabled', client_ip
93
+ return nil
94
+ end
95
+ add_success_to user, '(LDAP)', client_ip
96
+ return user
97
+ end
98
+ else
99
+ user = User.find_by(email: email)
100
+ if user
101
+ # user must be enabled, cannot be LDAP, and the password must match.
102
+ if user.ldap?
103
+ add_failure_to user, '(DB) cannot authenticate LDAP user', client_ip
104
+ return nil
105
+ end
106
+ unless user.enabled?
107
+ add_failure_to user, '(DB) account disabled', client_ip
108
+ return nil
109
+ end
110
+ if user.authenticate(password)
111
+ add_success_to user, '(DB)', client_ip
112
+ return user
113
+ else
114
+ add_failure_to user, '(DB) invalid password', client_ip
115
+ return nil
116
+ end
117
+ end
118
+ end
119
+ end
120
+ add_failure_to email, 'invalid email', client_ip
121
+ nil
122
+ end
123
+
124
+ ##
125
+ # Attempts to authenticate the user and returns the model on success.
126
+ def self.authenticate(email, password, client_ip)
127
+ default.authenticate email, password, client_ip
128
+ end
129
+
130
+ ##
131
+ # Should valid ldap users be auto-activated on first login?
132
+ def auto_activate_ldap?
133
+ @options[:ldap_auto_activate]
134
+ end
135
+
136
+ ##
137
+ # Should valid ldap users be auto-activated on first login?
138
+ def self.auto_activate_ldap?
139
+ default.auto_activate_ldap?
140
+ end
141
+
142
+ ##
143
+ # Gets the list of ldap groups that map to system administrators.
144
+ def ldap_system_admin_groups
145
+ @ldap_system_admin_groups ||=
146
+ begin
147
+ val = @options[:ldap_system_admin_groups]
148
+ val.blank? ? [] : val.strip.gsub(',', ';').split(';').map{|v| v.strip.upcase}
149
+ end
150
+ end
151
+
152
+ ##
153
+ # Gets the list of ldap groups that map to system administrators.
154
+ def self.ldap_system_admin_groups
155
+ default.ldap_system_admin_groups
156
+ end
157
+
158
+ private
159
+
160
+ def purge_old_history_for(user, max_months = 2)
161
+ user.login_histories.where('"user_login_histories"."created_at" <= ?', Time.zone.now - max_months.months).delete_all
162
+ end
163
+
164
+ def add_failure_to(user, message, client_ip)
165
+ Rails.logger.info "LOGIN(#{user}) FAILURE FROM #{client_ip}: #{message}"
166
+ history_length = 2
167
+ unless user.is_a?(User)
168
+ message = "[email: #{user}] #{message}"
169
+ user = User.anonymous
170
+ history_length = 6
171
+ end
172
+ purge_old_history_for user, history_length
173
+ user.login_histories.create(ip_address: client_ip, successful: false, message: message)
174
+ end
175
+
176
+ def add_success_to(user, message, client_ip)
177
+ Rails.logger.debug "LOGIN(#{user}) SUCCESS FROM #{client_ip}: #{message}"
178
+ purge_old_history_for user
179
+ user.login_histories.create(ip_address: client_ip, successful: true, message: message)
180
+ end
181
+
182
+ def sources
183
+ @sources ||=
184
+ if using_ldap? && using_db?
185
+ if primary_source == :db
186
+ [ :db, :ldap ]
187
+ else
188
+ [ :ldap, :db ]
189
+ end
190
+ elsif using_ldap?
191
+ [ :ldap ]
192
+ else
193
+ [ :db ]
194
+ end
195
+ end
196
+
197
+ def self.default
198
+ @default ||= UserManager.new(BarkestCore.auth_config)
199
+ end
200
+
201
+ # Decode a binary SID into the common string form.
202
+ # Used on AD servers to locate the primary group membership.
203
+ # See http://blogs.msdn.com/b/oldnewthing/archive/2004/03/15/89753.aspx
204
+ def self.decode_sid(binary_sid)
205
+
206
+ # only support SID revision 1
207
+ return false unless binary_sid && binary_sid[0].ord == 1
208
+
209
+ ret = 'S-1-'
210
+
211
+ dashes_remaining = binary_sid[1].ord
212
+
213
+ # remove first 2 bytes and continue.
214
+ binary_sid = binary_sid[2..-1]
215
+
216
+ # first group is 48-bit big-endian.
217
+ i = 0
218
+ binary_sid[0..5].chars.each do |b|
219
+ i = (i * 256) + b.ord
220
+ end
221
+
222
+ ret <<= i.to_s
223
+
224
+ # remaining groups are 32-bit little-endian.
225
+ binary_sid = binary_sid[6..-1]
226
+ while dashes_remaining > 0
227
+ i = 0
228
+ binary_sid[0..3].reverse.chars.each do |b|
229
+ i = (i * 256) + b.ord
230
+ end
231
+ ret <<= "-#{i}"
232
+ dashes_remaining -= 1
233
+ binary_sid = binary_sid[4..-1]
234
+ end
235
+
236
+ ret
237
+ end
238
+
239
+
240
+ def get_ldap_connection
241
+ ldap = Net::LDAP.new(host: @options[:ldap_host], port: @options[:ldap_port], base: @options[:ldap_base_dn])
242
+ ssl = @options[:ldap_ssl]
243
+ ssl = ssl.to_s.downcase
244
+ ssl = true if ssl == 'true'
245
+ ssl = false if ssl == 'false' || ssl == '' || ssl == 'nil'
246
+ ssl = ssl.to_sym if ssl.is_a?(String)
247
+
248
+ if ssl
249
+ if ssl == :simple_tls
250
+ ldap.encryption method: :simple_tls
251
+ elsif ssl == :start_tls
252
+ ldap.encryption method: :start_tls
253
+ else
254
+ if @options[:ldap_port] == 389
255
+ ldap.encryption method: :start_tls
256
+ else
257
+ ldap.encryption method: :simple_tls
258
+ end
259
+ end
260
+ end
261
+
262
+ if @options[:ldap_browse_user]
263
+ ldap.authenticate @options[:ldap_browse_user], @options[:ldap_browse_password]
264
+ end
265
+
266
+ ldap
267
+ end
268
+
269
+ def attrib_val(entry, attr)
270
+ return nil unless entry.attribute_names.include?(attr)
271
+ val = entry[attr]
272
+ val = val.first if val && val.respond_to?(:first)
273
+ val
274
+ end
275
+
276
+ def first_attrib_val(entry, *attr)
277
+ attr.each do |a|
278
+ v = attrib_val(entry, a)
279
+ return v if v
280
+ end
281
+ nil
282
+ end
283
+
284
+ def group_to_groups(group_entry, existing_groups)
285
+ return [] unless group_entry
286
+
287
+ ret = []
288
+
289
+ # get the group name.
290
+
291
+ name = first_attrib_val(group_entry, :samaccountname, :name, :cn)
292
+
293
+ return [] unless name
294
+
295
+ name.upcase!
296
+
297
+ # do not duplicate entries. this will also prevent the possibility of infinite recursion.
298
+ unless existing_groups.index { |x| x == name } || ret.index { |x| x == name }
299
+
300
+ # add this group.
301
+ ret <<= name
302
+
303
+ # if the group belongs to parent groups, add them as well.
304
+ if group_entry[:memberof] && group_entry[:memberof].respond_to?('each')
305
+ group_entry[:memberof].each do |dn|
306
+ parent_entry = @ldap.search(base: dn).first
307
+ ret += group_to_groups(parent_entry, ret + existing_groups)
308
+ end
309
+ end
310
+ end
311
+
312
+ ret
313
+ end
314
+
315
+ def load_ldap_user(entry, update_permissions = false, client_ip = '0.0.0.0')
316
+
317
+ # email is our unique identifier
318
+ email = attrib_val(entry, :mail)
319
+ return nil unless email
320
+ email.downcase!
321
+
322
+ # grab the SID and find the user.
323
+ ret = User.find_by(email: email)
324
+ pwd = SecureRandom.urlsafe_base64(53) # should generate a 71 character string.
325
+ # max supported by has_secure_password is 72 characters.
326
+
327
+ if ret
328
+ # set ldap flag and change to random password.
329
+ ret.ldap = true
330
+ ret.password = ret.password_confirmation = pwd
331
+ else
332
+ # create new user with random password.
333
+ ret = User.create!(
334
+ name: email,
335
+ email: email,
336
+ password: pwd,
337
+ password_confirmation: pwd,
338
+ enabled: true
339
+ )
340
+
341
+ if auto_activate_ldap?
342
+ ret.activate
343
+ else
344
+ ret.send_activation_email(client_ip)
345
+ end
346
+ end
347
+
348
+ # update the user attributes in the database.
349
+ ret.name = first_attrib_val(entry, :displayname, :givenname, :name, :cn)
350
+ ret.ldap = true
351
+ ret.save!
352
+
353
+ if update_permissions
354
+ # now we need the user group memberships from ldap
355
+ # once we get those, we can translate them over.
356
+ groups = []
357
+ entry[:memberof].each do |dn|
358
+ # load the group and get the group name (always in uppercase)
359
+ group_entry = @ldap.search(base: dn).first
360
+ groups += group_to_groups(group_entry, groups)
361
+ end
362
+
363
+ # there may be one missing group still, the default group is not included in the 'memberOf' attribute.
364
+ if (group_rid = attrib_val(entry, :primarygroupid))
365
+ # the primary group id is the relative ID within the domain SID for the group.
366
+ # so we'll get the domain SID from the user SID and append the group RID.
367
+ user_sid = UserManager.decode_sid(attrib_val(entry, :objectsid))
368
+ if user_sid
369
+ domain_sid = user_sid.rpartition('-')[0]
370
+ group_sid = "#{domain_sid}-#{group_rid}"
371
+
372
+ # the search takes the SID in string form, not in binary form (like in other places).
373
+ group_entry = @ldap.search(filter: "(&(objectClass=group)(objectSID=#{group_sid}))")
374
+
375
+ # did we locate the group?
376
+ if group_entry && group_entry.count == 1
377
+ groups += group_to_groups(group_entry.first, groups)
378
+ else
379
+ Rails.logger.warn "WARNING: Failed to locate group with SID=#{group_sid}"
380
+ end
381
+ end
382
+ end
383
+
384
+ # so now 'groups' contains a list of every ldap group the user belongs to.
385
+ ret.system_admin = false
386
+ ldap_system_admin_groups.each do |group|
387
+ ret.system_admin = true if groups.include?(group)
388
+ end
389
+
390
+ access_groups = []
391
+ groups.each do |group|
392
+ access_group = AccessGroup.find_by(name: group)
393
+ access_groups << access_group.group if access_group && !access_groups.include?(access_group.group)
394
+ end
395
+
396
+ ret.groups = access_groups
397
+ ret.save!
398
+ end
399
+
400
+ ret
401
+ end
402
+
403
+ end
404
+ end