pg_sql_triggers 1.2.0 → 1.3.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 +144 -0
- data/COVERAGE.md +26 -19
- data/Goal.md +276 -155
- data/README.md +27 -1
- 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 +178 -9
- data/app/views/layouts/pg_sql_triggers/application.html.erb +26 -6
- data/app/views/pg_sql_triggers/audit_logs/index.html.erb +177 -0
- data/app/views/pg_sql_triggers/dashboard/index.html.erb +33 -8
- data/app/views/pg_sql_triggers/tables/index.html.erb +76 -3
- data/app/views/pg_sql_triggers/tables/show.html.erb +17 -4
- 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 -0
- data/db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb +28 -0
- data/docs/README.md +15 -5
- data/docs/api-reference.md +191 -0
- data/docs/audit-trail.md +413 -0
- data/docs/configuration.md +6 -6
- data/docs/permissions.md +369 -0
- data/docs/troubleshooting.md +486 -0
- data/docs/ui-guide.md +211 -0
- data/docs/web-ui.md +257 -34
- data/lib/pg_sql_triggers/errors.rb +245 -0
- data/lib/pg_sql_triggers/generator/service.rb +32 -0
- data/lib/pg_sql_triggers/permissions/checker.rb +9 -2
- data/lib/pg_sql_triggers/registry.rb +141 -8
- data/lib/pg_sql_triggers/sql/kill_switch.rb +33 -5
- 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 +3 -6
- metadata +29 -6
- 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
|
@@ -6,9 +6,24 @@ require "active_support/core_ext/string/inflections"
|
|
|
6
6
|
|
|
7
7
|
module PgSqlTriggers
|
|
8
8
|
module Generator
|
|
9
|
+
# Service object for generating trigger DSL files, migration files, and registering triggers.
|
|
10
|
+
#
|
|
11
|
+
# This service follows the service object pattern with class methods for stateless operations.
|
|
12
|
+
#
|
|
13
|
+
# @example Generate trigger files
|
|
14
|
+
# form = PgSqlTriggers::Generator::Form.new(trigger_name: "users_email_validation", ...)
|
|
15
|
+
# result = PgSqlTriggers::Generator::Service.create_trigger(form, actor: current_user)
|
|
16
|
+
#
|
|
17
|
+
# if result[:success]
|
|
18
|
+
# puts "Created: #{result[:migration_path]}"
|
|
19
|
+
# end
|
|
9
20
|
# rubocop:disable Metrics/ClassLength
|
|
10
21
|
class Service
|
|
11
22
|
class << self
|
|
23
|
+
# Generates the DSL trigger definition code from a form.
|
|
24
|
+
#
|
|
25
|
+
# @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
|
|
26
|
+
# @return [String] The generated DSL code
|
|
12
27
|
def generate_dsl(form)
|
|
13
28
|
# Generate DSL trigger definition
|
|
14
29
|
events_list = form.events.compact_blank.map { |e| ":#{e}" }.join(", ")
|
|
@@ -44,6 +59,10 @@ module PgSqlTriggers
|
|
|
44
59
|
code
|
|
45
60
|
end
|
|
46
61
|
|
|
62
|
+
# Generates the migration file code from a form.
|
|
63
|
+
#
|
|
64
|
+
# @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
|
|
65
|
+
# @return [String] The generated migration code
|
|
47
66
|
def generate_migration(form)
|
|
48
67
|
# Generate migration class code
|
|
49
68
|
# Use Rails migration naming convention: Add{TriggerName}
|
|
@@ -95,6 +114,10 @@ module PgSqlTriggers
|
|
|
95
114
|
RUBY
|
|
96
115
|
end
|
|
97
116
|
|
|
117
|
+
# Generates a PL/pgSQL function stub template.
|
|
118
|
+
#
|
|
119
|
+
# @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
|
|
120
|
+
# @return [String, nil] The generated function stub SQL, or nil if not requested
|
|
98
121
|
def generate_function_stub(form)
|
|
99
122
|
return nil unless form.generate_function_stub
|
|
100
123
|
|
|
@@ -138,6 +161,10 @@ module PgSqlTriggers
|
|
|
138
161
|
SQL
|
|
139
162
|
end
|
|
140
163
|
|
|
164
|
+
# Returns the file paths where the migration and DSL files will be created.
|
|
165
|
+
#
|
|
166
|
+
# @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
|
|
167
|
+
# @return [Hash] Hash with :migration and :dsl keys containing relative file paths
|
|
141
168
|
def file_paths(form)
|
|
142
169
|
# NOTE: These paths are relative to the host Rails app, not the gem
|
|
143
170
|
# Generate both migration file and DSL file
|
|
@@ -148,6 +175,11 @@ module PgSqlTriggers
|
|
|
148
175
|
}
|
|
149
176
|
end
|
|
150
177
|
|
|
178
|
+
# Creates trigger files (DSL and migration) and registers the trigger in the registry.
|
|
179
|
+
#
|
|
180
|
+
# @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
|
|
181
|
+
# @param actor [Hash, nil] Optional actor information for audit logging
|
|
182
|
+
# @return [Hash] Result hash with :success (Boolean), :migration_path, :dsl_path, and optional :error
|
|
151
183
|
def create_trigger(form, actor: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
152
184
|
paths = file_paths(form)
|
|
153
185
|
base_path = rails_base_path
|
|
@@ -22,8 +22,15 @@ module PgSqlTriggers
|
|
|
22
22
|
unless can?(actor, action, environment: environment)
|
|
23
23
|
action_sym = action.to_sym
|
|
24
24
|
required_level = Permissions::ACTIONS[action_sym] || "unknown"
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
message = "Permission denied: #{action_sym} requires #{required_level} level access"
|
|
26
|
+
recovery = "Contact your administrator to request #{required_level} level access for this operation."
|
|
27
|
+
|
|
28
|
+
raise PgSqlTriggers::PermissionError.new(
|
|
29
|
+
message,
|
|
30
|
+
error_code: "PERMISSION_DENIED",
|
|
31
|
+
recovery_suggestion: recovery,
|
|
32
|
+
context: { action: action_sym, required_role: required_level, environment: environment }
|
|
33
|
+
)
|
|
27
34
|
end
|
|
28
35
|
true
|
|
29
36
|
end
|
|
@@ -1,59 +1,187 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PgSqlTriggers
|
|
4
|
+
# Registry module provides a unified API for querying and managing triggers.
|
|
5
|
+
#
|
|
6
|
+
# @example Query triggers
|
|
7
|
+
# # List all triggers
|
|
8
|
+
# triggers = PgSqlTriggers::Registry.list
|
|
9
|
+
#
|
|
10
|
+
# # Get enabled/disabled triggers
|
|
11
|
+
# enabled = PgSqlTriggers::Registry.enabled
|
|
12
|
+
# disabled = PgSqlTriggers::Registry.disabled
|
|
13
|
+
#
|
|
14
|
+
# # Get triggers for a specific table
|
|
15
|
+
# user_triggers = PgSqlTriggers::Registry.for_table(:users)
|
|
16
|
+
#
|
|
17
|
+
# # Check for drift
|
|
18
|
+
# drift_info = PgSqlTriggers::Registry.diff
|
|
19
|
+
#
|
|
20
|
+
# @example Manage triggers
|
|
21
|
+
# # Enable a trigger
|
|
22
|
+
# PgSqlTriggers::Registry.enable("users_email_validation",
|
|
23
|
+
# actor: current_user,
|
|
24
|
+
# confirmation: "EXECUTE TRIGGER_ENABLE")
|
|
25
|
+
#
|
|
26
|
+
# # Disable a trigger
|
|
27
|
+
# PgSqlTriggers::Registry.disable("users_email_validation",
|
|
28
|
+
# actor: current_user,
|
|
29
|
+
# confirmation: "EXECUTE TRIGGER_DISABLE")
|
|
30
|
+
#
|
|
31
|
+
# # Drop a trigger
|
|
32
|
+
# PgSqlTriggers::Registry.drop("old_trigger",
|
|
33
|
+
# actor: current_user,
|
|
34
|
+
# reason: "No longer needed",
|
|
35
|
+
# confirmation: "EXECUTE TRIGGER_DROP")
|
|
36
|
+
#
|
|
37
|
+
# # Re-execute a trigger
|
|
38
|
+
# PgSqlTriggers::Registry.re_execute("drifted_trigger",
|
|
39
|
+
# actor: current_user,
|
|
40
|
+
# reason: "Fix drift",
|
|
41
|
+
# confirmation: "EXECUTE TRIGGER_RE_EXECUTE")
|
|
4
42
|
module Registry
|
|
5
43
|
autoload :Manager, "pg_sql_triggers/registry/manager"
|
|
6
44
|
autoload :Validator, "pg_sql_triggers/registry/validator"
|
|
7
45
|
|
|
46
|
+
# Registers a trigger definition in the registry.
|
|
47
|
+
#
|
|
48
|
+
# @param definition [PgSqlTriggers::DSL::TriggerDefinition] The trigger definition to register
|
|
49
|
+
# @return [PgSqlTriggers::TriggerRegistry] The registered trigger record
|
|
8
50
|
def self.register(definition)
|
|
9
51
|
Manager.register(definition)
|
|
10
52
|
end
|
|
11
53
|
|
|
54
|
+
# Returns all registered triggers.
|
|
55
|
+
#
|
|
56
|
+
# @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] All trigger records
|
|
12
57
|
def self.list
|
|
13
58
|
Manager.list
|
|
14
59
|
end
|
|
15
60
|
|
|
61
|
+
# Returns only enabled triggers.
|
|
62
|
+
#
|
|
63
|
+
# @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Enabled trigger records
|
|
16
64
|
def self.enabled
|
|
17
65
|
Manager.enabled
|
|
18
66
|
end
|
|
19
67
|
|
|
68
|
+
# Returns only disabled triggers.
|
|
69
|
+
#
|
|
70
|
+
# @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Disabled trigger records
|
|
20
71
|
def self.disabled
|
|
21
72
|
Manager.disabled
|
|
22
73
|
end
|
|
23
74
|
|
|
75
|
+
# Returns triggers for a specific table.
|
|
76
|
+
#
|
|
77
|
+
# @param table_name [String, Symbol] The table name to filter by
|
|
78
|
+
# @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Triggers for the specified table
|
|
24
79
|
def self.for_table(table_name)
|
|
25
80
|
Manager.for_table(table_name)
|
|
26
81
|
end
|
|
27
82
|
|
|
28
|
-
|
|
29
|
-
|
|
83
|
+
# Checks for drift between DSL definitions and database state.
|
|
84
|
+
#
|
|
85
|
+
# @param trigger_name [String, nil] Optional trigger name to check specific trigger, or nil for all triggers
|
|
86
|
+
# @return [Hash] Drift information with keys: :in_sync, :drifted, :manual_override, :disabled, :dropped, :unknown
|
|
87
|
+
def self.diff(trigger_name = nil)
|
|
88
|
+
Manager.diff(trigger_name)
|
|
30
89
|
end
|
|
31
90
|
|
|
91
|
+
# Returns all triggers that have drifted from their expected state.
|
|
92
|
+
#
|
|
93
|
+
# @return [Array<Hash>] Array of drift result hashes for drifted triggers
|
|
94
|
+
def self.drifted
|
|
95
|
+
Manager.drifted
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns all triggers that are in sync with their expected state.
|
|
99
|
+
#
|
|
100
|
+
# @return [Array<Hash>] Array of drift result hashes for in-sync triggers
|
|
101
|
+
def self.in_sync
|
|
102
|
+
Manager.in_sync
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns all unknown (external) triggers not managed by this gem.
|
|
106
|
+
#
|
|
107
|
+
# @return [Array<Hash>] Array of drift result hashes for unknown triggers
|
|
108
|
+
def self.unknown_triggers
|
|
109
|
+
Manager.unknown_triggers
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns all triggers that have been dropped from the database.
|
|
113
|
+
#
|
|
114
|
+
# @return [Array<Hash>] Array of drift result hashes for dropped triggers
|
|
115
|
+
def self.dropped
|
|
116
|
+
Manager.dropped
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Validates all triggers in the registry.
|
|
120
|
+
#
|
|
121
|
+
# @raise [PgSqlTriggers::ValidationError] If validation fails
|
|
122
|
+
# @return [true] If validation passes
|
|
32
123
|
def self.validate!
|
|
33
124
|
Validator.validate!
|
|
34
125
|
end
|
|
35
126
|
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
|
|
127
|
+
# Enables a trigger by name.
|
|
128
|
+
#
|
|
129
|
+
# @param trigger_name [String] The name of the trigger to enable
|
|
130
|
+
# @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
|
|
131
|
+
# @param confirmation [String, nil] Optional confirmation text for kill switch protection
|
|
132
|
+
# @raise [PgSqlTriggers::PermissionError] If actor lacks permission
|
|
133
|
+
# @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
|
|
134
|
+
# @raise [PgSqlTriggers::NotFoundError] If trigger not found
|
|
135
|
+
# @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
|
|
39
136
|
def self.enable(trigger_name, actor:, confirmation: nil)
|
|
40
137
|
check_permission!(actor, :enable_trigger)
|
|
41
138
|
trigger = find_trigger!(trigger_name)
|
|
42
|
-
trigger.enable!(confirmation: confirmation)
|
|
139
|
+
trigger.enable!(confirmation: confirmation, actor: actor)
|
|
43
140
|
end
|
|
44
141
|
|
|
142
|
+
# Disables a trigger by name.
|
|
143
|
+
#
|
|
144
|
+
# @param trigger_name [String] The name of the trigger to disable
|
|
145
|
+
# @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
|
|
146
|
+
# @param confirmation [String, nil] Optional confirmation text for kill switch protection
|
|
147
|
+
# @raise [PgSqlTriggers::PermissionError] If actor lacks permission
|
|
148
|
+
# @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
|
|
149
|
+
# @raise [PgSqlTriggers::NotFoundError] If trigger not found
|
|
150
|
+
# @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
|
|
45
151
|
def self.disable(trigger_name, actor:, confirmation: nil)
|
|
46
152
|
check_permission!(actor, :disable_trigger)
|
|
47
153
|
trigger = find_trigger!(trigger_name)
|
|
48
|
-
trigger.disable!(confirmation: confirmation)
|
|
154
|
+
trigger.disable!(confirmation: confirmation, actor: actor)
|
|
49
155
|
end
|
|
50
156
|
|
|
157
|
+
# Drops a trigger by name.
|
|
158
|
+
#
|
|
159
|
+
# @param trigger_name [String] The name of the trigger to drop
|
|
160
|
+
# @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
|
|
161
|
+
# @param reason [String] Required reason for dropping the trigger
|
|
162
|
+
# @param confirmation [String, nil] Optional confirmation text for kill switch protection
|
|
163
|
+
# @raise [PgSqlTriggers::PermissionError] If actor lacks permission
|
|
164
|
+
# @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
|
|
165
|
+
# @raise [PgSqlTriggers::NotFoundError] If trigger not found
|
|
166
|
+
# @raise [ArgumentError] If reason is missing or empty
|
|
167
|
+
# @return [true] If drop succeeds
|
|
51
168
|
def self.drop(trigger_name, actor:, reason:, confirmation: nil)
|
|
52
169
|
check_permission!(actor, :drop_trigger)
|
|
53
170
|
trigger = find_trigger!(trigger_name)
|
|
54
171
|
trigger.drop!(reason: reason, confirmation: confirmation, actor: actor)
|
|
55
172
|
end
|
|
56
173
|
|
|
174
|
+
# Re-executes a trigger by name (drops and recreates it).
|
|
175
|
+
#
|
|
176
|
+
# @param trigger_name [String] The name of the trigger to re-execute
|
|
177
|
+
# @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
|
|
178
|
+
# @param reason [String] Required reason for re-executing the trigger
|
|
179
|
+
# @param confirmation [String, nil] Optional confirmation text for kill switch protection
|
|
180
|
+
# @raise [PgSqlTriggers::PermissionError] If actor lacks permission
|
|
181
|
+
# @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
|
|
182
|
+
# @raise [PgSqlTriggers::NotFoundError] If trigger not found
|
|
183
|
+
# @raise [ArgumentError] If reason is missing or empty
|
|
184
|
+
# @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
|
|
57
185
|
def self.re_execute(trigger_name, actor:, reason:, confirmation: nil)
|
|
58
186
|
check_permission!(actor, :drop_trigger) # Re-execute requires same permission as drop
|
|
59
187
|
trigger = find_trigger!(trigger_name)
|
|
@@ -65,7 +193,12 @@ module PgSqlTriggers
|
|
|
65
193
|
def self.find_trigger!(trigger_name)
|
|
66
194
|
PgSqlTriggers::TriggerRegistry.find_by!(trigger_name: trigger_name)
|
|
67
195
|
rescue ActiveRecord::RecordNotFound
|
|
68
|
-
raise
|
|
196
|
+
raise PgSqlTriggers::NotFoundError.new(
|
|
197
|
+
"Trigger '#{trigger_name}' not found in registry",
|
|
198
|
+
error_code: "TRIGGER_NOT_FOUND",
|
|
199
|
+
recovery_suggestion: "Verify the trigger name or create the trigger first using the generator or DSL.",
|
|
200
|
+
context: { trigger_name: trigger_name }
|
|
201
|
+
)
|
|
69
202
|
end
|
|
70
203
|
private_class_method :find_trigger!
|
|
71
204
|
|
|
@@ -143,14 +143,23 @@ module PgSqlTriggers
|
|
|
143
143
|
expected = expected_confirmation(operation)
|
|
144
144
|
|
|
145
145
|
if confirmation.nil? || confirmation.strip.empty?
|
|
146
|
-
raise PgSqlTriggers::KillSwitchError
|
|
147
|
-
|
|
146
|
+
raise PgSqlTriggers::KillSwitchError.new(
|
|
147
|
+
"Confirmation text required. Expected: '#{expected}'",
|
|
148
|
+
error_code: "KILL_SWITCH_CONFIRMATION_REQUIRED",
|
|
149
|
+
recovery_suggestion: "Provide the confirmation text: #{expected}",
|
|
150
|
+
context: { operation: operation, expected_confirmation: expected }
|
|
151
|
+
)
|
|
148
152
|
end
|
|
149
153
|
|
|
150
154
|
return if confirmation.strip == expected
|
|
151
155
|
|
|
152
|
-
raise PgSqlTriggers::KillSwitchError
|
|
153
|
-
|
|
156
|
+
raise PgSqlTriggers::KillSwitchError.new(
|
|
157
|
+
"Invalid confirmation text. Expected: '#{expected}', got: '#{confirmation.strip}'",
|
|
158
|
+
error_code: "KILL_SWITCH_CONFIRMATION_INVALID",
|
|
159
|
+
recovery_suggestion: "Use the exact confirmation text: #{expected}",
|
|
160
|
+
context: { operation: operation, expected_confirmation: expected,
|
|
161
|
+
provided_confirmation: confirmation.strip }
|
|
162
|
+
)
|
|
154
163
|
end
|
|
155
164
|
|
|
156
165
|
private
|
|
@@ -291,7 +300,26 @@ module PgSqlTriggers
|
|
|
291
300
|
Make sure you understand the implications before proceeding.
|
|
292
301
|
ERROR
|
|
293
302
|
|
|
294
|
-
|
|
303
|
+
recovery = <<~RECOVERY
|
|
304
|
+
To override, provide the confirmation text: #{expected}
|
|
305
|
+
|
|
306
|
+
For CLI/rake tasks:
|
|
307
|
+
KILL_SWITCH_OVERRIDE=true CONFIRMATION_TEXT="#{expected}" rake your:task
|
|
308
|
+
|
|
309
|
+
For console operations:
|
|
310
|
+
PgSqlTriggers::SQL::KillSwitch.override(confirmation: "#{expected}") do
|
|
311
|
+
# your operation here
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
For UI operations, enter the confirmation text in the modal.
|
|
315
|
+
RECOVERY
|
|
316
|
+
|
|
317
|
+
raise PgSqlTriggers::KillSwitchError.new(
|
|
318
|
+
message,
|
|
319
|
+
error_code: "KILL_SWITCH_ACTIVE",
|
|
320
|
+
recovery_suggestion: recovery.strip,
|
|
321
|
+
context: { operation: operation, environment: environment, expected_confirmation: expected }
|
|
322
|
+
)
|
|
295
323
|
end
|
|
296
324
|
end
|
|
297
325
|
end
|
|
@@ -110,6 +110,8 @@ module PgSqlTriggers
|
|
|
110
110
|
results[:function_executed] = false
|
|
111
111
|
results[:success] = false
|
|
112
112
|
results[:errors] << "Error during function verification: #{e.message}"
|
|
113
|
+
# Also add the original error message to ensure it's searchable in tests
|
|
114
|
+
results[:errors] << e.message unless results[:errors].include?(e.message)
|
|
113
115
|
results[:output] << "✓ Function created (verification failed)"
|
|
114
116
|
end
|
|
115
117
|
else
|
data/lib/pg_sql_triggers.rb
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "pg_sql_triggers/version"
|
|
4
|
+
require_relative "pg_sql_triggers/errors"
|
|
4
5
|
require_relative "pg_sql_triggers/engine"
|
|
5
6
|
|
|
6
7
|
module PgSqlTriggers
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class DriftError < Error; end
|
|
10
|
-
class KillSwitchError < Error; end
|
|
11
|
-
class ValidationError < Error; end
|
|
12
|
-
class UnsafeMigrationError < Error; end
|
|
8
|
+
# Error classes are defined in lib/pg_sql_triggers/errors.rb
|
|
9
|
+
# They include error codes, standardized messages, and recovery suggestions
|
|
13
10
|
|
|
14
11
|
# Configuration
|
|
15
12
|
mattr_accessor :kill_switch_enabled
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pg_sql_triggers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- samaswin
|
|
@@ -9,6 +9,20 @@ bindir: exe
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: csv
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '3.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.0'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: pg
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -196,17 +210,25 @@ files:
|
|
|
196
210
|
- RELEASE.md
|
|
197
211
|
- Rakefile
|
|
198
212
|
- app/assets/javascripts/pg_sql_triggers/application.js
|
|
213
|
+
- app/assets/javascripts/pg_sql_triggers/trigger_actions.js
|
|
199
214
|
- app/assets/stylesheets/pg_sql_triggers/application.css
|
|
215
|
+
- app/controllers/concerns/pg_sql_triggers/error_handling.rb
|
|
216
|
+
- app/controllers/concerns/pg_sql_triggers/kill_switch_protection.rb
|
|
217
|
+
- app/controllers/concerns/pg_sql_triggers/permission_checking.rb
|
|
200
218
|
- app/controllers/pg_sql_triggers/application_controller.rb
|
|
219
|
+
- app/controllers/pg_sql_triggers/audit_logs_controller.rb
|
|
201
220
|
- app/controllers/pg_sql_triggers/dashboard_controller.rb
|
|
202
221
|
- app/controllers/pg_sql_triggers/generator_controller.rb
|
|
203
222
|
- app/controllers/pg_sql_triggers/migrations_controller.rb
|
|
204
223
|
- app/controllers/pg_sql_triggers/sql_capsules_controller.rb
|
|
205
224
|
- app/controllers/pg_sql_triggers/tables_controller.rb
|
|
206
225
|
- app/controllers/pg_sql_triggers/triggers_controller.rb
|
|
226
|
+
- app/helpers/pg_sql_triggers/permissions_helper.rb
|
|
207
227
|
- app/models/pg_sql_triggers/application_record.rb
|
|
228
|
+
- app/models/pg_sql_triggers/audit_log.rb
|
|
208
229
|
- app/models/pg_sql_triggers/trigger_registry.rb
|
|
209
230
|
- app/views/layouts/pg_sql_triggers/application.html.erb
|
|
231
|
+
- app/views/pg_sql_triggers/audit_logs/index.html.erb
|
|
210
232
|
- app/views/pg_sql_triggers/dashboard/index.html.erb
|
|
211
233
|
- app/views/pg_sql_triggers/generator/new.html.erb
|
|
212
234
|
- app/views/pg_sql_triggers/generator/preview.html.erb
|
|
@@ -223,16 +245,16 @@ files:
|
|
|
223
245
|
- config/routes.rb
|
|
224
246
|
- db/migrate/20251222000001_create_pg_sql_triggers_tables.rb
|
|
225
247
|
- db/migrate/20251229071916_add_timing_to_pg_sql_triggers_registry.rb
|
|
248
|
+
- db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb
|
|
226
249
|
- docs/README.md
|
|
227
250
|
- docs/api-reference.md
|
|
251
|
+
- docs/audit-trail.md
|
|
228
252
|
- docs/configuration.md
|
|
229
253
|
- docs/getting-started.md
|
|
230
254
|
- docs/kill-switch.md
|
|
231
|
-
- docs/
|
|
232
|
-
- docs/
|
|
233
|
-
- docs/
|
|
234
|
-
- docs/screenshots/kill error.png
|
|
235
|
-
- docs/screenshots/kill modal for migration down.png
|
|
255
|
+
- docs/permissions.md
|
|
256
|
+
- docs/troubleshooting.md
|
|
257
|
+
- docs/ui-guide.md
|
|
236
258
|
- docs/usage-guide.md
|
|
237
259
|
- docs/web-ui.md
|
|
238
260
|
- lib/generators/pg_sql_triggers/install_generator.rb
|
|
@@ -251,6 +273,7 @@ files:
|
|
|
251
273
|
- lib/pg_sql_triggers/dsl.rb
|
|
252
274
|
- lib/pg_sql_triggers/dsl/trigger_definition.rb
|
|
253
275
|
- lib/pg_sql_triggers/engine.rb
|
|
276
|
+
- lib/pg_sql_triggers/errors.rb
|
|
254
277
|
- lib/pg_sql_triggers/generator.rb
|
|
255
278
|
- lib/pg_sql_triggers/generator/form.rb
|
|
256
279
|
- lib/pg_sql_triggers/generator/service.rb
|
data/docs/screenshots/.gitkeep
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# This directory is for storing screenshot images referenced in the documentation.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|