rubycas-client-rails-vpsa 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.project ADDED
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>rubycas-client-rails</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>org.radrails.rails.core.railsnature</nature>
16
+ <nature>com.aptana.ruby.core.rubynature</nature>
17
+ </natures>
18
+ </projectDescription>
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 University of Toronto
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,4 @@
1
+ RubyCAS-Client-Rails
2
+ ====================
3
+
4
+ Fork do projeto [RubyCAS-Client-Rails](https://github.com/rubycas/rubycas-client-rails) adaptado para a VPSA.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the rubycas_client_rails plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the rubycas_client_rails plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'RubycasClientRails'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ # Include hook code here
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,430 @@
1
+
2
+ require 'casclient'
3
+
4
+ module RubyCAS
5
+ class Railtie < Rails::Railtie
6
+ config.rubycas = ActiveSupport::OrderedOptions.new
7
+
8
+ initializer 'rubycas.initialize' do |app|
9
+ RubyCAS::Filter.setup(config.rubycas)
10
+ end
11
+ end
12
+
13
+ class Filter
14
+ cattr_reader :config, :log, :client
15
+
16
+ # These are initialized when you call setup.
17
+ @@client = nil
18
+ @@log = nil
19
+ @@fake_user = nil
20
+ @@fake_extra_attributes = nil
21
+
22
+ class << self
23
+ def setup(config)
24
+ @@config = config
25
+ @@config[:logger] = Rails.logger unless @@config[:logger]
26
+ @@client = CASClient::Client.new(@@config)
27
+ @@log = @@client.log
28
+ end
29
+
30
+ def filter(controller)
31
+ raise "Cannot use the CASClient filter because it has not yet been configured." if config.nil?
32
+
33
+ if @@fake_user
34
+ controller.session[client.username_session_key] = @@fake_user
35
+ controller.session[:casfilteruser] = @@fake_user
36
+ controller.session[client.extra_attributes_session_key] = @@fake_extra_attributes
37
+ return true
38
+ end
39
+
40
+ ### patch this line to recreate the 2 items from cookie
41
+ last_st = controller.session[:cas_last_valid_ticket]
42
+ last_st_service = controller.session[:cas_last_valid_ticket_service]
43
+
44
+ if single_sign_out(controller)
45
+ controller.send(:render, :text => "CAS Single-Sign-Out request intercepted.")
46
+ return false
47
+ end
48
+
49
+ st = read_ticket(controller)
50
+
51
+ # is_new_session = true
52
+
53
+ if st && last_st &&
54
+ last_st == st.ticket &&
55
+ last_st_service == st.service
56
+ # warn() rather than info() because we really shouldn't be re-validating the same ticket.
57
+ # The only situation where this is acceptable is if the user manually does a refresh and
58
+ # the same ticket happens to be in the URL.
59
+ log.warn("Re-using previously validated ticket since the ticket id and service are the same.")
60
+ #st = last_st
61
+ return true
62
+ elsif last_st &&
63
+ !config[:authenticate_on_every_request] &&
64
+ controller.session[client.username_session_key]
65
+ # Re-use the previous ticket if the user already has a local CAS session (i.e. if they were already
66
+ # previously authenticated for this service). This is to prevent redirection to the CAS server on every
67
+ # request.
68
+ #
69
+ # This behaviour can be disabled (so that every request is routed through the CAS server) by setting
70
+ # the :authenticate_on_every_request config option to true. However, this is not desirable since
71
+ # it will almost certainly break POST request, AJAX calls, etc.
72
+ log.debug "Existing local CAS session detected for #{controller.session[client.username_session_key].inspect}. "+
73
+ "Previous ticket #{last_st_service} will be re-used."
74
+ #st = last_st
75
+ return true
76
+ end
77
+
78
+ if st
79
+ client.validate_service_ticket(st) unless st.has_been_validated?
80
+ #vr = st.success
81
+
82
+ if st.is_valid?
83
+ #if is_new_session
84
+ log.info("Ticket #{st.ticket.inspect} for service #{st.service.inspect} belonging to user #{st.user.inspect} is VALID.")
85
+ controller.session[client.username_session_key] = st.user.dup
86
+ controller.session[client.extra_attributes_session_key] = HashWithIndifferentAccess.new(st.extra_attributes) if st.extra_attributes
87
+
88
+ if st.extra_attributes
89
+ log.debug("Extra user attributes provided along with ticket #{st.ticket.inspect}: #{st.extra_attributes.inspect}.")
90
+ end
91
+
92
+ # RubyCAS-Client 1.x used :casfilteruser as it's username session key,
93
+ # so we need to set this here to ensure compatibility with configurations
94
+ # built around the old client.
95
+ controller.session[:casfilteruser] = st.user
96
+
97
+ if config[:enable_single_sign_out]
98
+ f = store_service_session_lookup(st, controller.request.session_options[:id] || controller.session.session_id)
99
+ log.debug("Wrote service session lookup file to #{f.inspect} with session id #{controller.request.session_options[:id] || controller.session.session_id.inspect}.")
100
+ end
101
+ #end
102
+
103
+ # Store the ticket in the session to avoid re-validating the same service
104
+ # ticket with the CAS server.
105
+ controller.session[:cas_last_valid_ticket] = st.ticket
106
+ controller.session[:cas_last_valid_ticket_service] = st.service
107
+
108
+ if st.pgt_iou
109
+ unless controller.session[:cas_pgt] && controller.session[:cas_pgt].ticket && controller.session[:cas_pgt].iou == st.pgt_iou
110
+ log.info("Receipt has a proxy-granting ticket IOU. Attempting to retrieve the proxy-granting ticket...")
111
+ pgt = client.retrieve_proxy_granting_ticket(st.pgt_iou)
112
+
113
+ if pgt
114
+ log.debug("Got PGT #{pgt.ticket.inspect} for PGT IOU #{pgt.iou.inspect}. This will be stored in the session.")
115
+ controller.session[:cas_pgt] = pgt
116
+ # For backwards compatibility with RubyCAS-Client 1.x configurations...
117
+ controller.session[:casfilterpgt] = pgt
118
+ else
119
+ log.error("Failed to retrieve a PGT for PGT IOU #{st.pgt_iou}!")
120
+ end
121
+ else
122
+ log.info("PGT is present in session and PGT IOU #{st.pgt_iou} matches the saved PGT IOU. Not retrieving new PGT.")
123
+ end
124
+
125
+ end
126
+
127
+ return true
128
+ else
129
+ log.warn("Ticket #{st.ticket.inspect} failed validation -- #{st.failure_code}: #{st.failure_message}")
130
+ unauthorized!(controller, st)
131
+ return false
132
+ end
133
+ else # no service ticket was present in the request
134
+ if returning_from_gateway?(controller)
135
+ log.info "Returning from CAS gateway without authentication."
136
+
137
+ # unset, to allow for the next request to be authenticated if necessary
138
+ controller.session[:cas_sent_to_gateway] = false
139
+
140
+ if use_gatewaying?
141
+ log.info "This CAS client is configured to use gatewaying, so we will permit the user to continue without authentication."
142
+ controller.session[client.username_session_key] = nil
143
+ return true
144
+ else
145
+ log.warn "The CAS client is NOT configured to allow gatewaying, yet this request was gatewayed. Something is not right!"
146
+ end
147
+ end
148
+
149
+ unauthorized!(controller)
150
+ return false
151
+ end
152
+ rescue OpenSSL::SSL::SSLError => sslexception
153
+ log.error("SSL Error: #{sslexception}")
154
+ unauthorized!(controller)
155
+ return false
156
+ end
157
+
158
+ # used to allow faking for testing
159
+ # with cucumber and other tools.
160
+ # use like
161
+ # CASClient::Frameworks::Rails::Filter.fake("homer")
162
+ # you can also fake extra attributes by including a second parameter
163
+ # CASClient::Frameworks::Rails::Filter.fake("homer", {:roles => ['dad', 'husband']})
164
+ def fake(username, extra_attributes = nil)
165
+ @@fake_user = username
166
+ @@fake_extra_attributes = extra_attributes
167
+ end
168
+
169
+ def use_gatewaying?
170
+ @@config[:use_gatewaying]
171
+ end
172
+
173
+ # Returns the login URL for the current controller.
174
+ # Useful when you want to provide a "Login" link in a GatewayFilter'ed
175
+ # action.
176
+ def login_url(controller)
177
+ service_url = read_service_url(controller)
178
+ url = client.add_service_to_login_url(service_url)
179
+ log.debug("Generated login url: #{url}")
180
+ return url
181
+ end
182
+
183
+ # allow controllers to reuse the existing config to auto-login to
184
+ # the service
185
+ #
186
+ # Use this from within a controller. Pass the controller, the
187
+ # login-credentials and the path that you want the user
188
+ # resdirected to on success.
189
+ #
190
+ # When writing a login-action you must check the return-value of
191
+ # the response to see if it failed!
192
+ #
193
+ # If it worked - you need to redirect the user to the service -
194
+ # path, because that has the ticket that will *actually* log them
195
+ # into your system
196
+ #
197
+ # example:
198
+ # def autologin
199
+ # resp = CASClient::Frameworks::Rails::Filter.login_to_service(self, credentials, dashboard_url)
200
+ # if resp.is_faiulure?
201
+ # flash[:error] = 'Login failed'
202
+ # render :action => 'login'
203
+ # else
204
+ # return redirect_to(@resp.service_redirect_url)
205
+ # end
206
+ # end
207
+ def login_to_service(controller, credentials, return_path)
208
+ resp = @@client.login_to_service(credentials, return_path)
209
+ if resp.is_failure?
210
+ log.info("Validation failed for service #{return_path.inspect} reason: '#{resp.failure_message}'")
211
+ else
212
+ log.info("Ticket #{resp.ticket.inspect} for service #{return_path.inspect} is VALID.")
213
+ end
214
+
215
+ resp
216
+ end
217
+
218
+ # Clears the given controller's local Rails session, does some local
219
+ # CAS cleanup, and redirects to the CAS logout page. Additionally, the
220
+ # <tt>request.referer</tt> value from the <tt>controller</tt> instance
221
+ # is passed to the CAS server as a 'destination' parameter. This
222
+ # allows RubyCAS server to provide a follow-up login page allowing
223
+ # the user to log back in to the service they just logged out from
224
+ # using a different username and password. Other CAS server
225
+ # implemenations may use this 'destination' parameter in different
226
+ # ways.
227
+ # If given, the optional <tt>service</tt> URL overrides
228
+ # <tt>request.referer</tt>.
229
+ def logout(controller, service = nil)
230
+ referer = service || controller.request.referer
231
+ st = controller.session[:cas_last_valid_ticket]
232
+ delete_service_session_lookup(st) if st
233
+ controller.send(:reset_session)
234
+ controller.send(:redirect_to, client.logout_url(referer))
235
+ end
236
+
237
+ def unauthorized!(controller, vr = nil)
238
+ if controller.params[:format] == "xml"
239
+ if vr
240
+ controller.send(:render, :xml => "<errors><error>#{vr.failure_message}</error></errors>", :status => 401)
241
+ else
242
+ controller.send(:head, 401)
243
+ end
244
+ else
245
+ redirect_to_cas_for_authentication(controller)
246
+ end
247
+ end
248
+
249
+ def redirect_to_cas_for_authentication(controller)
250
+ redirect_url = login_url(controller)
251
+
252
+ if use_gatewaying?
253
+ controller.session[:cas_sent_to_gateway] = true
254
+ redirect_url << "&gateway=true"
255
+ else
256
+ controller.session[:cas_sent_to_gateway] = false
257
+ end
258
+
259
+ if controller.session[:previous_redirect_to_cas] &&
260
+ controller.session[:previous_redirect_to_cas] > (Time.now - 1.second)
261
+ log.warn("Previous redirect to the CAS server was less than a second ago. The client at #{controller.request.remote_ip.inspect} may be stuck in a redirection loop!")
262
+ controller.session[:cas_validation_retry_count] ||= 0
263
+
264
+ if controller.session[:cas_validation_retry_count] > 3
265
+ log.error("Redirection loop intercepted. Client at #{controller.request.remote_ip.inspect} will be redirected back to login page and forced to renew authentication.")
266
+ redirect_url += "&renew=1&redirection_loop_intercepted=1"
267
+ end
268
+
269
+ controller.session[:cas_validation_retry_count] += 1
270
+ else
271
+ controller.session[:cas_validation_retry_count] = 0
272
+ end
273
+ controller.session[:previous_redirect_to_cas] = Time.now
274
+
275
+ log.debug("Redirecting to #{redirect_url.inspect}")
276
+ controller.send(:redirect_to, redirect_url)
277
+ end
278
+
279
+ private
280
+ def single_sign_out(controller)
281
+
282
+ # Avoid calling raw_post (which may consume the post body) if
283
+ # this seems to be a file upload
284
+ if content_type = controller.request.headers["CONTENT_TYPE"] &&
285
+ content_type =~ %r{^multipart/}
286
+ return false
287
+ end
288
+
289
+ if controller.request.post? &&
290
+ controller.params['logoutRequest'] &&
291
+ URI.unescape(controller.params['logoutRequest']) =~
292
+ %r{^<samlp:LogoutRequest.*?<samlp:SessionIndex>(.*)</samlp:SessionIndex>}m
293
+ # TODO: Maybe check that the request came from the registered CAS server? Although this might be
294
+ # pointless since it's easily spoofable...
295
+ si = $~[1]
296
+
297
+ unless config[:enable_single_sign_out]
298
+ log.warn "Ignoring single-sign-out request for CAS session #{si.inspect} because ssout functionality is not enabled (see the :enable_single_sign_out config option)."
299
+ return false
300
+ end
301
+
302
+ log.debug "Intercepted single-sign-out request for CAS session #{si.inspect}."
303
+
304
+ # Rails 2.3
305
+ ##required_sess_store = ActiveRecord::SessionStore
306
+ ##current_sess_store = ActionController::Base.session_store
307
+
308
+ # Rails 2.2
309
+ ## required_sess_store = CGI::Session::ActiveRecordStore
310
+ ## current_sess_store = ActionController::Base.session_options[:database_manager]
311
+
312
+ # Rails 3.0
313
+ #required_sess_store = ActiveRecord::SessionStore
314
+ current_sess_store = ::Rails.application.config.session_store
315
+
316
+ #if current_sess_store == required_sess_store
317
+ session_id = read_service_session_lookup(si)
318
+
319
+ if session_id
320
+ session = current_sess_store::Session.find_by_session_id(session_id)
321
+ if session
322
+ st = session.data[:cas_last_valid_ticket] || si
323
+ delete_service_session_lookup(st) if st
324
+ session.destroy
325
+ log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{si.inspect}.")
326
+ else
327
+ log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.")
328
+ end
329
+
330
+ log.info("Single-sign-out for session #{session_id.inspect} completed successfuly.")
331
+ else
332
+ log.warn("Couldn't destroy session with SessionIndex #{si} because no corresponding session id could be looked up.")
333
+ end
334
+ #else
335
+ # log.error "Cannot process logout request because this Rails application's session store is "+
336
+ # " #{current_sess_store.name.inspect}. Single Sign-Out only works with the "+
337
+ # " #{required_sess_store.name.inspect} session store."
338
+ #end
339
+
340
+ # Return true to indicate that a single-sign-out request was detected
341
+ # and that further processing of the request is unnecessary.
342
+ return true
343
+ end
344
+
345
+ # This is not a single-sign-out request.
346
+ return false
347
+ end
348
+
349
+ def read_ticket(controller)
350
+ # Note that we are now deleting the 'ticket' and 'renew' parameters, since they really
351
+ # have no business getting passed on to the controller action.
352
+
353
+ ticket = controller.params.delete(:ticket)
354
+
355
+ return nil unless ticket
356
+
357
+ log.debug("Request contains ticket #{ticket.inspect}.")
358
+
359
+ if ticket =~ /^PT-/
360
+ CASClient::ProxyTicket.new(ticket, read_service_url(controller), controller.params.delete(:renew))
361
+ else
362
+ CASClient::ServiceTicket.new(ticket, read_service_url(controller), controller.params.delete(:renew))
363
+ end
364
+ end
365
+
366
+ def returning_from_gateway?(controller)
367
+ controller.session[:cas_sent_to_gateway]
368
+ end
369
+
370
+ def read_service_url(controller)
371
+ if config[:service_url]
372
+ log.debug("Using explicitly set service url: #{config[:service_url]}")
373
+ return config[:service_url]
374
+ end
375
+
376
+ params = controller.params.dup
377
+ params.delete(:ticket)
378
+ service_url = controller.url_for(params)
379
+ log.debug("Guessed service url: #{service_url.inspect}")
380
+ return service_url
381
+ end
382
+
383
+ # Creates a file in tmp/sessions linking a SessionTicket
384
+ # with the local Rails session id. The file is named
385
+ # cas_sess.<session ticket> and its text contents is the corresponding
386
+ # Rails session id.
387
+ # Returns the filename of the lookup file created.
388
+ def store_service_session_lookup(st, sid)
389
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
390
+ f = File.new(filename_of_service_session_lookup(st), 'w')
391
+ f.write(sid)
392
+ f.close
393
+ return f.path
394
+ end
395
+
396
+ # Returns the local Rails session ID corresponding to the given
397
+ # ServiceTicket. This is done by reading the contents of the
398
+ # cas_sess.<session ticket> file created in a prior call to
399
+ # #store_service_session_lookup.
400
+ def read_service_session_lookup(st)
401
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
402
+ ssl_filename = filename_of_service_session_lookup(st)
403
+ return File.exists?(ssl_filename) && IO.read(ssl_filename)
404
+ end
405
+
406
+ # Removes a stored relationship between a ServiceTicket and a local
407
+ # Rails session id. This should be called when the session is being
408
+ # closed.
409
+ #
410
+ # See #store_service_session_lookup.
411
+ def delete_service_session_lookup(st)
412
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
413
+ ssl_filename = filename_of_service_session_lookup(st)
414
+ File.delete(ssl_filename) if File.exists?(ssl_filename)
415
+ end
416
+
417
+ # Returns the path and filename of the service session lookup file.
418
+ def filename_of_service_session_lookup(st)
419
+ st = st.ticket if st.kind_of? CASClient::ServiceTicket
420
+ return "#{Rails.root}/tmp/sessions/cas_sess.#{st}"
421
+ end
422
+ end
423
+ end
424
+
425
+ class GatewayFilter < Filter
426
+ def self.use_gatewaying?
427
+ return true unless @@config[:use_gatewaying] == false
428
+ end
429
+ end
430
+ end
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{rubycas-client-rails-vpsa}
3
+ s.version = "0.1.1"
4
+
5
+ s.authors = ["VPSA"]
6
+ s.date = %q{2012-11-21}
7
+ s.description = %q{Cliente CAS para a VPSA.}
8
+ s.summary = %q{Adaptacao do rubycas-client-rails para a VPSA.}
9
+ s.email = %q{suporte at vpsa dot com dot br}
10
+ s.files = `git ls-files`.split("\n")
11
+ s.homepage = %q{http://rubycas-client.rubyforge.org}
12
+ s.rdoc_options = ["--main", "README.txt"]
13
+ s.require_paths = ["lib"]
14
+ s.rubyforge_project = %q{rubycas-client}
15
+
16
+ s.add_dependency('rails', '>= 3.0.0')
17
+ s.add_dependency('rubycas-client', '~> 2.3.9.rc1')
18
+ end
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubycas-client-rails-vpsa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - VPSA
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rubycas-client
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 2.3.9.rc1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 2.3.9.rc1
46
+ description: Cliente CAS para a VPSA.
47
+ email: suporte at vpsa dot com dot br
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .project
53
+ - MIT-LICENSE
54
+ - README.markdown
55
+ - Rakefile
56
+ - init.rb
57
+ - install.rb
58
+ - lib/rubycas-client-rails-vpsa.rb
59
+ - rubycas-client-rails-vpsa-0.1.1.gem
60
+ - rubycas-client-rails-vpsa.gemspec
61
+ - uninstall.rb
62
+ homepage: http://rubycas-client.rubyforge.org
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --main
67
+ - README.txt
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project: rubycas-client
84
+ rubygems_version: 1.8.23
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Adaptacao do rubycas-client-rails para a VPSA.
88
+ test_files: []