action-audit 1.0.1
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +17 -0
- data/CHANGELOG.md +29 -0
- data/CODE_OF_CONDUCT.md +25 -0
- data/LICENSE +21 -0
- data/README.md +232 -0
- data/Rakefile +12 -0
- data/docs/README.md +25 -0
- data/docs/api-reference.md +434 -0
- data/docs/configuration.md +230 -0
- data/docs/examples.md +609 -0
- data/docs/installation.md +114 -0
- data/docs/migration.md +571 -0
- data/docs/multi-engine.md +413 -0
- data/docs/troubleshooting.md +577 -0
- data/docs/usage.md +347 -0
- data/lib/action-audit.rb +3 -0
- data/lib/action_audit/audit_messages.rb +73 -0
- data/lib/action_audit/engine.rb +19 -0
- data/lib/action_audit/version.rb +5 -0
- data/lib/action_audit.rb +75 -0
- data/lib/generators/action_audit/install_generator.rb +25 -0
- data/lib/generators/action_audit/templates/README +25 -0
- data/lib/generators/action_audit/templates/action_audit.rb +17 -0
- data/lib/generators/action_audit/templates/audit.yml +30 -0
- data/sig/action_audit.rbs +4 -0
- metadata +146 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Multi-Engine Setup Guide
|
|
2
|
+
|
|
3
|
+
ActionAudit is designed to work seamlessly across multiple Rails engines, automatically discovering and loading audit configurations from each engine.
|
|
4
|
+
|
|
5
|
+
## How Multi-Engine Support Works
|
|
6
|
+
|
|
7
|
+
ActionAudit uses a Rails engine (`ActionAudit::Engine`) that automatically:
|
|
8
|
+
|
|
9
|
+
1. **Discovers all mounted engines** in your Rails application
|
|
10
|
+
2. **Looks for `config/audit.yml`** files in each engine's root directory
|
|
11
|
+
3. **Merges all configurations** into a single audit message registry
|
|
12
|
+
4. **Handles configuration reloading** in development mode
|
|
13
|
+
|
|
14
|
+
## Setting Up Multi-Engine Auditing
|
|
15
|
+
|
|
16
|
+
### Main Application Setup
|
|
17
|
+
|
|
18
|
+
1. **Add ActionAudit to your main app's Gemfile:**
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
# Gemfile
|
|
22
|
+
gem 'action_audit'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. **Create your main app's audit configuration:**
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
# config/audit.yml (main app)
|
|
29
|
+
sessions:
|
|
30
|
+
create: "User logged in with %{email}"
|
|
31
|
+
destroy: "User logged out"
|
|
32
|
+
|
|
33
|
+
profiles:
|
|
34
|
+
update: "User updated their profile"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. **Configure logging in your main app:**
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
# config/initializers/action_audit.rb (main app)
|
|
41
|
+
ActionAudit.log_tag = "AUDIT"
|
|
42
|
+
ActionAudit.log_formatter = ->(controller, action, msg) do
|
|
43
|
+
"[#{Time.current.iso8601}] #{controller}/#{action} | #{msg}"
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Engine Setup
|
|
48
|
+
|
|
49
|
+
Each engine can have its own audit configuration:
|
|
50
|
+
|
|
51
|
+
#### Engine 1: Admin Engine
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
# engines/admin_engine/lib/admin_engine.rb
|
|
55
|
+
module AdminEngine
|
|
56
|
+
class Engine < ::Rails::Engine
|
|
57
|
+
isolate_namespace AdminEngine
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
# engines/admin_engine/config/audit.yml
|
|
64
|
+
admin:
|
|
65
|
+
users:
|
|
66
|
+
create: "Admin created user %{email}"
|
|
67
|
+
update: "Admin updated user %{id}"
|
|
68
|
+
destroy: "Admin deleted user %{id}"
|
|
69
|
+
|
|
70
|
+
settings:
|
|
71
|
+
update: "Admin updated %{setting_name} setting"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
# engines/admin_engine/app/controllers/admin/users_controller.rb
|
|
76
|
+
class Admin::UsersController < ApplicationController
|
|
77
|
+
include ActionAudit
|
|
78
|
+
|
|
79
|
+
def create
|
|
80
|
+
# Will log: "Admin created user john@example.com"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### Engine 2: API Engine
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# engines/api_engine/lib/api_engine.rb
|
|
89
|
+
module ApiEngine
|
|
90
|
+
class Engine < ::Rails::Engine
|
|
91
|
+
isolate_namespace ApiEngine
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
# engines/api_engine/config/audit.yml
|
|
98
|
+
api:
|
|
99
|
+
v1:
|
|
100
|
+
webhooks:
|
|
101
|
+
create: "Webhook received from %{source}"
|
|
102
|
+
|
|
103
|
+
users:
|
|
104
|
+
create: "API user created with %{email}"
|
|
105
|
+
update: "API user %{id} updated"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
# engines/api_engine/app/controllers/api/v1/users_controller.rb
|
|
110
|
+
class API::V1::UsersController < ApplicationController
|
|
111
|
+
include ActionAudit
|
|
112
|
+
|
|
113
|
+
def create
|
|
114
|
+
# Will log: "API user created with jane@example.com"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Configuration Merging
|
|
120
|
+
|
|
121
|
+
ActionAudit automatically merges configurations from all engines. The final merged configuration would look like:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
# Merged configuration (conceptual view)
|
|
125
|
+
sessions: # from main app
|
|
126
|
+
create: "User logged in with %{email}"
|
|
127
|
+
destroy: "User logged out"
|
|
128
|
+
|
|
129
|
+
profiles: # from main app
|
|
130
|
+
update: "User updated their profile"
|
|
131
|
+
|
|
132
|
+
admin: # from admin_engine
|
|
133
|
+
users:
|
|
134
|
+
create: "Admin created user %{email}"
|
|
135
|
+
update: "Admin updated user %{id}"
|
|
136
|
+
destroy: "Admin deleted user %{id}"
|
|
137
|
+
settings:
|
|
138
|
+
update: "Admin updated %{setting_name} setting"
|
|
139
|
+
|
|
140
|
+
api: # from api_engine
|
|
141
|
+
v1:
|
|
142
|
+
webhooks:
|
|
143
|
+
create: "Webhook received from %{source}"
|
|
144
|
+
users:
|
|
145
|
+
create: "API user created with %{email}"
|
|
146
|
+
update: "API user %{id} updated"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Engine Directory Structure
|
|
150
|
+
|
|
151
|
+
Here's a typical directory structure for a multi-engine Rails application:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
my_rails_app/
|
|
155
|
+
├── config/
|
|
156
|
+
│ ├── audit.yml # Main app audit config
|
|
157
|
+
│ └── initializers/
|
|
158
|
+
│ └── action_audit.rb # Global audit configuration
|
|
159
|
+
├── engines/
|
|
160
|
+
│ ├── admin_engine/
|
|
161
|
+
│ │ ├── config/
|
|
162
|
+
│ │ │ └── audit.yml # Admin engine audit config
|
|
163
|
+
│ │ └── app/controllers/
|
|
164
|
+
│ │ └── admin/
|
|
165
|
+
│ │ └── users_controller.rb
|
|
166
|
+
│ └── api_engine/
|
|
167
|
+
│ ├── config/
|
|
168
|
+
│ │ └── audit.yml # API engine audit config
|
|
169
|
+
│ └── app/controllers/
|
|
170
|
+
│ └── api/
|
|
171
|
+
│ └── v1/
|
|
172
|
+
│ └── users_controller.rb
|
|
173
|
+
└── Gemfile
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Development Mode Behavior
|
|
177
|
+
|
|
178
|
+
In development mode, ActionAudit automatically reloads all audit configurations when files change. This means:
|
|
179
|
+
|
|
180
|
+
1. **File watching**: Changes to any `config/audit.yml` file are detected
|
|
181
|
+
2. **Automatic reload**: Configurations are reloaded without restarting the server
|
|
182
|
+
3. **Merged updates**: New configurations are merged with existing ones
|
|
183
|
+
|
|
184
|
+
## Production Deployment
|
|
185
|
+
|
|
186
|
+
### Configuration Loading Order
|
|
187
|
+
|
|
188
|
+
ActionAudit loads configurations in this order:
|
|
189
|
+
|
|
190
|
+
1. **Main application** `config/audit.yml`
|
|
191
|
+
2. **Each engine** `config/audit.yml` (in the order Rails discovers them)
|
|
192
|
+
|
|
193
|
+
### Conflict Resolution
|
|
194
|
+
|
|
195
|
+
If multiple engines define the same audit path, the **last loaded configuration wins**. For example:
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
# Engine A: config/audit.yml
|
|
199
|
+
users:
|
|
200
|
+
create: "Engine A created user %{email}"
|
|
201
|
+
|
|
202
|
+
# Engine B: config/audit.yml
|
|
203
|
+
users:
|
|
204
|
+
create: "Engine B created user %{email}" # This will be used
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
To avoid conflicts, use namespaced controller paths:
|
|
208
|
+
|
|
209
|
+
```yaml
|
|
210
|
+
# Engine A: config/audit.yml
|
|
211
|
+
engine_a:
|
|
212
|
+
users:
|
|
213
|
+
create: "Engine A created user %{email}"
|
|
214
|
+
|
|
215
|
+
# Engine B: config/audit.yml
|
|
216
|
+
engine_b:
|
|
217
|
+
users:
|
|
218
|
+
create: "Engine B created user %{email}"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Testing Multi-Engine Setup
|
|
222
|
+
|
|
223
|
+
### Verifying Configuration Loading
|
|
224
|
+
|
|
225
|
+
You can verify that configurations from all engines are loaded:
|
|
226
|
+
|
|
227
|
+
```ruby
|
|
228
|
+
# In Rails console
|
|
229
|
+
ActionAudit::AuditMessages.messages
|
|
230
|
+
# Should show merged configuration from all engines
|
|
231
|
+
|
|
232
|
+
# Check specific messages
|
|
233
|
+
ActionAudit::AuditMessages.lookup("admin/users", "create")
|
|
234
|
+
ActionAudit::AuditMessages.lookup("api/v1/users", "create")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Testing Individual Engines
|
|
238
|
+
|
|
239
|
+
Test each engine's audit configuration separately:
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
# spec/engines/admin_engine_spec.rb
|
|
243
|
+
RSpec.describe "AdminEngine audit configuration" do
|
|
244
|
+
it "loads admin user audit messages" do
|
|
245
|
+
message = ActionAudit::AuditMessages.lookup("admin/users", "create")
|
|
246
|
+
expect(message).to eq("Admin created user %{email}")
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Best Practices
|
|
252
|
+
|
|
253
|
+
### 1. Use Namespaced Paths
|
|
254
|
+
|
|
255
|
+
Always namespace your audit configurations to avoid conflicts:
|
|
256
|
+
|
|
257
|
+
```yaml
|
|
258
|
+
# Good: Namespaced
|
|
259
|
+
admin_engine:
|
|
260
|
+
users:
|
|
261
|
+
create: "Admin created user %{email}"
|
|
262
|
+
|
|
263
|
+
# Bad: Generic (could conflict)
|
|
264
|
+
users:
|
|
265
|
+
create: "Created user %{email}"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 2. Consistent Parameter Naming
|
|
269
|
+
|
|
270
|
+
Use consistent parameter names across engines:
|
|
271
|
+
|
|
272
|
+
```yaml
|
|
273
|
+
# Good: Consistent naming
|
|
274
|
+
admin:
|
|
275
|
+
users:
|
|
276
|
+
create: "Admin created user %{email}"
|
|
277
|
+
|
|
278
|
+
api:
|
|
279
|
+
users:
|
|
280
|
+
create: "API created user %{email}"
|
|
281
|
+
|
|
282
|
+
# Both use %{email} consistently
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 3. Engine-Specific Initializers
|
|
286
|
+
|
|
287
|
+
Each engine can have its own ActionAudit configuration:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
# engines/admin_engine/config/initializers/action_audit.rb
|
|
291
|
+
if defined?(ActionAudit)
|
|
292
|
+
# Engine-specific configuration
|
|
293
|
+
# This runs after the main app's initializer
|
|
294
|
+
end
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 4. Shared Configuration
|
|
298
|
+
|
|
299
|
+
For shared audit messages, create a separate configuration file:
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
# config/shared_audit.yml
|
|
303
|
+
shared:
|
|
304
|
+
sessions:
|
|
305
|
+
create: "User logged in with %{email}"
|
|
306
|
+
destroy: "User logged out"
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Then load it in your main app's initializer:
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
# config/initializers/action_audit.rb
|
|
313
|
+
shared_config = Rails.root.join("config", "shared_audit.yml")
|
|
314
|
+
ActionAudit::AuditMessages.load_from_file(shared_config) if File.exist?(shared_config)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Troubleshooting Multi-Engine Issues
|
|
318
|
+
|
|
319
|
+
### Configuration Not Loading
|
|
320
|
+
|
|
321
|
+
1. **Check file paths**: Ensure `config/audit.yml` exists in each engine's root
|
|
322
|
+
2. **Verify engine mounting**: Make sure all engines are properly mounted in your main app
|
|
323
|
+
3. **Check YAML syntax**: Invalid YAML will prevent loading
|
|
324
|
+
|
|
325
|
+
### Conflicting Messages
|
|
326
|
+
|
|
327
|
+
1. **Use namespaces**: Avoid generic controller paths
|
|
328
|
+
2. **Check loading order**: Later engines override earlier ones
|
|
329
|
+
3. **Use unique paths**: Make controller paths engine-specific
|
|
330
|
+
|
|
331
|
+
### Development Reloading Issues
|
|
332
|
+
|
|
333
|
+
1. **Restart server**: Sometimes manual restart is needed
|
|
334
|
+
2. **Check file permissions**: Ensure Rails can read all audit.yml files
|
|
335
|
+
3. **Verify file changes**: Make sure files are actually being modified
|
|
336
|
+
|
|
337
|
+
## Example: Complete Multi-Engine Setup
|
|
338
|
+
|
|
339
|
+
Here's a complete example of a multi-engine Rails application with ActionAudit:
|
|
340
|
+
|
|
341
|
+
### Main Application
|
|
342
|
+
|
|
343
|
+
```ruby
|
|
344
|
+
# config/application.rb
|
|
345
|
+
require_relative "boot"
|
|
346
|
+
require "rails/all"
|
|
347
|
+
|
|
348
|
+
Bundler.require(*Rails.groups)
|
|
349
|
+
|
|
350
|
+
module MyRailsApp
|
|
351
|
+
class Application < Rails::Application
|
|
352
|
+
config.load_defaults 7.0
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
# config/audit.yml
|
|
359
|
+
app:
|
|
360
|
+
sessions:
|
|
361
|
+
create: "User logged in with %{email}"
|
|
362
|
+
destroy: "User logged out"
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Admin Engine
|
|
366
|
+
|
|
367
|
+
```ruby
|
|
368
|
+
# engines/admin/lib/admin.rb
|
|
369
|
+
module Admin
|
|
370
|
+
class Engine < ::Rails::Engine
|
|
371
|
+
isolate_namespace Admin
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
```yaml
|
|
377
|
+
# engines/admin/config/audit.yml
|
|
378
|
+
admin:
|
|
379
|
+
users:
|
|
380
|
+
create: "Admin created user %{email}"
|
|
381
|
+
update: "Admin updated user %{id}"
|
|
382
|
+
dashboard:
|
|
383
|
+
show: "Admin accessed dashboard"
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### API Engine
|
|
387
|
+
|
|
388
|
+
```ruby
|
|
389
|
+
# engines/api/lib/api.rb
|
|
390
|
+
module Api
|
|
391
|
+
class Engine < ::Rails::Engine
|
|
392
|
+
isolate_namespace Api
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
```yaml
|
|
398
|
+
# engines/api/config/audit.yml
|
|
399
|
+
api:
|
|
400
|
+
v1:
|
|
401
|
+
users:
|
|
402
|
+
create: "API user created %{email}"
|
|
403
|
+
webhooks:
|
|
404
|
+
create: "Webhook %{event} from %{source}"
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
This setup provides complete audit coverage across all engines while maintaining clear separation of concerns.
|
|
408
|
+
|
|
409
|
+
## Next Steps
|
|
410
|
+
|
|
411
|
+
- [Learn about API reference](api-reference.md)
|
|
412
|
+
- [See real-world examples](examples.md)
|
|
413
|
+
- [Check troubleshooting guide](troubleshooting.md)
|