web47core 0.3.2 → 0.3.3
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.
- 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
|
+
* [](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Grade)
|
|
7
|
+
* [](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
|
|
8
|
+
* Develop: [](https://circleci.com/gh/App47/web47core/tree/develop)
|
|
9
|
+
* Master: [](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
|