328148fe18daf712f478e7372bd1cf7caeaf5640
[rails.git] / app / controllers / application.rb
1 # Filters added to this controller will be run for all controllers in the application.
2 # Likewise, all the methods added will be available for all controllers.
3 class ApplicationController < ActionController::Base
4
5   def authorize_web
6     @user = User.find_by_token(session[:token])
7   end
8
9   def require_user
10     redirect_to :controller => 'user', :action => 'login', :next_controller => controller_name, :next_action => action_name unless @user
11   end
12
13   def authorize(realm='Web Password', errormessage="Couldn't authenticate you") 
14     unless request.get?
15       username, passwd = get_auth_data # parse from headers
16       # authenticate per-scheme
17       if username.nil?
18         @user = nil # no authentication provided - perhaps first connect (client should retry after 401)
19       elsif username == 'token' 
20         @user = User.authenticate_token(passwd) # preferred - random token for user from db, passed in basic auth
21       else
22         @user = User.authenticate(username, passwd) # basic auth
23       end
24
25       # handle authenticate pass/fail
26       if @user
27         # user exists and password is correct ... horray! 
28         if @user.methods.include? 'lastlogin'         # note last login 
29           @session['lastlogin'] = user.lastlogin 
30           @user.last.login = Time.now 
31           @user.save() 
32           @session["User.id"] = @user.id 
33         end             
34       else 
35         # no auth, the user does not exist or the password was wrong
36         response.headers["Status"] = "Unauthorized" 
37         response.headers["WWW-Authenticate"] = "Basic realm=\"#{realm}\"" 
38         render_text(errormessage, 401) # :unauthorized
39       end 
40     end
41   end 
42
43   # Report and error to the user
44   # (If anyone ever fixes Rails so it can set a http status "reason phrase",
45   #  rather than only a status code and having the web engine make up a 
46   #  phrase from that, we can also put the error message into the status
47   #  message. For now, rails won't let us)
48   def report_error(message)
49     render :nothing => true, :status => 400
50     # Todo: some sort of escaping of problem characters in the message
51     response.headers['Error'] = message
52   end
53
54   # extract authorisation credentials from headers, returns user = nil if none
55   private 
56   def get_auth_data 
57     if request.env.has_key? 'X-HTTP_AUTHORIZATION'          # where mod_rewrite might have put it 
58       authdata = request.env['X-HTTP_AUTHORIZATION'].to_s.split 
59     elsif request.env.has_key? 'HTTP_AUTHORIZATION'         # regular location
60       authdata = request.env['HTTP_AUTHORIZATION'].to_s.split
61     end 
62     # only basic authentication supported
63     if authdata and authdata[0] == 'Basic' 
64       user, pass = Base64.decode64(authdata[1]).split(':')[0..1] 
65     end 
66     return [user, pass] 
67   end 
68
69 end