Class: Legate::Auth::Manager
- Inherits:
-
Object
- Object
- Legate::Auth::Manager
- Includes:
- Singleton
- Defined in:
- lib/legate/auth/manager.rb
Overview
The AuthManager is a singleton that manages authentication schemes and credentials. It provides a centralized registry for authentication schemes and credentials, as well as methods for finding the appropriate scheme and credential for a given URL.
Instance Attribute Summary collapse
- #credentials ⇒ Hash{Symbol => Legate::Auth::Credential} readonly
-
#schemes ⇒ Hash{Symbol => Legate::Auth::Scheme}
readonly
Read access to the registered schemes/credentials/url-mappings.
- #store ⇒ Legate::Auth::ManagerStore::RedisStore, ... readonly
- #url_mappings ⇒ Array<Hash> readonly
Instance Method Summary collapse
-
#find_scheme(scheme_type) ⇒ Legate::Auth::Scheme?
Find a scheme by type without requiring credentials.
-
#find_scheme_and_credential(url: nil, scheme_type: nil, credential_name: nil) ⇒ Array<Legate::Auth::Scheme, Legate::Auth::Credential>?
Find the appropriate scheme and credential for a URL.
-
#get_credential(name) ⇒ Legate::Auth::Credential?
Get a registered credential.
-
#get_scheme(name) ⇒ Legate::Auth::Scheme?
Get a registered scheme.
-
#initialize ⇒ Manager
constructor
A new instance of Manager.
-
#load_from_store ⇒ Boolean
Load all schemes, credentials, and URL mappings from the store.
-
#register_credential(credential, name, persist: true) ⇒ Symbol
Register a credential.
-
#register_scheme(scheme, name = nil, persist: true) ⇒ Symbol
Register an authentication scheme.
-
#register_url_mapping(url_pattern, scheme_name, credential_name, persist: true) ⇒ Object
Register a URL mapping to a scheme and credential.
-
#reload_from_store ⇒ Object
Force reload from store (useful after external changes).
-
#remove_url_mapping(index, persist: true) ⇒ Boolean
Remove a URL mapping by index.
-
#replace_url_mappings(mappings, persist: true) ⇒ Array<Hash>
Replaces the full set of URL mappings and persists them.
-
#set_store(store, load_immediately: true) ⇒ Object
Set the persistence store and load existing data.
-
#unregister_credential(name, persist: true) ⇒ Boolean
Unregister/delete a credential.
-
#unregister_scheme(name, persist: true) ⇒ Boolean
Unregister/delete a scheme.
Constructor Details
#initialize ⇒ Manager
Returns a new instance of Manager.
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/legate/auth/manager.rb', line 36 def initialize @schemes = {} @credentials = {} @url_mappings = [] @store = nil @loaded_from_store = false # Register built-in schemes register_default_schemes end |
Instance Attribute Details
#credentials ⇒ Hash{Symbol => Legate::Auth::Credential} (readonly)
32 33 34 |
# File 'lib/legate/auth/manager.rb', line 32 def credentials @credentials end |
#schemes ⇒ Hash{Symbol => Legate::Auth::Scheme} (readonly)
Read access to the registered schemes/credentials/url-mappings. Exposed so callers (e.g. the web routes) don’t reach in via instance_variable_get.
30 31 32 |
# File 'lib/legate/auth/manager.rb', line 30 def schemes @schemes end |
#store ⇒ Legate::Auth::ManagerStore::RedisStore, ... (readonly)
25 26 27 |
# File 'lib/legate/auth/manager.rb', line 25 def store @store end |
#url_mappings ⇒ Array<Hash> (readonly)
34 35 36 |
# File 'lib/legate/auth/manager.rb', line 34 def url_mappings @url_mappings end |
Instance Method Details
#find_scheme(scheme_type) ⇒ Legate::Auth::Scheme?
Find a scheme by type without requiring credentials
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/legate/auth/manager.rb', line 217 def find_scheme(scheme_type) scheme_sym = scheme_type.to_sym # Try to find by exact scheme_type match first scheme = @schemes.values.find { |s| s.scheme_type == scheme_sym } # If not found by scheme_type, try to find by registration name # This handles cases like :oidc -> OpenIDConnect where scheme_type is :openid_connect scheme ||= @schemes[scheme_sym] # Special mappings for backward compatibility and aliases if scheme.nil? scheme_mappings = { oidc: :openid_connect, openid_connect: :oidc } # Try the mapped scheme type mapped_type = scheme_mappings[scheme_sym] if mapped_type scheme = @schemes.values.find { |s| s.scheme_type == mapped_type } || @schemes[mapped_type] end end scheme end |
#find_scheme_and_credential(url: nil, scheme_type: nil, credential_name: nil) ⇒ Array<Legate::Auth::Scheme, Legate::Auth::Credential>?
Find the appropriate scheme and credential for a URL
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/legate/auth/manager.rb', line 250 def find_scheme_and_credential(url: nil, scheme_type: nil, credential_name: nil) # Case 1: Direct credential and matching scheme specified if credential_name credential = get_credential(credential_name) return nil unless credential if scheme_type # Find scheme of the specified type scheme = @schemes.values.find { |s| s.scheme_type == scheme_type.to_sym } return [scheme, credential] if scheme else # Try to find a compatible scheme for this credential scheme = find_compatible_scheme(credential) return [scheme, credential] if scheme end end # Case 2: URL matching if url found_mapping = @url_mappings.find do |mapping| pattern = mapping[:pattern] # Check if URL matches the pattern (pattern.is_a?(Regexp) && url =~ pattern) || (pattern.is_a?(String) && url.include?(pattern)) end if found_mapping scheme = get_scheme(found_mapping[:scheme_name]) credential = get_credential(found_mapping[:credential_name]) # Skip if we're filtering by scheme_type and it doesn't match return nil if scheme_type && scheme.scheme_type != scheme_type.to_sym return [scheme, credential] if scheme && credential end # No matching URL mapping found, if a URL was provided and no mapping matched # but scheme_type was specified, we shouldn't continue to Case 3 return nil if scheme_type && url end # Case 3: Just trying to find by scheme_type with any credential if scheme_type scheme_sym = scheme_type.to_sym # Try to find by exact scheme_type match first scheme = @schemes.values.find { |s| s.scheme_type == scheme_sym } # If not found by scheme_type, try to find by registration name # This handles cases like :oidc -> OpenIDConnect where scheme_type is :openid_connect scheme ||= @schemes[scheme_sym] # Special mappings for backward compatibility and aliases if scheme.nil? scheme_mappings = { oidc: :openid_connect, openid_connect: :oidc } # Try the mapped scheme type mapped_type = scheme_mappings[scheme_sym] if mapped_type scheme = @schemes.values.find { |s| s.scheme_type == mapped_type } || @schemes[mapped_type] end end return nil unless scheme # Find any compatible credential @credentials.each_value do |cred| return [scheme, cred] if credential_compatible_with_scheme?(cred, scheme) end end nil end |
#get_credential(name) ⇒ Legate::Auth::Credential?
Get a registered credential
210 211 212 |
# File 'lib/legate/auth/manager.rb', line 210 def get_credential(name) @credentials[name.to_sym] end |
#get_scheme(name) ⇒ Legate::Auth::Scheme?
Get a registered scheme
203 204 205 |
# File 'lib/legate/auth/manager.rb', line 203 def get_scheme(name) @schemes[name.to_sym] end |
#load_from_store ⇒ Boolean
Load all schemes, credentials, and URL mappings from the store
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/legate/auth/manager.rb', line 57 def load_from_store return false unless @store&.available? return true if @loaded_from_store # Don't reload if already loaded Legate.logger&.info('Loading authentication configuration from store...') # Load credentials first (schemes might depend on them for URL mappings) load_credentials_from_store # Load schemes (will overwrite defaults with stored config) load_schemes_from_store # Load URL mappings load_url_mappings_from_store @loaded_from_store = true Legate.logger&.info('Authentication configuration loaded from store.') true rescue StandardError => e Legate.logger&.error("Failed to load auth config from store: #{e.}") false end |
#register_credential(credential, name, persist: true) ⇒ Symbol
Register a credential
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/legate/auth/manager.rb', line 124 def register_credential(credential, name, persist: true) raise ArgumentError, 'Credential must be an Legate::Auth::Credential' unless credential.is_a?(Legate::Auth::Credential) raise ArgumentError, 'Name must be provided' if name.nil? name = name.to_sym @credentials[name] = credential # Persist to store if available and persistence is enabled @store&.save_credential(name, credential) if persist && @store&.available? name end |
#register_scheme(scheme, name = nil, persist: true) ⇒ Symbol
Register an authentication scheme
91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/legate/auth/manager.rb', line 91 def register_scheme(scheme, name = nil, persist: true) raise ArgumentError, 'Scheme must be an Legate::Auth::Scheme' unless scheme.is_a?(Legate::Auth::Scheme) # Use scheme type as name if not provided name ||= scheme.scheme_type name = name.to_sym @schemes[name] = scheme # Persist to store if available and persistence is enabled @store&.save_scheme(name, scheme) if persist && @store&.available? name end |
#register_url_mapping(url_pattern, scheme_name, credential_name, persist: true) ⇒ Object
Register a URL mapping to a scheme and credential
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/legate/auth/manager.rb', line 155 def register_url_mapping(url_pattern, scheme_name, credential_name, persist: true) scheme_name = scheme_name.to_sym credential_name = credential_name.to_sym raise ArgumentError, "Unknown scheme: #{scheme_name}" unless @schemes.key?(scheme_name) raise ArgumentError, "Unknown credential: #{credential_name}" unless @credentials.key?(credential_name) @url_mappings << { pattern: url_pattern, scheme_name: scheme_name, credential_name: credential_name } # Persist all URL mappings to store @store&.save_url_mappings(@url_mappings) if persist && @store&.available? end |
#reload_from_store ⇒ Object
Force reload from store (useful after external changes)
81 82 83 84 |
# File 'lib/legate/auth/manager.rb', line 81 def reload_from_store @loaded_from_store = false load_from_store end |
#remove_url_mapping(index, persist: true) ⇒ Boolean
Remove a URL mapping by index
177 178 179 180 181 182 183 184 185 186 |
# File 'lib/legate/auth/manager.rb', line 177 def remove_url_mapping(index, persist: true) return false if index < 0 || index >= @url_mappings.size @url_mappings.delete_at(index) # Persist all URL mappings to store @store&.save_url_mappings(@url_mappings) if persist && @store&.available? true end |
#replace_url_mappings(mappings, persist: true) ⇒ Array<Hash>
Replaces the full set of URL mappings and persists them. Used by the web UI, which manages a richer mapping shape (pattern/priority/active) than register_url_mapping and edits the array in place before saving.
194 195 196 197 198 |
# File 'lib/legate/auth/manager.rb', line 194 def replace_url_mappings(mappings, persist: true) @url_mappings = mappings @store&.save_url_mappings(@url_mappings) if persist && @store&.available? @url_mappings end |
#set_store(store, load_immediately: true) ⇒ Object
Set the persistence store and load existing data
50 51 52 53 |
# File 'lib/legate/auth/manager.rb', line 50 def set_store(store, load_immediately: true) @store = store load_from_store if load_immediately && store&.available? end |
#unregister_credential(name, persist: true) ⇒ Boolean
Unregister/delete a credential
141 142 143 144 145 146 147 148 |
# File 'lib/legate/auth/manager.rb', line 141 def unregister_credential(name, persist: true) name = name.to_sym deleted = @credentials.delete(name) @store&.delete_credential(name) if persist && deleted && @store&.available? !deleted.nil? end |
#unregister_scheme(name, persist: true) ⇒ Boolean
Unregister/delete a scheme
110 111 112 113 114 115 116 117 |
# File 'lib/legate/auth/manager.rb', line 110 def unregister_scheme(name, persist: true) name = name.to_sym deleted = @schemes.delete(name) @store&.delete_scheme(name) if persist && deleted && @store&.available? !deleted.nil? end |