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/README.md
CHANGED
|
@@ -9,12 +9,16 @@ Welcome to the PgSqlTriggers documentation. This directory contains comprehensiv
|
|
|
9
9
|
|
|
10
10
|
### Core Guides
|
|
11
11
|
- **[Usage Guide](usage-guide.md)** - DSL syntax, migrations, and drift detection
|
|
12
|
-
- **[
|
|
12
|
+
- **[UI Guide](ui-guide.md)** - Quick start guide for the web interface
|
|
13
|
+
- **[Web UI Guide](web-ui.md)** - Comprehensive web dashboard documentation
|
|
13
14
|
- **[Kill Switch Guide](kill-switch.md)** - Production safety features
|
|
15
|
+
- **[Permissions Guide](permissions.md)** - Configuring and using permissions
|
|
16
|
+
- **[Audit Trail Guide](audit-trail.md)** - Viewing and exporting audit logs
|
|
14
17
|
|
|
15
18
|
### Reference
|
|
16
19
|
- **[Configuration Reference](configuration.md)** - Complete configuration options
|
|
17
20
|
- **[API Reference](api-reference.md)** - Console API and programmatic usage
|
|
21
|
+
- **[Troubleshooting Guide](troubleshooting.md)** - Common issues and solutions
|
|
18
22
|
|
|
19
23
|
## Quick Links
|
|
20
24
|
|
|
@@ -30,20 +34,26 @@ See [Usage Guide - Declaring Triggers](usage-guide.md#declaring-triggers)
|
|
|
30
34
|
See [Usage Guide - Trigger Migrations](usage-guide.md#trigger-migrations)
|
|
31
35
|
|
|
32
36
|
#### Use the web dashboard
|
|
33
|
-
|
|
37
|
+
Start with [UI Guide](ui-guide.md) or see [Web UI Documentation](web-ui.md) for comprehensive details
|
|
38
|
+
|
|
39
|
+
#### Configure permissions
|
|
40
|
+
See [Permissions Guide](permissions.md) or [Configuration - Permission System](configuration.md#permission-system)
|
|
41
|
+
|
|
42
|
+
#### View audit logs
|
|
43
|
+
See [Audit Trail Guide](audit-trail.md)
|
|
34
44
|
|
|
35
45
|
#### Protect production
|
|
36
46
|
See [Kill Switch Documentation](kill-switch.md)
|
|
37
47
|
|
|
38
|
-
#### Configure permissions
|
|
39
|
-
See [Configuration - Permission System](configuration.md#permission-system)
|
|
40
|
-
|
|
41
48
|
#### Use the console API
|
|
42
49
|
See [API Reference](api-reference.md)
|
|
43
50
|
|
|
44
51
|
#### Handle drift detection
|
|
45
52
|
See [Usage Guide - Drift Detection](usage-guide.md#drift-detection)
|
|
46
53
|
|
|
54
|
+
#### Troubleshoot issues
|
|
55
|
+
See [Troubleshooting Guide](troubleshooting.md)
|
|
56
|
+
|
|
47
57
|
## Screenshots
|
|
48
58
|
|
|
49
59
|
Screenshots referenced in the documentation are stored in the [screenshots](screenshots/) directory.
|
data/docs/api-reference.md
CHANGED
|
@@ -9,6 +9,9 @@ Complete reference for using PgSqlTriggers programmatically from the Rails conso
|
|
|
9
9
|
- [Kill Switch API](#kill-switch-api)
|
|
10
10
|
- [DSL API](#dsl-api)
|
|
11
11
|
- [TriggerRegistry Model](#triggerregistry-model)
|
|
12
|
+
- [Audit Log API](#audit-log-api)
|
|
13
|
+
|
|
14
|
+
> **Removed in 1.4.0**: `SQL::Capsule` and `SQL::Executor` have been removed. See [CHANGELOG](../CHANGELOG.md) for details.
|
|
12
15
|
|
|
13
16
|
## Registry API
|
|
14
17
|
|
|
@@ -97,6 +100,76 @@ end
|
|
|
97
100
|
|
|
98
101
|
**Returns**: Hash with drift categories
|
|
99
102
|
|
|
103
|
+
### `PgSqlTriggers::Registry.drifted`
|
|
104
|
+
|
|
105
|
+
Returns all triggers that have drifted from their expected state.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
drifted_triggers = PgSqlTriggers::Registry.drifted
|
|
109
|
+
# => [
|
|
110
|
+
# { state: "drifted", trigger_name: "users_email_validation", ... },
|
|
111
|
+
# ...
|
|
112
|
+
# ]
|
|
113
|
+
|
|
114
|
+
drifted_triggers.each do |trigger|
|
|
115
|
+
puts "Drifted: #{trigger[:trigger_name]}"
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Returns**: Array of drift result hashes for drifted triggers
|
|
120
|
+
|
|
121
|
+
### `PgSqlTriggers::Registry.in_sync`
|
|
122
|
+
|
|
123
|
+
Returns all triggers that are in sync with their expected state.
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
in_sync_triggers = PgSqlTriggers::Registry.in_sync
|
|
127
|
+
# => [
|
|
128
|
+
# { state: "in_sync", trigger_name: "billing_trigger", ... },
|
|
129
|
+
# ...
|
|
130
|
+
# ]
|
|
131
|
+
|
|
132
|
+
puts "In sync triggers: #{in_sync_triggers.count}"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Returns**: Array of drift result hashes for in-sync triggers
|
|
136
|
+
|
|
137
|
+
### `PgSqlTriggers::Registry.unknown_triggers`
|
|
138
|
+
|
|
139
|
+
Returns all unknown (external) triggers not managed by this gem.
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
unknown = PgSqlTriggers::Registry.unknown_triggers
|
|
143
|
+
# => [
|
|
144
|
+
# { state: "unknown", trigger_name: "external_trigger", ... },
|
|
145
|
+
# ...
|
|
146
|
+
# ]
|
|
147
|
+
|
|
148
|
+
unknown.each do |trigger|
|
|
149
|
+
puts "External trigger: #{trigger[:trigger_name]}"
|
|
150
|
+
end
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Returns**: Array of drift result hashes for unknown triggers
|
|
154
|
+
|
|
155
|
+
### `PgSqlTriggers::Registry.dropped`
|
|
156
|
+
|
|
157
|
+
Returns all triggers that have been dropped from the database.
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
dropped_triggers = PgSqlTriggers::Registry.dropped
|
|
161
|
+
# => [
|
|
162
|
+
# { state: "dropped", trigger_name: "old_trigger", ... },
|
|
163
|
+
# ...
|
|
164
|
+
# ]
|
|
165
|
+
|
|
166
|
+
dropped_triggers.each do |trigger|
|
|
167
|
+
puts "Dropped: #{trigger[:trigger_name]}"
|
|
168
|
+
end
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Returns**: Array of drift result hashes for dropped triggers
|
|
172
|
+
|
|
100
173
|
### `PgSqlTriggers::Registry.validate!`
|
|
101
174
|
|
|
102
175
|
Validates all triggers and raises an error if any are invalid.
|
|
@@ -414,124 +487,6 @@ end
|
|
|
414
487
|
|
|
415
488
|
**Returns**: Result of the block
|
|
416
489
|
|
|
417
|
-
## SQL Capsule API
|
|
418
|
-
|
|
419
|
-
The SQL Capsule API provides emergency SQL execution capabilities with safety checks.
|
|
420
|
-
|
|
421
|
-
### `PgSqlTriggers::SQL::Capsule.new(name:, environment:, purpose:, sql:, created_at: nil)`
|
|
422
|
-
|
|
423
|
-
Creates a new SQL capsule for emergency operations.
|
|
424
|
-
|
|
425
|
-
```ruby
|
|
426
|
-
capsule = PgSqlTriggers::SQL::Capsule.new(
|
|
427
|
-
name: "fix_user_permissions",
|
|
428
|
-
environment: "production",
|
|
429
|
-
purpose: "Emergency fix for user permission issue after deployment",
|
|
430
|
-
sql: "UPDATE users SET role = 'admin' WHERE email = 'admin@example.com';"
|
|
431
|
-
)
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**Parameters**:
|
|
435
|
-
- `name` (String): Unique name for the capsule (alphanumeric, underscores, hyphens only)
|
|
436
|
-
- `environment` (String): Target environment (e.g., "production", "staging")
|
|
437
|
-
- `purpose` (String): Description of what the capsule does and why (required for audit trail)
|
|
438
|
-
- `sql` (String): The SQL statement(s) to execute
|
|
439
|
-
- `created_at` (Time, optional): Creation timestamp (defaults to current time)
|
|
440
|
-
|
|
441
|
-
**Raises**: `ArgumentError` if validation fails
|
|
442
|
-
|
|
443
|
-
### `capsule.checksum`
|
|
444
|
-
|
|
445
|
-
Returns the SHA256 checksum of the SQL content.
|
|
446
|
-
|
|
447
|
-
```ruby
|
|
448
|
-
capsule = PgSqlTriggers::SQL::Capsule.new(name: "fix", ...)
|
|
449
|
-
puts capsule.checksum
|
|
450
|
-
# => "a3f5b8c9d2e..."
|
|
451
|
-
```
|
|
452
|
-
|
|
453
|
-
**Returns**: String (SHA256 hash)
|
|
454
|
-
|
|
455
|
-
### `capsule.to_h`
|
|
456
|
-
|
|
457
|
-
Converts the capsule to a hash for storage or serialization.
|
|
458
|
-
|
|
459
|
-
```ruby
|
|
460
|
-
capsule_data = capsule.to_h
|
|
461
|
-
# => {
|
|
462
|
-
# name: "fix_user_permissions",
|
|
463
|
-
# environment: "production",
|
|
464
|
-
# purpose: "Emergency fix...",
|
|
465
|
-
# sql: "UPDATE users...",
|
|
466
|
-
# checksum: "a3f5b8c9d2e...",
|
|
467
|
-
# created_at: 2026-01-01 12:00:00 UTC
|
|
468
|
-
# }
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
**Returns**: Hash
|
|
472
|
-
|
|
473
|
-
## SQL Executor API
|
|
474
|
-
|
|
475
|
-
The SQL Executor API handles safe execution of SQL capsules with comprehensive logging.
|
|
476
|
-
|
|
477
|
-
### `PgSqlTriggers::SQL::Executor.execute(capsule, actor:, confirmation: nil, dry_run: false)`
|
|
478
|
-
|
|
479
|
-
Executes a SQL capsule with safety checks and logging.
|
|
480
|
-
|
|
481
|
-
```ruby
|
|
482
|
-
capsule = PgSqlTriggers::SQL::Capsule.new(
|
|
483
|
-
name: "emergency_fix",
|
|
484
|
-
environment: "production",
|
|
485
|
-
purpose: "Fix critical data corruption",
|
|
486
|
-
sql: "UPDATE orders SET status = 'completed' WHERE id IN (123, 456);"
|
|
487
|
-
)
|
|
488
|
-
|
|
489
|
-
# Execute the capsule
|
|
490
|
-
result = PgSqlTriggers::SQL::Executor.execute(
|
|
491
|
-
capsule,
|
|
492
|
-
actor: { type: "user", id: "admin@example.com" },
|
|
493
|
-
confirmation: "EXECUTE SQL"
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
if result[:success]
|
|
497
|
-
puts "SQL executed successfully"
|
|
498
|
-
puts "Rows affected: #{result[:data][:rows_affected]}"
|
|
499
|
-
else
|
|
500
|
-
puts "Execution failed: #{result[:message]}"
|
|
501
|
-
end
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
**Parameters**:
|
|
505
|
-
- `capsule` (Capsule): The SQL capsule to execute
|
|
506
|
-
- `actor` (Hash): Information about who is executing (Admin permission required)
|
|
507
|
-
- `confirmation` (String, optional): Kill switch confirmation text
|
|
508
|
-
- `dry_run` (Boolean): If true, validates without executing (default: false)
|
|
509
|
-
|
|
510
|
-
**Returns**: Hash with `:success`, `:message`, and `:data` keys
|
|
511
|
-
|
|
512
|
-
**Raises**: Permission and kill switch errors are returned in the result hash
|
|
513
|
-
|
|
514
|
-
### `PgSqlTriggers::SQL::Executor.execute_capsule(capsule_name, actor:, confirmation: nil, dry_run: false)`
|
|
515
|
-
|
|
516
|
-
Executes a previously stored SQL capsule by name from the registry.
|
|
517
|
-
|
|
518
|
-
```ruby
|
|
519
|
-
# Execute a capsule stored in the registry
|
|
520
|
-
result = PgSqlTriggers::SQL::Executor.execute_capsule(
|
|
521
|
-
"emergency_fix",
|
|
522
|
-
actor: { type: "user", id: "admin@example.com" },
|
|
523
|
-
confirmation: "EXECUTE SQL"
|
|
524
|
-
)
|
|
525
|
-
```
|
|
526
|
-
|
|
527
|
-
**Parameters**:
|
|
528
|
-
- `capsule_name` (String): Name of the capsule in the registry
|
|
529
|
-
- `actor` (Hash): Information about who is executing
|
|
530
|
-
- `confirmation` (String, optional): Kill switch confirmation text
|
|
531
|
-
- `dry_run` (Boolean): If true, validates without executing
|
|
532
|
-
|
|
533
|
-
**Returns**: Hash with execution results
|
|
534
|
-
|
|
535
490
|
## DSL API
|
|
536
491
|
|
|
537
492
|
The DSL API is used to define triggers in your application.
|
|
@@ -545,10 +500,10 @@ PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
|
|
|
545
500
|
table :users
|
|
546
501
|
on :insert, :update
|
|
547
502
|
function :validate_user_email
|
|
548
|
-
version 1
|
|
549
|
-
enabled
|
|
503
|
+
self.version = 1
|
|
504
|
+
self.enabled = true
|
|
550
505
|
timing :before
|
|
551
|
-
|
|
506
|
+
for_each_row
|
|
552
507
|
end
|
|
553
508
|
```
|
|
554
509
|
|
|
@@ -580,7 +535,7 @@ on :insert, :update, :delete
|
|
|
580
535
|
```
|
|
581
536
|
|
|
582
537
|
**Parameters**:
|
|
583
|
-
- `events` (Symbols): One or more of `:insert`, `:update`, `:delete`
|
|
538
|
+
- `events` (Symbols): One or more of `:insert`, `:update`, `:delete`, `:truncate`
|
|
584
539
|
|
|
585
540
|
#### `function(function_name)`
|
|
586
541
|
|
|
@@ -593,37 +548,48 @@ function :validate_user_email
|
|
|
593
548
|
**Parameters**:
|
|
594
549
|
- `function_name` (Symbol): Function name
|
|
595
550
|
|
|
596
|
-
#### `version
|
|
551
|
+
#### `self.version = number`
|
|
597
552
|
|
|
598
553
|
Sets the trigger version.
|
|
599
554
|
|
|
600
555
|
```ruby
|
|
601
|
-
version 1
|
|
602
|
-
version 2
|
|
556
|
+
self.version = 1 # Increment when trigger logic changes
|
|
557
|
+
self.version = 2
|
|
603
558
|
```
|
|
604
559
|
|
|
605
560
|
**Parameters**:
|
|
606
561
|
- `number` (Integer): Version number
|
|
607
562
|
|
|
608
|
-
#### `enabled
|
|
563
|
+
#### `self.enabled = state`
|
|
609
564
|
|
|
610
|
-
Sets the initial enabled state.
|
|
565
|
+
Sets the initial enabled state. Defaults to `true`.
|
|
611
566
|
|
|
612
567
|
```ruby
|
|
613
|
-
enabled true
|
|
614
|
-
enabled false
|
|
568
|
+
self.enabled = true # Trigger is active (default)
|
|
569
|
+
self.enabled = false # Trigger is inactive
|
|
615
570
|
```
|
|
616
571
|
|
|
617
572
|
**Parameters**:
|
|
618
573
|
- `state` (Boolean): Initial state
|
|
619
574
|
|
|
575
|
+
#### `for_each_row` / `for_each_statement`
|
|
576
|
+
|
|
577
|
+
Specifies PostgreSQL execution granularity. Defaults to `for_each_row`.
|
|
578
|
+
|
|
579
|
+
```ruby
|
|
580
|
+
for_each_row # FOR EACH ROW (default)
|
|
581
|
+
for_each_statement # FOR EACH STATEMENT
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Stored in the `for_each` column on the registry table and included in checksum calculation.
|
|
585
|
+
|
|
620
586
|
#### `when_env(*environments)`
|
|
621
587
|
|
|
622
|
-
Restricts trigger to specific environments.
|
|
588
|
+
**Deprecated.** Restricts trigger to specific environments. Emits a deprecation warning on every call and will be removed in a future major version. Use application-level configuration to gate trigger behaviour by environment instead.
|
|
623
589
|
|
|
624
590
|
```ruby
|
|
625
|
-
when_env :production
|
|
626
|
-
when_env :production, :staging
|
|
591
|
+
when_env :production # Deprecated — avoid in new code
|
|
592
|
+
when_env :production, :staging # Deprecated — avoid in new code
|
|
627
593
|
```
|
|
628
594
|
|
|
629
595
|
**Parameters**:
|
|
@@ -641,8 +607,6 @@ timing :after # Trigger fires after constraint checks
|
|
|
641
607
|
**Parameters**:
|
|
642
608
|
- `timing_value` (Symbol or String): Either `:before` or `:after`
|
|
643
609
|
|
|
644
|
-
**Returns**: Current timing value if called without argument
|
|
645
|
-
|
|
646
610
|
## TriggerRegistry Model
|
|
647
611
|
|
|
648
612
|
The `TriggerRegistry` ActiveRecord model represents a trigger in the registry.
|
|
@@ -657,12 +621,13 @@ trigger.table_name # => "users"
|
|
|
657
621
|
trigger.function_name # => "validate_user_email"
|
|
658
622
|
trigger.events # => ["insert", "update"]
|
|
659
623
|
trigger.version # => 1
|
|
660
|
-
trigger.enabled
|
|
661
|
-
trigger.timing
|
|
662
|
-
trigger.
|
|
663
|
-
trigger.
|
|
664
|
-
trigger.
|
|
665
|
-
trigger.
|
|
624
|
+
trigger.enabled # => true
|
|
625
|
+
trigger.timing # => "before" or "after"
|
|
626
|
+
trigger.for_each # => "row" or "statement"
|
|
627
|
+
trigger.environments # => [] (when_env is deprecated)
|
|
628
|
+
trigger.condition # => "NEW.status = 'active'" or nil
|
|
629
|
+
trigger.created_at # => 2023-12-15 12:00:00 UTC
|
|
630
|
+
trigger.updated_at # => 2023-12-15 12:00:00 UTC
|
|
666
631
|
```
|
|
667
632
|
|
|
668
633
|
### Instance Methods
|
|
@@ -745,7 +710,7 @@ trigger.re_execute!(
|
|
|
745
710
|
- `confirmation` (String, optional): Kill switch confirmation text
|
|
746
711
|
- `actor` (Hash, optional): Information about who is performing the operation
|
|
747
712
|
|
|
748
|
-
**Raises**: `ArgumentError` if reason is blank
|
|
713
|
+
**Raises**: `ArgumentError` if reason is blank, `PgSqlTriggers::KillSwitchError`, `StandardError`
|
|
749
714
|
|
|
750
715
|
**Returns**: `true` on success
|
|
751
716
|
|
|
@@ -833,8 +798,12 @@ triggers = PgSqlTriggers::Registry.list
|
|
|
833
798
|
puts "Total triggers: #{triggers.count}"
|
|
834
799
|
|
|
835
800
|
# 4. Check for drift
|
|
836
|
-
|
|
837
|
-
|
|
801
|
+
drifted = PgSqlTriggers::Registry.drifted
|
|
802
|
+
in_sync = PgSqlTriggers::Registry.in_sync
|
|
803
|
+
unknown = PgSqlTriggers::Registry.unknown_triggers
|
|
804
|
+
dropped = PgSqlTriggers::Registry.dropped
|
|
805
|
+
|
|
806
|
+
puts "Drifted: #{drifted.count}, In Sync: #{in_sync.count}, Unknown: #{unknown.count}, Dropped: #{dropped.count}"
|
|
838
807
|
|
|
839
808
|
# 5. Enable specific trigger
|
|
840
809
|
trigger = PgSqlTriggers::TriggerRegistry.find_by(trigger_name: "users_email_validation")
|
|
@@ -876,16 +845,16 @@ end
|
|
|
876
845
|
### Inspection and Reporting
|
|
877
846
|
|
|
878
847
|
```ruby
|
|
879
|
-
# Generate a drift report
|
|
880
|
-
drift = PgSqlTriggers::Registry.diff
|
|
881
|
-
|
|
848
|
+
# Generate a drift report using dedicated query methods
|
|
882
849
|
puts "=== Drift Report ==="
|
|
883
|
-
puts "In Sync: #{
|
|
884
|
-
puts "Drifted: #{
|
|
850
|
+
puts "In Sync: #{PgSqlTriggers::Registry.in_sync.count}"
|
|
851
|
+
puts "Drifted: #{PgSqlTriggers::Registry.drifted.count}"
|
|
852
|
+
puts "Dropped: #{PgSqlTriggers::Registry.dropped.count}"
|
|
853
|
+
puts "Unknown: #{PgSqlTriggers::Registry.unknown_triggers.count}"
|
|
854
|
+
|
|
855
|
+
# Or get the full categorised hash
|
|
856
|
+
drift = PgSqlTriggers::Registry.diff
|
|
885
857
|
puts "Manual Override: #{drift[:manual_override].count}"
|
|
886
|
-
puts "Disabled: #{drift[:disabled].count}"
|
|
887
|
-
puts "Dropped: #{drift[:dropped].count}"
|
|
888
|
-
puts "Unknown: #{drift[:unknown].count}"
|
|
889
858
|
|
|
890
859
|
# List all triggers with details
|
|
891
860
|
triggers = PgSqlTriggers::Registry.list
|
|
@@ -897,6 +866,7 @@ triggers.each do |trigger|
|
|
|
897
866
|
puts " Function: #{trigger.function_name}"
|
|
898
867
|
puts " Events: #{trigger.events.join(', ')}"
|
|
899
868
|
puts " Timing: #{trigger.timing}"
|
|
869
|
+
puts " For Each: #{trigger.for_each}"
|
|
900
870
|
puts " Version: #{trigger.version}"
|
|
901
871
|
puts " Enabled: #{trigger.enabled}"
|
|
902
872
|
puts " Drift: #{trigger.drift_status}"
|
|
@@ -922,6 +892,118 @@ rescue StandardError => e
|
|
|
922
892
|
end
|
|
923
893
|
```
|
|
924
894
|
|
|
895
|
+
## Audit Log API
|
|
896
|
+
|
|
897
|
+
The Audit Log API provides methods for querying and managing audit log entries.
|
|
898
|
+
|
|
899
|
+
### `PgSqlTriggers::AuditLog`
|
|
900
|
+
|
|
901
|
+
The `AuditLog` model provides methods for querying audit log entries.
|
|
902
|
+
|
|
903
|
+
#### Class Methods
|
|
904
|
+
|
|
905
|
+
##### `AuditLog.for_trigger_name(trigger_name)`
|
|
906
|
+
|
|
907
|
+
Get audit log entries for a specific trigger.
|
|
908
|
+
|
|
909
|
+
**Parameters:**
|
|
910
|
+
- `trigger_name` (String): The trigger name to query
|
|
911
|
+
|
|
912
|
+
**Returns:** `ActiveRecord::Relation` - Audit log entries for the trigger, ordered by most recent first
|
|
913
|
+
|
|
914
|
+
**Example:**
|
|
915
|
+
```ruby
|
|
916
|
+
# Get all audit log entries for a specific trigger
|
|
917
|
+
entries = PgSqlTriggers::AuditLog.for_trigger_name("users_email_validation")
|
|
918
|
+
entries.each do |entry|
|
|
919
|
+
puts "#{entry.operation}: #{entry.status} at #{entry.created_at}"
|
|
920
|
+
end
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
##### `AuditLog.log_success(...)`
|
|
924
|
+
|
|
925
|
+
Log a successful operation to the audit log.
|
|
926
|
+
|
|
927
|
+
**Parameters:**
|
|
928
|
+
- `operation:` (Symbol, String): The operation being performed (e.g., `:trigger_enable`)
|
|
929
|
+
- `trigger_name:` (String, nil): The trigger name (if applicable)
|
|
930
|
+
- `actor:` (Hash): Information about who performed the action (e.g., `{ type: "UI", id: "123" }`)
|
|
931
|
+
- `environment:` (String, nil): The environment
|
|
932
|
+
- `reason:` (String, nil): Reason for the operation
|
|
933
|
+
- `confirmation_text:` (String, nil): Confirmation text used
|
|
934
|
+
- `before_state:` (Hash, nil): State before operation
|
|
935
|
+
- `after_state:` (Hash, nil): State after operation
|
|
936
|
+
- `diff:` (String, nil): Diff information
|
|
937
|
+
|
|
938
|
+
**Returns:** `AuditLog` instance or `nil` if logging fails
|
|
939
|
+
|
|
940
|
+
**Example:**
|
|
941
|
+
```ruby
|
|
942
|
+
PgSqlTriggers::AuditLog.log_success(
|
|
943
|
+
operation: :trigger_enable,
|
|
944
|
+
trigger_name: "users_email_validation",
|
|
945
|
+
actor: { type: "Console", id: "admin@example.com" },
|
|
946
|
+
environment: "production",
|
|
947
|
+
before_state: { enabled: false },
|
|
948
|
+
after_state: { enabled: true }
|
|
949
|
+
)
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
##### `AuditLog.log_failure(...)`
|
|
953
|
+
|
|
954
|
+
Log a failed operation to the audit log.
|
|
955
|
+
|
|
956
|
+
**Parameters:**
|
|
957
|
+
- `operation:` (Symbol, String): The operation being performed
|
|
958
|
+
- `trigger_name:` (String, nil): The trigger name (if applicable)
|
|
959
|
+
- `actor:` (Hash): Information about who performed the action
|
|
960
|
+
- `environment:` (String, nil): The environment
|
|
961
|
+
- `error_message:` (String): Error message (required)
|
|
962
|
+
- `reason:` (String, nil): Reason for the operation (if provided before failure)
|
|
963
|
+
- `confirmation_text:` (String, nil): Confirmation text used
|
|
964
|
+
- `before_state:` (Hash, nil): State before operation
|
|
965
|
+
|
|
966
|
+
**Returns:** `AuditLog` instance or `nil` if logging fails
|
|
967
|
+
|
|
968
|
+
**Example:**
|
|
969
|
+
```ruby
|
|
970
|
+
PgSqlTriggers::AuditLog.log_failure(
|
|
971
|
+
operation: :trigger_enable,
|
|
972
|
+
trigger_name: "users_email_validation",
|
|
973
|
+
actor: { type: "UI", id: "user_123" },
|
|
974
|
+
environment: "production",
|
|
975
|
+
error_message: "Trigger does not exist in database",
|
|
976
|
+
before_state: { enabled: false }
|
|
977
|
+
)
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
#### Scopes
|
|
981
|
+
|
|
982
|
+
The `AuditLog` model provides several useful scopes:
|
|
983
|
+
|
|
984
|
+
- `AuditLog.for_trigger(trigger_name)` - Filter by trigger name
|
|
985
|
+
- `AuditLog.for_operation(operation)` - Filter by operation type
|
|
986
|
+
- `AuditLog.for_environment(env)` - Filter by environment
|
|
987
|
+
- `AuditLog.successful` - Only successful operations
|
|
988
|
+
- `AuditLog.failed` - Only failed operations
|
|
989
|
+
- `AuditLog.recent` - Order by most recent first
|
|
990
|
+
|
|
991
|
+
**Example:**
|
|
992
|
+
```ruby
|
|
993
|
+
# Get all failed operations in production
|
|
994
|
+
failed_ops = PgSqlTriggers::AuditLog
|
|
995
|
+
.failed
|
|
996
|
+
.for_environment("production")
|
|
997
|
+
.recent
|
|
998
|
+
.limit(10)
|
|
999
|
+
|
|
1000
|
+
# Get all enable operations for a trigger
|
|
1001
|
+
enable_ops = PgSqlTriggers::AuditLog
|
|
1002
|
+
.for_trigger("users_email_validation")
|
|
1003
|
+
.for_operation("trigger_enable")
|
|
1004
|
+
.recent
|
|
1005
|
+
```
|
|
1006
|
+
|
|
925
1007
|
## Next Steps
|
|
926
1008
|
|
|
927
1009
|
- [Usage Guide](usage-guide.md) - Learn the DSL and migration system
|