Class: Karst::Identity::WardenAdapter

Inherits:
Object
  • Object
show all
Defined in:
lib/karst/identity/warden_adapter.rb

Overview

Optional convenience for a request-like object whose Rack environment already contains a Warden proxy. Warden cannot be bootstrapped safely from a bare ActionDispatch::Integration::Session, so applications using those sessions should configure explicit hooks (usually test endpoints).

scope: is the Warden/Devise scope (e.g. :user, :admin) this adapter operates under. When known (see DeviseSupport), it is always passed explicitly rather than relying on Warden's own default scope -- a Devise app almost always protects routes with a specific scope, and guessing wrong would silently authenticate under the wrong one. When nil, set_user/logout are called without a scope, matching Warden's own default behavior for a plain, non-Devise Warden setup.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(scope: nil) ⇒ WardenAdapter

Returns a new instance of WardenAdapter.



68
69
70
# File 'lib/karst/identity/warden_adapter.rb', line 68

def initialize(scope: nil)
  @scope = scope
end

Instance Attribute Details

#scopeObject (readonly)

Returns the value of attribute scope.



66
67
68
# File 'lib/karst/identity/warden_adapter.rb', line 66

def scope
  @scope
end

Class Method Details

.hook_installable?Boolean

Registered once per process (Warden::Hooks callbacks are class-level, so this necessarily runs for every Warden::Manager instance, including the host application's own) and is a no-op unless this exact thread has a principal queued. The real Warden gem always provides Warden::Manager.on_request (Warden::Hooks is core, not an extra); the guard exists only so a minimal Warden::Manager stand-in (a bare stub Class, as several existing specs use to exercise ambiguous-Devise-setup paths that never reach this code) can't crash Karst with a NoMethodError instead of deferral simply staying unavailable, same as before this existed.

Returns:

  • (Boolean)


48
49
50
# File 'lib/karst/identity/warden_adapter.rb', line 48

def hook_installable?
  defined?(Warden::Manager) && Warden::Manager.respond_to?(:on_request)
end

.install_hook!Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/karst/identity/warden_adapter.rb', line 52

def install_hook!
  return if @installed

  @installed = true
  Warden::Manager.on_request do |proxy|
    pending = Karst::ExecutionContext.delete(PENDING_PRINCIPAL_KEY)
    next unless pending

    principal, scope = pending
    scope ? proxy.set_user(principal, scope: scope) : proxy.set_user(principal)
  end
end

Instance Method Details

#assume(session, principal) ⇒ Object

Raises:



72
73
74
75
76
77
78
# File 'lib/karst/identity/warden_adapter.rb', line 72

def assume(session, principal)
  proxy = existing_proxy(session)
  return apply(proxy, principal) if proxy
  return queue_for_next_request(principal) if deferrable?(session)

  raise Unavailable, "the session has no initialized Warden proxy; configure identity hooks"
end

#clear(session) ⇒ Object



80
81
82
83
84
85
# File 'lib/karst/identity/warden_adapter.rb', line 80

def clear(session)
  proxy = proxy_for(session)
  @scope ? proxy.logout(@scope) : proxy.logout
ensure
  Karst::ExecutionContext.delete(PENDING_PRINCIPAL_KEY)
end