Skip to content

Allow Safeguards to be added and/or overridden outside of core #720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jslucas
Copy link

@jslucas jslucas commented May 9, 2025

Allow consumers to define their own safeguards and maintain existing behavior for backwards compatibility.

  • Updates Safeguard to use a registry
    Similar to how RuboCop handles Cops from itself, gems, plugins, and local repos. Safeguard.run executes each registered safeguard.
  • Adds Safeguard::Base class
    Consumers can create new safeguards by inheriting this class. Safeguards are added to the registry through inherited.
  • Adds Safeguard::Deprecated class
    Just a marker for the existing core-defined safeguards. The idea is that these would eventually get deleted after the adapters are updated to implement their own.
  • Enables "overriding" of core-defined safeguards
    If a safeguard is registered by the same name as a deprecated safeguard it will be executed instead.

This will allow the resolution issues like #659 and #684 by enabling adapters (or users) to define their own safeguards.

For example, to resolve #684 database_cleaner-active_record can implement its own AllowedUrl to override the existing behavior.

Simplified example:

# config/database.yml
test:
  adapter: postgresql
  host: postgres
  port: 5432
  database: myapp_test
  username: dbuser
  password: dbpassword
  pool: 5
  encoding: unicode
module DatabaseCleaner
  module ActiveRecord
    module Safeguards
      class AllowedUrl < DatabaseCleaner::Safeguard::Base
        def run
          return if skip?
          raise Error::UrlNotAllowed if database_url_not_allowed?
        end

        private

          def database_url_not_allowed?
            !DatabaseCleaner.url_allowlist.any? {|allowed| allowed === database_url }
          end  
         
         # ...
         
          def database_url
            return ENV['DATABASE_URL'] unless ENV['DATABASE_URL'].nil? || ENV['DATABASE_URL'].strip.empty?

            # ...build a connection url from ::ActiveRecord::Base.connection_db_config
            # => "postgresql://dbuser:dbpassword@postgres:5432/myapp_test=5&encoding=unicode"
          end
      end
    end
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

url_allowlist only works against DATABASE_URL
1 participant