public
Rubygem
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb-core.git
merb-core / lib / merb-core / controller / mixins / authentication.rb
100644 88 lines (77 sloc) 2.481 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
module Merb::AuthenticationMixin
  
  # Attempts to authenticate the user via HTTP Basic authentication. Takes a
  # block with the username and password, if the block yields false the
  # authentication is not accepted and :halt is thrown.
  #
  # If no block is passed, +basic_authentication+, the +request+ and +authenticate+
  # methods can be chained. These can be used to independently request authentication
  # or confirm it, if more control is desired.
  #
  # ==== Parameters
  # realm<~to_s>:: The realm to authenticate against. Defaults to 'Application'.
  # &authenticator:: A block to check if the authentication is valid.
  #
  # ==== Examples
  # class Application < Merb::Controller
  #
  # before :authenticate
  #
  # protected
  #
  # def authenticate
  # basic_authentication("My App") do |username, password|
  # password == "secret"
  # end
  # end
  #
  # end
  #
  # class Application < Merb::Controller
  #
  # before :authenticate
  #
  # def authenticate
  # user = basic_authentication.authenticate do |username, password|
  # User.authenticate(username, password)
  # end
  #
  # if user
  # @current_user = user
  # else
  # basic_authentication.request
  # end
  # end
  #
  # end
  #
  #---
  # @public
  def basic_authentication(realm = "Application", &authenticator)
    BasicAuthentication.new(self, realm, &authenticator)
  end
  
  class BasicAuthentication #:nodoc:
    # So we can have access to the status codes
    include Merb::ControllerExceptions
 
    def initialize(controller, realm = "Application", &authenticator)
      @controller = controller
      @realm = realm
      authenticate_or_request(&authenticator) if authenticator
    end
 
    def authenticate(&authenticator)
      auth = Rack::Auth::Basic::Request.new(@controller.request.env)
 
      if auth.provided? and auth.basic?
        authenticator.call(*auth.credentials)
      else
        false
      end
    end
 
    def request
      @controller.headers['WWW-Authenticate'] = 'Basic realm="%s"' % @realm
      throw :halt, @controller.render("HTTP Basic: Access denied.\n", :status => Unauthorized::STATUS, :layout => false)
    end
    
    protected
    
    def authenticate_or_request(&authenticator)
      authenticate(&authenticator) || request
    end
    
  end
 
end