rubycas-server 0.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.
- data/CHANGELOG.txt +3 -0
- data/LICENSE.txt +339 -0
- data/Manifest.txt +32 -0
- data/README.txt +27 -0
- data/Rakefile +59 -0
- data/bin/rubycas-server +8 -0
- data/config.example.yml +197 -0
- data/lib/casserver.rb +152 -0
- data/lib/casserver/authenticators/active_directory_ldap.rb +8 -0
- data/lib/casserver/authenticators/base.rb +22 -0
- data/lib/casserver/authenticators/ldap.rb +40 -0
- data/lib/casserver/authenticators/sql.rb +37 -0
- data/lib/casserver/authenticators/test.rb +8 -0
- data/lib/casserver/cas.rb +224 -0
- data/lib/casserver/conf.rb +78 -0
- data/lib/casserver/controllers.rb +253 -0
- data/lib/casserver/models.rb +109 -0
- data/lib/casserver/utils.rb +33 -0
- data/lib/casserver/version.rb +9 -0
- data/lib/casserver/views.rb +185 -0
- data/lib/themes/cas.css +112 -0
- data/lib/themes/ok.png +0 -0
- data/lib/themes/simple/bg.png +0 -0
- data/lib/themes/simple/login_box_bg.png +0 -0
- data/lib/themes/simple/logo.png +0 -0
- data/lib/themes/simple/theme.css +28 -0
- data/lib/themes/urbacon/bg.png +0 -0
- data/lib/themes/urbacon/login_box_bg.png +0 -0
- data/lib/themes/urbacon/logo.png +0 -0
- data/lib/themes/urbacon/theme.css +33 -0
- data/lib/themes/warning.png +0 -0
- data/setup.rb +1585 -0
- data/test/test_casserver.rb +150 -0
- metadata +103 -0
data/bin/rubycas-server
ADDED
data/config.example.yml
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
# IMPORTANT NOTE ABOUT YAML CONFIGURATION FILES
|
2
|
+
# ---> Be sure to use spaces instead of tabs for indentation. Yaml is white-space sensitive!
|
3
|
+
|
4
|
+
##### SERVER ########################################################################
|
5
|
+
|
6
|
+
# Under what environment are you running the CAS server? The following methods
|
7
|
+
# are currently supported:
|
8
|
+
#
|
9
|
+
# webrick -- run as a stand-alone webrick server; this is the default method
|
10
|
+
# mongrel -- run as a stand-alone mongrel server; fast, but you'll need to install
|
11
|
+
# mongrel and run it behind an https reverse proxy like Pound or Apache 2.2's mod_proxy)
|
12
|
+
# cgi -- slow, but simple to set up if you're already familliar with deploying CGI scripts
|
13
|
+
# fastcgi -- see http://www.fastcgi.com (e.g. under Apache you can use this with mod_fastcgi)
|
14
|
+
#
|
15
|
+
# The cgi and fastcgi methods have not been thoroughly tested!
|
16
|
+
# Please report any problems to the authors.
|
17
|
+
#
|
18
|
+
# IMPORTANT: If you use mongrel, you will need to run the server behind a reverse proxy
|
19
|
+
# (Pound, Apache 2.2 with mod_proxy, etc.) since mongrel does not support SSL/HTTPS.
|
20
|
+
# See the RubyCAS-Server install docs for more info. Also, mongrel requries
|
21
|
+
# Camping 1.5.180 which as of writing is only available via SVN. You can install
|
22
|
+
# this by running `gem install camping --source code.whytheluckystiff.net`
|
23
|
+
|
24
|
+
### webrick example
|
25
|
+
|
26
|
+
server: webrick
|
27
|
+
port: 443
|
28
|
+
ssl_cert: /path/to/your/ssl.pem
|
29
|
+
# ssl_key: /path/to/your/private_key.pem <-- if private key is separate from cert
|
30
|
+
|
31
|
+
### mongrel example (you will need to run this behind an https reverse proxy,
|
32
|
+
### since mongrel doesn't support SSL on its own)
|
33
|
+
|
34
|
+
#server: mongrel
|
35
|
+
#port: 110011
|
36
|
+
|
37
|
+
### cgi example (you'll need to serve this via an SSL-capable server like Apache)
|
38
|
+
|
39
|
+
#server: cgi
|
40
|
+
|
41
|
+
### fastcgi example (you'll need to serve this via an SSL-capable server like Apache)
|
42
|
+
|
43
|
+
#server: fastcgi
|
44
|
+
|
45
|
+
|
46
|
+
##### DATABASE #######################################################################
|
47
|
+
|
48
|
+
# Set up the database connection. Make sure that this database is secure!
|
49
|
+
#
|
50
|
+
# By default, we use sqlite3 since it works without any extra configuration.
|
51
|
+
# You can also use MySQL, PostgreSQL, MSSQL, or anything else supported by ActiveRecord.
|
52
|
+
#
|
53
|
+
# For example, with MySQL, your config wold be something like:
|
54
|
+
#
|
55
|
+
#database:
|
56
|
+
# adapter: mysql
|
57
|
+
# database: casserver
|
58
|
+
# user: root
|
59
|
+
# password:
|
60
|
+
# server: localhost
|
61
|
+
#
|
62
|
+
|
63
|
+
database:
|
64
|
+
adapter: sqlite3
|
65
|
+
dbfile: /var/lib/casserver.db
|
66
|
+
|
67
|
+
|
68
|
+
##### AUTHENTICATION #################################################################
|
69
|
+
|
70
|
+
# Configure how username/passwords are validated.
|
71
|
+
#
|
72
|
+
# !!! YOU MUST CONFIGURE ONE (AND ONLY ONE) OF THESE AUTHENTICATION METHODS !!!
|
73
|
+
#
|
74
|
+
# Currently there are three built-in methods for authentication:
|
75
|
+
# SQL, ActiveDirectory, and LDAP. If none of these work for you, it is relatively
|
76
|
+
# easy to write your own custom Authenticator class.
|
77
|
+
#
|
78
|
+
# ==> SQL Authentication:
|
79
|
+
# The simplest method is to validate against a SQL database. This assumes
|
80
|
+
# that all of your users are stored in a table that has a 'username' column
|
81
|
+
# and a 'password' column. When the user logs in, CAS conects to this database
|
82
|
+
# and look for a matching username/password in the users table. If a matching
|
83
|
+
# username and password is found, authentication is successful.
|
84
|
+
#
|
85
|
+
# Example:
|
86
|
+
#
|
87
|
+
#authenticator:
|
88
|
+
# class: CASServer::Authenticators::SQL
|
89
|
+
# database:
|
90
|
+
# adapter: mysql
|
91
|
+
# database: some_database_with_users_table
|
92
|
+
# user: root
|
93
|
+
# password:
|
94
|
+
# server: localhost
|
95
|
+
# user_table: user
|
96
|
+
# username_column: username
|
97
|
+
# password_column: password
|
98
|
+
#
|
99
|
+
#
|
100
|
+
# ==> ActiveDirectory Authentication:
|
101
|
+
# This method authenticates against Microsoft's ActiveDirectory using LDAP.
|
102
|
+
# You must enter your ActiveDirectory server, and base DN. The port number
|
103
|
+
# and LDAP filter are optional. You must also enter a username and password
|
104
|
+
# for an "authenticator" user. The authenticator users this account to
|
105
|
+
# log in to the ActiveDirectory server and search LDAP. This does not have
|
106
|
+
# to be an administrative account; it only has to be able to search for other
|
107
|
+
# users.
|
108
|
+
#
|
109
|
+
# Example:
|
110
|
+
#
|
111
|
+
#authenticator:
|
112
|
+
# class: CASServer::Authenticators::ActiveDirectoryLDAP
|
113
|
+
# ldap:
|
114
|
+
# server: ad.example.net
|
115
|
+
# port: 389
|
116
|
+
# base: dc=example,dc=net
|
117
|
+
# filter: (objectClass=person)
|
118
|
+
# auth_user: authenticator
|
119
|
+
# auth_password: itsasecret
|
120
|
+
#
|
121
|
+
#
|
122
|
+
# ==> LDAP Authentication:
|
123
|
+
# This is a more general version of the ActiveDirectory authenticator.
|
124
|
+
# The configuration is similar, except you don't need an authenticator
|
125
|
+
# username or password. Note that this authenticator hasn't been widely
|
126
|
+
# tested, so it is not guaranteed to work.
|
127
|
+
#
|
128
|
+
#authenticator:
|
129
|
+
# class: CASServer::Authenticators::ActiveDirectoryLDAP
|
130
|
+
# ldap:
|
131
|
+
# server: ad.example.net
|
132
|
+
# port: 389
|
133
|
+
# base: dc=example,dc=net
|
134
|
+
# filter: (objectClass=person)
|
135
|
+
#
|
136
|
+
#
|
137
|
+
# ==> Custom Authentication:
|
138
|
+
# It should be relatively easy to write your own Authenticator class. Have a look
|
139
|
+
# at the built-in authenticators in the casserver/authenticators directory. Your
|
140
|
+
# authenticator should extend the CASServer::Authenticators::Base class and must
|
141
|
+
# implement a validate() method that takes a single hash argument. When the user submits
|
142
|
+
# the login form, the username and password they entered is passed to validate()
|
143
|
+
# as a hash under :username and :password keys. In the future, this hash
|
144
|
+
# might also contain other data such as the domain that the user is logging in to.
|
145
|
+
#
|
146
|
+
# To use your custom authenticator, specify it's class name in the authenticator section
|
147
|
+
# of the config. You will also probably have to load the class using using a `require`
|
148
|
+
# call at the top of casserver.rb. Any other parameters you specify in the authenticator
|
149
|
+
# configuration will be passed on to the authenticator and made availabe in the validate()
|
150
|
+
# method as an @options hash.
|
151
|
+
#
|
152
|
+
# Example:
|
153
|
+
#
|
154
|
+
#authenticator:
|
155
|
+
# class: FooModule::MyCustomAuthenticator
|
156
|
+
# option_a: foo
|
157
|
+
# another_option: yeeha
|
158
|
+
|
159
|
+
|
160
|
+
##### LOOK & FEEL ######################################################################
|
161
|
+
|
162
|
+
# Set the path to the theme directory that determines how your CAS pages look.
|
163
|
+
#
|
164
|
+
# Custom themes are not well supported yet, but will be in the near future. In the
|
165
|
+
# meantime, if you want to create a custom theme, you can create a subdirectory
|
166
|
+
# under the CASServer's themes dir (for example '/usr/lib/ruby/1.8/gems/casserver-xxx/lib/themes',
|
167
|
+
# if you installed CASServer on Linux as a gem). A theme is basically just a theme.css
|
168
|
+
# file that overrides the themes/cas.css styles along with a collection of image files
|
169
|
+
# like logo.png and bg.png.
|
170
|
+
#
|
171
|
+
# By default, we use the 'simple' theme which you can find in themes/simple.
|
172
|
+
theme: simple
|
173
|
+
|
174
|
+
# The name of your company/organization. This will show up on the login page.
|
175
|
+
organization: CAS
|
176
|
+
|
177
|
+
# A short bit of text that shows up on the login page. You can make this blank if you prefer.
|
178
|
+
infoline: Powered by <a href="http://code.google.com/p/rubycas-server/">RubyCAS-Server</a>
|
179
|
+
|
180
|
+
|
181
|
+
##### LOGGING #########################################################################
|
182
|
+
|
183
|
+
# Configure general logging. This log is where you'll want to look in case of problems.
|
184
|
+
#
|
185
|
+
# You may want to change the file to something like /var/log/casserver.log
|
186
|
+
# Set the level to DEBUG if you want more detailed logging.
|
187
|
+
|
188
|
+
log:
|
189
|
+
file: /var/log/casserver.log
|
190
|
+
level: INFO
|
191
|
+
|
192
|
+
|
193
|
+
# If you want full database logging, uncomment this next section.
|
194
|
+
# Every SQL query will be logged here. This is useful for debugging database problems.
|
195
|
+
#
|
196
|
+
#db_log:
|
197
|
+
# file: /var/log/casserver_db.log
|
data/lib/casserver.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# change to current directory when invoked on its own
|
4
|
+
Dir.chdir(File.dirname(File.expand_path(__FILE__))) if __FILE__ == $0
|
5
|
+
|
6
|
+
# add current directory to load path
|
7
|
+
$: << File.dirname(File.expand_path(__FILE__))
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require_gem 'camping', '~> 1.5'
|
11
|
+
require 'camping'
|
12
|
+
|
13
|
+
require 'active_support'
|
14
|
+
require 'yaml'
|
15
|
+
|
16
|
+
# enable xhtml source code indentation for debugging views
|
17
|
+
Markaby::Builder.set(:indent, 2)
|
18
|
+
|
19
|
+
# seed the random number generator (ruby does this by default, but it doesn't hurt to do it here just to be sure)
|
20
|
+
srand
|
21
|
+
|
22
|
+
# Camping.goes must be called after the authenticator class is loaded, otherwise weird things happen
|
23
|
+
Camping.goes :CASServer
|
24
|
+
|
25
|
+
module CASServer
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'casserver/utils'
|
29
|
+
require 'casserver/models'
|
30
|
+
require 'casserver/cas'
|
31
|
+
require 'casserver/conf'
|
32
|
+
require 'casserver/views'
|
33
|
+
require 'casserver/controllers'
|
34
|
+
|
35
|
+
# init the logger
|
36
|
+
$LOG = CASServer::Utils::Logger.new(CASServer::Conf.log[:file])
|
37
|
+
$LOG.level = "CASServer::Utils::Logger::#{CASServer::Conf.log[:level]}".constantize
|
38
|
+
|
39
|
+
# do initialization stuff
|
40
|
+
def CASServer.create
|
41
|
+
CASServer::Models.create_schema
|
42
|
+
|
43
|
+
$LOG.info("RubyCAS-Server initialized.")
|
44
|
+
|
45
|
+
$LOG.debug("Configuration is:\n#{$CONF.to_yaml}")
|
46
|
+
$LOG.debug("Authenticator is: #{$AUTH}")
|
47
|
+
|
48
|
+
CASServer::Models::ServiceTicket.cleanup_expired(CASServer::Conf.service_ticket_expiry)
|
49
|
+
CASServer::Models::LoginTicket.cleanup_expired(CASServer::Conf.login_ticket_expiry)
|
50
|
+
CASServer::Models::ProxyGrantingTicket.cleanup_expired(CASServer::Conf.proxy_granting_ticket_expiry)
|
51
|
+
CASServer::Models::TicketGrantingTicket.cleanup_expired(CASServer::Conf.ticket_granting_ticket_expiry)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# this gets run if we launch directly (i.e. `ruby casserver.rb` rather than `camping casserver`)
|
56
|
+
if __FILE__ == $0 || $RUN
|
57
|
+
CASServer::Models::Base.establish_connection(CASServer::Conf.database)
|
58
|
+
if CASServer::Conf.db_log
|
59
|
+
CASServer::Models::Base.logger = Logger.new(CASServer::Conf.db_log[:file] || 'casserver_db.log')
|
60
|
+
CASServer::Models::Base.logger.level = "CASServer::Utils::Logger::#{CASServer::Conf.db_log[:level] || 'DEBUG'}".constantize
|
61
|
+
end
|
62
|
+
|
63
|
+
case CASServer::Conf.server
|
64
|
+
when "webrick", :webrick
|
65
|
+
require 'webrick/httpserver'
|
66
|
+
require 'webrick/https'
|
67
|
+
require 'camping/webrick'
|
68
|
+
|
69
|
+
# TODO: verify the certificate's validity
|
70
|
+
# example of how to do this is here: http://pablotron.org/download/ruri-20050331.rb
|
71
|
+
|
72
|
+
cert_path = CASServer::Conf.ssl_cert
|
73
|
+
key_path = CASServer::Conf.ssl_key || CASServer::Conf.ssl_cert
|
74
|
+
# look for the key in the ssl_cert if no ssl_key is specified
|
75
|
+
|
76
|
+
raise "'#{cert_path}' is not a valid ssl certificate. Your 'ssl_cert' configuration" +
|
77
|
+
" setting must be a path to a valid ssl certificate file." unless
|
78
|
+
File.exists? cert_path
|
79
|
+
|
80
|
+
raise "'#{key_path}' is not a valid ssl private key. Your 'ssl_key' configuration" +
|
81
|
+
" setting must be a path to a valid ssl private key file." unless
|
82
|
+
File.exists? key_path
|
83
|
+
|
84
|
+
cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
|
85
|
+
key = OpenSSL::PKey::RSA.new(File.read(key_path))
|
86
|
+
|
87
|
+
begin
|
88
|
+
s = WEBrick::HTTPServer.new(
|
89
|
+
:BindAddress => "0.0.0.0",
|
90
|
+
:Port => CASServer::Conf.port,
|
91
|
+
:SSLEnable => true,
|
92
|
+
:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
|
93
|
+
:SSLCertificate => cert,
|
94
|
+
:SSLPrivateKey => key
|
95
|
+
)
|
96
|
+
rescue Errno::EACCES
|
97
|
+
puts "\nThe server could not launch. Are you running on a privileged port? (e.g. port 443) If so, you must run the server as root."
|
98
|
+
exit 2
|
99
|
+
end
|
100
|
+
|
101
|
+
CASServer.create
|
102
|
+
s.mount "#{CASServer::Conf.uri_path}", WEBrick::CampingHandler, CASServer
|
103
|
+
|
104
|
+
puts "\n** CASServer is running at http://localhost:#{CASServer::Conf.port}#{CASServer::Conf.uri_path} and logging to '#{CASServer::Conf.log[:file]}'\n\n"
|
105
|
+
|
106
|
+
# This lets Ctrl+C shut down your server
|
107
|
+
trap(:INT) do
|
108
|
+
s.shutdown
|
109
|
+
end
|
110
|
+
|
111
|
+
s.start
|
112
|
+
|
113
|
+
when "mongrel", :mongrel
|
114
|
+
require 'rubygems'
|
115
|
+
require 'mongrel/camping'
|
116
|
+
|
117
|
+
# camping has fixes for mongrel currently only availabe in SVN
|
118
|
+
# ... you can install camping from svn (1.5.180) by running:
|
119
|
+
# gem install camping --source code.whytheluckystiff.net
|
120
|
+
require_gem 'camping', '~> 1.5.180'
|
121
|
+
|
122
|
+
CASServer.create
|
123
|
+
|
124
|
+
begin
|
125
|
+
server = Mongrel::Camping::start("0.0.0.0",CASServer::Conf.port,"#{CASServer::Conf.uri_path}",CASServer)
|
126
|
+
rescue Errno::EACCES
|
127
|
+
puts "\nThe server could not launch. Are you running on a privileged port? (e.g. port 443) If so, you must run the server as root."
|
128
|
+
exit 2
|
129
|
+
end
|
130
|
+
|
131
|
+
puts "\n** CASServer is running at http://localhost:#{CASServer::Conf.port}#{CASServer::Conf.uri_path} and logging to '#{CASServer::Conf.log[:file]}'"
|
132
|
+
server.run.join
|
133
|
+
|
134
|
+
when "fastcgi", :fastcgi
|
135
|
+
require 'camping/fastcgi'
|
136
|
+
Dir.chdir('/srv/www/camping/casserver/')
|
137
|
+
|
138
|
+
CASServer.create
|
139
|
+
Camping::FastCGI.start(CASServer)
|
140
|
+
|
141
|
+
when "cgi", :cgi
|
142
|
+
CASServer.create
|
143
|
+
puts CASServer.run
|
144
|
+
|
145
|
+
else
|
146
|
+
if CASServer::Conf.server
|
147
|
+
raise "The server setting '#{CASServer::Conf.server}' in your config.yml file is invalid."
|
148
|
+
else
|
149
|
+
raise "You must have a 'server' setting in your config.yml file. Please see the RubyCAS-Server documentation."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CASServer
|
2
|
+
module Authenticators
|
3
|
+
class Base
|
4
|
+
attr_accessor :options
|
5
|
+
|
6
|
+
def validate(credentials)
|
7
|
+
raise NotImplementedError, "This method must be implemented by a class extending #{self.class}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def configure(options)
|
11
|
+
raise ArgumentError, "options must be a HashWithIndifferentAccess" unless options.kind_of? HashWithIndifferentAccess
|
12
|
+
@options = options.dup
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
def read_standard_credentials(credentials)
|
17
|
+
@username = credentials[:username]
|
18
|
+
@password = credentials[:password]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'casserver/authenticators/base'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'net/ldap'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require_gem 'ruby-net-ldap', '~> 0.0.4'
|
8
|
+
require 'net/ldap'
|
9
|
+
end
|
10
|
+
|
11
|
+
class CASServer::Authenticators::LDAP < CASServer::Authenticators::Base
|
12
|
+
def validate(credentials)
|
13
|
+
read_standard_credentials(credentials)
|
14
|
+
|
15
|
+
raise "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
16
|
+
raise "Invalid authenticator configuration!" unless @options[:ldap]
|
17
|
+
raise "You must specify an ldap server in the configuration!" unless @options[:ldap][:server]
|
18
|
+
|
19
|
+
ldap = Net::LDAP.new
|
20
|
+
ldap.host = @options[:ldap][:server]
|
21
|
+
ldap.port = @options[:ldap][:port] if @options[:ldap][:port]
|
22
|
+
|
23
|
+
if @options[:ldap][:auth_user]
|
24
|
+
raise "A password must be specified in the configuration for the authenticator user!" unless @options[:ldap][:auth_password]
|
25
|
+
ldap.authenticate(@options[:ldap][:auth_user], @options[:ldap][:auth_password])
|
26
|
+
end
|
27
|
+
|
28
|
+
filter = "(#{@options[:ldap][:username_attribute] || default_username_attribute}=#{@username})"
|
29
|
+
filter += " & (#{@options[:ldap][:filter]})" if @options[:ldap][:filter]
|
30
|
+
|
31
|
+
result = ldap.bind_as(:base => @options[:ldap][:base], :filter => filter, :password => @password)
|
32
|
+
|
33
|
+
return result
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def default_username_attribute
|
38
|
+
"uid"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'casserver/authenticators/base'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'active_record'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rubygems'
|
7
|
+
require 'active_record'
|
8
|
+
end
|
9
|
+
|
10
|
+
class CASServer::Authenticators::SQL < CASServer::Authenticators::Base
|
11
|
+
|
12
|
+
def validate(credentials)
|
13
|
+
read_standard_credentials(credentials)
|
14
|
+
|
15
|
+
raise "Cannot validate credentials because the authenticator hasn't yet been configured" unless @options
|
16
|
+
raise "Invalid authenticator configuration!" unless @options[:database]
|
17
|
+
|
18
|
+
CASUser.establish_connection @options[:database]
|
19
|
+
CASUser.set_table_name @options[:user_table] || "users"
|
20
|
+
|
21
|
+
username_column = @options[:username_column] || 'username'
|
22
|
+
password_column = @options[:password_column] || 'password'
|
23
|
+
|
24
|
+
results = CASUser.find(:all, :conditions => ["#{username_column} = ? AND #{password_column} = ?", @username, @password])
|
25
|
+
|
26
|
+
if results.size > 0
|
27
|
+
$LOG.warn("Multiple matches found for user '#{@username}'") if results.size > 1
|
28
|
+
return true
|
29
|
+
else
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class CASUser < ActiveRecord::Base
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|