barkest_core 1.5.3.0

Sign up to get free protection for your applications and to get access to all the features.
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