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,101 @@
1
+ require 'time'
2
+
3
+ module BarkestCore
4
+
5
+ ##
6
+ # Reads a log line from a JSON log file.
7
+ class LogEntry
8
+
9
+ include ActiveModel::Model
10
+ include ActiveModel::Validations
11
+ include Comparable
12
+
13
+ attr_reader :level, :time, :message, :app_name, :app_version, :process_id
14
+
15
+ validates :level, presence: true
16
+ validates :time, presence: true
17
+ validates :message, presence: true
18
+
19
+ SEVERITY_LIST = %w(DEBUG INFO WARN ERROR FATAL)
20
+
21
+ ##
22
+ # Creates a LogEntry.
23
+ #
24
+ # The args can either be a JSON string or a Hash.
25
+ def initialize(*args)
26
+ args.each do |arg|
27
+ if arg.is_a?(String)
28
+ arg = JSON.parse(arg).symbolize_keys rescue nil
29
+ end
30
+ if arg.is_a?(Hash)
31
+ arg.each do |k,v|
32
+ k = k.to_sym
33
+ v = case k
34
+ when :level
35
+ v.to_sym
36
+ when :time
37
+ Time.parse(v)
38
+ when :process_id
39
+ v.to_i
40
+ else
41
+ v
42
+ end
43
+ instance_variable_set(:"@#{k}", v)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ ##
50
+ # Gets the index in the log file.
51
+ def index
52
+ @index ||= 0
53
+ end
54
+
55
+ ##
56
+ # Gets the level as a numeric ID.
57
+ def level_id
58
+ @level_id ||= SEVERITY_LIST.index(level.to_s.upcase) || 5
59
+ end
60
+
61
+ # :nodoc:
62
+ def inspect
63
+ "#<#{self.class.name} #{level} #{time} [#{app_name} #{app_version} (#{process_id})] #{message.length > 32 ? (message[0...32] + '...') : message}>"
64
+ end
65
+
66
+ # :nodoc:
67
+ def to_s
68
+ "#{level} #{time} [#{app_name} #{app_version} (#{process_id})] #{message}"
69
+ end
70
+
71
+ # :nodoc:
72
+ def <=>(other)
73
+ return 1 unless other.is_a?(LogEntry)
74
+ if index == other.index
75
+ time <=> other.time
76
+ else
77
+ index <=> other.index
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Reads a log file consisting of JSON records.
83
+ #
84
+ # If no log file is specified, the default log file is assumed.
85
+ def self.read_log(log_file = nil)
86
+ log_file ||= Rails.root.join('log', "#{Rails.env}.log")
87
+
88
+ ret = []
89
+
90
+ if File.exist?(log_file)
91
+ File.foreach(log_file, "\n").with_index do |line, index|
92
+ line = JSON.parse(line) rescue nil
93
+ ret << LogEntry.new(line.symbolize_keys.merge(index: index)) if line.is_a?(Hash)
94
+ end
95
+ end
96
+
97
+ ret
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,51 @@
1
+ module BarkestCore
2
+ class LogViewOptions
3
+ include ActiveModel::Model
4
+ include BarkestCore::DateParser
5
+
6
+ attr_accessor :search, :max_records
7
+ attr_reader :start_time, :end_time
8
+
9
+
10
+ def min_severity=(value)
11
+ @min_severity = BarkestCore::LogEntry::SEVERITY_LIST.index(value.to_s.upcase)
12
+ end
13
+
14
+ def min_severity
15
+ return nil unless instance_variable_defined?(:@min_severity)
16
+ return nil unless @min_severity
17
+ BarkestCore::LogEntry::SEVERITY_LIST[@min_severity]
18
+ end
19
+
20
+ def min_severity_id
21
+ return nil unless instance_variable_defined?(:@min_severity)
22
+ @min_severity
23
+ end
24
+
25
+ def start_time=(value)
26
+ @start_time = parse_for_date_column(value)
27
+ end
28
+
29
+ def end_time=(value)
30
+ @end_time = parse_for_date_column(value)
31
+ end
32
+
33
+ def search_regex
34
+ @search_regex ||=
35
+ if search.blank?
36
+ nil
37
+ else
38
+ /#{search.gsub('[]', '\[\]')}/i rescue nil
39
+ end
40
+ end
41
+
42
+ def keep_log_entry?(log_entry)
43
+ return false if min_severity_id && log_entry.level_id < min_severity_id
44
+ return false if start_time && log_entry.time < start_time
45
+ return false if end_time && log_entry.time > (end_time + 1.day) # include events from the end date.
46
+ return false unless search_regex.nil? || search_regex.match(log_entry.message)
47
+ true
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,441 @@
1
+ module BarkestCore
2
+ ##
3
+ # This class can be used to conditionally update a target SQL database with custom code.
4
+ #
5
+ # The updater will hunt through the SQL files found in the +sql_sources+ passed in.
6
+ # For each source, the updater calculates the new version and compares it against the
7
+ # existing version. If the new version is actually newer, the updater will update the
8
+ # object in the database.
9
+ class MsSqlDbDefinition
10
+
11
+ ##
12
+ # The base error for errors raised by the updater class.
13
+ UpdateError = Class.new(StandardError)
14
+
15
+ ##
16
+ # The error raised when the provided connection does not provide a user with full control over the database.
17
+ NeedFullAccess = Class.new(UpdateError)
18
+
19
+ ##
20
+ # The error raised when an object type doesn't match the previous type for the object with the specified name.
21
+ ObjectTypeMismatch = Class.new(UpdateError)
22
+
23
+ ##
24
+ # The name of the table holding the object versions.
25
+ VERSION_TABLE_NAME = 'zz_barkest__versions'
26
+
27
+
28
+ attr_reader :table_prefix
29
+
30
+ class Conn < ActiveRecord::Base
31
+ self.abstract_class = true
32
+ end
33
+
34
+ ##
35
+ # Defines a new updater.
36
+ #
37
+ # Options can include +source_paths+, +before_update+, and +after_update+.
38
+ #
39
+ # The +before_update+ and +after_update+ options define a callback to be run before or after
40
+ # the database update is performed. This can be a string referencing a method or it can be a Proc.
41
+ #
42
+ # MsSqlDbDefinition.new(
43
+ # :before_update => 'MyClass.my_method(db_conn,user)',
44
+ # :after_update => Proc.new do |db_conn, user|
45
+ # ...
46
+ # end
47
+ # )
48
+ #
49
+ # If you use the string option, note that the +db_conn+ and +user+ variables are available. In the example
50
+ # above they are being passed to the method as arguments.
51
+ def initialize(options = {})
52
+ options = {
53
+ table_name_prefix: 'zz_barkest_'
54
+ }.merge(options || {}).symbolize_keys
55
+
56
+ @table_prefix = options[:table_name_prefix].to_s
57
+ valid_regex = /^[a-z][a-z0-9_]*$/im
58
+ raise 'invalid table prefix' unless valid_regex.match(@table_prefix)
59
+
60
+ @sources = [ ]
61
+ @source_paths = [ ]
62
+ @pre_update = options.delete(:before_update) || options.delete(:pre_update)
63
+ @post_update = options.delete(:after_update) || options.delete(:post_update)
64
+
65
+ # and any other paths provided via options.
66
+ if options[:source_paths]
67
+ if options[:source_paths].is_a?(String)
68
+ add_source_path options[:source_paths]
69
+ elsif options[:source_paths].respond_to?(:each)
70
+ options[:source_paths].each do |path|
71
+ add_source_path path.to_s
72
+ end
73
+ else
74
+ add_source_path options[:source_paths].to_s
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ ##
81
+ # Gets an object's name according to this DB updater.
82
+ def object_name(unprefixed_name)
83
+ name = unprefixed_name.to_s
84
+ return name if name.index(table_prefix) == 0
85
+ "#{table_prefix}#{name}"
86
+ end
87
+
88
+ ##
89
+ # Gets all of the source paths that have currently been searched.
90
+ def source_paths
91
+ @source_paths.dup.freeze
92
+ end
93
+
94
+ ##
95
+ # Gets all of the sources currently loaded.
96
+ def sources
97
+ @sources.dup.map{|t| t.name_prefix = table_prefix; t}.freeze
98
+ end
99
+
100
+ ##
101
+ # Adds a source using a specific timestamp.
102
+ #
103
+ # The first line of the SQL should be a comment specifying the timestamp for the source.
104
+ # -- 2016-12-19 15:45
105
+ # -- 2016-12-19
106
+ # -- 201612191545
107
+ # -- 20161219
108
+ #
109
+ # The timestamp will be converted into a 12-digit number, if time is not specified it will be right-padded
110
+ # with zeroes to get to the 12-digit number.
111
+ #
112
+ # The +sql+ should be a valid create/alter table/view/function statement.
113
+ def add_source(sql)
114
+ sql_def = BarkestCore::MsSqlDefinition.new(sql, '')
115
+ sql_def.instance_variable_set(:@source_location, "::#{sql_def.name}::")
116
+ add_sql_def sql_def
117
+ nil
118
+ end
119
+
120
+ ##
121
+ # Adds a MsSqlDefinition object to the sources for this updater.
122
+ #
123
+ # The +definition+ should be a previously created MsSqlDefinition object.
124
+ def add_source_definition(definition)
125
+ add_sql_def definition
126
+ nil
127
+ end
128
+
129
+ ##
130
+ # Adds all SQL files found in the specified directory to the sources for this updater.
131
+ #
132
+ # The +path+ should contain the SQL files. If there are subdirectories, you should
133
+ # include them individually.
134
+ #
135
+ # The source files should specify a timestamp in the first comment.
136
+ # -- 2016-12-19 15:45
137
+ # -- 2016-12-19
138
+ # -- 201612191545
139
+ # -- 20161219
140
+ #
141
+ # The timestamp will be converted into a 12-digit number, if time is not specified it will be right-padded
142
+ # with zeroes to get to the 12-digit number.
143
+ #
144
+ def add_source_path(path)
145
+ raise 'path must be a string' unless path.is_a?(String)
146
+
147
+ path = File.expand_path(path)
148
+ raise 'cannot add root path' if path == '/'
149
+ path = path[0...-1] if path[-1] == '/'
150
+
151
+ unless @source_paths.include?(path)
152
+ @source_paths << path
153
+
154
+ if Dir.exist?(path)
155
+ Dir.glob("#{path}/*.sql").each do |source|
156
+ add_sql_def BarkestCore::MsSqlDefinition.new(File.read(source), source, File.mtime(source))
157
+ end
158
+ end
159
+ end
160
+
161
+ nil
162
+ end
163
+
164
+ ##
165
+ # Performs the database update using the specified configuration.
166
+ #
167
+ # A warning will be logged if the runtime user has full access to the database.
168
+ #
169
+ # An error will be raised if there is the runtime user does not have full access and no update_user is provided,
170
+ # or if an update_user is provided who also does not have full access to the database.
171
+ def update_db(config, options = {})
172
+
173
+ begin
174
+ options ||= {}
175
+
176
+ runtime_user = config[:username]
177
+
178
+ Conn.remove_connection
179
+ Conn.establish_connection config
180
+
181
+ if have_db_control?
182
+ warn "WARNING: Runtime user '#{runtime_user}' has full access to the database. (this is not recommended)" unless Rails.env.test?
183
+ else
184
+ raise NeedFullAccess, 'please provide update_username and update_password for a user with full access to the database' unless config[:update_username]
185
+
186
+ use_config = config.dup
187
+ use_config[:username] = config[:update_username]
188
+ use_config[:password] = config[:update_password]
189
+
190
+ Conn.remove_connection
191
+ Conn.establish_connection use_config
192
+
193
+ raise NeedFullAccess, 'provided update user does not have full access to the database' unless have_db_control?
194
+ end
195
+
196
+ unless Conn.object_exists?(VERSION_TABLE_NAME)
197
+ debug 'Creating version tracking table...'
198
+ db_connection.execute <<-EOSQL
199
+ CREATE TABLE [#{VERSION_TABLE_NAME}] (
200
+ [object_name] VARCHAR(120) NOT NULL PRIMARY KEY,
201
+ [object_type] VARCHAR(40) NOT NULL,
202
+ [object_version] VARCHAR(40) NOT NULL,
203
+ [created] DATETIME NOT NULL,
204
+ [updated] DATETIME NOT NULL,
205
+ [created_by] VARCHAR(120),
206
+ [updated_by] VARCHAR(120)
207
+ )
208
+ EOSQL
209
+ end
210
+
211
+ if (proc = (options[:before_update] || options[:pre_update] || @pre_update))
212
+ if proc.is_a?(String)
213
+ code = proc
214
+ proc = Proc.new { |db_conn, user| eval code }
215
+ end
216
+ if proc.respond_to?(:call)
217
+ debug 'Running pre-update code...'
218
+ proc.call db_connection, runtime_user
219
+ end
220
+ end
221
+
222
+ debug 'Processing source list...'
223
+ sources.each do |src|
224
+ src.name_prefix = table_prefix
225
+
226
+ cur_ver = get_version src.prefixed_name
227
+
228
+ if cur_ver
229
+ raise ObjectTypeMismatch, "object type mismatch for #{src.prefixed_name}" unless src.type.upcase == cur_ver['object_type'].upcase
230
+ if cur_ver['object_version'].to_i >= src.version.to_i
231
+ debug " > Preserving #{src.prefixed_name}..."
232
+ next # source
233
+ else
234
+ debug " > Updating #{src.prefixed_name}..."
235
+ if src.is_create?
236
+ db_connection.execute src.drop_sql
237
+ end
238
+ end
239
+ else
240
+ debug " > Creating #{src.prefixed_name}..."
241
+ end
242
+
243
+ db_connection.execute src.update_sql
244
+ db_connection.execute src.grant_sql(runtime_user)
245
+ set_version src.prefixed_name, src.type, src.version
246
+
247
+ src.name_prefix = ''
248
+ end
249
+
250
+ if (proc = (options[:after_update] || options[:post_update] || @post_update))
251
+ if proc.is_a?(String)
252
+ code = proc
253
+ proc = Proc.new { |db_conn, user| eval code }
254
+ end
255
+ if proc.respond_to?(:call)
256
+ debug 'Running post-update code...'
257
+ proc.call db_connection, runtime_user
258
+ end
259
+ end
260
+
261
+ yield db_connection, runtime_user if block_given?
262
+
263
+ ensure
264
+ Conn.remove_connection
265
+ end
266
+
267
+ true
268
+ end
269
+
270
+ ##
271
+ # Registers a DB updater and tells BarkestCore that the named database exists and could use a configuration.
272
+ #
273
+ # The +options+ will be passed to the MsSqlDbDefinition constructor, except for the +extra_params+ key.
274
+ # If this key is provided, it is pulled out and used for the defaults for the database configuration.
275
+ #
276
+ # Ideally this is to provide the +extra_[1|2]_name+, +extra_[1|2]_type+, and +extra_[1|2]_value+ parameters, but
277
+ # you can also use it to provide reasonable defaults for +host+, +database+, or even credentials.
278
+ #
279
+ def self.register(name, options={})
280
+ name = symbolize_name name
281
+
282
+ raise 'already registered' if registered.include?(name)
283
+
284
+ options = (options || {}).symbolize_keys
285
+
286
+ extra_params = options.delete(:extra_params)
287
+ if extra_params.is_a?(Hash)
288
+ repeat = true
289
+ while repeat
290
+ repeat = false
291
+ extra_params.dup.each do |k,v|
292
+ if v.is_a?(Hash)
293
+ extra_params.delete(k)
294
+ v.each do |subk,subv|
295
+ extra_params[:"#{k}_#{subk}"] = subv
296
+ end
297
+ repeat = true
298
+ end
299
+ end
300
+ end
301
+ end
302
+
303
+ options[:table_name_prefix] ||=
304
+ if name.to_s.index('barkest') == 0
305
+ "zz_#{name}_"
306
+ else
307
+ "zz_barkest_#{name}_"
308
+ end
309
+
310
+ updater = MsSqlDbDefinition.new(options)
311
+
312
+ registered[name] = updater
313
+
314
+ # Register with DatabaseConfig to enable the config page for this DB.
315
+ DatabaseConfig.register name
316
+
317
+ cfg_def = (extra_params.is_a?(Hash) ? extra_params : {})
318
+ .merge(
319
+ {
320
+ adapter: 'sqlserver',
321
+ pool: 5,
322
+ timeout: 30000,
323
+ port: 1433,
324
+ }
325
+ )
326
+
327
+ # Register with BarkestCore so that the default configuration is somewhat appropriate.
328
+ BarkestCore.register_db_config_defaults name, cfg_def
329
+
330
+ updater
331
+ end
332
+
333
+ ##
334
+ # Gets a DB updater by name.
335
+ def self.[](name)
336
+ name = symbolize_name name
337
+ registered[name]
338
+ end
339
+
340
+ ##
341
+ # Gets a list of all the DB updaters currently registered.
342
+ def self.keys
343
+ registered.keys
344
+ end
345
+
346
+ ##
347
+ # Iterates through the registered DB updaters.
348
+ #
349
+ # Yields the db_name and the db_updater to the block.
350
+ def self.each
351
+ registered.each do |k,v|
352
+ yield k, v if block_given?
353
+ end
354
+ end
355
+
356
+ private
357
+
358
+ def self.symbolize_name(name)
359
+ name.to_s.underscore.gsub('/', '_').to_sym
360
+ end
361
+
362
+ def self.registered
363
+ @registered ||= {}
364
+ end
365
+
366
+ def get_version(object_name)
367
+ object_name = object_name.to_s.gsub("'", "''")
368
+ db_connection.exec_query("SELECT [object_name], [object_type], [object_version], [created], [updated], [created_by], [updated_by] FROM [#{VERSION_TABLE_NAME}] WHERE [object_name]='#{object_name}'").first
369
+ end
370
+
371
+ def set_version(object_name, object_type, object_version)
372
+ raw_obj_name = object_name
373
+ existing = get_version(raw_obj_name)
374
+
375
+ object_name = object_name.to_s.gsub("'", "''")
376
+ object_type = object_type.to_s.gsub("'", "''")
377
+ object_version = object_version.to_s.gsub("'", "''")
378
+ time = Time.now.strftime('%Y-%m-%d %H:%M:%S').gsub("'", "''")
379
+ app = (Rails && Rails.application) ? Rails.application.class.to_s.gsub("'", "''") : '<UNKNOWN>'
380
+
381
+ if existing
382
+ raise ObjectTypeMismatch, 'object type mismatch' unless existing['object_type'] == object_type
383
+ db_connection.execute "UPDATE [#{VERSION_TABLE_NAME}] SET [object_version]='#{object_version}', [updated]='#{time}', [updated_by]='#{app}' WHERE [object_name]='#{object_name}'"
384
+ else
385
+ db_connection.execute "INSERT INTO [#{VERSION_TABLE_NAME}] ([object_name], [object_type], [object_version], [created], [updated], [created_by], [updated_by]) VALUES ('#{object_name}','#{object_type}','#{object_version}','#{time}','#{time}','#{app}','#{app}')"
386
+ end
387
+
388
+ get_version raw_obj_name
389
+ end
390
+
391
+ def db_connection
392
+ Conn.connection
393
+ end
394
+
395
+ def have_db_control?
396
+ # user must have CONTROL permission on the database itself.
397
+ # if it does, then we are good to move forward.
398
+ result = db_connection.exec_query('SELECT COUNT(*) AS "one" FROM "fn_my_permissions"(NULL, \'DATABASE\') WHERE "permission_name"=\'CONTROL\'').first
399
+ result && result['one'] == 1
400
+ end
401
+
402
+ def debug(s)
403
+ if Rails && Rails.logger && Rails.logger.respond_to?(:debug)
404
+ Rails.logger.debug(s)
405
+ else
406
+ $stdout.puts s
407
+ end
408
+ end
409
+
410
+ def warn(s)
411
+ if Rails && Rails.logger && Rails.logger.respond_to?(:warn)
412
+ Rails.logger.warn(s)
413
+ else
414
+ $stderr.puts s
415
+ end
416
+ end
417
+
418
+ def add_sql_def(sql_def)
419
+ existing = @sources.find{ |item| item.name == sql_def.name }
420
+ if existing
421
+ if existing == sql_def
422
+ debug "A #{existing.type.downcase} named #{existing.name} is already defined with the same source."
423
+ return nil
424
+ end
425
+ if existing.type != sql_def.type
426
+ raise ObjectTypeMismatch, "Cannot change type of object named #{existing.name} from #{existing.type} to #{sql_def.type}."
427
+ end
428
+ if existing.version.to_i > sql_def.version.to_i
429
+ warn "A #{existing.type.downcase} named #{existing.name} is already defined with newer source."
430
+ return nil
431
+ end
432
+ if sql_def.is_create?
433
+ warn "Removing old definition for #{existing.type.downcase} named #{existing.name}."
434
+ @sources.delete existing
435
+ end
436
+ end
437
+ @sources << sql_def
438
+ end
439
+
440
+ end
441
+ end