@@ -18,7 +18,7 @@ class PoliciesController < RestController
1818 def get
1919 action = :read
2020 unless params [ :kind ] == 'policy'
21- raise ( Errors ::EffectivePolicy ::PathParamError . new ( params [ :kind ] ) )
21+ raise Errors ::EffectivePolicy ::PathParamError , params [ :kind ]
2222 end
2323
2424 authorize_ownership
@@ -152,6 +152,7 @@ def load_policy(mode, mode_class, delete_permitted:)
152152 get_policy_mode . call ( strategy_class )
153153 policy_mode . call_pr ( policy_result ) unless policy_erred . call
154154 rescue => e
155+ e = sql_to_policy_error ( e )
155156 policy_result . error = ( enhance_error ( e ) )
156157 end
157158 }
@@ -212,7 +213,7 @@ def load_policy(mode, mode_class, delete_permitted:)
212213 rescue => e
213214 original_error = e
214215 if e . instance_of? ( Exceptions ::EnhancedPolicyError ) && e . original_error
215- original_error = e . original_error
216+ original_error = e . original_error
216217 end
217218
218219 audit_failure ( original_error , mode )
@@ -337,4 +338,20 @@ def parse_submitted_policy(policy_result)
337338 def publish_event
338339 Monitoring ::PubSub . instance . publish ( 'conjur.policy_loaded' )
339340 end
341+
342+ # This method is used to convert a Sequel::ForeignKeyConstraintViolation error
343+ # into a PolicyLoadRecordNotFound error.
344+ def sql_to_policy_error ( exception )
345+ if !exception . is_a? ( Sequel ::ForeignKeyConstraintViolation ) ||
346+ !exception . cause . is_a? ( PG ::ForeignKeyViolation )
347+ return exception
348+ end
349+
350+ # Try to parse the error message to find the violating key. This is based on
351+ # `foreign_key_constraint_violation` in application_controller.rb.
352+ return exception unless exception . cause . result . error_field ( PG ::PG_DIAG_MESSAGE_DETAIL ) =~ /Key \( ([^)]+)\) =\( ([^)]+)\) is not present in table "([^"]+)"/
353+
354+ violating_key = ::Regexp . last_match ( 2 )
355+ Exceptions ::PolicyLoadRecordNotFound . new ( violating_key )
356+ end
340357end
0 commit comments