Module: Karst::Identity::DeviseSupport

Defined in:
lib/karst/identity/devise_support.rb

Overview

Reads Devise's own routing-registered mapping metadata to determine which model(s) Devise protects and which Warden scope each one uses -- never by scanning ObjectSpace, guessing from a model's name (User, Account, ...), or inferring from column names (encrypted_password, email, ...).

Devise.mappings is populated by devise_for in config/routes.rb (the same metadata Devise itself relies on for authenticate_user!, current_user, and friends), so by the time a real request reaches Karst, every conventional Devise application already has it populated.

Constant Summary collapse

Mapping =

One Devise-registered model/Warden-scope pair, straight from Devise's own mapping -- never guessed.

Value.define(:model, :scope)

Class Method Summary collapse

Class Method Details

.authentication_key_for(model) ⇒ Object

Returns the sole authentication key Devise declares for model. Multiple keys are intentionally treated as ambiguous: Karst cannot know which value is the useful login identity (or whether the combination itself is sensitive).



27
28
29
30
31
32
33
34
35
# File 'lib/karst/identity/devise_support.rb', line 27

def authentication_key_for(model)
  mapping = mapping_for(model)
  return nil unless mapping && model.respond_to?(:authentication_keys)

  keys = Array(model.authentication_keys).filter_map { |key| normalized_key(key) }.uniq
  keys.first if keys.size == 1
rescue StandardError
  nil
end

.available?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/karst/identity/devise_support.rb', line 37

def available?
  !!(defined?(Devise) && Devise.respond_to?(:mappings))
end

.mapping_for(model) ⇒ Object

The Devise mapping for one specific model class (including a subclass of a mapped model, e.g. STI), if Devise itself registers it. Used once a principal model is already known -- from an actual principal instance or an explicitly configured source -- so this never has to guess which of several Devise models is intended.



64
65
66
67
68
# File 'lib/karst/identity/devise_support.rb', line 64

def mapping_for(model)
  return nil unless model.is_a?(Class)

  mappings.find { |mapping| model <= mapping.model }
end

.mappingsObject

Every Devise-registered mapping currently known to the framework. Empty when Devise is unavailable or has registered nothing yet.



43
44
45
46
47
48
49
# File 'lib/karst/identity/devise_support.rb', line 43

def mappings
  return [] unless available?

  Devise.mappings.values.filter_map { |mapping| build(mapping) }
rescue StandardError
  []
end

.unambiguous_mappingObject

The single unambiguous Devise mapping, or nil when there are zero or more than one -- multiple Devise models are a deliberate ambiguity boundary Karst never guesses across.



54
55
56
57
# File 'lib/karst/identity/devise_support.rb', line 54

def unambiguous_mapping
  candidates = mappings
  candidates.first if candidates.size == 1
end