rubycas-server 0.7.1.1 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. data/CHANGELOG +292 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +26 -0
  4. data/README.md +36 -0
  5. data/Rakefile +0 -3
  6. data/bin/rubycas-server +24 -19
  7. data/lib/casserver.rb +7 -110
  8. data/lib/casserver/authenticators/active_directory_ldap.rb +8 -0
  9. data/lib/casserver/authenticators/active_resource.rb +125 -0
  10. data/lib/casserver/authenticators/authlogic_crypto_providers/aes256.rb +43 -0
  11. data/lib/casserver/authenticators/authlogic_crypto_providers/bcrypt.rb +92 -0
  12. data/lib/casserver/authenticators/authlogic_crypto_providers/md5.rb +34 -0
  13. data/lib/casserver/authenticators/authlogic_crypto_providers/sha1.rb +59 -0
  14. data/lib/casserver/authenticators/authlogic_crypto_providers/sha512.rb +50 -0
  15. data/lib/casserver/authenticators/base.rb +30 -11
  16. data/lib/casserver/authenticators/client_certificate.rb +7 -6
  17. data/lib/casserver/authenticators/google.rb +13 -9
  18. data/lib/casserver/authenticators/ldap.rb +37 -28
  19. data/lib/casserver/authenticators/ntlm.rb +9 -9
  20. data/lib/casserver/authenticators/open_id.rb +3 -3
  21. data/lib/casserver/authenticators/sql.rb +65 -34
  22. data/lib/casserver/authenticators/sql_authlogic.rb +93 -0
  23. data/lib/casserver/authenticators/sql_encrypted.rb +44 -44
  24. data/lib/casserver/authenticators/sql_md5.rb +2 -2
  25. data/lib/casserver/authenticators/sql_rest_auth.rb +82 -0
  26. data/lib/casserver/authenticators/test.rb +10 -7
  27. data/lib/casserver/cas.rb +94 -94
  28. data/lib/casserver/localization.rb +91 -0
  29. data/lib/casserver/model.rb +270 -0
  30. data/lib/casserver/server.rb +745 -0
  31. data/lib/casserver/utils.rb +9 -7
  32. data/lib/casserver/views/_login_form.erb +42 -0
  33. data/lib/casserver/views/layout.erb +18 -0
  34. data/lib/casserver/views/login.erb +30 -0
  35. data/lib/casserver/views/proxy.builder +12 -0
  36. data/lib/casserver/views/proxy_validate.builder +25 -0
  37. data/lib/casserver/views/service_validate.builder +18 -0
  38. data/lib/casserver/views/validate.erb +2 -0
  39. data/po/de_DE/rubycas-server.po +127 -0
  40. data/po/es_ES/rubycas-server.po +123 -0
  41. data/po/fr_FR/rubycas-server.po +128 -0
  42. data/po/ja_JP/rubycas-server.po +126 -0
  43. data/po/pl_PL/rubycas-server.po +123 -0
  44. data/po/pt_BR/rubycas-server.po +123 -0
  45. data/po/ru_RU/rubycas-server.po +118 -0
  46. data/po/rubycas-server.pot +112 -0
  47. data/po/zh_CN/rubycas-server.po +113 -0
  48. data/po/zh_TW/rubycas-server.po +113 -0
  49. data/public/themes/cas.css +121 -0
  50. data/{lib → public}/themes/notice.png +0 -0
  51. data/{lib → public}/themes/ok.png +0 -0
  52. data/{lib → public}/themes/simple/bg.png +0 -0
  53. data/public/themes/simple/favicon.png +0 -0
  54. data/{lib → public}/themes/simple/login_box_bg.png +0 -0
  55. data/{lib → public}/themes/simple/logo.png +0 -0
  56. data/public/themes/simple/theme.css +28 -0
  57. data/{lib → public}/themes/urbacon/bg.png +0 -0
  58. data/{lib → public}/themes/urbacon/login_box_bg.png +0 -0
  59. data/{lib → public}/themes/urbacon/logo.png +0 -0
  60. data/public/themes/urbacon/theme.css +33 -0
  61. data/{lib → public}/themes/warning.png +0 -0
  62. data/resources/init.d.sh +1 -1
  63. data/rubycas-server.gemspec +57 -0
  64. data/setup.rb +4 -4
  65. data/spec/alt_config.yml +50 -0
  66. data/spec/authenticators/active_resource_spec.rb +109 -0
  67. data/spec/authenticators/ldap_spec.rb +53 -0
  68. data/spec/casserver_spec.rb +149 -0
  69. data/spec/default_config.yml +50 -0
  70. data/spec/model_spec.rb +42 -0
  71. data/spec/spec.opts +4 -0
  72. data/spec/spec_helper.rb +88 -0
  73. data/spec/utils_spec.rb +53 -0
  74. data/tasks/bundler.rake +4 -0
  75. data/tasks/db/migrate.rake +12 -0
  76. data/tasks/localization.rake +13 -0
  77. data/tasks/spec.rake +10 -0
  78. metadata +294 -91
  79. data/CHANGELOG.txt +0 -1
  80. data/History.txt +0 -252
  81. data/LICENSE.txt +0 -504
  82. data/Manifest.txt +0 -72
  83. data/PostInstall.txt +0 -3
  84. data/README.txt +0 -25
  85. data/bin/rubycas-server-ctl +0 -22
  86. data/config.example.yml +0 -442
  87. data/config/hoe.rb +0 -76
  88. data/config/requirements.rb +0 -15
  89. data/custom_views.example.rb +0 -11
  90. data/lib/casserver/conf.rb +0 -112
  91. data/lib/casserver/controllers.rb +0 -452
  92. data/lib/casserver/environment.rb +0 -30
  93. data/lib/casserver/models.rb +0 -218
  94. data/lib/casserver/postambles.rb +0 -174
  95. data/lib/casserver/version.rb +0 -9
  96. data/lib/casserver/views.rb +0 -243
  97. data/lib/rubycas-server.rb +0 -1
  98. data/lib/rubycas-server/version.rb +0 -1
  99. data/lib/themes/cas.css +0 -121
  100. data/lib/themes/simple/theme.css +0 -28
  101. data/lib/themes/urbacon/theme.css +0 -33
  102. data/misc/basic_cas_single_signon_mechanism_diagram.png +0 -0
  103. data/misc/basic_cas_single_signon_mechanism_diagram.svg +0 -652
  104. data/script/console +0 -10
  105. data/script/destroy +0 -14
  106. data/script/generate +0 -14
  107. data/script/txt2html +0 -82
  108. data/tasks/deployment.rake +0 -34
  109. data/tasks/environment.rake +0 -7
  110. data/tasks/website.rake +0 -17
  111. data/vendor/isaac_0.9.1/LICENSE +0 -26
  112. data/vendor/isaac_0.9.1/README +0 -78
  113. data/vendor/isaac_0.9.1/TODO +0 -3
  114. data/vendor/isaac_0.9.1/VERSIONS +0 -3
  115. data/vendor/isaac_0.9.1/crypt/ISAAC.rb +0 -171
  116. data/vendor/isaac_0.9.1/isaac.gemspec +0 -39
  117. data/vendor/isaac_0.9.1/setup.rb +0 -596
  118. data/vendor/isaac_0.9.1/test/TC_ISAAC.rb +0 -76
  119. data/website/index.html +0 -40
  120. data/website/index.txt +0 -3
  121. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  122. data/website/stylesheets/screen.css +0 -138
  123. data/website/template.html.erb +0 -40
@@ -9,7 +9,7 @@ require 'casserver/authenticators/base'
9
9
  # fall back to some other authentication mechanism.
10
10
  #
11
11
  # Here's an example of how to use two chained authenticators in the config.yml
12
- # file. The server will first use the ClientCertificate authenticator, and
12
+ # file. The server will first use the ClientCertificate authenticator, and
13
13
  # only fall back to the SQL authenticator of the first one fails:
14
14
  #
15
15
  # authenticator:
@@ -30,17 +30,18 @@ require 'casserver/authenticators/base'
30
30
  class CASServer::Authenticators::ClientCertificate < CASServer::Authenticators::Base
31
31
  def validate(credentials)
32
32
  read_standard_credentials(credentials)
33
-
33
+
34
34
  @client_cert = credentials[:request]['SSL_CLIENT_CERT']
35
-
35
+
36
36
  # note that I haven't actually tested to see if SSL_CLIENT_CERT gets
37
37
  # filled with data when a client cert is provided, but this should be
38
38
  # the case at least in theory :)
39
-
39
+
40
40
  return false if @client_cert.blank?
41
-
41
+
42
42
  # IMPLEMENT SSL CERTIFICATE VALIDATION CODE HERE
43
-
43
+ raise NotImplementedError, "#{self.class.name}#validate NOT YET IMPLEMENTED!"
44
+
44
45
  return true # if SSL certificate is valid, false otherwise
45
46
  end
46
47
  end
@@ -4,7 +4,7 @@ require 'net/http'
4
4
  require 'net/https'
5
5
  require 'timeout'
6
6
 
7
- # Validates Google accounts against Google's authentication service -- in other
7
+ # Validates Google accounts against Google's authentication service -- in other
8
8
  # words, this authenticator allows users to log in to CAS using their
9
9
  # Gmail/Google accounts.
10
10
  class CASServer::Authenticators::Google < CASServer::Authenticators::Base
@@ -12,19 +12,23 @@ class CASServer::Authenticators::Google < CASServer::Authenticators::Base
12
12
  read_standard_credentials(credentials)
13
13
 
14
14
  return false if @username.blank? || @password.blank?
15
-
15
+
16
16
  auth_data = {
17
- 'Email' => @username,
18
- 'Passwd' => @password,
19
- 'service' => 'xapi',
17
+ 'Email' => @username,
18
+ 'Passwd' => @password,
19
+ 'service' => 'xapi',
20
20
  'source' => 'RubyCAS-Server',
21
21
  'accountType' => 'HOSTED_OR_GOOGLE'
22
22
  }
23
-
23
+
24
24
  url = URI.parse('https://www.google.com/accounts/ClientLogin')
25
- http = Net::HTTP.new(url.host, url.port)
25
+ if @options[:proxy]
26
+ http = Net::HTTP.Proxy(@options[:proxy][:host], @options[:proxy][:port], @options[:proxy][:username], @options[:proxy][:password]).new(url.host, url.port)
27
+ else
28
+ http = Net::HTTP.new(url.host, url.port)
29
+ end
26
30
  http.use_ssl = true
27
-
31
+
28
32
  # TODO: make the timeout configurable
29
33
  wait_seconds = 10
30
34
  begin
@@ -34,7 +38,7 @@ class CASServer::Authenticators::Google < CASServer::Authenticators::Base
34
38
  req.set_form_data(auth_data,'&')
35
39
  conn.request(req)
36
40
  end
37
-
41
+
38
42
  case res
39
43
  when Net::HTTPSuccess
40
44
  true
@@ -5,12 +5,13 @@ begin
5
5
  rescue LoadError
6
6
  require 'rubygems'
7
7
  begin
8
- gem 'ruby-net-ldap', '~> 0.0.4'
8
+ gem 'net-ldap', '~> 0.1.1'
9
9
  rescue Gem::LoadError
10
10
  $stderr.puts
11
11
  $stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
12
12
  $stderr.puts
13
- $stderr.puts "To use the LDAP/AD authenticator, you must first install the 'ruby-net-ldap' gem."
13
+ $stderr.puts "To use the LDAP/AD authenticator, you must first install the 'net-ldap' gem."
14
+ $stderr.puts " See http://github.com/RoryO/ruby-net-ldap for details."
14
15
  $stderr.puts
15
16
  $stderr.puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
16
17
  exit 1
@@ -26,47 +27,47 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
26
27
  read_standard_credentials(credentials)
27
28
 
28
29
  return false if @password.blank?
29
-
30
+
30
31
  raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
31
32
  raise CASServer::AuthenticatorError, "Invalid LDAP authenticator configuration!" unless @options[:ldap]
32
33
  raise CASServer::AuthenticatorError, "You must specify a server host in the LDAP configuration!" unless @options[:ldap][:host] || @options[:ldap][:server]
33
-
34
+
34
35
  raise CASServer::AuthenticatorError, "The username '#{@username}' contains invalid characters." if (@username =~ /[*\(\)\0\/]/)
35
-
36
+
36
37
  preprocess_username
37
-
38
+
38
39
  @ldap = Net::LDAP.new
39
-
40
-
40
+
41
+
41
42
  @options[:ldap][:host] ||= @options[:ldap][:server]
42
43
  @ldap.host = @options[:ldap][:host]
43
44
  @ldap.port = @options[:ldap][:port] if @options[:ldap][:port]
44
45
  @ldap.encryption(@options[:ldap][:encryption].intern) if @options[:ldap][:encryption]
45
-
46
+
46
47
  begin
47
48
  if @options[:ldap][:auth_user]
48
49
  bind_success = bind_by_username_with_preauthentication
49
50
  else
50
51
  bind_success = bind_by_username
51
52
  end
52
-
53
+
53
54
  return false unless bind_success
54
-
55
+
55
56
  entry = find_user
56
57
  extract_extra_attributes(entry)
57
-
58
+
58
59
  return true
59
60
  rescue Net::LDAP::LdapError => e
60
61
  raise CASServer::AuthenticatorError,
61
62
  "LDAP authentication failed with '#{e}'. Check your authenticator configuration."
62
63
  end
63
64
  end
64
-
65
+
65
66
  protected
66
67
  def default_username_attribute
67
68
  "cn"
68
69
  end
69
-
70
+
70
71
  private
71
72
  # Add prefix to username, if :username_prefix was specified in the :ldap config.
72
73
  def preprocess_username
@@ -78,56 +79,64 @@ class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
78
79
  # added to the LDAP query for the username.
79
80
  def bind_by_username
80
81
  username_attribute = options[:ldap][:username_attribute] || default_username_attribute
81
-
82
+
82
83
  @ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
83
84
  end
84
85
 
85
86
  # If an auth_user is specified, we will connect ("pre-authenticate") with the
86
87
  # LDAP server using the authenticator account, and then attempt to bind as the
87
- # user who is actually trying to authenticate. Note that you need to set up
88
+ # user who is actually trying to authenticate. Note that you need to set up
88
89
  # the special authenticator account first. Also, auth_user must be the authenticator
89
90
  # user's full CN, which is probably not the same as their username.
90
91
  #
91
92
  # This pre-authentication process is necessary because binding can only be done
92
- # using the CN, so having just the username is not enough. We connect as auth_user,
93
+ # using the CN, so having just the username is not enough. We connect as auth_user,
93
94
  # and then try to find the target user's CN based on the given username. Then we bind
94
95
  # as the target user to validate their credentials.
95
96
  def bind_by_username_with_preauthentication
96
- raise CASServer::AuthenticatorError, "A password must be specified in the configuration for the authenticator user!" unless
97
+ raise CASServer::AuthenticatorError, "A password must be specified in the configuration for the authenticator user!" unless
97
98
  @options[:ldap][:auth_password]
98
-
99
+
99
100
  @ldap.authenticate(@options[:ldap][:auth_user], @options[:ldap][:auth_password])
100
-
101
+
101
102
  @ldap.bind_as(:base => @options[:ldap][:base], :password => @password, :filter => user_filter)
102
103
  end
103
-
104
+
104
105
  # Combine the filter for finding the user with the optional extra filter specified in the config
105
106
  # (if any).
106
107
  def user_filter
107
108
  username_attribute = options[:ldap][:username_attribute] || default_username_attribute
108
-
109
- filter = Net::LDAP::Filter.eq(username_attribute, @username)
109
+
110
+ filter = Array(username_attribute).map { |ua| Net::LDAP::Filter.eq(ua, @username) }.reduce(:|)
110
111
  unless @options[:ldap][:filter].blank?
111
112
  filter &= Net::LDAP::Filter.construct(@options[:ldap][:filter])
112
113
  end
114
+
115
+ filter
113
116
  end
114
-
117
+
115
118
  # Finds the user based on the user_filter (this is called after authentication).
116
119
  # We do this to make it possible to extract extra_attributes.
117
120
  def find_user
118
121
  results = @ldap.search( :base => options[:ldap][:base], :filter => user_filter)
119
122
  return results.first
120
123
  end
121
-
124
+
122
125
  def extract_extra_attributes(ldap_entry)
123
126
  @extra_attributes = {}
124
127
  extra_attributes_to_extract.each do |attr|
125
- v = !ldap_entry[attr].blank? && ldap_entry[attr].first
126
- if v
128
+ v = ldap_entry[attr]
129
+ next if !v || (v.respond_to?(:empty?) && v.empty?)
130
+ if v.kind_of?(Array)
131
+ @extra_attributes[attr] = []
132
+ ldap_entry[attr].each do |a|
133
+ @extra_attributes[attr] << a.to_s
134
+ end
135
+ else
127
136
  @extra_attributes[attr] = v.to_s
128
137
  end
129
138
  end
130
-
139
+
131
140
  if @extra_attributes.empty?
132
141
  $LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
133
142
  else
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # I started working on this but run into a wall, so I am commiting what I've got
4
4
  # done and leaving it here with hopes of one day finishing it.
5
- #
5
+ #
6
6
  # The main problem is that although I've got the Lan Manager/NTLM password hash,
7
7
  # I'm not sure what to do with it. i.e. I need to check it against the AD or SMB
8
8
  # server or something... maybe faking an SMB share connection and using the LM
@@ -35,10 +35,10 @@ module CASServer
35
35
  else
36
36
  raise "Invalid NTLM reply from client."
37
37
  end
38
-
38
+
39
39
  if t1
40
40
  $LOG.debug "T1: #{t1.inspect}"
41
-
41
+
42
42
  # now put together a Type2 message asking for the client to send
43
43
  # back NTLM credentials (LM hash and such)
44
44
  t2 = Net::NTLM::Message::Type2.new
@@ -46,11 +46,11 @@ module CASServer
46
46
  t2.set_flag :NTLM
47
47
  t2.context = 0x0000000000000000 # this can probably just be left unassigned
48
48
  t2.challenge = 0x0123456789abcdef # this should be a random 8-byte integer
49
-
49
+
50
50
  $LOG.debug "T2: #{t2.inspect}"
51
51
  $LOG.debug "T2: #{t2.serialize}"
52
52
  headers["WWW-Authenticate"] = "NTLM #{t2.encode64}"
53
-
53
+
54
54
  # the client should respond to this with a Type3 message...
55
55
  r('401', '', headers)
56
56
  return
@@ -58,7 +58,7 @@ module CASServer
58
58
  # NOTE: for some reason the server never receives the T3 response, even though monitoring
59
59
  # the HTTP traffic I can see that the client does send it back... there's probably
60
60
  # another bug hiding somewhere here
61
-
61
+
62
62
  lm_response = t3.lm_response
63
63
  ntlm_response = t3.ntlm_response
64
64
  username = t3.user
@@ -67,8 +67,8 @@ module CASServer
67
67
  # call would do it?
68
68
  $LOG.debug "T3 LM: #{lm_response.inspect}"
69
69
  $LOG.debug "T3 NTLM: #{ntlm_response.inspect}"
70
-
71
- # assuming the authentication was successful, we'll now need to do something in the
70
+
71
+ # assuming the authentication was successful, we'll now need to do something in the
72
72
  # controller acting as if we'd received correct login credentials (i.e. proceed as if
73
73
  # CAS authentication was successful).... if authentication failed, then we should
74
74
  # just fall back to old-school web-based authentication, asking the user to enter
@@ -85,4 +85,4 @@ module CASServer
85
85
  end
86
86
  end
87
87
  end
88
- end
88
+ end
@@ -13,10 +13,10 @@ class CASServer::Authenticators::OpenID < CASServer::Authenticators::Base
13
13
  def validate(credentials)
14
14
  raise NotImplementedError, "The OpenID authenticator is not yet implemented. "+
15
15
  "See http://code.google.com/p/rubycas-server/issues/detail?id=36 if you are interested in helping this along."
16
-
16
+
17
17
  read_standard_credentials(credentials)
18
-
18
+
19
19
  store = OpenID::Store::Memory.new
20
20
  consumer = OpenID::Consumer.new({}, store)
21
21
  end
22
- end
22
+ end
@@ -7,15 +7,15 @@ rescue LoadError
7
7
  require 'active_record'
8
8
  end
9
9
 
10
- # Authenticates against a plain SQL table.
11
- #
12
- # This assumes that all of your users are stored in a table that has a 'username'
13
- # column and a 'password' column. When the user logs in, CAS conects to the
14
- # database and looks for a matching username/password in the users table. If a
10
+ # Authenticates against a plain SQL table.
11
+ #
12
+ # This assumes that all of your users are stored in a table that has a 'username'
13
+ # column and a 'password' column. When the user logs in, CAS conects to the
14
+ # database and looks for a matching username/password in the users table. If a
15
15
  # matching username and password is found, authentication is successful.
16
16
  #
17
17
  # Any database backend supported by ActiveRecord can be used.
18
- #
18
+ #
19
19
  # Config example:
20
20
  #
21
21
  # authenticator:
@@ -24,7 +24,7 @@ end
24
24
  # adapter: mysql
25
25
  # database: some_database_with_users_table
26
26
  # username: root
27
- # password:
27
+ # password:
28
28
  # server: localhost
29
29
  # user_table: users
30
30
  # username_column: username
@@ -34,10 +34,10 @@ end
34
34
  # provide the client with the authenticated user's username. However it is now
35
35
  # possible for the server to provide the client with additional attributes.
36
36
  # You can configure the SQL authenticator to provide data from additional
37
- # columns in the users table by listing the names of the columns under the
37
+ # columns in the users table by listing the names of the columns under the
38
38
  # 'extra_attributes' option. Note though that this functionality is experimental.
39
39
  # It should work with RubyCAS-Client, but may or may not work with other CAS
40
- # clients.
40
+ # clients.
41
41
  #
42
42
  # For example, with this configuration, the 'full_name' and 'access_level'
43
43
  # columns will be provided to your CAS clients along with the username:
@@ -50,24 +50,44 @@ end
50
50
  # user_table: users
51
51
  # username_column: username
52
52
  # password_column: password
53
+ # ignore_type_column: true # indicates if you want to ignore Single Table Inheritance 'type' field
53
54
  # extra_attributes: full_name, access_level
54
- #
55
+ #
55
56
  class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
57
+ def self.setup(options)
58
+ raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless options[:database]
59
+
60
+ user_model_name = "CASUser_#{options[:auth_index]}"
61
+ $LOG.debug "CREATING USER MODEL #{user_model_name}"
62
+
63
+ class_eval %{
64
+ class #{user_model_name} < ActiveRecord::Base
65
+ end
66
+ }
67
+
68
+ @user_model = const_get(user_model_name)
69
+ @user_model.establish_connection(options[:database])
70
+ @user_model.set_table_name(options[:user_table] || 'users')
71
+ @user_model.inheritance_column = 'no_inheritance_column' if options[:ignore_type_column]
72
+ end
73
+
74
+ def self.user_model
75
+ @user_model
76
+ end
56
77
 
57
78
  def validate(credentials)
58
79
  read_standard_credentials(credentials)
59
-
60
- raise CASServer::AuthenticatorError, "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
61
- raise CASServer::AuthenticatorError, "Invalid authenticator configuration!" unless @options[:database]
62
-
63
- CASUser.establish_connection @options[:database]
64
- CASUser.set_table_name @options[:user_table] || "users"
65
-
80
+ raise_if_not_configured
81
+
82
+ user_model = self.class.user_model
83
+
66
84
  username_column = @options[:username_column] || 'username'
67
85
  password_column = @options[:password_column] || 'password'
68
86
 
69
- results = CASUser.find(:all, :conditions => ["#{username_column} = ? AND #{password_column} = ?", @username, @password])
70
-
87
+ $LOG.debug "#{self.class}: [#{user_model}] " + "Connection pool size: #{user_model.connection_pool.instance_variable_get(:@checked_out).length}/#{user_model.connection_pool.instance_variable_get(:@connections).length}"
88
+ results = user_model.find(:all, :conditions => ["#{username_column} = ? AND #{password_column} = ?", @username, @password])
89
+ user_model.connection_pool.checkin(user_model.connection)
90
+
71
91
  if results.size > 0
72
92
  $LOG.warn("#{self.class}: Multiple matches found for user #{@username.inspect}") if results.size > 1
73
93
 
@@ -76,27 +96,38 @@ class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
76
96
  $LOG.warn("#{self.class}: Unable to extract extra_attributes because multiple matches were found for #{@username.inspect}")
77
97
  else
78
98
  user = results.first
79
-
80
- @extra_attributes = {}
81
- extra_attributes_to_extract.each do |col|
82
- @extra_attributes[col] = user.send(col)
83
- end
84
-
85
- if @extra_attributes.empty?
86
- $LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
87
- else
88
- $LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
89
- end
99
+
100
+ extract_extra(user)
101
+ log_extra
90
102
  end
91
103
  end
92
-
104
+
93
105
  return true
94
106
  else
95
107
  return false
96
108
  end
97
109
  end
98
-
99
- class CASUser < ActiveRecord::Base
110
+
111
+ protected
112
+
113
+ def raise_if_not_configured
114
+ raise CASServer::AuthenticatorError.new(
115
+ "Cannot validate credentials because the authenticator hasn't yet been configured"
116
+ ) unless @options
117
+ end
118
+
119
+ def extract_extra user
120
+ @extra_attributes = {}
121
+ extra_attributes_to_extract.each do |col|
122
+ @extra_attributes[col] = user.send(col)
123
+ end
100
124
  end
101
125
 
102
- end
126
+ def log_extra
127
+ if @extra_attributes.empty?
128
+ $LOG.warn("#{self.class}: Did not read any extra_attributes for user #{@username.inspect} even though an :extra_attributes option was provided.")
129
+ else
130
+ $LOG.debug("#{self.class}: Read the following extra_attributes for user #{@username.inspect}: #{@extra_attributes.inspect}")
131
+ end
132
+ end
133
+ end