web47core 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +41 -41
- data/lib/app/jobs/cron/command.rb +11 -4
- data/lib/app/jobs/cron/server.rb +1 -3
- data/lib/app/models/audit_log.rb +28 -0
- data/lib/app/models/concerns/app47_logger.rb +9 -5
- data/lib/app/models/concerns/roleable.rb +12 -0
- data/lib/app/models/concerns/standard_model.rb +195 -1
- data/lib/app/models/notification_template.rb +0 -1
- data/lib/app/models/user_action_audit_log.rb +19 -0
- data/lib/app/models/user_audit_log.rb +44 -0
- data/lib/app/models/user_model_audit_log.rb +19 -0
- data/lib/web47core/config.rb +20 -1
- data/lib/web47core/version.rb +1 -1
- data/lib/web47core.rb +9 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37c68ad675e2db02ba5189cbdee9077a4cc8498dbfdb7e33491ac0f84f5293a6
|
4
|
+
data.tar.gz: eb82f4a26de3a7dee42eb8b9d9b35cd4e8f64f5b8f78a1f816b6a3fa1a445190
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3ca1165e76a47c65a1eb9dee9a40905ab1e139b246200d1671515fd5d0cda04f961f27747e08c01e870af82c3fa645de685ab784eb016b9a0b37c1f62348fb9
|
7
|
+
data.tar.gz: 8461c3e37316fe7e564683577639668745d4b910c56ed242fc7c3ecf78e673003a0a3e9a302633fe7faca72e8c70a6e14648119048fb0f0d598b56403db9848d
|
data/README.md
CHANGED
@@ -3,14 +3,14 @@ Core components used commonly among all web apps for both App47 and RedMonocle
|
|
3
3
|
|
4
4
|
## We don't need no sticking badges
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
* [![Codacy Badge](https://api.codacy.com/project/badge/Grade/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Grade)
|
7
|
+
* [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
|
8
|
+
* Develop: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/develop.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/develop)
|
9
|
+
* Master: [![CircleCI](https://circleci.com/gh/App47/web47core/tree/master.svg?style=svg&circle-token=9999e0634dd96ad5414f4f3e56c39ba6d3e0e4e6)](https://circleci.com/gh/App47/web47core/tree/master)
|
10
10
|
|
11
11
|
## Requirements
|
12
12
|
|
13
|
-
|
13
|
+
* Ruby 2.4.1
|
14
14
|
|
15
15
|
### Working with Bundler and RVM
|
16
16
|
|
@@ -44,9 +44,9 @@ bundle exec rake test
|
|
44
44
|
## Deployment
|
45
45
|
The `web47core` project is a gem that will be deployed via [Ruby Gems](https://rubygems.org). When an update is ready, the following steps should be followed
|
46
46
|
|
47
|
-
1. Build the gem `gem build web47core.gemspec`
|
48
|
-
2. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-version.gem`
|
49
|
-
3. There may be a delay when using the gem file
|
47
|
+
1. Build the gem `gem build web47core.gemspec`
|
48
|
+
2. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-version.gem`
|
49
|
+
3. There may be a delay when using the gem file
|
50
50
|
|
51
51
|
## Usage
|
52
52
|
### Importing the gem
|
@@ -69,31 +69,31 @@ gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :develop
|
|
69
69
|
_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_
|
70
70
|
|
71
71
|
### Remove the following files
|
72
|
-
1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
|
73
|
-
2. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
|
74
|
-
3. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
|
75
|
-
4. `Formable` - Consolidated into StandardModel, was used to provide common form operations for mongoid documents
|
76
|
-
5. `EmailNotification`
|
77
|
-
6. `EmailTemplate`
|
78
|
-
7. `Notification`
|
79
|
-
8. `NotificationTemplate`
|
80
|
-
9. `SlackNotification`
|
81
|
-
10. `SmsNotification`
|
82
|
-
11. `Template`
|
83
|
-
12. `App47Logger` and `App47LoggerTest`
|
84
|
-
13. `Emailable` or `EmailAble` and `EamailbleTest`, be sure to change `Emailable` to `EmailAble`
|
85
|
-
14. `RedisConfiguration` and `RedisConfgurationTest`
|
86
|
-
15. `Searchable` and `SearchableTest`, be sure to change `Searchable` to `SearchAble`
|
87
|
-
16. `TimezoneAble` and `TimezoneAbleTest`
|
88
|
-
17. `CronJobServer` and `CronJobServerTest`
|
89
|
-
18. `JobCronTab` and `JobCronTabTest`
|
90
|
-
19. `CronTab`
|
72
|
+
1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
|
73
|
+
2. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
|
74
|
+
3. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
|
75
|
+
4. `Formable` - Consolidated into StandardModel, was used to provide common form operations for mongoid documents
|
76
|
+
5. `EmailNotification`
|
77
|
+
6. `EmailTemplate`
|
78
|
+
7. `Notification`
|
79
|
+
8. `NotificationTemplate`
|
80
|
+
9. `SlackNotification`
|
81
|
+
10. `SmsNotification`
|
82
|
+
11. `Template`
|
83
|
+
12. `App47Logger` and `App47LoggerTest`
|
84
|
+
13. `Emailable` or `EmailAble` and `EamailbleTest`, be sure to change `Emailable` to `EmailAble`
|
85
|
+
14. `RedisConfiguration` and `RedisConfgurationTest`
|
86
|
+
15. `Searchable` and `SearchableTest`, be sure to change `Searchable` to `SearchAble`
|
87
|
+
16. `TimezoneAble` and `TimezoneAbleTest`
|
88
|
+
17. `CronJobServer` and `CronJobServerTest`
|
89
|
+
18. `JobCronTab` and `JobCronTabTest`
|
90
|
+
19. `CronTab`
|
91
91
|
|
92
92
|
#### Models
|
93
93
|
##### Concerns
|
94
|
-
1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
|
95
|
-
2. `CoreSystemConfiguration` - Base system configuration to be included in the app's SystemConfiguration Object
|
96
|
-
3. `CoreAccount` - Base account object that is related to notifications and the ilk.
|
94
|
+
1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
|
95
|
+
2. `CoreSystemConfiguration` - Base system configuration to be included in the app's SystemConfiguration Object
|
96
|
+
3. `CoreAccount` - Base account object that is related to notifications and the ilk.
|
97
97
|
##### System Configuration
|
98
98
|
Define a `SystemConfiguration` class in your project and import the core concern.
|
99
99
|
|
@@ -120,9 +120,9 @@ end
|
|
120
120
|
```
|
121
121
|
##### Cron
|
122
122
|
Cron infrastructure for running jobs every minute, hour, day, week, month or some combination
|
123
|
-
1. Remove `config/initializers/job_cron_tabs.rb` that was previous used to ensure cron tabs, they will be loaded automatically now
|
124
|
-
2. Remove the `Delayed::Backend::Mongoid::Job` class definition, not the settings from `config/initializers/delayed_job.rb`, these are included in this gem now.
|
125
|
-
3. Cron jobs should extend from `Cron::Job` now and specify `cron_tab_entry` within the class.
|
123
|
+
1. Remove `config/initializers/job_cron_tabs.rb` that was previous used to ensure cron tabs, they will be loaded automatically now
|
124
|
+
2. Remove the `Delayed::Backend::Mongoid::Job` class definition, not the settings from `config/initializers/delayed_job.rb`, these are included in this gem now.
|
125
|
+
3. Cron jobs should extend from `Cron::Job` now and specify `cron_tab_entry` within the class.
|
126
126
|
```ruby
|
127
127
|
module Cron
|
128
128
|
class MyJob < Job
|
@@ -134,14 +134,14 @@ module Cron
|
|
134
134
|
end
|
135
135
|
```
|
136
136
|
Allowed values of cron_tab_entry are
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
137
|
+
* `:always` - run every minute
|
138
|
+
* `:hourly` - run every hour
|
139
|
+
* `:daily` - run every day
|
140
|
+
* `:weekly` - run every week on Sunday
|
141
|
+
* `:monthly` - run every month on the first day of the month
|
142
|
+
* `'*/5 1,3 * 2 *'` - Run according to unix crontab entry format. This would run every tuesday on the 1st and 3rd hour, for any minute divisible by 5, so 0, 5, 10, 15, etc..
|
143
|
+
|
144
|
+
Before starting the server, you need to run the database command
|
145
145
|
```mongo
|
146
146
|
db.cron_tabs.updateMany({_type: 'JobCronTab'}, {$set: {_type: 'Cron::JobTab'}});
|
147
147
|
```
|
@@ -15,8 +15,9 @@ module Cron
|
|
15
15
|
#
|
16
16
|
class Command
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
#
|
19
|
+
# Initialize the command
|
20
|
+
#
|
20
21
|
def initialize(args)
|
21
22
|
@options = { pid_dir: "#{root}/tmp/pids", log_dir: "#{root}/log", monitor: false }
|
22
23
|
|
@@ -27,7 +28,7 @@ module Cron
|
|
27
28
|
warn opt
|
28
29
|
exit 1
|
29
30
|
end
|
30
|
-
opt.on('-e', '--environment=NAME', 'Specifies the environment to run this delayed jobs under (test/development/production).') do
|
31
|
+
opt.on('-e', '--environment=NAME', 'Specifies the environment to run this delayed jobs under (test/development/production).') do
|
31
32
|
warn 'The -e/--environment option has been deprecated and has no effect. Use RAILS_ENV and see http://github.com/collectiveidea/delayed_job/issues/7'
|
32
33
|
end
|
33
34
|
opt.on('--pid-dir=DIR', 'Specifies an alternate directory in which to store the process ids.') do |dir|
|
@@ -49,6 +50,9 @@ module Cron
|
|
49
50
|
@args = opts.parse!(args) + (@daemon_options || [])
|
50
51
|
end
|
51
52
|
|
53
|
+
#
|
54
|
+
# Start the background loop
|
55
|
+
#
|
52
56
|
def daemonize
|
53
57
|
dir = @options[:pid_dir]
|
54
58
|
FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
@@ -61,8 +65,11 @@ module Cron
|
|
61
65
|
|
62
66
|
private
|
63
67
|
|
68
|
+
#
|
69
|
+
# Get the root file
|
70
|
+
#
|
64
71
|
def root
|
65
|
-
@root ||= defined?(::Rails.root) ? ::Rails.root :
|
72
|
+
@root ||= defined?(::Rails.root) ? ::Rails.root : Pathname.new(Dir.pwd)
|
66
73
|
end
|
67
74
|
end
|
68
75
|
end
|
data/lib/app/jobs/cron/server.rb
CHANGED
@@ -110,12 +110,10 @@ module Cron
|
|
110
110
|
|
111
111
|
#
|
112
112
|
# Become secondary node
|
113
|
-
# TODO: [CMS] Update when auditing in place
|
114
113
|
#
|
115
114
|
def become_secondary(user = nil)
|
116
115
|
if user.present?
|
117
|
-
|
118
|
-
update! state: STATE_SECONDARY
|
116
|
+
update_and_log! user, state: STATE_SECONDARY
|
119
117
|
else
|
120
118
|
update! state: STATE_SECONDARY
|
121
119
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Base AuditLog class, changes made outside of users
|
5
|
+
#
|
6
|
+
class AuditLog
|
7
|
+
include StandardModel
|
8
|
+
include SearchAble
|
9
|
+
#
|
10
|
+
# Constants
|
11
|
+
#
|
12
|
+
CREATE_ACTION = 'create' unless defined? CREATE_ACTION
|
13
|
+
UPDATE_ACTION = 'update' unless defined? UPDATE_ACTION
|
14
|
+
DELETE_ACTION = 'delete' unless defined? DELETE_ACTION
|
15
|
+
ALL_ACTIONS = [CREATE_ACTION, UPDATE_ACTION, DELETE_ACTION].freeze unless defined? ALL_ACTIONS
|
16
|
+
#
|
17
|
+
# Fields
|
18
|
+
#
|
19
|
+
field :action, type: String
|
20
|
+
#
|
21
|
+
# Validations
|
22
|
+
#
|
23
|
+
validates :action, inclusion: {in: ALL_ACTIONS}
|
24
|
+
|
25
|
+
def self.sort_order
|
26
|
+
[:created_at, -1]
|
27
|
+
end
|
28
|
+
end
|
@@ -143,14 +143,18 @@ module App47Logger
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
+
def clean_params(pars)
|
147
|
+
App47Logger.clean_params(pars)
|
148
|
+
end
|
149
|
+
|
146
150
|
#
|
147
151
|
# Recursively hide any fields in the rails config filter_parameters
|
148
152
|
#
|
149
|
-
def clean_params(pars)
|
153
|
+
def self.clean_params(pars)
|
150
154
|
pars.each do |key, value|
|
151
|
-
if mask_parameter_keys.include?(key)
|
155
|
+
if App47Logger.mask_parameter_keys.include?(key.to_s)
|
152
156
|
pars[key] = '[FILTERED]'
|
153
|
-
elsif delete_parameter_keys.include?(key)
|
157
|
+
elsif App47Logger.delete_parameter_keys.include?(key.to_s)
|
154
158
|
pars.delete(key)
|
155
159
|
elsif value.is_a?(Hash) || value.is_a?(ActionController::Parameters)
|
156
160
|
pars[key] = clean_params(value)
|
@@ -162,14 +166,14 @@ module App47Logger
|
|
162
166
|
#
|
163
167
|
# which parameters to filter out
|
164
168
|
#
|
165
|
-
def mask_parameter_keys
|
169
|
+
def self.mask_parameter_keys
|
166
170
|
@mask_parameter_keys ||= Rails.application.config.filter_parameters
|
167
171
|
end
|
168
172
|
|
169
173
|
#
|
170
174
|
# which parameters to filter out
|
171
175
|
#
|
172
|
-
def delete_parameter_keys
|
176
|
+
def self.delete_parameter_keys
|
173
177
|
@delete_parameter_keys ||= %w[file authenticity_token commit upload]
|
174
178
|
end
|
175
179
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Constants for a role
|
5
|
+
#
|
6
|
+
module Roleable
|
7
|
+
ROLE_NONE = 'none' unless defined? ROLE_NONE
|
8
|
+
ROLE_VIEW = 'view' unless defined? ROLE_VIEW
|
9
|
+
ROLE_EDIT = 'edit' unless defined? ROLE_EDIT
|
10
|
+
ROLE_ADMIN = 'admin' unless defined? ROLE_ADMIN
|
11
|
+
ALL_ROLES = [ROLE_NONE, ROLE_VIEW, ROLE_EDIT, ROLE_ADMIN].freeze unless defined? ALL_ROLES
|
12
|
+
end
|
@@ -9,15 +9,28 @@ module StandardModel
|
|
9
9
|
include Mongoid::Document
|
10
10
|
include Mongoid::Timestamps
|
11
11
|
include App47Logger
|
12
|
-
# include Auditable
|
13
12
|
|
14
13
|
def self.included(base)
|
15
14
|
base.class_eval do
|
15
|
+
#
|
16
|
+
# Fields
|
17
|
+
#
|
18
|
+
field :last_modified_by_email
|
19
|
+
field :last_modified_by_name
|
20
|
+
field :created_by_email
|
21
|
+
field :created_by_name
|
22
|
+
#
|
23
|
+
# Relationships
|
24
|
+
#
|
25
|
+
belongs_to :last_modified_by, class_name: 'User', optional: true
|
26
|
+
belongs_to :created_by, class_name: 'User', optional: true
|
27
|
+
has_many Web47core::Config.user_audit_model_log_symbol, dependent: :nullify
|
16
28
|
#
|
17
29
|
# Callbacks
|
18
30
|
#
|
19
31
|
after_save :clear_cache
|
20
32
|
before_destroy :clear_cache
|
33
|
+
before_save :capture_user_info
|
21
34
|
end
|
22
35
|
end
|
23
36
|
|
@@ -92,6 +105,48 @@ module StandardModel
|
|
92
105
|
end
|
93
106
|
associations
|
94
107
|
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Find or create by filter, the log the action
|
111
|
+
#
|
112
|
+
def find_or_create_by_and_log!(user, attributes)
|
113
|
+
model = find_or_initialize_by(attributes)
|
114
|
+
log_change(user, model, attributes) if model.new_record? && model.valid?
|
115
|
+
model.save!
|
116
|
+
model
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Record the creation with this user
|
121
|
+
#
|
122
|
+
def create_and_log(user, attributes)
|
123
|
+
attributes[:last_modified_by_id] = user.id
|
124
|
+
attributes[:created_by_id] = user.id
|
125
|
+
model = create(attributes)
|
126
|
+
log_change(user, model, attributes) if model.valid?
|
127
|
+
model
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Record the creation with this user
|
132
|
+
#
|
133
|
+
def create_and_log!(user, attributes)
|
134
|
+
attributes[:last_modified_by_id] = user.id
|
135
|
+
attributes[:created_by_id] = user.id
|
136
|
+
model = create!(attributes)
|
137
|
+
log_change(user, model, attributes)
|
138
|
+
model
|
139
|
+
end
|
140
|
+
|
141
|
+
#
|
142
|
+
# Log the audit record
|
143
|
+
#
|
144
|
+
def log_change(user, model, changes)
|
145
|
+
Web47core::Config.user_audit_model_log_class.create!(Web47core::Config.user_audit_model => user,
|
146
|
+
model: model,
|
147
|
+
action: model.audit_action,
|
148
|
+
changed_values: App47Logger.clean_params(changes).to_json)
|
149
|
+
end
|
95
150
|
end
|
96
151
|
|
97
152
|
#
|
@@ -136,4 +191,143 @@ module StandardModel
|
|
136
191
|
rescue StandardError
|
137
192
|
false
|
138
193
|
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# record a change for the object instance
|
197
|
+
#
|
198
|
+
def log_change(user, changes, action)
|
199
|
+
Web47core::Config.user_audit_model_log_class.create!(Web47core::Config.user_audit_model => user,
|
200
|
+
model: self,
|
201
|
+
action: action,
|
202
|
+
changed_values: App47Logger.clean_params(changes).to_json)
|
203
|
+
end
|
204
|
+
|
205
|
+
def audit_action
|
206
|
+
new_record? ? AuditLog::CREATE_ACTION : AuditLog::UPDATE_ACTION
|
207
|
+
end
|
208
|
+
|
209
|
+
#
|
210
|
+
# Safely get the display name of who last modified this object
|
211
|
+
#
|
212
|
+
def last_modified_by_display_name
|
213
|
+
last_modified_by.name
|
214
|
+
rescue StandardError
|
215
|
+
"#{last_modified_by_name} (#{last_modified_by_email}) - deleted"
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# Safely get the display name of who created this object
|
220
|
+
#
|
221
|
+
def created_by_display_name
|
222
|
+
created_by.name
|
223
|
+
rescue StandardError
|
224
|
+
"#{created_by_name} (#{created_by_email}) - deleted"
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Record an update
|
229
|
+
#
|
230
|
+
def update_and_log(user, attributes)
|
231
|
+
return self if attributes.blank?
|
232
|
+
|
233
|
+
action = audit_action
|
234
|
+
attributes[:last_modified_by_id] = user.id
|
235
|
+
result = update(attributes)
|
236
|
+
log_change(user, attributes, action) if valid?
|
237
|
+
result
|
238
|
+
end
|
239
|
+
|
240
|
+
alias update_attributes_and_log update_and_log
|
241
|
+
|
242
|
+
#
|
243
|
+
# Record an update
|
244
|
+
#
|
245
|
+
def update_and_log!(user, attributes)
|
246
|
+
return self if attributes.blank?
|
247
|
+
|
248
|
+
action = audit_action
|
249
|
+
attributes[:last_modified_by_id] = user.id
|
250
|
+
result = update!(attributes)
|
251
|
+
log_change(user, attributes, action)
|
252
|
+
result
|
253
|
+
end
|
254
|
+
|
255
|
+
alias update_attributes_and_log! update_and_log!
|
256
|
+
|
257
|
+
#
|
258
|
+
# Record a save
|
259
|
+
#
|
260
|
+
def save_and_log(user, options = {})
|
261
|
+
self.created_by = user if new_record?
|
262
|
+
self.last_modified_by = user
|
263
|
+
model_changes = changes
|
264
|
+
action = audit_action
|
265
|
+
result = save(options)
|
266
|
+
log_change(user, model_changes, action) if valid?
|
267
|
+
result
|
268
|
+
end
|
269
|
+
|
270
|
+
#
|
271
|
+
# Record an save
|
272
|
+
#
|
273
|
+
def save_and_log!(user, options = {})
|
274
|
+
self.created_by = user if new_record?
|
275
|
+
self.last_modified_by = user
|
276
|
+
model_changes = changes
|
277
|
+
action = audit_action
|
278
|
+
result = save!(options)
|
279
|
+
log_change(user, model_changes, action)
|
280
|
+
result
|
281
|
+
end
|
282
|
+
|
283
|
+
#
|
284
|
+
# Record a destroy and destroy the thingy
|
285
|
+
#
|
286
|
+
def destroy_and_log(user)
|
287
|
+
log_deletion(user, self)
|
288
|
+
destroy
|
289
|
+
end
|
290
|
+
|
291
|
+
#
|
292
|
+
# Record a delete and delete the thingy
|
293
|
+
#
|
294
|
+
def delete_and_log(user)
|
295
|
+
log_deletion(user, self)
|
296
|
+
delete
|
297
|
+
end
|
298
|
+
|
299
|
+
#
|
300
|
+
# Log the deletion, capturing the current values of the record before it is removed from the system
|
301
|
+
#
|
302
|
+
def log_deletion(user, model)
|
303
|
+
Web47core::Config.user_audit_model_log_class.create!(Web47core::Config.user_audit_model => user,
|
304
|
+
model: model,
|
305
|
+
action: AuditLog::DELETE_ACTION,
|
306
|
+
changed_values: App47Logger.clean_params(attributes).to_json)
|
307
|
+
end
|
308
|
+
|
309
|
+
def capture_user_info
|
310
|
+
auto_strip_attributes
|
311
|
+
if last_modified_by.present?
|
312
|
+
self.last_modified_by_name = last_modified_by.name
|
313
|
+
self.last_modified_by_email = last_modified_by.email
|
314
|
+
end
|
315
|
+
return unless created_by.present? && new_record?
|
316
|
+
|
317
|
+
self.created_by_name = created_by.name
|
318
|
+
self.created_by_email = created_by.email
|
319
|
+
end
|
320
|
+
|
321
|
+
#
|
322
|
+
# Automatically strip any leading or trailing whitespace on model attribute
|
323
|
+
# values.
|
324
|
+
#
|
325
|
+
def auto_strip_attributes
|
326
|
+
# Iterate through all attributes and strip those which respond
|
327
|
+
# to the method
|
328
|
+
attribute_names.each do |name|
|
329
|
+
attr = send(name)
|
330
|
+
send("#{name}=", attr.strip) if attr.respond_to?(:strip)
|
331
|
+
end
|
332
|
+
end
|
139
333
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Keep track of User Actions
|
5
|
+
#
|
6
|
+
class UserActionAuditLog < UserAuditLog
|
7
|
+
#
|
8
|
+
# Fields
|
9
|
+
#
|
10
|
+
field :name, type: String
|
11
|
+
field :params, type: String
|
12
|
+
field :request_ip, type: String
|
13
|
+
field :request_agent, type: String
|
14
|
+
field :response_code, type: Integer
|
15
|
+
|
16
|
+
def search_fields
|
17
|
+
%w[name action response_code request_ip request_agent] + super
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# UserAuditLog class, changes made by users
|
5
|
+
#
|
6
|
+
class UserAuditLog < AuditLog
|
7
|
+
#
|
8
|
+
# Fields
|
9
|
+
#
|
10
|
+
field :raw_user_name, type: String
|
11
|
+
field :raw_email, type: String
|
12
|
+
#
|
13
|
+
# Relationships
|
14
|
+
#
|
15
|
+
belongs_to :user
|
16
|
+
#
|
17
|
+
# Call backs
|
18
|
+
#
|
19
|
+
before_validation :record_names
|
20
|
+
|
21
|
+
def search_fields
|
22
|
+
%w[raw_user_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Safely return the user name
|
27
|
+
#
|
28
|
+
def user_name
|
29
|
+
user.name
|
30
|
+
rescue StandardError
|
31
|
+
raw_user_name || 'Unknown'
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
#
|
37
|
+
# update the user name in case it is deleted
|
38
|
+
#
|
39
|
+
def record_names
|
40
|
+
return if user.blank?
|
41
|
+
self.raw_user_name = user.name
|
42
|
+
self.raw_email = user.email
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Keep track of User Model changes
|
5
|
+
#
|
6
|
+
class UserModelAuditLog < UserAuditLog
|
7
|
+
#
|
8
|
+
# Fields
|
9
|
+
#
|
10
|
+
field :changed_values, type: String
|
11
|
+
#
|
12
|
+
# Relationships
|
13
|
+
#
|
14
|
+
belongs_to :model, polymorphic: true, dependent: :nullify
|
15
|
+
|
16
|
+
def search_fields
|
17
|
+
%w[action] + super
|
18
|
+
end
|
19
|
+
end
|
data/lib/web47core/config.rb
CHANGED
@@ -6,11 +6,30 @@ module Web47core
|
|
6
6
|
#
|
7
7
|
class Config
|
8
8
|
include Singleton
|
9
|
-
attr_accessor :email_able_models, :switchboard_able_models
|
9
|
+
attr_accessor :email_able_models, :switchboard_able_models, :user_audit_model
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@email_able_models = []
|
13
13
|
@switchboard_able_models = []
|
14
|
+
@user_audit_model = :user
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reset
|
18
|
+
instance.email_able_models = []
|
19
|
+
instance.switchboard_able_models = []
|
20
|
+
instance.user_audit_model = :user
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.user_audit_model_log_class
|
24
|
+
user_audit_model_log_class_name.constantize
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.user_audit_model_log_class_name
|
28
|
+
user_audit_model_log_symbol.camelize
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.user_audit_model_log_symbol
|
32
|
+
"#{instance.user_audit_model}_model_audit_log"
|
14
33
|
end
|
15
34
|
|
16
35
|
#
|
data/lib/web47core/version.rb
CHANGED
data/lib/web47core.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'web47core/config'
|
1
2
|
require 'app/models/concerns/app47_logger'
|
2
3
|
require 'app/models/concerns/cdn_url'
|
3
4
|
require 'app/models/concerns/email_able'
|
@@ -34,11 +35,18 @@ require 'app/jobs/cron/trim_notifications'
|
|
34
35
|
require 'app/jobs/cron/trim_cron_servers'
|
35
36
|
require 'app/jobs/cron/trim_failed_delayed_jobs'
|
36
37
|
#
|
38
|
+
# Audit Logs
|
39
|
+
#
|
40
|
+
require 'app/models/audit_log'
|
41
|
+
require 'app/models/user_audit_log'
|
42
|
+
require 'app/models/user_action_audit_log'
|
43
|
+
require 'app/models/user_model_audit_log'
|
44
|
+
#
|
45
|
+
#
|
37
46
|
# Controllers
|
38
47
|
#
|
39
48
|
require 'web47core/engine'
|
40
49
|
require 'web47core/version'
|
41
|
-
require 'web47core/config'
|
42
50
|
require 'app/controllers/concerns/restful_controller'
|
43
51
|
require 'app/controllers/concerns/core_controller'
|
44
52
|
require 'app/controllers/concerns/core_system_configuration_controller'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web47core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schroeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -607,11 +607,13 @@ files:
|
|
607
607
|
- lib/app/jobs/cron/trim_cron_servers.rb
|
608
608
|
- lib/app/jobs/cron/trim_failed_delayed_jobs.rb
|
609
609
|
- lib/app/jobs/cron/trim_notifications.rb
|
610
|
+
- lib/app/models/audit_log.rb
|
610
611
|
- lib/app/models/concerns/app47_logger.rb
|
611
612
|
- lib/app/models/concerns/cdn_url.rb
|
612
613
|
- lib/app/models/concerns/core_account.rb
|
613
614
|
- lib/app/models/concerns/core_system_configuration.rb
|
614
615
|
- lib/app/models/concerns/email_able.rb
|
616
|
+
- lib/app/models/concerns/roleable.rb
|
615
617
|
- lib/app/models/concerns/search_able.rb
|
616
618
|
- lib/app/models/concerns/standard_model.rb
|
617
619
|
- lib/app/models/concerns/switchboard_able.rb
|
@@ -626,6 +628,9 @@ files:
|
|
626
628
|
- lib/app/models/sms_notification.rb
|
627
629
|
- lib/app/models/smtp_configuration.rb
|
628
630
|
- lib/app/models/template.rb
|
631
|
+
- lib/app/models/user_action_audit_log.rb
|
632
|
+
- lib/app/models/user_audit_log.rb
|
633
|
+
- lib/app/models/user_model_audit_log.rb
|
629
634
|
- lib/templates/email/notification_failure.liquid
|
630
635
|
- lib/templates/email/notification_failure.subject.liquid
|
631
636
|
- lib/templates/slack/error_message.liquid
|