public
Rubygem
Description: JSON Web App Framework
Homepage: http://halcyon.rubyforge.org/
Clone URL: git://github.com/mtodd/halcyon.git
Click here to lend your support to: halcyon and make a donation at www.pledgie.com !
Fixed some issues with Basic Auth, changed how the basic_auth test is 
written, updated documentation related to these changes.

git-svn-id: svn+ssh://rubyforge.org/var/svn/halcyon/trunk@40 
334d6d1c-2662-47f5-9f2d-00d938bdab95
mtodd (author)
Mon Feb 04 22:57:12 -0800 2008
commit  bab0c0a4ae6bb549706b2945d9eae6f50c34de7c
tree    27ef696edc45b61138fa37d92af2a9342b771f29
parent  8209d263957584be5c84966b307d63480c52df93
...
1
2
 
 
 
3
4
5
...
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
...
1
2
3
4
5
6
7
8
...
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
0
@@ -1,5 +1,8 @@
0
 %w(rubygems halcyon/server).each{|dep|require dep}
0
 class Simple < Halcyon::Server::Auth::Basic
0
+ basic_auth :only => [:greet] do |username, password|
0
+ [username, password] == ['rupert', 'secret']
0
+ end
0
   route do |r|
0
     r.match('/user/show/:id').to(:module => 'user', :action => 'show')
0
     r.match('/show/:id').to(:action => 'show')
0
@@ -9,32 +12,28 @@ class Simple < Halcyon::Server::Auth::Basic
0
     {:action => 'what_are_you_looking_for?'}
0
   end
0
   
0
- def basic_authentication(username, password)
0
- [username, password] == ['rupert', 'secret']
0
- end
0
-
0
- def greet(params)
0
- standard_response("Hello #{params[:name]}!")
0
+ def greet
0
+ ok("Hello #{params[:name]}!")
0
   end
0
- def wink(params)
0
- standard_response("I'm winking at you right now.")
0
+ def wink
0
+ ok("I'm winking at you right now.")
0
   end
0
- def index(params)
0
+ def index
0
     {:status => 200, :body => 'Wish you were cooler.'}
0
   end
0
   
0
   user do
0
- def show(params)
0
+ def show
0
       {:status => 200, :body => "You request: #{params[:id]}"}
0
     end
0
   end
0
   
0
- def show(params)
0
+ def show
0
     {:status => 200, :body => "This method does not conflict with the show method in the user module."}
0
   end
0
   
0
   # custom 404 error handler
0
- def what_are_you_looking_for?(params)
0
+ def what_are_you_looking_for?
0
     raise Exceptions::NotFound.new(404, 'Not Found; You did not find what you were expecting because it is not here. What are you looking for?')
0
   end
0
 end
...
58
59
60
61
62
63
64
 
65
66
67
68
69
70
 
71
72
73
74
75
 
76
77
78
...
58
59
60
 
 
 
 
61
62
63
64
65
66
 
67
68
69
70
71
 
72
73
74
75
0
@@ -58,21 +58,18 @@ class Server < Halcyon::Server::Base
0
     r.match('/u/:user/prefs').to(:action => 'prefs')
0
   end
0
   
0
- def initialize options = {}
0
- # let Halcyon do its thing and set up @config
0
- super options
0
-
0
+ def startup
0
     # app setup
0
     Pref.load_db(@config[:manager][:db])
0
   end
0
   
0
   # Retreives all of the preferences for a given user
0
- def prefs(params)
0
+ def prefs
0
     ok Pref.new(params[:user]).prefs
0
   end
0
   
0
   # Handles preference CRUD
0
- def pref(params)
0
+ def pref
0
     # get data
0
     user = Pref.new(params[:user])
0
     pref = params[:pref]
...
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
...
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
0
@@ -9,28 +9,28 @@ class Simple < Halcyon::Server::Base
0
     {:action => 'what_are_you_looking_for?'}
0
   end
0
   
0
- def greet(params)
0
+ def greet
0
     standard_response("Hello #{params[:name]}!")
0
   end
0
- def wink(params)
0
- standard_response("I'm winking at you right now.")
0
+ def wink
0
+ ok("I'm winking at you right now.")
0
   end
0
- def index(params)
0
+ def index
0
     {:status => 200, :body => 'Wish you were cooler.'}
0
   end
0
   
0
   user do
0
- def show(params)
0
+ def show
0
       {:status => 200, :body => "You request: #{params[:id]}"}
0
     end
0
   end
0
   
0
- def show(params)
0
+ def show
0
     {:status => 200, :body => "This method does not conflict with the show method in the user module."}
0
   end
0
   
0
   # custom 404 error handler
0
- def what_are_you_looking_for?(params)
0
+ def what_are_you_looking_for?
0
     raise Exceptions::NotFound.new(404, 'Not Found; You did not find what you were expecting because it is not here. What are you looking for?')
0
   end
0
 end
...
17
18
19
20
 
21
22
23
...
17
18
19
 
20
21
22
23
0
@@ -17,7 +17,7 @@ $:.unshift File.dirname(__FILE__)
0
 #++
0
 
0
 module Halcyon
0
- VERSION = [0,3,28]
0
+ VERSION = [0,3,29]
0
   def self.version
0
     VERSION.join('.')
0
   end
...
48
49
50
51
52
53
54
 
 
 
 
 
 
 
55
56
57
58
59
60
61
62
63
64
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
67
68
...
73
74
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
77
78
...
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
...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
0
@@ -48,21 +48,30 @@ module Halcyon
0
         alias :_run :run
0
         
0
         # Ensures that the HTTP Authentication header is included, the Basic
0
- # scheme is being used, and the credentials pass the
0
- # +basic_authentication+ test. If any of these fail, an Unauthorized
0
- # exception is raised (except for non-Basic schemes), otherwise the
0
- # +route+ is +run+ normally.
0
+ # scheme is being used, and the credentials pass the +basic_auth+
0
+ # test. If any of these fail, an Unauthorized exception is raised
0
+ # (except for non-Basic schemes), otherwise the +route+ is +run+
0
+ # normally.
0
+ #
0
+ # See the documentation for the +basic_auth+ class method for details
0
+ # concerning the credentials and action inclusion/exclusion.
0
         def run(route)
0
- # make sure there's an authorization header
0
- raise Base::Exceptions::Unauthorized.new unless !authorization_key.nil?
0
-
0
- # make sure the request is via the Basic protocol
0
- scheme = @env[authorization_key].split.first.downcase.to_sym
0
- raise Base::Exceptions::BadRequest.new unless scheme == :basic
0
-
0
- # make sure the credentials pass the test
0
- credentials = @env[authorization_key].split.last.unpack("m*").first.split(/:/, 2)
0
- raise Base::Exceptions::Unauthorized.new unless basic_authentication(*credentials)
0
+ # test credentials if the action is one specified to be tested
0
+ if ((@@auth[:except].nil? && @@auth[:only].nil?) || # the default is to test if no restrictions
0
+ (!@@auth[:only].nil? && @@auth[:only].include?(route[:action].to_sym)) || # but if the action is in the :only directive, test
0
+ (!@@auth[:except].nil? && !@@auth[:except].include?(route[:action].to_sym))) # or if the action is not in the :except directive, test
0
+
0
+ # make sure there's an authorization header
0
+ raise Base::Exceptions::Unauthorized.new unless !authorization_key.nil?
0
+
0
+ # make sure the request is via the Basic protocol
0
+ scheme = @env[authorization_key].split.first.downcase.to_sym
0
+ raise Base::Exceptions::BadRequest.new unless scheme == :basic
0
+
0
+ # make sure the credentials pass the test
0
+ credentials = @env[authorization_key].split.last.unpack("m*").first.split(':', 2)
0
+ raise Base::Exceptions::Unauthorized.new unless @@auth[:method].call(*credentials)
0
+ end
0
           
0
           # success, so run the route normally
0
           _run(route)
0
@@ -73,6 +82,24 @@ module Halcyon
0
           {:status => e.status, :body => e.error}
0
         end
0
         
0
+ # Provides a way to define a test as well as set limits on what is
0
+ # tested for Basic Authorization. This method should be called in the
0
+ # definition of the server. A simple example would look like:
0
+ #
0
+ # class Servr < Halcyon::Server::Auth::Basic
0
+ # basic_auth :only => [:grant] do |user, pass|
0
+ # # test credentials
0
+ # end
0
+ # # routes and actions follow...
0
+ # end
0
+ #
0
+ # Two acceptable options include <tt>:only</tt> and <tt>:except</tt>.
0
+ def self.basic_auth(options={}, &proc)
0
+ instance_eval do
0
+ @@auth = options.merge(:method => proc)
0
+ end
0
+ end
0
+
0
       end
0
       
0
     end

Comments

    No one has commented yet.