web47core 0.0.8 → 0.0.9

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -14
  3. data/Gemfile.lock +30 -9
  4. data/README.md +27 -4
  5. data/lib/app/models/concerns/app47_logger.rb +175 -0
  6. data/lib/app/models/concerns/core_account.rb +51 -0
  7. data/lib/app/models/concerns/standard_model.rb +104 -6
  8. data/lib/app/models/email_notification.rb +253 -0
  9. data/lib/app/models/email_template.rb +6 -0
  10. data/lib/app/models/notification.rb +276 -0
  11. data/lib/app/models/notification_template.rb +20 -0
  12. data/lib/app/models/slack_notification.rb +89 -0
  13. data/lib/app/models/sms_notification.rb +56 -0
  14. data/lib/app/models/smtp_configuration.rb +148 -0
  15. data/lib/app/models/template.rb +21 -0
  16. data/lib/templates/email/notification_failure.liquid +10 -0
  17. data/lib/templates/email/notification_failure.subject.liquid +1 -0
  18. data/lib/templates/slack/error_message.liquid +1 -0
  19. data/lib/web47core.rb +10 -2
  20. data/test/factories/account_factories.rb +9 -0
  21. data/test/factories/notification_factories.rb +14 -0
  22. data/test/models/app47_logger_test.rb +88 -0
  23. data/test/models/concerns/{formable_test.rb → standard_model_test.rb} +24 -5
  24. data/test/models/email_notification_test.rb +297 -0
  25. data/test/models/notification_test.rb +127 -0
  26. data/test/models/slack_notification_test.rb +50 -0
  27. data/test/notification_test_helper.rb +146 -0
  28. data/test/rails_setup.rb +4 -0
  29. data/test/test_helper.rb +10 -4
  30. data/test/test_models_helper.rb +14 -0
  31. data/web47core.gemspec +5 -2
  32. metadata +87 -14
  33. data/lib/app/models/concerns/auto_clear_cache.rb +0 -34
  34. data/lib/app/models/concerns/formable.rb +0 -111
  35. data/test/models/concerns/auto_clear_cache_test.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e82f9597abea49e585537bf7b37dd78220136b34e2f2bc0ade5592e4d70ae9d
4
- data.tar.gz: 523f737ac0beae20e3203ba4188c66e4cf5c09b8749084bf67dfd07fb039a3e7
3
+ metadata.gz: 623ae80309063bdc6c27dee1668a86ae4473da7db27a6ffedb9bd75df3b83d40
4
+ data.tar.gz: e39e28438fb5247ddb2cc65c9dd3b5c8edb8a98d9079921b3dc07d511b587ecb
5
5
  SHA512:
6
- metadata.gz: e4a973a0840c34dc033b5f512e9e5bb62618afa44f20fc5b9e6993a59ef0cbde59befc204becd175dd15db7f02f4952f516af9d77dfb9cbb8fd70fd17991fc32
7
- data.tar.gz: 6b2dff4fb23a286a60a0cccc2cd618d17b38379148aad5d385463df8a81ce55542ec9cde451516a52c6dfaf68204f585682849d546c6989800c4006fac95c091
6
+ metadata.gz: db0cd4d93d34398cf6e3a4739016db9fd63337e048917403ea9ec624ee5f516ecdb8a9ac278925f8f329dde34c3a42af16b856530ae976c5cc9534eca0999143
7
+ data.tar.gz: b5304422a552e6ec81a9e188000533a8a4652e66d3e6e8096b81abaf45d5e4646cc5ed5b7591265c5639f56225e977ba26cb68351eda9e1c20743d70b81b3580
data/Gemfile CHANGED
@@ -1,19 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
  ruby '2.4.1'
3
3
 
4
- git_source(:github) do |repo_name|
5
- repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
6
- "https://github.com/#{repo_name}.git"
7
- end
8
-
9
4
  # Specify your gem's dependencies
10
5
  gemspec
11
-
12
- gem 'aws-sdk-ec2'
13
- gem 'jwt'
14
- gem 'mongoid', '~> 6.4'
15
-
16
- group :test do
17
- gem 'simplecov'
18
- gem 'simplecov-lcov'
19
- end
data/Gemfile.lock CHANGED
@@ -1,15 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- web47core (0.0.8)
4
+ web47core (0.0.9)
5
5
  activesupport (~> 5.0)
6
- aws-sdk-ec2 (>= 1.60, <= 1.151)
6
+ aws-sdk-ec2 (> 1.140, <= 1.160)
7
7
  delayed_job_mongoid (~> 2.3)
8
+ haml
8
9
  jwt
10
+ liquid
9
11
  mongoid (> 6, < 7)
10
12
  rails (>= 4.2, < 5.3)
11
13
  redis (~> 4.1)
12
14
  redis-rails (> 5, < 6)
15
+ rest-client (>= 0, <= 2.1.0)
13
16
 
14
17
  GEM
15
18
  remote: https://rubygems.org/
@@ -60,7 +63,7 @@ GEM
60
63
  ansi (1.5.0)
61
64
  arel (9.0.0)
62
65
  aws-eventstream (1.0.3)
63
- aws-partitions (1.286.0)
66
+ aws-partitions (1.288.0)
64
67
  aws-sdk-core (3.92.0)
65
68
  aws-eventstream (~> 1.0, >= 1.0.2)
66
69
  aws-partitions (~> 1, >= 1.239.0)
@@ -94,6 +97,8 @@ GEM
94
97
  mongoid (>= 3.0, < 8)
95
98
  mongoid-compatibility (>= 0.4.0)
96
99
  docile (1.3.2)
100
+ domain_name (0.5.20190701)
101
+ unf (>= 0.0.5, < 1.0.0)
97
102
  erubi (1.9.0)
98
103
  factory_bot (5.1.1)
99
104
  activesupport (>= 4.2.0)
@@ -103,12 +108,19 @@ GEM
103
108
  ffi (1.12.2)
104
109
  globalid (0.4.2)
105
110
  activesupport (>= 4.2.0)
111
+ haml (5.1.2)
112
+ temple (>= 0.8.0)
113
+ tilt
106
114
  hashdiff (1.0.1)
115
+ http-accept (1.7.0)
116
+ http-cookie (1.0.3)
117
+ domain_name (~> 0.5)
107
118
  i18n (1.8.2)
108
119
  concurrent-ruby (~> 1.0)
109
120
  jmespath (1.4.0)
110
121
  json (2.3.0)
111
122
  jwt (2.2.1)
123
+ liquid (4.0.3)
112
124
  listen (3.2.1)
113
125
  rb-fsevent (~> 0.10, >= 0.10.3)
114
126
  rb-inotify (~> 0.9, >= 0.9.10)
@@ -120,6 +132,9 @@ GEM
120
132
  marcel (0.3.3)
121
133
  mimemagic (~> 0.3.2)
122
134
  method_source (1.0.0)
135
+ mime-types (3.3.1)
136
+ mime-types-data (~> 3.2015)
137
+ mime-types-data (3.2019.1009)
123
138
  mimemagic (0.3.4)
124
139
  mini_mime (1.0.2)
125
140
  mini_portile2 (2.4.0)
@@ -152,6 +167,7 @@ GEM
152
167
  mongoid-compatibility (0.5.1)
153
168
  activesupport
154
169
  mongoid (>= 2.0)
170
+ netrc (0.11.0)
155
171
  nio4r (2.5.2)
156
172
  nokogiri (1.10.9)
157
173
  mini_portile2 (~> 2.4.0)
@@ -205,6 +221,11 @@ GEM
205
221
  redis-store (>= 1.2, < 2)
206
222
  redis-store (1.8.2)
207
223
  redis (>= 4, < 5)
224
+ rest-client (2.1.0)
225
+ http-accept (>= 1.7.0, < 2.0)
226
+ http-cookie (>= 1.0.2, < 2.0)
227
+ mime-types (>= 1.16, < 4.0)
228
+ netrc (~> 0.8)
208
229
  ruby-progressbar (1.10.1)
209
230
  safe_yaml (1.0.5)
210
231
  shoulda (3.6.0)
@@ -218,7 +239,6 @@ GEM
218
239
  json (>= 1.8, < 3)
219
240
  simplecov-html (~> 0.10.0)
220
241
  simplecov-html (0.10.2)
221
- simplecov-lcov (0.8.0)
222
242
  sprockets (3.7.2)
223
243
  concurrent-ruby (~> 1.0)
224
244
  rack (> 1, < 3)
@@ -226,12 +246,17 @@ GEM
226
246
  actionpack (>= 4.0)
227
247
  activesupport (>= 4.0)
228
248
  sprockets (>= 3.0.0)
249
+ temple (0.8.2)
229
250
  test-unit (3.3.5)
230
251
  power_assert
231
252
  thor (1.0.1)
232
253
  thread_safe (0.3.6)
254
+ tilt (2.0.10)
233
255
  tzinfo (1.2.6)
234
256
  thread_safe (~> 0.1)
257
+ unf (0.1.4)
258
+ unf_ext
259
+ unf_ext (0.0.7.6)
235
260
  vcr (5.1.0)
236
261
  webmock (3.8.3)
237
262
  addressable (>= 2.3.6)
@@ -247,24 +272,20 @@ PLATFORMS
247
272
  ruby
248
273
 
249
274
  DEPENDENCIES
250
- aws-sdk-ec2
251
275
  bundler
252
276
  codacy-coverage (~> 2.1.0)
253
277
  database_cleaner
254
278
  factory_bot
255
279
  factory_bot_rails
256
- jwt
257
280
  listen
258
281
  minitest (= 5.10.3)
259
282
  minitest-rails (= 3.0.0)
260
283
  minitest-rails-capybara (= 3.0.1)
261
284
  minitest-reporters
262
285
  mocha
263
- mongoid (~> 6.4)
264
286
  shoulda (= 3.6.0)
265
287
  shoulda-matchers (= 3.1.2)
266
- simplecov
267
- simplecov-lcov
288
+ simplecov (= 0.16.1)
268
289
  test-unit
269
290
  vcr
270
291
  web47core!
data/README.md CHANGED
@@ -61,13 +61,24 @@ gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :develop
61
61
 
62
62
  _Please do not ship to production code using the git repo, as the production servers will not have keys to pull from the web47core repo_
63
63
 
64
- ## Features
65
-
66
- ### Models
67
- #### Concerns
64
+ ## Remove the following files
68
65
  1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
69
66
  1. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
70
67
  1. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
68
+ 1. `Formable` - Consolidated into StandardModel, was used to provide common form operations for mongoid documents
69
+ 1. `EmailNotification`
70
+ 1. `EmailTemplate`
71
+ 1. `Notification`
72
+ 1. `NotificationTemplate`
73
+ 1. `SlackNotification`
74
+ 1. `SmsNotification`
75
+ 1. `Template`
76
+
77
+ ### Models
78
+ #### Concerns
79
+ 1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
80
+ 1. `CoreSystemConfiguration` - Base system configuration to be included in the app's SystemConfiguration Object
81
+ 1. `CoreAccount` - Base account object that is related to notifications and the ilk.
71
82
  #### System Configuration
72
83
  Define a `SystemConfiguration` class in your project and import the core concern.
73
84
 
@@ -80,4 +91,16 @@ class SystemConfiguration
80
91
  field :google_sso_client_id, type: String
81
92
  end
82
93
  ```
94
+ #### Account
95
+ Define a `Account` class in your project and import the core concern.
96
+
97
+ ```
98
+ class Account
99
+ include StandardModel
100
+ include CoreAccount
101
+
102
+ # Include your additional system configuration fields and methods
103
+ has_many :users
104
+ end
105
+ ```
83
106
 
@@ -0,0 +1,175 @@
1
+ #
2
+ # Mixin for App47 objects to handle logging in both the rails environment as well
3
+ # as the delayed jobs environment that doesn't know about Rails.logger
4
+ #
5
+ # Provides ways to log at the class level as well as instance level.
6
+ #
7
+ #
8
+ # Usage:
9
+ # App47Logger.log_debug('message')
10
+ #
11
+ # or
12
+ #
13
+ # class ClassName
14
+ # include App47Logger
15
+ #
16
+ # def method_name
17
+ # log_debug('message')
18
+ # end
19
+ #
20
+ module App47Logger
21
+ #
22
+ # Log a debug messages
23
+ #
24
+ def self.log_debug(message)
25
+ log_message :debug, message
26
+ end
27
+
28
+ #
29
+ # Log a warning messages
30
+ #
31
+ # 1. Prints the messages
32
+ # 2. If an exception is passed n
33
+ # 2a prints the exception message
34
+ # 2b prints the stack trace
35
+ #
36
+ def self.log_warn(message, exception = nil)
37
+ log_message :warn, message
38
+ log_exception :warn, exception
39
+ end
40
+
41
+ #
42
+ # Log an error messages
43
+ #
44
+ # 1. Prints the messages
45
+ # 2. If an exception is passed n
46
+ # 2a prints the exception message
47
+ # 2b prints the stack trace
48
+ #
49
+ def self.log_error(message, exception = nil)
50
+ log_message :error, message
51
+ log_exception(:error, exception)
52
+ message = { message: message, exception: exception&.message }
53
+ SlackNotification.say message, template: :error_message
54
+ end
55
+
56
+ #
57
+ # Log a given exception, but only the first 10 lines in anything but test.
58
+ #
59
+ # In testing, we want the full stack to know the test case that failed.
60
+ #
61
+ def self.log_exception(level, exception = nil, max_frame = 9)
62
+ return if exception.blank?
63
+
64
+ max_frame = -1 if ENV['RACK_ENV'].eql?('test')
65
+ log_message(level, exception.message)
66
+ exception.backtrace[0..max_frame].each { |frame| log_message(level, frame) } unless exception.backtrace.blank?
67
+ end
68
+
69
+ #
70
+ # Log a given message at the given level
71
+ #
72
+ def self.log_message(level, message)
73
+ if Rails.env.test?
74
+ puts "#{level}: #{message}"
75
+ elsif Delayed::Worker.logger.nil?
76
+ Rails.logger.send level, message
77
+ else
78
+ Delayed::Worker.logger.send level, message
79
+ end
80
+ end
81
+
82
+ #
83
+ # Log a debug message as part of the mixin
84
+ #
85
+ def log_message(level, message)
86
+ App47Logger.log_message level, message
87
+ end
88
+
89
+ #
90
+ # Log a debug message as part of the mixin
91
+ #
92
+ def log_debug(message)
93
+ App47Logger.log_debug message
94
+ end
95
+
96
+ #
97
+ # Log a warning message as part of the mixin
98
+ #
99
+ def log_warn(message, exception = nil)
100
+ App47Logger.log_warn message, exception
101
+ end
102
+
103
+ #
104
+ # Log an error message as part of the mixin
105
+ #
106
+ def log_error(message, exception = nil)
107
+ App47Logger.log_error message, exception
108
+ end
109
+
110
+ #
111
+ # Log a controller error message
112
+ #
113
+ def log_controller_error(exception, redirecting = false)
114
+ if exception.is_a? ActionController::RoutingError
115
+ App47Logger.log_warn "#{controller_name}##{action_name} #{clean_params(params)}", exception
116
+ else
117
+ App47Logger.log_error "#{controller_name}##{action_name} #{clean_params(params)}", exception
118
+ end
119
+ update_flash_messages(exception, redirecting) if defined?(request) && request.present?
120
+ end
121
+
122
+ #
123
+ # Update the flash message based on the type of exception we get
124
+ # Currently we only handle mongoid errors, but there may be other
125
+ # common errors we can handle formatting for...
126
+ #
127
+ def update_flash_messages(exception, redirecting = false)
128
+ case exception
129
+ when Mongoid::Errors::Validations
130
+ if redirecting
131
+ flash[:error] = exception.problem
132
+ flash[:warning] = exception.summary
133
+ else
134
+ flash.now[:error] = exception.problem
135
+ flash.now[:warning] = exception.summary
136
+ end
137
+ else
138
+ if redirecting
139
+ flash[:error] = exception.message
140
+ else
141
+ flash.now[:error] = exception.message
142
+ end
143
+ end
144
+ end
145
+
146
+ #
147
+ # Recursively hide any fields in the rails config filter_parameters
148
+ #
149
+ def clean_params(pars)
150
+ pars.each do |key, value|
151
+ if mask_parameter_keys.include?(key)
152
+ pars[key] = '[FILTERED]'
153
+ elsif delete_parameter_keys.include?(key)
154
+ pars.delete(key)
155
+ elsif value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
156
+ pars[key] = clean_params(value)
157
+ end
158
+ end
159
+ pars
160
+ end
161
+
162
+ #
163
+ # which parameters to filter out
164
+ #
165
+ def mask_parameter_keys
166
+ @mask_parameter_keys ||= Rails.application.config.filter_parameters
167
+ end
168
+
169
+ #
170
+ # which parameters to filter out
171
+ #
172
+ def delete_parameter_keys
173
+ @delete_parameter_keys ||= %w[file authenticity_token commit upload]
174
+ end
175
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # The System configuration. Various configuration items that can be updated/defined at run time
5
+ #
6
+ # Use of this class allows you to simply ask for the configuration parameter directly without
7
+ # first having to get an instance of it.
8
+ #
9
+ # SystemConfiguration.queue_impl #=> 'RedisQueue'
10
+ #
11
+ # This method only is allowed for accessors, you should NEVER set values on the SystemConfiguration
12
+ # unless you are updating via the Admin or Stack UI, or during testing to setup a specific configuration
13
+ # for that.
14
+ #
15
+ module CoreAccount
16
+ extend ActiveSupport::Concern
17
+
18
+ def self.included(base)
19
+ base.class_eval do
20
+ #
21
+ # Fields
22
+ #
23
+ field :name, type: String
24
+ #
25
+ # Relationships
26
+ #
27
+ has_many :notifications, dependent: :delete do
28
+ def emails
29
+ where(_type: 'EmailNotification')
30
+ end
31
+
32
+ def slacks
33
+ where(_type: 'SlackNotification')
34
+ end
35
+
36
+ def sms
37
+ where(_type: 'SmsNotification')
38
+ end
39
+ end
40
+ has_many :templates, dependent: :delete
41
+ embeds_one :smtp_configuration
42
+ end
43
+ end
44
+
45
+ #
46
+ # Return or build the smtp configuration for the account
47
+ #
48
+ def fetch_smtp_configuration
49
+ smtp_configuration || build_smtp_configuration
50
+ end
51
+ end
@@ -6,15 +6,18 @@
6
6
  #
7
7
  module StandardModel
8
8
  extend ActiveSupport::Concern
9
+ include Mongoid::Document
10
+ include Mongoid::Timestamps
11
+ include App47Logger
12
+ # include Auditable
9
13
 
10
14
  def self.included(base)
11
15
  base.class_eval do
12
- include Mongoid::Document
13
- include Mongoid::Timestamps
14
- # include App47Logger
15
- # include Auditable
16
- include Formable
17
- include AutoClearCache
16
+ #
17
+ # Callbacks
18
+ #
19
+ after_save :clear_cache
20
+ before_destroy :clear_cache
18
21
  end
19
22
  end
20
23
 
@@ -37,5 +40,100 @@ module StandardModel
37
40
  def make_options(options)
38
41
  options.collect { |t| [t, t.humanize] }
39
42
  end
43
+
44
+ #
45
+ # Return the complete list of key names that would appear in the form.
46
+ #
47
+ def allowed_param_names(filter_names = [])
48
+ # Always filter out the mongoid reserved items
49
+ filter_names += %w[created_at updated_at _type _id]
50
+ associations = all_associations
51
+ # filter out the relationship names so we don't have dups
52
+ associations.each { |association| filter_names << association.keys.first }
53
+ (field_names + associations).delete_if { |name| filter_names.include?(name) }
54
+ rescue StandardError
55
+ attribute_names.delete_if { |name| filter_names.include?(name) }
56
+ end
57
+
58
+ #
59
+ # allow the model to filter out a name if they want to, meaning the model
60
+ # can return a subset of attribute names
61
+ #
62
+ def field_names
63
+ attribute_names
64
+ end
65
+
66
+ #
67
+ # gather up the collections we care about and return them. For now, the
68
+ # many to many associations are the ones that need some extra help.
69
+ #
70
+ def all_associations
71
+ many_to_many_associations
72
+ end
73
+
74
+ #
75
+ # Return a collection of many to many assocations. We basically
76
+ # need to turn the current value returned by attribute names
77
+ #
78
+ # relationship_ids
79
+ #
80
+ # to
81
+ #
82
+ # { relationship_ids => [] }
83
+ #
84
+ # Telling the permit command to accept the value as an array of items.
85
+ #
86
+ def many_to_many_associations
87
+ associations = []
88
+ reflect_on_all_associations.each do |association|
89
+ next unless association.macro == :has_and_belongs_to_many
90
+
91
+ associations << { association.key => [] }
92
+ end
93
+ associations
94
+ end
95
+ end
96
+
97
+ #
98
+ # Remove updates for secure fields that come across as blank to start with and get removed on update
99
+ #
100
+ def update(params)
101
+ super(remove_blank_secure_fields(params))
102
+ end
103
+
104
+ alias :update_attributes :update
105
+
106
+ #
107
+ # Remove updates for secure fields that come across as blank to start with and get removed on update
108
+ #
109
+ def update!(params)
110
+ super(remove_blank_secure_fields(params))
111
+ end
112
+
113
+ alias :update_attributes! :update!
114
+
115
+ #
116
+ # List of secure fields, to add fields in concrete class, simply override this method
117
+ #
118
+ def secure_fields
119
+ []
120
+ end
121
+
122
+ def remove_blank_secure_fields(params)
123
+ secure_fields.each { |field| params.delete(field) if params[field].blank? }
124
+ params
125
+ end
126
+
127
+ #
128
+ # Clear the cache
129
+ #
130
+ def clear_cache
131
+ Rails.cache.delete_matched "*#{id}*"
132
+ return unless respond_to?(:account) && account.present? && account.is_a?(Account)
133
+
134
+ Rails.cache.delete_matched "*#{account.id}*"
135
+ true # Force a return of true so that we don't break the callback chain.
136
+ rescue StandardError
137
+ false
40
138
  end
41
139
  end