summaryrefslogtreecommitdiff
blob: ad98c7ff1a5608303011c217f9c4d6229db7f629 (plain)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# ===GLSAMaker v2
#  Copyright (C) 2009 Alex Legler <a3li@gentoo.org>
#  Copyright (C) 2009 Pierre-Yves Rofes <py@gentoo.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# For more information, see the LICENSE file.

# Authentication module
module Authentication
  protected
    # Login filter to be applied to *all* pages on GLSAMaker
    def login_required
      # Production authentication via REMOTE_USER
      if RAILS_ENV == "production" or GLSAMAKER_FORCE_PRODUCTION_AUTH
        # REMOTE_USER should be there in FCGI or Passenger
        env_user_name = user_name
      
        # Autentication system most likely broken
        if env_user_name.nil?
          logger.warn "Neither REMOTE_USER nor HTTP_AUTHORIZATION set in environment."
          redirect_to :controller => 'index', :action => 'error', :type => 'system'
          return
        end

        user = User.find_by_login(env_user_name)
        
        # User not known to GLSAMaker
        if user == nil
          logger.warn "Unknown user #{env_user_name} tried to log in from #{request.remote_ip}"
          redirect_to :controller => 'index', :action => 'error', :type => 'user'
          return
        end

        # User is marked as disabled in the DB
        if user.disabled
          logger.warn "Disabled user #{env_user_name} tried to log in from #{request.remote_ip}"
          redirect_to :controller => 'index', :action => 'error', :type => 'disabled'
          return
        end

        # Auth is fine now.
        logger.debug "Environment username: #{env_user_name}"

      # For all other environments request, HTTP auth by ourselves
      # The password can be set in config/initializers/glsamaker.rb
      else
        authenticate_or_request_with_http_basic("GLSAMaker testing environment") do |username, password|
          logger.debug "Environment username: #{username}"
          check_auth(username, password)
        end
      end
    end
    
    # Returns the ActiveRecord object of the currently logged in user
    def current_user
      User.find_by_login(user_name)
    end
    
    # Populate user to views, shamelessly stolen from restful auth. ;)
    def self.included(base)
      base.send :helper_method, :current_user if base.respond_to? :helper_method
    end
    
  private
    # Tries to find out the user name used for HTTP auth from two sources
    def user_name
      if request.env.include?('REMOTE_USER') then
        u = request.env['REMOTE_USER']
        return u unless u.nil?
      else
        auth = http_authorization_data
        return auth[0] unless auth.nil?
      end
      return nil
    end
    
    def check_auth(username, password)
      user = User.find_by_login(username)
      
      return false if user.nil?
      return false if user.disabled
      
      password == GLSAMAKER_DEVEL_PASSWORD
    end
  
    def http_authorization_data
      return nil unless request.env.include?('HTTP_AUTHORIZATION')
      return nil if request.env['HTTP_AUTHORIZATION'].nil?
      
      auth_info = request.env['HTTP_AUTHORIZATION'].split
      
      if auth_info[0] == "Basic"
        auth_info[1].unpack("m*").first.split(/:/, 2)
      else
        logger.fatal "Non-Basic HTTP authentication given. I can't process that"
        raise RuntimeError, "Cannot process this type of HTTP authentication"
      end
    end
end