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,7 @@
1
+ module BarkestCore
2
+ ##
3
+ # A simple wrapper for a standard error to allow distinguishing authorization errors.
4
+ class AuthorizeFailure < StandardError
5
+
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module BarkestCore
2
+ ##
3
+ # Defines the message generated by the generic contact form.
4
+ class ContactMessage
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+ include BarkestCore::EmailTester
8
+
9
+ attr_accessor :your_name, :your_email, :related_to, :subject, :body, :remote_ip
10
+
11
+ validates :your_name, presence: true
12
+ validates :your_email, presence: true, format: { with: VALID_EMAIL_REGEX }
13
+ validates :related_to, presence: true
14
+ validates :subject, presence: true, if: :need_subject?
15
+ validates :body, presence: true
16
+
17
+ ##
18
+ # Gets the full subject for the message.
19
+ def full_subject
20
+ return related_to if subject.blank?
21
+ "#{related_to}: #{subject}"
22
+ end
23
+
24
+ ##
25
+ # Sends the message.
26
+ def send_message
27
+ BarkestCore::ContactForm.contact(self).deliver_now
28
+ end
29
+
30
+ private
31
+
32
+ def need_subject?
33
+ related_to.to_s.downcase == 'other'
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,223 @@
1
+ module BarkestCore
2
+
3
+ ##
4
+ # Defines a database configuration for a database other than the core database.
5
+ #
6
+ # The core database must be configurared in +database.yml+ since it defines the SystemConfig.
7
+ #
8
+ # Other databases (say for a 3rd party database) can easily be defined using SystemConfig
9
+ # and this class.
10
+ class DatabaseConfig
11
+ include ActiveModel::Model
12
+ include ActiveModel::Validations
13
+
14
+ attr_accessor :name, :adapter, :encoding, :reconnect, :database, :pool, :username, :password, :timeout, :host, :port
15
+ attr_accessor :extra_1_name, :extra_1_label, :extra_1_type
16
+ attr_accessor :extra_2_name, :extra_2_label, :extra_2_type
17
+ attr_accessor :extra_3_name, :extra_3_label, :extra_3_type
18
+ attr_accessor :extra_4_name, :extra_4_label, :extra_4_type
19
+ attr_accessor :extra_5_name, :extra_5_label, :extra_5_type
20
+ attr_writer :extra_1_value, :extra_2_value, :extra_3_value, :extra_4_value, :extra_5_value
21
+ attr_accessor :update_username, :update_password
22
+
23
+ VALID_ADAPTERS = %w(sqlite3 mysql2 postgresql sqlserver)
24
+
25
+ validates :adapter, inclusion: { in: VALID_ADAPTERS }
26
+ validates :name, presence: true, length: { maximum: 128 }
27
+ validates :database, presence: true
28
+ validates :pool, presence: true
29
+ validates :timeout, presence: true
30
+
31
+ EXTRA_REGEX = /^extra_(?<KEY>\d+)_(?<VAR>name|label|type|value)$/
32
+ VALID_EXTRA_KEY = (1..5)
33
+ private_constant :EXTRA_REGEX, :VALID_EXTRA_KEY
34
+
35
+ ##
36
+ # Initializes the configuration.
37
+ #
38
+ # Define the parameters as hash values. A string without a key will be used to set the name.
39
+ def initialize(*args)
40
+ @extra = []
41
+ args.each do |arg|
42
+ if arg.is_a?(String)
43
+ self.name = arg
44
+ elsif arg.is_a?(Hash)
45
+ arg.each do |k,v|
46
+ if respond_to?(:"#{k}?")
47
+ send :"#{k}=", ((v === true || v === '1') ? '1' : '0')
48
+ elsif respond_to?(:"#{k}")
49
+ send :"#{k}=", v.to_s
50
+ elsif (extra = EXTRA_REGEX.match(k.to_s))
51
+ key = extra['KEY'].to_i
52
+ if VALID_EXTRA_KEY.include?(key)
53
+ send :"extra_#{key}_#{extra['VAR']}=", v.to_s
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # :nodoc:
62
+ def method_missing(m,*a,&b)
63
+ m = m.to_s
64
+
65
+ if (key = EXTRA_REGEX.match(m))
66
+ if key['VAR'] == 'value'
67
+ key = key['KEY'].to_i
68
+ if VALID_EXTRA_KEY.include?(key)
69
+ ivar = :"@#{m}"
70
+ val = instance_variable_defined?(ivar) ? instance_variable_get(ivar) : nil
71
+ tp = send("extra_#{key}_type")
72
+ if tp == 'boolean'
73
+ val = ((val === true) || (val == '1')) ? '1' : '0'
74
+ end
75
+ return val
76
+ end
77
+ end
78
+ end
79
+
80
+ super m, *a, &b
81
+ end
82
+
83
+ ##
84
+ # Is the database configured to reconnect?
85
+ def reconnect?
86
+ reconnect.to_s.to_i != 0
87
+ end
88
+
89
+ ##
90
+ # Gets the name for an extra value.
91
+ def extra_name(index)
92
+ return nil if index < 1 || index > 5
93
+ send "extra_#{index}_name"
94
+ end
95
+
96
+ ##
97
+ # Gets the label for an extra value.
98
+ def extra_label(index)
99
+ return nil if index < 1 || index > 5
100
+ txt = send("extra_#{index}_label")
101
+ txt = extra_name(index).to_s.humanize.capitalize if txt.blank?
102
+ txt
103
+ end
104
+
105
+ ##
106
+ # Gets the type for an extra value.
107
+ def extra_type(index)
108
+ return nil if index < 1 || index > 5
109
+ send "extra_#{index}_type"
110
+ end
111
+
112
+ ##
113
+ # Gets the field type for an extra value.
114
+ def extra_field_type(index)
115
+ t = extra_type(index).to_s
116
+ case t
117
+ when 'password'
118
+ 'password'
119
+ when 'integer', 'float'
120
+ 'number'
121
+ when 'boolean'
122
+ 'checkbox'
123
+ else
124
+ if t.downcase.index('in:')
125
+ 'select'
126
+ else
127
+ 'text'
128
+ end
129
+ end
130
+ end
131
+
132
+ ##
133
+ # Gets the options for a select field.
134
+ def extra_field_options(index)
135
+ if extra_field_type(index) == 'select'
136
+ eval extra_type(index).partition(':')[2]
137
+ else
138
+ nil
139
+ end
140
+ end
141
+
142
+ ##
143
+ # Gets an extra value.
144
+ def extra_value(index, convert = false)
145
+ return nil if index < 1 || index > 5
146
+ val = send "extra_#{index}_value"
147
+ if convert
148
+ case extra_type(index)
149
+ when 'boolean'
150
+ BarkestCore::BooleanParser.parse_for_boolean_column(val)
151
+ when 'integer'
152
+ BarkestCore::NumberParser.parse_for_int_column(val)
153
+ when 'float'
154
+ BarkestCore::NumberParser.parse_for_float_column(val)
155
+ else
156
+ val.to_s
157
+ end
158
+ end
159
+ end
160
+
161
+
162
+ ##
163
+ # Converts this configuration into a hash.
164
+ def to_h(convert_extra = true)
165
+ ret = {
166
+ adapter: adapter.to_s,
167
+ database: database.to_s,
168
+ pool: pool.to_s.to_i,
169
+ timeout: timeout.to_s.to_i,
170
+ reconnect: reconnect?,
171
+ encoding: encoding ? encoding.to_s : nil,
172
+ host: host.blank? ? nil : host.to_s,
173
+ port: port.blank? ? nil : port.to_s.to_i,
174
+ username: username.blank? ? nil : username.to_s,
175
+ password: password.blank? ? nil : password.to_s,
176
+ update_username: update_username.blank? ? nil : update_username.to_s,
177
+ update_password: update_password.blank? ? nil : update_password.to_s,
178
+ }
179
+ VALID_EXTRA_KEY.each do |idx|
180
+ if convert_extra
181
+ unless extra_name(idx).blank?
182
+ ret[extra_name(idx).to_sym] = extra_value(idx, true)
183
+ end
184
+ else
185
+ ret[:"extra_#{idx}_name"] = send(:"extra_#{idx}_name")
186
+ ret[:"extra_#{idx}_label"] = send(:"extra_#{idx}_label")
187
+ ret[:"extra_#{idx}_type"] = send(:"extra_#{idx}_type")
188
+ ret[:"extra_#{idx}_value"] = send(:"extra_#{idx}_value")
189
+ end
190
+ end
191
+ ret
192
+ end
193
+
194
+ ##
195
+ # Saves this configuration (encrypted) to SystemConfig.
196
+ def save
197
+ SystemConfig.set name, to_h(false), true
198
+ end
199
+
200
+ ##
201
+ # Loads the configuration for the specified database from SystemConfig.
202
+ def DatabaseConfig.load(name)
203
+ DatabaseConfig.new(name, SystemConfig.get(name))
204
+ end
205
+
206
+ ##
207
+ # Gets a list of the registered databases for enumeration.
208
+ def DatabaseConfig.registered
209
+ @registered ||= []
210
+ end
211
+
212
+ ##
213
+ # Registers a database for enumeration.
214
+ def DatabaseConfig.register(db_id)
215
+ db_id = db_id.to_s.downcase
216
+ unless db_id.blank?
217
+ registered << db_id unless registered.include?(db_id)
218
+ end
219
+ nil
220
+ end
221
+
222
+ end
223
+ end
@@ -0,0 +1,21 @@
1
+ # this shouldn't be necessary, but engines seem to have a few weak spots.
2
+ require 'will_paginate/active_record'
3
+
4
+ module BarkestCore
5
+
6
+ ##
7
+ # This class serves as a base class for other models.
8
+ #
9
+ # This way we can guarantee that all of our models can use an explicit configuration
10
+ # when desirable.
11
+ class DbTable < ActiveRecord::Base
12
+ self.abstract_class = true
13
+
14
+ # Ensure that we only establish a new connection if needed.
15
+ unless BarkestCore.db_config.symbolize_keys == ActiveRecord::Base.connection_config.symbolize_keys
16
+ establish_connection BarkestCore.db_config
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,132 @@
1
+ module BarkestCore
2
+ ##
3
+ # Defines the email configuration for the system.
4
+ class EmailConfig
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+
8
+ attr_accessor :config_mode, :default_sender, :default_recipient, :default_hostname
9
+ attr_accessor :address, :port, :authentication, :ssl, :enable_starttls_auto, :user_name, :password
10
+
11
+ VALID_CONFIG_MODES = %w(none smtp test)
12
+ VALID_AUTH_MODES = %w(none plain login cram_md5 ntlm)
13
+
14
+ validates :config_mode, inclusion: { in: VALID_CONFIG_MODES }
15
+ validates :default_sender, presence: true
16
+ validates :default_recipient, presence: true
17
+ validates :default_hostname, presence: true
18
+
19
+ with_options if: :smtp?, presence: true do
20
+ validates :address
21
+ validates :port
22
+ validates :authentication, inclusion: { in: VALID_AUTH_MODES }
23
+ end
24
+
25
+ validate :smtp_validate, if: :smtp?
26
+
27
+ ##
28
+ # Initializes the configuration.
29
+ def initialize(*args)
30
+ args.each do |arg|
31
+ if arg.is_a?(Hash)
32
+ arg.each do |k,v|
33
+ if respond_to?(:"#{k}?")
34
+ send :"#{k}=", ((v === true || v === '1') ? '1' : '0')
35
+ elsif respond_to?(k)
36
+ send :"#{k}=", v.to_s
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ ##
44
+ # Is SMTP enabled?
45
+ def smtp?
46
+ config_mode.to_s.downcase == 'smtp'
47
+ end
48
+
49
+ ##
50
+ # Is SSL enabled for SMTP?
51
+ def ssl?
52
+ ssl.to_s.to_i != 0
53
+ end
54
+
55
+ ##
56
+ # Is STARTTLS enabled for SMTP?
57
+ def enable_starttls_auto?
58
+ enable_starttls_auto.to_s.to_i != 0
59
+ end
60
+
61
+ ##
62
+ # Converts this configuration into a hash.
63
+ def to_h
64
+ {
65
+ config_mode: config_mode.to_s.to_sym,
66
+ default_sender: default_sender.to_s,
67
+ default_recipient: default_recipient.to_s,
68
+ default_hostname: default_hostname.to_s,
69
+ address: address.to_s,
70
+ port: port.to_s.to_i,
71
+ authentication: authentication.to_s.to_sym,
72
+ ssl: ssl?,
73
+ enable_starttls_auto: enable_starttls_auto?,
74
+ user_name: user_name.to_s,
75
+ password: password.to_s,
76
+ }
77
+ end
78
+
79
+ ##
80
+ # Saves this configuration (encrypted) to SystemConfig.
81
+ def save
82
+ SystemConfig.set :email, to_h, true
83
+ end
84
+
85
+ ##
86
+ # Loads the configuration from SystemConfig.
87
+ def EmailConfig.load
88
+ EmailConfig.new SystemConfig.get(:email)
89
+ end
90
+
91
+ private
92
+
93
+ def smtp_validate
94
+ return nil if Rails.env.test?
95
+
96
+ # no need to test unless we are configured for SMTP.
97
+ return nil unless smtp?
98
+
99
+ # already failed if these are missing.
100
+ return nil if address.blank? || port.blank? || authentication.blank?
101
+
102
+ # or these
103
+ return nil if default_sender.blank? || default_recipient.blank? || default_hostname.blank?
104
+
105
+ # send a test message.
106
+ begin
107
+ client = Net::SMTP.new(address, port)
108
+ begin
109
+ client.enable_ssl if ssl?
110
+ client.start(default_hostname, user_name, password, authentication.to_sym)
111
+ msgstr = <<-MESSAGE
112
+ From: #{default_sender}
113
+ To: #{default_recipient}
114
+ Subject: Test message
115
+
116
+ This is a test message sent with the new #{Rails.env} configuration for #{default_hostname}.
117
+ This message was sent at #{Time.zone.now}.
118
+ MESSAGE
119
+ client.send_message(msgstr, default_sender, default_recipient)
120
+ ensure
121
+ client.finish rescue nil
122
+ end
123
+
124
+ nil
125
+ rescue =>e
126
+ errors.add :base, "Failed to send test message. " + e.message
127
+ end
128
+ end
129
+
130
+
131
+ end
132
+ end
@@ -0,0 +1,267 @@
1
+ module BarkestCore
2
+ ##
3
+ # An interface to a global status/lock file.
4
+ #
5
+ # The global status/lock file is a simple two line file.
6
+ # The first line is the global status message.
7
+ # The second line is the global status progress.
8
+ #
9
+ # The real magic comes when we take advantage of exclusive locks.
10
+ # The process that will be managing the status takes an exclusive lock on the status/lock file.
11
+ # This prevents any other process from taking an exclusive lock.
12
+ # It does not prevent other processes from reading from the file.
13
+ #
14
+ # So the main process can update the file at any time, until it releases the lock.
15
+ # The other processes can read the file at any time, and test for the lock state to determine if the main
16
+ # process is still busy.
17
+ #
18
+ #
19
+ class GlobalStatus
20
+
21
+ ##
22
+ # The exception raised in the +lock_for+ method when +raise_on_failure+ is set.
23
+ FailureToLock = Class.new(StandardError)
24
+
25
+ ##
26
+ # Creates a new GlobalStatus object.
27
+ #
28
+ # If you specify a status file, then that file will be used for the locking and status reporting.
29
+ # Otherwise, the "global_lock" file will be used.
30
+ def initialize(status_file = nil)
31
+ @lock_handle = nil
32
+ @stat_handle = nil
33
+ @status_file_path = status_file
34
+ end
35
+
36
+ ##
37
+ # Gets the path to the global status file.
38
+ def status_file_path
39
+ @status_file_path ||= WorkPath.path_for('global_status')
40
+ end
41
+
42
+ ##
43
+ # Gets the path to the global lock file.
44
+ def lock_file_path
45
+ @lock_file_path ||= WorkPath.path_for('global_lock')
46
+ end
47
+
48
+ ##
49
+ # Determines if this instance has a lock on the status/lock file.
50
+ def have_lock?
51
+ !!@lock_handle
52
+ end
53
+
54
+ ##
55
+ # Determines if any process has a lock on the status/lock file.
56
+ def is_locked?
57
+ begin
58
+ return true if have_lock?
59
+ return true unless acquire_lock
60
+ ensure
61
+ release_lock
62
+ end
63
+ false
64
+ end
65
+
66
+ ##
67
+ # Gets the current status message from the status/lock file.
68
+ def get_message
69
+ get_status[:message]
70
+ end
71
+
72
+ ##
73
+ # Gets the current progress from the status/lock file.
74
+ def get_percentage
75
+ r = get_status[:percent]
76
+ r.blank? ? nil : r.to_i
77
+ end
78
+
79
+ ##
80
+ # Gets the current status from the status/lock file.
81
+ #
82
+ # Returns a hash with three elements:
83
+ #
84
+ # message::
85
+ # The current status message.
86
+ #
87
+ # percent::
88
+ # The current status progress.
89
+ #
90
+ # locked::
91
+ # The current lock state of the status/lock file. (true for locked, false for unlocked)
92
+ #
93
+ def get_status
94
+ r = {}
95
+ if have_lock?
96
+ @stat_handle.rewind
97
+ r[:message] = (@stat_handle.eof? ? 'The current process is busy.' : @stat_handle.readline.strip)
98
+ r[:percent] = (@stat_handle.eof? ? '' : @stat_handle.readline.strip)
99
+ r[:locked] = true
100
+ elsif is_locked?
101
+ if File.exist?(status_file_path)
102
+ begin
103
+ File.open(status_file_path, 'r') do |f|
104
+ r[:message] = (f.eof? ? 'The system is busy.' : f.readline.strip)
105
+ r[:percent] = (f.eof? ? '' : f.readline.strip)
106
+ end
107
+ rescue
108
+ r[:message] = 'The system appears busy.'
109
+ r[:percent] = ''
110
+ end
111
+ else
112
+ r[:message] = 'No status file.'
113
+ r[:percent] = ''
114
+ end
115
+ r[:locked] = true
116
+ else
117
+ r[:message] = 'The system is no longer busy.'
118
+ r[:percent] = '-'
119
+ r[:locked] = false
120
+ end
121
+ r
122
+ end
123
+
124
+ ##
125
+ # Sets the status message if this instance has a lock on the status/lock file.
126
+ #
127
+ # Returns true after successfully setting the message.
128
+ # Returns false if this instance does not currently hold the lock.
129
+ #
130
+ def set_message(value)
131
+ return false unless have_lock?
132
+ cur = get_status
133
+ set_status(value, cur[:percent])
134
+ end
135
+
136
+ ##
137
+ # Sets the status progress if this instance has a lock on the status/lock file.
138
+ #
139
+ # Returns true after successfully setting the progress.
140
+ # Returns false if this instance does not currently hold the lock.
141
+ #
142
+ def set_percentage(value)
143
+ return false unless have_lock?
144
+ cur = get_status
145
+ set_status(cur[:message], value)
146
+ end
147
+
148
+ ##
149
+ # Sets the status message and progress if this instance has a lock on the status/lock file.
150
+ #
151
+ # Returns true after successfully setting the status.
152
+ # Returns false if this instance does not currently hold the lock.
153
+ #
154
+ def set_status(message, percentage)
155
+ return false unless have_lock?
156
+ @stat_handle.rewind
157
+ @stat_handle.truncate 0
158
+ @stat_handle.write(message.to_s.strip + "\n")
159
+ @stat_handle.write(percentage.to_s.strip + "\n")
160
+ @stat_handle.flush
161
+ true
162
+ end
163
+
164
+ ##
165
+ # Releases the lock on the status/lock file if this instance holds the lock.
166
+ #
167
+ # Returns true.
168
+ #
169
+ def release_lock
170
+ return true unless @lock_handle
171
+ begin
172
+ set_message ''
173
+ @lock_handle.flock(File::LOCK_UN)
174
+ ensure
175
+ @stat_handle.close rescue nil
176
+ @lock_handle.close rescue nil
177
+ @stat_handle = @lock_handle = nil
178
+ end
179
+
180
+ true
181
+ end
182
+
183
+ ##
184
+ # Acquires the lock on the status/lock file.
185
+ #
186
+ # Returns true on success or if this instance already holds the lock.
187
+ # Returns false if another process holds the lock.
188
+ #
189
+ def acquire_lock
190
+ return true if @lock_handle
191
+ begin
192
+ @lock_handle = File.open(lock_file_path, File::RDWR | File::CREAT)
193
+ raise StandardError.new('Already locked') unless @lock_handle.flock(File::LOCK_EX | File::LOCK_NB)
194
+ @lock_handle.rewind
195
+ @lock_handle.truncate 0
196
+ @stat_handle = File.open(status_file_path, File::RDWR | File::CREAT)
197
+ raise StandardError.new('Failed to open status') unless @stat_handle
198
+ @stat_handle.rewind
199
+ @stat_handle.truncate 0
200
+ rescue
201
+ if @stat_handle
202
+ @stat_handle.close rescue nil
203
+ end
204
+ if @lock_handle
205
+ @lock_handle.flock(File::LOCK_UN) rescue nil
206
+ @lock_handle.close rescue nil
207
+ end
208
+ @stat_handle = nil
209
+ @lock_handle = nil
210
+ end
211
+ !!@lock_handle
212
+ end
213
+
214
+ ##
215
+ # Determines if any process currently holds the lock on the status/lock file.
216
+ #
217
+ # Returns true if the file is locked, otherwise returns false.
218
+ #
219
+ def self.locked?
220
+ global_instance.is_locked?
221
+ end
222
+
223
+ ##
224
+ # Gets the current status from the status/lock file.
225
+ #
226
+ # See #get_status for a description of the returned hash.
227
+ #
228
+ def self.current
229
+ global_instance.get_status
230
+ end
231
+
232
+ ##
233
+ # Runs the provided block with a lock on the status/lock file.
234
+ #
235
+ # If a lock can be acquired, a GlobalStatus object is yielded to the block.
236
+ # The lock will automatically be released when the block exits.
237
+ #
238
+ # If a lock cannot be acquire, then false is yielded to the block.
239
+ # The block needs to test for this case to ensure that the appropriate
240
+ # error handling is performed.
241
+ #
242
+ # The only time that the block is not called is if +raise_on_failure+ is set,
243
+ # in which case an exception is raised instead of yielding to the block.
244
+ #
245
+ def self.lock_for(raise_on_failure = false, &block)
246
+ return unless block_given?
247
+ status = GlobalStatus.new
248
+ if status.acquire_lock
249
+ begin
250
+ yield status
251
+ ensure
252
+ status.release_lock
253
+ end
254
+ else
255
+ raise BarkestCore::GlobalStatus::FailureToLock.new if raise_on_failure
256
+ yield false
257
+ end
258
+ end
259
+
260
+ private
261
+
262
+ def self.global_instance
263
+ @global_instance ||= GlobalStatus.new
264
+ end
265
+
266
+ end
267
+ end