pg_sql_triggers 1.2.0 → 1.4.0
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/CHANGELOG.md +397 -1
- data/COVERAGE.md +26 -19
- data/GEM_ANALYSIS.md +368 -0
- data/Goal.md +276 -155
- data/README.md +45 -22
- data/app/assets/javascripts/pg_sql_triggers/trigger_actions.js +50 -0
- data/app/controllers/concerns/pg_sql_triggers/error_handling.rb +56 -0
- data/app/controllers/concerns/pg_sql_triggers/kill_switch_protection.rb +66 -0
- data/app/controllers/concerns/pg_sql_triggers/permission_checking.rb +117 -0
- data/app/controllers/pg_sql_triggers/application_controller.rb +10 -62
- data/app/controllers/pg_sql_triggers/audit_logs_controller.rb +102 -0
- data/app/controllers/pg_sql_triggers/dashboard_controller.rb +4 -9
- data/app/controllers/pg_sql_triggers/tables_controller.rb +30 -4
- data/app/controllers/pg_sql_triggers/triggers_controller.rb +3 -21
- data/app/helpers/pg_sql_triggers/permissions_helper.rb +43 -0
- data/app/models/pg_sql_triggers/audit_log.rb +106 -0
- data/app/models/pg_sql_triggers/trigger_registry.rb +218 -13
- data/app/views/layouts/pg_sql_triggers/application.html.erb +25 -6
- data/app/views/pg_sql_triggers/audit_logs/index.html.erb +177 -0
- data/app/views/pg_sql_triggers/dashboard/index.html.erb +34 -12
- data/app/views/pg_sql_triggers/tables/index.html.erb +75 -5
- data/app/views/pg_sql_triggers/tables/show.html.erb +17 -6
- data/app/views/pg_sql_triggers/triggers/_drop_modal.html.erb +16 -7
- data/app/views/pg_sql_triggers/triggers/_re_execute_modal.html.erb +16 -7
- data/app/views/pg_sql_triggers/triggers/show.html.erb +26 -6
- data/config/routes.rb +2 -14
- data/db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb +28 -0
- data/db/migrate/20260228000001_add_for_each_to_pg_sql_triggers_registry.rb +8 -0
- data/docs/README.md +15 -5
- data/docs/api-reference.md +233 -151
- data/docs/audit-trail.md +413 -0
- data/docs/configuration.md +28 -7
- data/docs/getting-started.md +17 -16
- data/docs/permissions.md +369 -0
- data/docs/troubleshooting.md +486 -0
- data/docs/ui-guide.md +211 -0
- data/docs/usage-guide.md +38 -67
- data/docs/web-ui.md +251 -128
- data/lib/generators/pg_sql_triggers/templates/trigger_dsl.rb.tt +11 -0
- data/lib/generators/pg_sql_triggers/templates/trigger_migration_full.rb.tt +29 -0
- data/lib/generators/pg_sql_triggers/trigger_generator.rb +83 -0
- data/lib/pg_sql_triggers/drift/db_queries.rb +12 -8
- data/lib/pg_sql_triggers/drift/detector.rb +51 -38
- data/lib/pg_sql_triggers/dsl/trigger_definition.rb +17 -23
- data/lib/pg_sql_triggers/engine.rb +14 -0
- data/lib/pg_sql_triggers/errors.rb +245 -0
- data/lib/pg_sql_triggers/migrator/pre_apply_comparator.rb +8 -9
- data/lib/pg_sql_triggers/migrator/safety_validator.rb +32 -12
- data/lib/pg_sql_triggers/migrator.rb +53 -6
- data/lib/pg_sql_triggers/permissions/checker.rb +9 -2
- data/lib/pg_sql_triggers/registry/manager.rb +36 -11
- data/lib/pg_sql_triggers/registry/validator.rb +62 -5
- data/lib/pg_sql_triggers/registry.rb +141 -8
- data/lib/pg_sql_triggers/sql/kill_switch.rb +153 -247
- data/lib/pg_sql_triggers/sql.rb +0 -6
- data/lib/pg_sql_triggers/testing/function_tester.rb +2 -0
- data/lib/pg_sql_triggers/version.rb +1 -1
- data/lib/pg_sql_triggers.rb +7 -7
- data/pg_sql_triggers.gemspec +53 -0
- metadata +35 -18
- data/app/controllers/pg_sql_triggers/generator_controller.rb +0 -213
- data/app/controllers/pg_sql_triggers/sql_capsules_controller.rb +0 -161
- data/app/views/pg_sql_triggers/generator/new.html.erb +0 -388
- data/app/views/pg_sql_triggers/generator/preview.html.erb +0 -305
- data/app/views/pg_sql_triggers/sql_capsules/new.html.erb +0 -81
- data/app/views/pg_sql_triggers/sql_capsules/show.html.erb +0 -85
- data/docs/screenshots/.gitkeep +0 -1
- data/docs/screenshots/Generate Trigger.png +0 -0
- data/docs/screenshots/Triggers Page.png +0 -0
- data/docs/screenshots/kill error.png +0 -0
- data/docs/screenshots/kill modal for migration down.png +0 -0
- data/lib/generators/trigger/migration_generator.rb +0 -60
- data/lib/pg_sql_triggers/generator/form.rb +0 -80
- data/lib/pg_sql_triggers/generator/service.rb +0 -307
- data/lib/pg_sql_triggers/generator.rb +0 -8
- data/lib/pg_sql_triggers/sql/capsule.rb +0 -79
- data/lib/pg_sql_triggers/sql/executor.rb +0 -200
data/docs/audit-trail.md
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Audit Trail Guide
|
|
2
|
+
|
|
3
|
+
PgSqlTriggers provides comprehensive audit logging for all trigger operations. This guide explains how to view, filter, and export audit logs.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Accessing Audit Logs](#accessing-audit-logs)
|
|
9
|
+
- [Viewing Audit Logs](#viewing-audit-logs)
|
|
10
|
+
- [Filtering Logs](#filtering-logs)
|
|
11
|
+
- [Exporting Logs](#exporting-logs)
|
|
12
|
+
- [Console API](#console-api)
|
|
13
|
+
- [Logged Operations](#logged-operations)
|
|
14
|
+
- [Audit Log Structure](#audit-log-structure)
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
The audit trail captures:
|
|
19
|
+
|
|
20
|
+
- **Who**: Actor information (user type and ID)
|
|
21
|
+
- **What**: Operation performed (enable, disable, drop, re-execute, etc.)
|
|
22
|
+
- **When**: Timestamp of the operation
|
|
23
|
+
- **Where**: Environment where operation occurred
|
|
24
|
+
- **Result**: Success or failure status
|
|
25
|
+
- **Context**: Before/after state, reasons, confirmation text, error messages
|
|
26
|
+
|
|
27
|
+
All operations are automatically logged, providing a complete audit trail for compliance and debugging.
|
|
28
|
+
|
|
29
|
+
## Accessing Audit Logs
|
|
30
|
+
|
|
31
|
+
### Via Web UI
|
|
32
|
+
|
|
33
|
+
Navigate to the Audit Log page:
|
|
34
|
+
|
|
35
|
+
1. Go to the PgSqlTriggers dashboard
|
|
36
|
+
2. Click "Audit Log" in the navigation menu
|
|
37
|
+
3. URL: `http://localhost:3000/pg_sql_triggers/audit_logs`
|
|
38
|
+
|
|
39
|
+
### Via Console API
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
# Get all audit logs
|
|
43
|
+
PgSqlTriggers::AuditLog.all
|
|
44
|
+
|
|
45
|
+
# Get logs for a specific trigger
|
|
46
|
+
PgSqlTriggers::AuditLog.for_trigger_name("users_email_validation")
|
|
47
|
+
|
|
48
|
+
# Get recent logs
|
|
49
|
+
PgSqlTriggers::AuditLog.recent.limit(100)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Viewing Audit Logs
|
|
53
|
+
|
|
54
|
+
### Audit Log Table
|
|
55
|
+
|
|
56
|
+
The audit log table displays:
|
|
57
|
+
|
|
58
|
+
- **Timestamp**: When the operation occurred
|
|
59
|
+
- **Operation**: Type of operation (enable, disable, drop, etc.)
|
|
60
|
+
- **Trigger Name**: Affected trigger (if applicable)
|
|
61
|
+
- **Actor**: Who performed the operation (type and ID)
|
|
62
|
+
- **Environment**: Environment where operation occurred
|
|
63
|
+
- **Status**: Success or failure
|
|
64
|
+
- **Reason**: Reason provided (for drop/re-execute operations)
|
|
65
|
+
|
|
66
|
+
### Viewing Details
|
|
67
|
+
|
|
68
|
+
Click on any audit log entry to view detailed information:
|
|
69
|
+
|
|
70
|
+
- **Before State**: State before the operation (enabled/disabled, function body, etc.)
|
|
71
|
+
- **After State**: State after the operation
|
|
72
|
+
- **Diff**: Changes made (for re-execute operations)
|
|
73
|
+
- **Confirmation Text**: Confirmation text used (if applicable)
|
|
74
|
+
- **Error Message**: Error details (for failed operations)
|
|
75
|
+
|
|
76
|
+
## Filtering Logs
|
|
77
|
+
|
|
78
|
+
### Filter Options
|
|
79
|
+
|
|
80
|
+
Filter audit logs by:
|
|
81
|
+
|
|
82
|
+
- **Trigger Name**: Filter by specific trigger
|
|
83
|
+
- **Operation**: Filter by operation type (enable, disable, drop, etc.)
|
|
84
|
+
- **Status**: Filter by success or failure
|
|
85
|
+
- **Environment**: Filter by environment (production, staging, etc.)
|
|
86
|
+
- **Sort Order**: Newest first or oldest first
|
|
87
|
+
|
|
88
|
+
### Using Filters in UI
|
|
89
|
+
|
|
90
|
+
1. Navigate to Audit Log page
|
|
91
|
+
2. Use filter dropdowns at the top
|
|
92
|
+
3. Click "Apply Filters"
|
|
93
|
+
4. Use "Clear" to reset filters
|
|
94
|
+
|
|
95
|
+
### Filtering via Console API
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
# Filter by trigger
|
|
99
|
+
PgSqlTriggers::AuditLog.for_trigger("users_email_validation")
|
|
100
|
+
|
|
101
|
+
# Filter by operation
|
|
102
|
+
PgSqlTriggers::AuditLog.for_operation("trigger_enable")
|
|
103
|
+
|
|
104
|
+
# Filter by environment
|
|
105
|
+
PgSqlTriggers::AuditLog.for_environment("production")
|
|
106
|
+
|
|
107
|
+
# Filter by status
|
|
108
|
+
PgSqlTriggers::AuditLog.successful
|
|
109
|
+
PgSqlTriggers::AuditLog.failed
|
|
110
|
+
|
|
111
|
+
# Combine filters
|
|
112
|
+
PgSqlTriggers::AuditLog
|
|
113
|
+
.for_trigger("users_email_validation")
|
|
114
|
+
.for_operation("trigger_enable")
|
|
115
|
+
.successful
|
|
116
|
+
.recent
|
|
117
|
+
.limit(50)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Advanced Filtering
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
# Get failed operations in production
|
|
124
|
+
PgSqlTriggers::AuditLog
|
|
125
|
+
.for_environment("production")
|
|
126
|
+
.failed
|
|
127
|
+
.recent
|
|
128
|
+
|
|
129
|
+
# Get all drop operations
|
|
130
|
+
PgSqlTriggers::AuditLog
|
|
131
|
+
.for_operation("trigger_drop")
|
|
132
|
+
.includes(:trigger_name)
|
|
133
|
+
|
|
134
|
+
# Get operations by specific actor
|
|
135
|
+
PgSqlTriggers::AuditLog
|
|
136
|
+
.where("actor->>'type' = ? AND actor->>'id' = ?", "User", "123")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Exporting Logs
|
|
140
|
+
|
|
141
|
+
### CSV Export via UI
|
|
142
|
+
|
|
143
|
+
1. Apply any desired filters
|
|
144
|
+
2. Click "Export CSV" button
|
|
145
|
+
3. CSV file downloads with all visible entries
|
|
146
|
+
4. Filters are preserved in the export
|
|
147
|
+
|
|
148
|
+
### CSV Export Format
|
|
149
|
+
|
|
150
|
+
The CSV includes all columns:
|
|
151
|
+
|
|
152
|
+
- Timestamp
|
|
153
|
+
- Operation
|
|
154
|
+
- Trigger Name
|
|
155
|
+
- Actor Type
|
|
156
|
+
- Actor ID
|
|
157
|
+
- Environment
|
|
158
|
+
- Status
|
|
159
|
+
- Reason
|
|
160
|
+
- Error Message (for failures)
|
|
161
|
+
- Created At
|
|
162
|
+
|
|
163
|
+
### Programmatic Export
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
# Export to CSV
|
|
167
|
+
require 'csv'
|
|
168
|
+
|
|
169
|
+
logs = PgSqlTriggers::AuditLog.recent.limit(1000)
|
|
170
|
+
|
|
171
|
+
CSV.open("audit_logs.csv", "w") do |csv|
|
|
172
|
+
csv << ["Timestamp", "Operation", "Trigger", "Actor", "Environment", "Status", "Reason"]
|
|
173
|
+
|
|
174
|
+
logs.each do |log|
|
|
175
|
+
csv << [
|
|
176
|
+
log.created_at,
|
|
177
|
+
log.operation,
|
|
178
|
+
log.trigger_name,
|
|
179
|
+
"#{log.actor['type']}:#{log.actor['id']}",
|
|
180
|
+
log.environment,
|
|
181
|
+
log.status,
|
|
182
|
+
log.reason
|
|
183
|
+
]
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Console API
|
|
189
|
+
|
|
190
|
+
### Querying Audit Logs
|
|
191
|
+
|
|
192
|
+
```ruby
|
|
193
|
+
# Get logs for a trigger
|
|
194
|
+
PgSqlTriggers::AuditLog.for_trigger_name("users_email_validation")
|
|
195
|
+
|
|
196
|
+
# Returns: ActiveRecord::Relation ordered by most recent first
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Logging Operations
|
|
200
|
+
|
|
201
|
+
Operations are automatically logged, but you can also log manually:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
# Log a successful operation
|
|
205
|
+
PgSqlTriggers::AuditLog.log_success(
|
|
206
|
+
operation: :trigger_enable,
|
|
207
|
+
trigger_name: "users_email_validation",
|
|
208
|
+
actor: { type: "Console", id: "admin@example.com" },
|
|
209
|
+
environment: "production",
|
|
210
|
+
before_state: { enabled: false },
|
|
211
|
+
after_state: { enabled: true }
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Log a failed operation
|
|
215
|
+
PgSqlTriggers::AuditLog.log_failure(
|
|
216
|
+
operation: :trigger_drop,
|
|
217
|
+
trigger_name: "old_trigger",
|
|
218
|
+
actor: { type: "UI", id: "user_123" },
|
|
219
|
+
environment: "production",
|
|
220
|
+
error_message: "Trigger not found",
|
|
221
|
+
reason: "Cleanup"
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Logged Operations
|
|
226
|
+
|
|
227
|
+
The following operations are automatically logged:
|
|
228
|
+
|
|
229
|
+
### Trigger Operations
|
|
230
|
+
|
|
231
|
+
- **`trigger_enable`**: Trigger enabled
|
|
232
|
+
- **`trigger_disable`**: Trigger disabled
|
|
233
|
+
- **`trigger_drop`**: Trigger dropped from database
|
|
234
|
+
- **`trigger_re_execute`**: Trigger re-executed (drop and recreate)
|
|
235
|
+
|
|
236
|
+
### Migration Operations
|
|
237
|
+
|
|
238
|
+
- **`migration_up`**: Migration applied (up)
|
|
239
|
+
- **`migration_down`**: Migration rolled back (down)
|
|
240
|
+
|
|
241
|
+
### SQL Capsule Operations
|
|
242
|
+
|
|
243
|
+
- **`sql_capsule_execute`**: SQL capsule executed
|
|
244
|
+
- **`sql_capsule_dry_run`**: SQL capsule dry-run performed
|
|
245
|
+
|
|
246
|
+
### Generator Operations
|
|
247
|
+
|
|
248
|
+
- **`trigger_generate`**: Trigger generated via UI
|
|
249
|
+
|
|
250
|
+
## Audit Log Structure
|
|
251
|
+
|
|
252
|
+
### Database Schema
|
|
253
|
+
|
|
254
|
+
The audit log table (`pg_sql_triggers_audit_log`) contains:
|
|
255
|
+
|
|
256
|
+
| Column | Type | Description |
|
|
257
|
+
|--------|------|-------------|
|
|
258
|
+
| `id` | integer | Primary key |
|
|
259
|
+
| `trigger_name` | string | Trigger name (nullable) |
|
|
260
|
+
| `operation` | string | Operation type |
|
|
261
|
+
| `actor` | jsonb | Actor information (type, id) |
|
|
262
|
+
| `environment` | string | Environment name |
|
|
263
|
+
| `status` | string | "success" or "failure" |
|
|
264
|
+
| `reason` | text | Reason for operation (nullable) |
|
|
265
|
+
| `confirmation_text` | text | Confirmation text used (nullable) |
|
|
266
|
+
| `before_state` | jsonb | State before operation (nullable) |
|
|
267
|
+
| `after_state` | jsonb | State after operation (nullable) |
|
|
268
|
+
| `diff` | text | Diff information (nullable) |
|
|
269
|
+
| `error_message` | text | Error message (for failures) |
|
|
270
|
+
| `created_at` | timestamp | When operation occurred |
|
|
271
|
+
| `updated_at` | timestamp | Last update time |
|
|
272
|
+
|
|
273
|
+
### Actor Format
|
|
274
|
+
|
|
275
|
+
Actor information is stored as JSON:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"type": "User",
|
|
280
|
+
"id": "123"
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Or for console operations:
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"type": "Console",
|
|
289
|
+
"id": "admin@example.com"
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### State Format
|
|
294
|
+
|
|
295
|
+
Before and after states are stored as JSON:
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"enabled": true,
|
|
300
|
+
"function_body": "CREATE FUNCTION...",
|
|
301
|
+
"version": 1,
|
|
302
|
+
"drift_state": "in_sync"
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Use Cases
|
|
307
|
+
|
|
308
|
+
### Compliance Auditing
|
|
309
|
+
|
|
310
|
+
Track who performed what operations for compliance:
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
# Get all admin operations in production
|
|
314
|
+
PgSqlTriggers::AuditLog
|
|
315
|
+
.for_environment("production")
|
|
316
|
+
.where("actor->>'type' = ?", "Admin")
|
|
317
|
+
.recent
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Debugging Failed Operations
|
|
321
|
+
|
|
322
|
+
Find and analyze failed operations:
|
|
323
|
+
|
|
324
|
+
```ruby
|
|
325
|
+
# Get recent failures
|
|
326
|
+
failures = PgSqlTriggers::AuditLog.failed.recent.limit(50)
|
|
327
|
+
|
|
328
|
+
failures.each do |log|
|
|
329
|
+
puts "#{log.created_at}: #{log.operation} on #{log.trigger_name}"
|
|
330
|
+
puts "Error: #{log.error_message}"
|
|
331
|
+
puts "Actor: #{log.actor}"
|
|
332
|
+
puts "---"
|
|
333
|
+
end
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Trigger History
|
|
337
|
+
|
|
338
|
+
View complete history of a trigger:
|
|
339
|
+
|
|
340
|
+
```ruby
|
|
341
|
+
history = PgSqlTriggers::AuditLog.for_trigger_name("users_email_validation")
|
|
342
|
+
|
|
343
|
+
history.each do |log|
|
|
344
|
+
puts "#{log.created_at}: #{log.operation} - #{log.status}"
|
|
345
|
+
if log.reason
|
|
346
|
+
puts " Reason: #{log.reason}"
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Operation Analysis
|
|
352
|
+
|
|
353
|
+
Analyze operation patterns:
|
|
354
|
+
|
|
355
|
+
```ruby
|
|
356
|
+
# Count operations by type
|
|
357
|
+
PgSqlTriggers::AuditLog
|
|
358
|
+
.group(:operation)
|
|
359
|
+
.count
|
|
360
|
+
|
|
361
|
+
# Count failures by operation
|
|
362
|
+
PgSqlTriggers::AuditLog
|
|
363
|
+
.failed
|
|
364
|
+
.group(:operation)
|
|
365
|
+
.count
|
|
366
|
+
|
|
367
|
+
# Operations by environment
|
|
368
|
+
PgSqlTriggers::AuditLog
|
|
369
|
+
.group(:environment)
|
|
370
|
+
.count
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Best Practices
|
|
374
|
+
|
|
375
|
+
1. **Regular Reviews**: Review audit logs regularly for anomalies
|
|
376
|
+
2. **Retention Policy**: Implement a retention policy for old logs
|
|
377
|
+
3. **Monitoring**: Set up alerts for failed operations
|
|
378
|
+
4. **Backup**: Include audit logs in your backup strategy
|
|
379
|
+
5. **Analysis**: Use audit logs to understand usage patterns
|
|
380
|
+
|
|
381
|
+
## Troubleshooting
|
|
382
|
+
|
|
383
|
+
### Audit logs not appearing
|
|
384
|
+
|
|
385
|
+
**Problem**: Operations are not being logged.
|
|
386
|
+
|
|
387
|
+
**Solution**:
|
|
388
|
+
- Check that migrations are run (`rails db:migrate`)
|
|
389
|
+
- Verify the audit log table exists
|
|
390
|
+
- Check Rails logs for audit logging errors
|
|
391
|
+
|
|
392
|
+
### Performance issues with large logs
|
|
393
|
+
|
|
394
|
+
**Problem**: Audit log queries are slow.
|
|
395
|
+
|
|
396
|
+
**Solution**:
|
|
397
|
+
- Add indexes on frequently queried columns
|
|
398
|
+
- Implement pagination
|
|
399
|
+
- Archive old logs regularly
|
|
400
|
+
- Use filtering to reduce result set size
|
|
401
|
+
|
|
402
|
+
### Missing actor information
|
|
403
|
+
|
|
404
|
+
**Problem**: Actor shows as "unknown".
|
|
405
|
+
|
|
406
|
+
**Solution**: Ensure `current_actor` method is properly implemented in your controllers.
|
|
407
|
+
|
|
408
|
+
## Related Documentation
|
|
409
|
+
|
|
410
|
+
- [Web UI Guide](web-ui.md#audit-log) - Using the audit log UI
|
|
411
|
+
- [API Reference](api-reference.md#audit-log-api) - Console API methods
|
|
412
|
+
- [Configuration Reference](configuration.md) - Configuration options
|
|
413
|
+
|
data/docs/configuration.md
CHANGED
|
@@ -50,6 +50,25 @@ config.default_environment = -> {
|
|
|
50
50
|
config.default_environment = -> { 'production' }
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
### `db_schema`
|
|
54
|
+
|
|
55
|
+
The PostgreSQL schema in which triggers are managed. All system catalog queries use this value. Override when your triggers live in a non-`public` schema.
|
|
56
|
+
|
|
57
|
+
- **Type**: String
|
|
58
|
+
- **Default**: `"public"`
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
config.db_schema = "public" # default
|
|
62
|
+
|
|
63
|
+
# Use a custom schema
|
|
64
|
+
config.db_schema = "app"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
You can also set this at runtime:
|
|
68
|
+
```ruby
|
|
69
|
+
PgSqlTriggers.db_schema = "app"
|
|
70
|
+
```
|
|
71
|
+
|
|
53
72
|
### `mount_path`
|
|
54
73
|
|
|
55
74
|
Customize where the web UI is mounted (configured in routes, not initializer).
|
|
@@ -192,6 +211,8 @@ Custom authorization logic for the web UI and API.
|
|
|
192
211
|
- **Returns**: Boolean
|
|
193
212
|
- **Default**: `->(_actor, _action, _environment) { true }`
|
|
194
213
|
|
|
214
|
+
> **Important**: If `permission_checker` is `nil` (not configured) and the app boots in **production**, the engine emits a `Rails.logger.warn` at startup. Configure a real checker before deploying to production.
|
|
215
|
+
|
|
195
216
|
```ruby
|
|
196
217
|
# Default: allow all (development only!)
|
|
197
218
|
config.permission_checker = ->(_actor, _action, _environment) { true }
|
|
@@ -208,12 +229,12 @@ config.permission_checker = ->(actor, action, environment) {
|
|
|
208
229
|
return false unless user
|
|
209
230
|
|
|
210
231
|
case action
|
|
211
|
-
when :
|
|
212
|
-
user.present?
|
|
213
|
-
when :
|
|
214
|
-
user.operator? || user.admin?
|
|
215
|
-
when :
|
|
216
|
-
user.admin?
|
|
232
|
+
when :view_triggers, :view_diffs
|
|
233
|
+
user.present? # Viewer level
|
|
234
|
+
when :enable_trigger, :disable_trigger, :apply_trigger, :test_trigger
|
|
235
|
+
user.operator? || user.admin? # Operator level
|
|
236
|
+
when :drop_trigger, :override_drift
|
|
237
|
+
user.admin? # Admin level
|
|
217
238
|
else
|
|
218
239
|
false
|
|
219
240
|
end
|
|
@@ -287,7 +308,7 @@ The permission checker should handle three levels:
|
|
|
287
308
|
#### `:admin`
|
|
288
309
|
- All `:operate` permissions
|
|
289
310
|
- Drop triggers
|
|
290
|
-
-
|
|
311
|
+
- Override drift
|
|
291
312
|
- Modify registry directly
|
|
292
313
|
|
|
293
314
|
## Environment Detection
|
data/docs/getting-started.md
CHANGED
|
@@ -45,9 +45,19 @@ After installation, you should have:
|
|
|
45
45
|
|
|
46
46
|
## Quick Start Example
|
|
47
47
|
|
|
48
|
-
### 1.
|
|
48
|
+
### 1. Scaffold a Trigger (DSL + Migration)
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
Use the CLI generator to create both files at once:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
rails generate pg_sql_triggers:trigger users_email_validation users insert update --timing before --function validate_user_email
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This creates:
|
|
57
|
+
- `app/triggers/users_email_validation.rb` — DSL stub
|
|
58
|
+
- `db/triggers/TIMESTAMP_users_email_validation.rb` — migration with function + trigger SQL
|
|
59
|
+
|
|
60
|
+
Edit the DSL stub to match your requirements:
|
|
51
61
|
|
|
52
62
|
```ruby
|
|
53
63
|
# app/triggers/users_email_validation.rb
|
|
@@ -56,21 +66,12 @@ PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
|
|
|
56
66
|
on :insert, :update
|
|
57
67
|
function :validate_user_email
|
|
58
68
|
|
|
59
|
-
version 1
|
|
60
|
-
enabled
|
|
61
|
-
|
|
62
|
-
when_env :production
|
|
69
|
+
self.version = 1
|
|
70
|
+
self.enabled = true
|
|
71
|
+
timing :before
|
|
63
72
|
end
|
|
64
73
|
```
|
|
65
74
|
|
|
66
|
-
### 2. Generate a Migration
|
|
67
|
-
|
|
68
|
-
Create a trigger migration to implement the function:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
rails generate trigger:migration add_email_validation
|
|
72
|
-
```
|
|
73
|
-
|
|
74
75
|
Edit the generated migration in `db/triggers/`:
|
|
75
76
|
|
|
76
77
|
```ruby
|
|
@@ -104,7 +105,7 @@ class AddEmailValidation < PgSqlTriggers::Migration
|
|
|
104
105
|
end
|
|
105
106
|
```
|
|
106
107
|
|
|
107
|
-
###
|
|
108
|
+
### 2. Run the Migration
|
|
108
109
|
|
|
109
110
|
Apply the trigger migration:
|
|
110
111
|
|
|
@@ -112,7 +113,7 @@ Apply the trigger migration:
|
|
|
112
113
|
rake trigger:migrate
|
|
113
114
|
```
|
|
114
115
|
|
|
115
|
-
###
|
|
116
|
+
### 3. Access the Web UI
|
|
116
117
|
|
|
117
118
|
Open your browser and navigate to:
|
|
118
119
|
|