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/usage-guide.md
CHANGED
|
@@ -15,7 +15,7 @@ PgSqlTriggers provides a Ruby DSL for defining triggers. Trigger definitions are
|
|
|
15
15
|
|
|
16
16
|
### Basic Trigger Definition
|
|
17
17
|
|
|
18
|
-
Create trigger definition files in `app/triggers
|
|
18
|
+
Create trigger definition files in `app/triggers/` (or scaffold them with the CLI generator — see below):
|
|
19
19
|
|
|
20
20
|
```ruby
|
|
21
21
|
# app/triggers/users_email_validation.rb
|
|
@@ -24,11 +24,9 @@ PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
|
|
|
24
24
|
on :insert, :update
|
|
25
25
|
function :validate_user_email
|
|
26
26
|
|
|
27
|
-
version 1
|
|
28
|
-
enabled
|
|
27
|
+
self.version = 1
|
|
28
|
+
self.enabled = true
|
|
29
29
|
timing :before
|
|
30
|
-
|
|
31
|
-
when_env :production
|
|
32
30
|
end
|
|
33
31
|
```
|
|
34
32
|
|
|
@@ -61,25 +59,30 @@ function :validate_user_email
|
|
|
61
59
|
Version number for tracking changes:
|
|
62
60
|
|
|
63
61
|
```ruby
|
|
64
|
-
version 1 # Increment when trigger logic changes
|
|
62
|
+
self.version = 1 # Increment when trigger logic changes
|
|
65
63
|
```
|
|
66
64
|
|
|
67
65
|
#### `enabled`
|
|
68
|
-
Initial state of the trigger:
|
|
66
|
+
Initial state of the trigger (defaults to `true`):
|
|
69
67
|
|
|
70
68
|
```ruby
|
|
71
|
-
enabled true # Trigger is active
|
|
72
|
-
enabled false # Trigger is inactive
|
|
69
|
+
self.enabled = true # Trigger is active (default)
|
|
70
|
+
self.enabled = false # Trigger is inactive
|
|
73
71
|
```
|
|
74
72
|
|
|
75
|
-
#### `
|
|
76
|
-
|
|
73
|
+
#### `for_each_row` / `for_each_statement`
|
|
74
|
+
PostgreSQL execution granularity (defaults to row-level):
|
|
77
75
|
|
|
78
76
|
```ruby
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
for_each_row # FOR EACH ROW (default)
|
|
78
|
+
for_each_statement # FOR EACH STATEMENT
|
|
81
79
|
```
|
|
82
80
|
|
|
81
|
+
#### `when_env`
|
|
82
|
+
**Deprecated.** Environment-specific trigger declarations cause schema drift between environments.
|
|
83
|
+
Use application-level configuration to gate trigger behaviour by environment instead.
|
|
84
|
+
Calling `when_env` emits a deprecation warning and will be removed in a future major version.
|
|
85
|
+
|
|
83
86
|
#### `timing`
|
|
84
87
|
Specifies when the trigger fires relative to the event (BEFORE or AFTER):
|
|
85
88
|
|
|
@@ -97,76 +100,44 @@ PgSqlTriggers::DSL.pg_sql_trigger "orders_billing_trigger" do
|
|
|
97
100
|
on :insert, :update
|
|
98
101
|
function :calculate_order_total
|
|
99
102
|
|
|
100
|
-
version 2
|
|
101
|
-
enabled true
|
|
103
|
+
self.version = 2
|
|
104
|
+
self.enabled = true
|
|
102
105
|
timing :after
|
|
103
|
-
|
|
104
|
-
when_env :production, :staging
|
|
106
|
+
for_each_row
|
|
105
107
|
end
|
|
106
108
|
```
|
|
107
109
|
|
|
108
110
|
## Trigger Generator
|
|
109
111
|
|
|
110
|
-
PgSqlTriggers provides a
|
|
112
|
+
PgSqlTriggers provides a CLI generator that scaffolds a DSL definition and migration together from the command line.
|
|
111
113
|
|
|
112
|
-
###
|
|
114
|
+
### CLI Generator
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
2. Fill in the trigger details:
|
|
118
|
-
- **Trigger Name**: Lowercase letters, numbers, and underscores only
|
|
119
|
-
- **Table Name**: The PostgreSQL table to attach the trigger to
|
|
120
|
-
- **Function Name**: The PostgreSQL function name (must match the function body)
|
|
121
|
-
- **Timing**: When the trigger fires - BEFORE (before constraint checks) or AFTER (after constraint checks)
|
|
122
|
-
- **Events**: Select one or more events (INSERT, UPDATE, DELETE, TRUNCATE)
|
|
123
|
-
- **Function Body**: The complete PostgreSQL function definition
|
|
124
|
-
- **Version**: Starting version number (default: 1)
|
|
125
|
-
- **Enabled**: Whether the trigger should be enabled initially
|
|
126
|
-
- **Environments**: Optional environment restrictions
|
|
127
|
-
- **Condition**: Optional WHEN condition for the trigger
|
|
128
|
-
3. Preview the generated DSL and migration code (includes timing and condition display)
|
|
129
|
-
4. Create the trigger files
|
|
130
|
-
|
|
131
|
-
The generator creates:
|
|
132
|
-
- A DSL definition file in `app/triggers/`
|
|
133
|
-
- A migration file in `db/triggers/`
|
|
134
|
-
- A registry entry in the database
|
|
135
|
-
|
|
136
|
-
### Rails Generators
|
|
116
|
+
```bash
|
|
117
|
+
rails generate pg_sql_triggers:trigger TRIGGER_NAME TABLE_NAME [EVENTS...] [--timing before|after] [--function fn_name]
|
|
118
|
+
```
|
|
137
119
|
|
|
138
|
-
|
|
120
|
+
Example:
|
|
139
121
|
|
|
140
122
|
```bash
|
|
141
|
-
|
|
142
|
-
rails generate trigger:migration add_user_validation
|
|
143
|
-
|
|
144
|
-
# Or using the full namespace
|
|
145
|
-
rails generate pg_sql_triggers:trigger_migration add_user_validation
|
|
123
|
+
rails generate pg_sql_triggers:trigger users_email_validation users insert update --timing before --function validate_user_email
|
|
146
124
|
```
|
|
147
125
|
|
|
148
|
-
This creates
|
|
126
|
+
This creates:
|
|
127
|
+
- `app/triggers/users_email_validation.rb` — DSL stub
|
|
128
|
+
- `db/triggers/TIMESTAMP_users_email_validation.rb` — migration with function + trigger SQL
|
|
149
129
|
|
|
150
|
-
|
|
130
|
+
Files are written directly into the working tree and go through version control and code review like any other source file.
|
|
151
131
|
|
|
152
|
-
|
|
153
|
-
- **Function Name Formatting**: Automatically quotes function names with special characters
|
|
154
|
-
- **Multiple Environments**: Supports multiple environment restrictions
|
|
155
|
-
- **Condition Escaping**: Properly escapes quotes in WHEN conditions
|
|
156
|
-
- **Event Combinations**: Handles single or multiple events (INSERT, UPDATE, DELETE, TRUNCATE)
|
|
157
|
-
- **Migration Numbering**: Automatically generates sequential migration numbers
|
|
158
|
-
- **Error Handling**: Graceful error handling with detailed error messages
|
|
132
|
+
### Migration-Only Generator
|
|
159
133
|
|
|
160
|
-
|
|
134
|
+
To generate a standalone trigger migration without a DSL stub:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
rails generate pg_sql_triggers:trigger_migration add_user_validation
|
|
138
|
+
```
|
|
161
139
|
|
|
162
|
-
|
|
163
|
-
- Function names with special characters (quoted vs unquoted)
|
|
164
|
-
- Multiple environments in a single trigger
|
|
165
|
-
- Complex WHEN conditions with quotes
|
|
166
|
-
- All event type combinations
|
|
167
|
-
- Standalone gem usage (without Rails context)
|
|
168
|
-
- Migration number collisions
|
|
169
|
-
- Blank events and environments (filtered automatically)
|
|
140
|
+
This creates a timestamped file in `db/triggers/` that you can edit to add your trigger logic.
|
|
170
141
|
|
|
171
142
|
## Trigger Migrations
|
|
172
143
|
|
|
@@ -177,7 +148,7 @@ Trigger migrations work similarly to Rails schema migrations but are specificall
|
|
|
177
148
|
Create a new trigger migration:
|
|
178
149
|
|
|
179
150
|
```bash
|
|
180
|
-
rails generate
|
|
151
|
+
rails generate pg_sql_triggers:trigger_migration add_validation_trigger
|
|
181
152
|
```
|
|
182
153
|
|
|
183
154
|
This creates a timestamped file in `db/triggers/`:
|
data/docs/web-ui.md
CHANGED
|
@@ -8,7 +8,7 @@ The PgSqlTriggers web interface provides a visual dashboard for managing trigger
|
|
|
8
8
|
- [Dashboard Overview](#dashboard-overview)
|
|
9
9
|
- [Managing Triggers](#managing-triggers)
|
|
10
10
|
- [Migration Management](#migration-management)
|
|
11
|
-
- [
|
|
11
|
+
- [Audit Log](#audit-log)
|
|
12
12
|
- [Permissions and Safety](#permissions-and-safety)
|
|
13
13
|
|
|
14
14
|
## Accessing the Web UI
|
|
@@ -34,11 +34,12 @@ The dashboard provides a comprehensive view of your trigger ecosystem.
|
|
|
34
34
|
|
|
35
35
|
### Main Features
|
|
36
36
|
|
|
37
|
-
1. **Trigger List**: View all triggers with their current status
|
|
37
|
+
1. **Trigger List**: View all triggers with their current status and "Last Applied" timestamps
|
|
38
38
|
2. **Drift Detection**: Visual indicators for drift states
|
|
39
39
|
3. **Migration Status**: See pending and applied migrations
|
|
40
|
-
4. **Quick Actions**: Enable/disable triggers, run migrations
|
|
40
|
+
4. **Quick Actions**: Enable/disable triggers, drop/re-execute triggers (based on permissions), run migrations
|
|
41
41
|
5. **Kill Switch Status**: Production environment indicator
|
|
42
|
+
6. **Audit Trail**: All operations are logged with actor information and viewable via Audit Log UI
|
|
42
43
|
|
|
43
44
|

|
|
44
45
|
|
|
@@ -50,32 +51,116 @@ The dashboard provides a comprehensive view of your trigger ecosystem.
|
|
|
50
51
|
- **○ Gray**: Disabled
|
|
51
52
|
- **? Purple**: Unknown
|
|
52
53
|
|
|
54
|
+
## Database Tables & Triggers
|
|
55
|
+
|
|
56
|
+
The Database Tables & Triggers page provides a comprehensive view of all tables in your database and their associated triggers. This page helps you understand which tables have triggers and which don't, making it easier to manage your trigger ecosystem.
|
|
57
|
+
|
|
58
|
+
### Accessing the Tables Page
|
|
59
|
+
|
|
60
|
+
1. Click "View Tables" from the dashboard
|
|
61
|
+
2. Or navigate directly to `/pg_sql_triggers/tables`
|
|
62
|
+
|
|
63
|
+
### Statistics Overview
|
|
64
|
+
|
|
65
|
+
The page displays three key statistics:
|
|
66
|
+
- **Tables with Triggers**: Count of tables that have at least one trigger
|
|
67
|
+
- **Tables without Triggers**: Count of tables that have no triggers
|
|
68
|
+
- **Total Tables**: Total count of all tables in the database
|
|
69
|
+
|
|
70
|
+
### Filtering Tables
|
|
71
|
+
|
|
72
|
+
Use the filter controls to view different subsets of tables:
|
|
73
|
+
- **All Tables**: Shows all tables regardless of trigger status
|
|
74
|
+
- **With Triggers**: Shows only tables that have at least one trigger (default)
|
|
75
|
+
- **Without Triggers**: Shows only tables that have no triggers
|
|
76
|
+
|
|
77
|
+
The active filter is highlighted with a colored background. Click any filter button to switch views.
|
|
78
|
+
|
|
79
|
+
### Pagination
|
|
80
|
+
|
|
81
|
+
When you have many tables, the list is paginated for better performance:
|
|
82
|
+
- **Default**: 20 tables per page
|
|
83
|
+
- **Configurable**: Choose 10, 20, 50, or 100 tables per page
|
|
84
|
+
- **Navigation**: Use Previous/Next buttons to move between pages
|
|
85
|
+
- **Filter Preservation**: Your selected filter is preserved when navigating pages
|
|
86
|
+
|
|
87
|
+
### Table Information
|
|
88
|
+
|
|
89
|
+
Each table row displays:
|
|
90
|
+
- **Table Name**: The name of the database table
|
|
91
|
+
- **Trigger Count**: Number of triggers on the table (badge indicator)
|
|
92
|
+
- **Trigger Names & Functions**: List of all triggers with their function names
|
|
93
|
+
- Registry triggers (blue border) - Triggers managed by pg_sql_triggers
|
|
94
|
+
- Database-only triggers (yellow border) - Triggers not in the registry
|
|
95
|
+
- **Status**: Summary of enabled/disabled triggers
|
|
96
|
+
- **Actions**:
|
|
97
|
+
- "View Details" - Navigate to the table detail page
|
|
98
|
+
- "Create Trigger" - Scaffold a new trigger for this table using the CLI generator (see [Trigger Generator](usage-guide.md#trigger-generator))
|
|
99
|
+
|
|
100
|
+
### Table Detail Page
|
|
101
|
+
|
|
102
|
+
Click "View Details" on any table to see:
|
|
103
|
+
- **Table Columns**: Complete list of columns with data types and nullability
|
|
104
|
+
- **Registered Triggers**: All triggers managed by pg_sql_triggers with full details
|
|
105
|
+
- **Database Triggers**: Triggers that exist in the database but aren't in the registry
|
|
106
|
+
|
|
107
|
+
From the table detail page, you can:
|
|
108
|
+
- Enable/disable individual triggers (Operator+ permission)
|
|
109
|
+
- Drop triggers (Admin permission)
|
|
110
|
+
- Re-execute drifted triggers (Admin permission)
|
|
111
|
+
- Create new triggers for the table
|
|
112
|
+
|
|
53
113
|
## Managing Triggers
|
|
54
114
|
|
|
55
115
|
### Viewing Trigger Details
|
|
56
116
|
|
|
57
|
-
Click on any trigger to
|
|
58
|
-
|
|
117
|
+
Click on any trigger name (from dashboard or table view) to access the trigger detail page. The detail page includes:
|
|
118
|
+
|
|
119
|
+
#### Navigation
|
|
120
|
+
- **Breadcrumb Navigation**: Dashboard → Tables → Table Name → Trigger Name
|
|
121
|
+
- **Quick Links**: Back to Dashboard, View Table
|
|
122
|
+
|
|
123
|
+
#### Summary Panel
|
|
124
|
+
- Current status and drift state with visual indicators
|
|
59
125
|
- Table and function information
|
|
60
|
-
- Version
|
|
61
|
-
-
|
|
62
|
-
-
|
|
126
|
+
- Version, source (DSL/generated/manual_sql), and environment
|
|
127
|
+
- **Last Applied**: Human-readable timestamp showing when trigger was last applied (e.g., "2 hours ago")
|
|
128
|
+
- **Last Verified**: Timestamp of last drift verification
|
|
129
|
+
- **Created At**: Original creation timestamp
|
|
130
|
+
|
|
131
|
+
#### SQL Information
|
|
132
|
+
- **Function Body**: Complete PL/pgSQL function code
|
|
133
|
+
- **Trigger Configuration**: Events, timing, conditions
|
|
134
|
+
- **SQL Diff View**: If drift detected, shows expected vs actual SQL side-by-side
|
|
135
|
+
|
|
136
|
+
#### Actions
|
|
137
|
+
All action buttons available based on permissions:
|
|
138
|
+
- Enable/Disable (Operator+)
|
|
139
|
+
- Re-Execute (Admin, shown only when drift detected)
|
|
140
|
+
- Drop (Admin)
|
|
63
141
|
|
|
64
142
|
### Enabling/Disabling Triggers
|
|
65
143
|
|
|
144
|
+
Triggers can be enabled or disabled from multiple locations:
|
|
145
|
+
- **Dashboard**: Quick action buttons in the trigger table (Operator+ permission)
|
|
146
|
+
- **Table Detail Page**: Action buttons for each trigger (Operator+ permission)
|
|
147
|
+
- **Trigger Detail Page**: Full action panel (Operator+ permission)
|
|
148
|
+
|
|
66
149
|
#### Enable a Trigger
|
|
67
150
|
|
|
68
|
-
1. Navigate to the trigger
|
|
69
|
-
2. Click the "Enable" button
|
|
151
|
+
1. Navigate to the trigger (dashboard, table view, or trigger detail page)
|
|
152
|
+
2. Click the "Enable" button (green button)
|
|
70
153
|
3. In production environments, enter the confirmation text when prompted
|
|
71
|
-
4. Confirm the action
|
|
154
|
+
4. Confirm the action in the modal
|
|
155
|
+
5. The trigger will be enabled and the operation logged to the audit trail
|
|
72
156
|
|
|
73
157
|
#### Disable a Trigger
|
|
74
158
|
|
|
75
|
-
1. Navigate to the trigger
|
|
76
|
-
2. Click the "Disable" button
|
|
159
|
+
1. Navigate to the trigger (dashboard, table view, or trigger detail page)
|
|
160
|
+
2. Click the "Disable" button (red button)
|
|
77
161
|
3. In production environments, enter the confirmation text when prompted
|
|
78
|
-
4. Confirm the action
|
|
162
|
+
4. Confirm the action in the modal
|
|
163
|
+
5. The trigger will be disabled and the operation logged to the audit trail
|
|
79
164
|
|
|
80
165
|
### Viewing Drift Status
|
|
81
166
|
|
|
@@ -99,14 +184,18 @@ Available actions depend on trigger state and your permissions:
|
|
|
99
184
|
|
|
100
185
|
### Drop Trigger
|
|
101
186
|
|
|
102
|
-
The drop action permanently removes a trigger from the database and registry.
|
|
187
|
+
The drop action permanently removes a trigger from the database and registry. Available from:
|
|
188
|
+
- **Dashboard**: "Drop" button in trigger table (Admin only)
|
|
189
|
+
- **Table Detail Page**: "Drop Trigger" button (Admin only)
|
|
190
|
+
- **Trigger Detail Page**: "Drop Trigger" button (Admin only)
|
|
103
191
|
|
|
104
|
-
|
|
105
|
-
|
|
192
|
+
**Steps**:
|
|
193
|
+
1. Navigate to the trigger (any view with drop button)
|
|
194
|
+
2. Click the "Drop Trigger" button (gray button with warning icon)
|
|
106
195
|
3. A modal will appear requiring:
|
|
107
196
|
- **Reason**: Explanation for dropping the trigger (required for audit trail)
|
|
108
197
|
- **Confirmation**: In protected environments, type the exact confirmation text shown
|
|
109
|
-
4. Review the warning message
|
|
198
|
+
4. Review the warning message carefully
|
|
110
199
|
5. Click "Drop Trigger" to confirm
|
|
111
200
|
|
|
112
201
|
**Important Notes**:
|
|
@@ -115,26 +204,34 @@ The drop action permanently removes a trigger from the database and registry.
|
|
|
115
204
|
- Protected by kill switch in production environments
|
|
116
205
|
- Reason is logged for compliance and audit purposes
|
|
117
206
|
- The trigger is removed from both the database and the registry
|
|
207
|
+
- Operation is logged to audit trail with actor information and state changes
|
|
118
208
|
|
|
119
209
|
### Re-Execute Trigger
|
|
120
210
|
|
|
121
|
-
The re-execute action fixes drifted triggers by dropping and recreating them from the registry definition.
|
|
211
|
+
The re-execute action fixes drifted triggers by dropping and recreating them from the registry definition. Available from:
|
|
212
|
+
- **Dashboard**: "Re-Execute" button in trigger table (Admin only, shown only when drift detected)
|
|
213
|
+
- **Table Detail Page**: "Re-Execute Trigger" button (Admin only, shown only when drift detected)
|
|
214
|
+
- **Trigger Detail Page**: "Re-Execute Trigger" button (Admin only, shown only when drift detected)
|
|
122
215
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
216
|
+
**Steps**:
|
|
217
|
+
1. Navigate to the trigger (any view with re-execute button)
|
|
218
|
+
2. If the trigger is drifted, you'll see a drift warning and the "Re-Execute" button will be visible
|
|
219
|
+
3. Click the "Re-Execute" button (yellow/warning button)
|
|
126
220
|
4. A modal will appear showing:
|
|
127
|
-
- **Drift Comparison**:
|
|
221
|
+
- **Drift Comparison**: Side-by-side differences between expected (registry) and actual (database) SQL
|
|
128
222
|
- **Reason Field**: Explanation for re-executing (required for audit trail)
|
|
129
223
|
- **Confirmation**: In protected environments, type the exact confirmation text shown
|
|
130
|
-
5. Review the drift differences to understand what will change
|
|
224
|
+
5. Review the drift differences carefully to understand what will change
|
|
131
225
|
6. Click "Re-Execute Trigger" to confirm
|
|
132
226
|
|
|
133
227
|
**What Happens**:
|
|
134
228
|
1. Current trigger is dropped from the database
|
|
135
229
|
2. New trigger is created using the registry definition (function_body, events, timing, condition)
|
|
136
230
|
3. Registry is updated with execution timestamp
|
|
137
|
-
4. Operation is logged
|
|
231
|
+
4. Operation is logged to audit trail with:
|
|
232
|
+
- Reason and actor information
|
|
233
|
+
- Before and after state
|
|
234
|
+
- SQL diff information
|
|
138
235
|
|
|
139
236
|
**Important Notes**:
|
|
140
237
|
- Requires **Admin** permission level
|
|
@@ -142,6 +239,7 @@ The re-execute action fixes drifted triggers by dropping and recreating them fro
|
|
|
142
239
|
- Reason is logged for compliance and audit purposes
|
|
143
240
|
- Executes in a database transaction (rolls back on error)
|
|
144
241
|
- Best used to fix triggers that have drifted from their DSL definition
|
|
242
|
+
- Button only appears when drift is detected
|
|
145
243
|
|
|
146
244
|
## Migration Management
|
|
147
245
|
|
|
@@ -204,82 +302,90 @@ After each migration action:
|
|
|
204
302
|
- **Error**: Red flash message with error details
|
|
205
303
|
- **Warnings**: Yellow flash message if issues occurred
|
|
206
304
|
|
|
207
|
-
##
|
|
208
|
-
|
|
209
|
-
SQL Capsules provide emergency escape hatches for executing SQL directly with comprehensive safety checks and audit logging.
|
|
210
|
-
|
|
211
|
-
### When to Use SQL Capsules
|
|
212
|
-
|
|
213
|
-
Use SQL Capsules for:
|
|
214
|
-
- Emergency fixes in production
|
|
215
|
-
- Critical data corrections
|
|
216
|
-
- Testing SQL functions
|
|
217
|
-
- Debugging trigger behavior
|
|
218
|
-
- One-off database operations
|
|
219
|
-
|
|
220
|
-
### Creating and Executing SQL Capsules
|
|
221
|
-
|
|
222
|
-
1. Navigate to "SQL Capsules" → "New SQL Capsule"
|
|
223
|
-
2. Fill in the capsule form:
|
|
224
|
-
- **Name**: Unique identifier (alphanumeric, underscores, hyphens only)
|
|
225
|
-
- **Environment**: Target environment (e.g., production, staging)
|
|
226
|
-
- **Purpose**: Detailed explanation of what the SQL does and why (required for audit trail)
|
|
227
|
-
- **SQL**: The SQL statement(s) to execute
|
|
228
|
-
3. Click "Create and Execute" or "Save for Later"
|
|
229
|
-
4. Review the capsule details on the confirmation page
|
|
230
|
-
5. In protected environments, enter confirmation text when prompted
|
|
231
|
-
6. Click "Execute" to run the SQL
|
|
232
|
-
7. Review the execution results
|
|
233
|
-
|
|
234
|
-
### Viewing Capsule History
|
|
235
|
-
|
|
236
|
-
1. Navigate to "SQL Capsules" → "History"
|
|
237
|
-
2. View list of previously executed capsules with:
|
|
238
|
-
- Name and purpose
|
|
239
|
-
- Environment and timestamp
|
|
240
|
-
- SQL checksum
|
|
241
|
-
- Execution status
|
|
242
|
-
3. Click on a capsule to view details
|
|
243
|
-
4. Re-execute historical capsules if needed
|
|
244
|
-
|
|
245
|
-
### Safety Features
|
|
246
|
-
|
|
247
|
-
- **Admin Permission Required**: Only Admin users can create and execute SQL capsules
|
|
248
|
-
- **Production Protection**: Requires typed confirmation in protected environments
|
|
249
|
-
- **Kill Switch Integration**: All executions are protected by kill switch
|
|
250
|
-
- **Comprehensive Logging**: All operations logged with actor, timestamp, and checksum
|
|
251
|
-
- **Transactional Execution**: SQL runs in a transaction and rolls back on error
|
|
252
|
-
- **Registry Storage**: All capsules are stored in the registry with checksums
|
|
253
|
-
- **Purpose Tracking**: Required purpose field ensures all executions are documented
|
|
254
|
-
|
|
255
|
-
### Example SQL Capsules
|
|
256
|
-
|
|
257
|
-
#### View All Triggers
|
|
258
|
-
```sql
|
|
259
|
-
SELECT
|
|
260
|
-
trigger_name,
|
|
261
|
-
event_object_table,
|
|
262
|
-
action_timing,
|
|
263
|
-
event_manipulation
|
|
264
|
-
FROM information_schema.triggers
|
|
265
|
-
WHERE trigger_schema = 'public';
|
|
266
|
-
```
|
|
305
|
+
## Audit Log
|
|
267
306
|
|
|
268
|
-
|
|
269
|
-
```sql
|
|
270
|
-
SELECT
|
|
271
|
-
routine_name,
|
|
272
|
-
routine_type
|
|
273
|
-
FROM information_schema.routines
|
|
274
|
-
WHERE routine_schema = 'public'
|
|
275
|
-
AND routine_name LIKE '%trigger%';
|
|
276
|
-
```
|
|
307
|
+
The Audit Log provides a comprehensive view of all trigger operations performed through the web UI, console APIs, and CLI. This feature is essential for compliance, debugging, and tracking changes to your trigger ecosystem.
|
|
277
308
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
309
|
+
### Accessing the Audit Log
|
|
310
|
+
|
|
311
|
+
1. Navigate to the "Audit Log" link in the main navigation menu
|
|
312
|
+
2. Or visit `/pg_sql_triggers/audit_logs` directly
|
|
313
|
+
|
|
314
|
+
### Viewing Audit Log Entries
|
|
315
|
+
|
|
316
|
+
The audit log displays all operations with the following information:
|
|
317
|
+
|
|
318
|
+
- **Time**: When the operation occurred (relative time with exact timestamp on hover)
|
|
319
|
+
- **Trigger**: The trigger name (clickable link to trigger detail page if available)
|
|
320
|
+
- **Operation**: The type of operation performed (e.g., `trigger_enable`, `trigger_drop`, `trigger_re_execute`)
|
|
321
|
+
- **Status**: Success or failure indicator
|
|
322
|
+
- **Environment**: The environment where the operation was performed
|
|
323
|
+
- **Actor**: Who performed the operation (e.g., `UI:user_id`, `Console:email`)
|
|
324
|
+
- **Reason**: Explanation for the operation (for drop/re-execute operations)
|
|
325
|
+
- **Error**: Error message if the operation failed
|
|
326
|
+
|
|
327
|
+
### Filtering Audit Logs
|
|
328
|
+
|
|
329
|
+
The audit log supports multiple filters to help you find specific entries:
|
|
330
|
+
|
|
331
|
+
1. **Trigger Name**: Filter by specific trigger name
|
|
332
|
+
2. **Operation**: Filter by operation type (enable, disable, drop, re_execute, etc.)
|
|
333
|
+
3. **Status**: Filter by success or failure
|
|
334
|
+
4. **Environment**: Filter by environment (production, staging, development, etc.)
|
|
335
|
+
5. **Sort Order**: Sort by date (newest first or oldest first)
|
|
336
|
+
|
|
337
|
+
Click "Apply Filters" to update the view, or "Clear" to remove all filters.
|
|
338
|
+
|
|
339
|
+
### Exporting Audit Logs
|
|
340
|
+
|
|
341
|
+
To export audit log entries:
|
|
342
|
+
|
|
343
|
+
1. Apply any desired filters
|
|
344
|
+
2. Click the "Export CSV" button
|
|
345
|
+
3. The CSV file will include all entries matching your filters (not just the current page)
|
|
346
|
+
4. File is named with timestamp: `audit_logs_YYYYMMDD_HHMMSS.csv`
|
|
347
|
+
|
|
348
|
+
The CSV export includes:
|
|
349
|
+
- ID, Trigger Name, Operation, Status, Environment
|
|
350
|
+
- Actor Type and ID
|
|
351
|
+
- Reason and Error Message
|
|
352
|
+
- Created At timestamp
|
|
353
|
+
|
|
354
|
+
### Pagination
|
|
355
|
+
|
|
356
|
+
The audit log uses pagination to handle large datasets:
|
|
357
|
+
|
|
358
|
+
- Default: 50 entries per page (adjustable via URL parameter)
|
|
359
|
+
- Maximum: 200 entries per page
|
|
360
|
+
- Navigate using "Previous" and "Next" buttons
|
|
361
|
+
- Page numbers and total count displayed
|
|
362
|
+
|
|
363
|
+
### What Gets Logged
|
|
364
|
+
|
|
365
|
+
All of the following operations are logged to the audit log:
|
|
366
|
+
|
|
367
|
+
- **Enable Trigger**: Success/failure, before/after state
|
|
368
|
+
- **Disable Trigger**: Success/failure, before/after state
|
|
369
|
+
- **Drop Trigger**: Success/failure, reason, state changes
|
|
370
|
+
- **Re-execute Trigger**: Success/failure, reason, drift diff information
|
|
371
|
+
- **Migration Operations**: Up, down, and redo operations (infrastructure ready)
|
|
372
|
+
|
|
373
|
+
Each log entry includes:
|
|
374
|
+
- Complete actor information (who performed the operation)
|
|
375
|
+
- Before and after state (for state-changing operations)
|
|
376
|
+
- Operation metadata (reason, confirmation text, environment)
|
|
377
|
+
- Error details (if the operation failed)
|
|
378
|
+
- Timestamp of the operation
|
|
379
|
+
|
|
380
|
+
### Use Cases
|
|
381
|
+
|
|
382
|
+
Common use cases for the audit log:
|
|
383
|
+
|
|
384
|
+
- **Compliance**: Track all changes for audit requirements
|
|
385
|
+
- **Debugging**: Understand what operations were performed before an issue
|
|
386
|
+
- **Accountability**: See who performed specific operations
|
|
387
|
+
- **Troubleshooting**: Review failed operations and their error messages
|
|
388
|
+
- **Change History**: Track the evolution of your trigger ecosystem over time
|
|
283
389
|
|
|
284
390
|
## Permissions and Safety
|
|
285
391
|
|
|
@@ -312,7 +418,6 @@ Cannot:
|
|
|
312
418
|
#### Admin (Full Access)
|
|
313
419
|
- All Operator permissions
|
|
314
420
|
- Drop triggers
|
|
315
|
-
- Execute SQL via capsules
|
|
316
421
|
- Modify registry directly
|
|
317
422
|
|
|
318
423
|
### Kill Switch Protection
|
|
@@ -322,7 +427,13 @@ In protected environments (production, staging), the Web UI enforces additional
|
|
|
322
427
|
1. **Status Indicator**: Kill switch badge shows protection status
|
|
323
428
|
2. **Confirmation Required**: Dangerous operations require typed confirmation
|
|
324
429
|
3. **Warning Banners**: Visual alerts for production environment
|
|
325
|
-
4. **Audit Logging**: All protected operations are logged
|
|
430
|
+
4. **Audit Logging**: All protected operations are logged with complete audit trail:
|
|
431
|
+
- Actor information (who performed the operation)
|
|
432
|
+
- Before and after state
|
|
433
|
+
- Operation details (reason, confirmation text)
|
|
434
|
+
- Success/failure status
|
|
435
|
+
- Error messages (if failed)
|
|
436
|
+
- Timestamp of operation
|
|
326
437
|
|
|
327
438
|
### Configuring Permissions
|
|
328
439
|
|
|
@@ -332,20 +443,26 @@ Set up custom permission checking in the initializer:
|
|
|
332
443
|
# config/initializers/pg_sql_triggers.rb
|
|
333
444
|
PgSqlTriggers.configure do |config|
|
|
334
445
|
config.permission_checker = ->(actor, action, environment) {
|
|
335
|
-
user = User.
|
|
446
|
+
user = User.find_by(id: actor[:id])
|
|
447
|
+
return false unless user
|
|
336
448
|
|
|
337
449
|
case action
|
|
338
|
-
when :
|
|
339
|
-
user.present?
|
|
340
|
-
when :
|
|
341
|
-
user.
|
|
342
|
-
when :
|
|
343
|
-
user.admin?
|
|
450
|
+
when :view_triggers, :view_diffs
|
|
451
|
+
user.present? # Viewer level
|
|
452
|
+
when :enable_trigger, :disable_trigger, :apply_trigger, :test_trigger
|
|
453
|
+
user.operator? || user.admin? # Operator level
|
|
454
|
+
when :drop_trigger, :override_drift
|
|
455
|
+
user.admin? # Admin level
|
|
344
456
|
else
|
|
345
457
|
false
|
|
346
458
|
end
|
|
347
459
|
}
|
|
348
460
|
end
|
|
461
|
+
```else
|
|
462
|
+
false
|
|
463
|
+
end
|
|
464
|
+
}
|
|
465
|
+
end
|
|
349
466
|
```
|
|
350
467
|
|
|
351
468
|
## Screenshots
|
|
@@ -353,39 +470,45 @@ end
|
|
|
353
470
|
### Main Dashboard
|
|
354
471
|

|
|
355
472
|
|
|
356
|
-
###
|
|
473
|
+
### Migration Management
|
|
474
|
+

|
|
475
|
+
|
|
476
|
+
### Kill Switch Protection
|
|
477
|
+

|
|
357
478
|
|
|
358
|
-
|
|
479
|
+
## Dashboard Enhancements (v1.3.0+)
|
|
359
480
|
|
|
360
|
-
|
|
361
|
-
2. **Trigger Events**: Select timing (BEFORE/AFTER) and events (INSERT, UPDATE, DELETE, TRUNCATE)
|
|
362
|
-
3. **Configuration**: Version, environments, WHEN condition, and enabled state
|
|
363
|
-
4. **Preview**: Review generated DSL and migration code with timing and condition information
|
|
481
|
+
### Last Applied Column
|
|
364
482
|
|
|
365
|
-
The
|
|
366
|
-
-
|
|
367
|
-
-
|
|
368
|
-
-
|
|
369
|
-
-
|
|
483
|
+
The dashboard now includes a "Last Applied" column showing when each trigger was last applied to the database:
|
|
484
|
+
- **Human-readable format**: Displays relative time (e.g., "2 hours ago", "3 days ago")
|
|
485
|
+
- **Tooltip**: Hover over the timestamp to see exact date and time
|
|
486
|
+
- **Default sorting**: Dashboard sorted by most recently applied triggers first
|
|
487
|
+
- **Never applied**: Shows "Never" if trigger has never been applied
|
|
370
488
|
|
|
371
|
-
|
|
489
|
+
This helps you quickly identify:
|
|
490
|
+
- Which triggers are actively maintained
|
|
491
|
+
- How recently triggers were updated
|
|
492
|
+
- Triggers that may need attention
|
|
372
493
|
|
|
373
|
-
###
|
|
374
|
-

|
|
494
|
+
### Quick Actions in Dashboard
|
|
375
495
|
|
|
376
|
-
|
|
377
|
-
|
|
496
|
+
The dashboard trigger table now includes quick action buttons:
|
|
497
|
+
- **Enable/Disable**: Toggle trigger state (Operator+ permission)
|
|
498
|
+
- **Drop**: Remove trigger permanently (Admin only)
|
|
499
|
+
- **Re-Execute**: Fix drifted triggers (Admin only, shown only when drift detected)
|
|
378
500
|
|
|
379
|
-
|
|
380
|
-

|
|
501
|
+
All actions respect permission levels and show/hide buttons based on your role.
|
|
381
502
|
|
|
382
503
|
## Tips and Best Practices
|
|
383
504
|
|
|
384
505
|
1. **Check Status Regularly**: Monitor drift detection to catch unexpected changes
|
|
385
506
|
2. **Use Confirmations**: Don't bypass production confirmations without understanding the impact
|
|
386
507
|
3. **Test in Development**: Always test UI actions in development before production
|
|
387
|
-
4. **Review Logs**: Check application logs after important operations
|
|
388
|
-
5. **Document Changes**: Add
|
|
508
|
+
4. **Review Logs**: Check application logs and audit trail after important operations
|
|
509
|
+
5. **Document Changes**: Add detailed reasons when dropping or re-executing triggers
|
|
510
|
+
6. **Monitor Last Applied**: Use the "Last Applied" column to track trigger maintenance activity
|
|
511
|
+
7. **Breadcrumb Navigation**: Use breadcrumbs on trigger detail page for easy navigation
|
|
389
512
|
|
|
390
513
|
## Troubleshooting
|
|
391
514
|
|