Skip to content
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

Refactor Authenticator to remove const manipulations #16869

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions app/models/authenticator.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
module Authenticator
require_nested :Base
require_nested :Database
require_nested :Httpd
require_nested :Ldap

def self.for(config, username = nil)
if username == 'admin'
Database.new(config)
else
authenticator_class(config[:mode]).new(config)
authenticator_class(config[:mode])&.new(config)
end
end

def self.authenticator_class(name)
authenticator_classes_cache[name.to_s]
end
def self.validate_config(config)
return [] if config[:mode] == "none"

def self.authenticator_classes_cache
@authenticator_classes_cache ||= Concurrent::Hash.new do |hash, name|
hash[name] = authenticator_class_for(name) || force_load_authenticator_for(name)
authenticator = self.for(config)
if authenticator
authenticator.validate_config
else
[:mode, "authentication type, #{config[:mode].inspect}, invalid. Should be one of: #{valid_modes.join(", ")}"]
end
end

def self.force_load_authenticator_for(name)
# try to constantize in case the subclass is not loaded yet, but it still exists
# this is happens with authenticators from provider gems
subclass = "Authenticator::#{name.camelize}".safe_constantize
subclass if subclass && subclass.authenticates_for.include?(name)
private_class_method def self.valid_modes
Base.subclasses.flat_map(&:authenticates_for).uniq << "none"
end

private_class_method def self.authenticator_class(name)
authenticator_classes_cache[name.to_s]
end

private_class_method def self.authenticator_classes_cache
@authenticator_classes_cache ||= Hash.new do |hash, name|
hash[name] = authenticator_class_for(name)
end
end

def self.authenticator_class_for(name)
private_class_method def self.authenticator_class_for(name)
Base.subclasses.find do |subclass|
subclass.authenticates_for.include?(name)
end
Expand Down
4 changes: 4 additions & 0 deletions app/models/authenticator/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def initialize(config)
@config = config
end

def validate_config
self.class.validate_config(config)
end

def uses_stored_password?
false
end
Expand Down
18 changes: 2 additions & 16 deletions lib/vmdb/config/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,9 @@ def webservices(data)
return valid, errors
end

AUTH_TYPES = %w(ldap ldaps httpd amazon database none)

def authentication(data)
valid, errors = true, []

return valid, errors if data.mode == 'none'

authenticator = Authenticator.authenticator_class(data.mode)

if authenticator
errors = authenticator.validate_config(data)
valid = errors.empty?
else
valid = false
errors << [:mode, "authentication type, \"#{data.mode}\", invalid. Should be one of: #{Authenticator::Base.subclasses.map(&:authenticates_for).join(", ")}"]
end

errors = Authenticator.validate_config(data)
valid = errors.empty?
return valid, errors
end

Expand Down