crowd_rails 0.5.11
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +88 -0
- data/Rakefile +62 -0
- data/VERSION +2 -0
- data/crowd_rails.gemspec +54 -0
- data/lib/crowd_rails.rb +1 -0
- data/lib/single_sign_on.rb +183 -0
- data/test/helper.rb +8 -0
- metadata +92 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Stefan Wille
|
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.rdoc
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
= crowd_rails
|
2
|
+
|
3
|
+
Single sign on (SSO) with Atlassian Crowd 2.0 for Ruby on Rails.
|
4
|
+
|
5
|
+
|
6
|
+
== INSTALL:
|
7
|
+
|
8
|
+
sudo gem install crowd_rails
|
9
|
+
|
10
|
+
== REQUIREMENTS:
|
11
|
+
|
12
|
+
* gem crowd-stefanwille
|
13
|
+
* soap4r[http://dev.ctor.org/soap4r] v1.5.8
|
14
|
+
* Atlassian Crowd v2.0
|
15
|
+
* Ruby v1.8.6 (or later)
|
16
|
+
* Rails 2.3.8 (or later)
|
17
|
+
|
18
|
+
== USE:
|
19
|
+
|
20
|
+
Add a file config/initializers/crowd_setup.rb and configure:
|
21
|
+
|
22
|
+
require 'crowd'
|
23
|
+
|
24
|
+
Crowd.crowd_url = 'http://127.0.0.1:8095/crowd/services/SecurityServer'
|
25
|
+
Crowd.crowd_app_name = 'soaptest'
|
26
|
+
Crowd.crowd_app_pword = 'soaptest'
|
27
|
+
Crowd.crowd_validation_factors_need_user_agent = false # false for Crowd 2.0.5, true for Crowd 2.0.2
|
28
|
+
Crowd.crowd_session_validationinterval = 0 # Set > 0 for authentication caching.
|
29
|
+
|
30
|
+
Then add this to your ApplicationController class:
|
31
|
+
|
32
|
+
class ApplicationController < ActionController::Base
|
33
|
+
include Crowd::SingleSignOn
|
34
|
+
|
35
|
+
...
|
36
|
+
before_filter :authenticate
|
37
|
+
|
38
|
+
private
|
39
|
+
def authenticate
|
40
|
+
return if RAILS_ENV == "test"
|
41
|
+
|
42
|
+
return if crowd_authenticated?
|
43
|
+
|
44
|
+
authenticate_or_request_with_http_basic('My Application') do |user_name, password|
|
45
|
+
crowd_authenticate(user_name, password)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
This will give you the usual gray password box (aka 'basic auth').
|
51
|
+
Replace Rails' the call to authenticate_or_request_with_http_basic()
|
52
|
+
that asks the user for username and password if you want some fancier.
|
53
|
+
|
54
|
+
There is an example Rails app at http://github.com/stefanwille/crowd_rails_test that implements this approach.
|
55
|
+
|
56
|
+
Assumptions (used above):
|
57
|
+
|
58
|
+
* Crowd Server is on localhost, port 8095
|
59
|
+
* There is an application configured in Crowd with name and password 'soaptest'
|
60
|
+
* Application 'soaptest' directory set to 'True'
|
61
|
+
|
62
|
+
== FEATURES:
|
63
|
+
|
64
|
+
* Interoperable single sign on with Atlassian Crowd 2.0.2 and 2.0.5.
|
65
|
+
* Can be configured for authentication caching.
|
66
|
+
|
67
|
+
Available methods in module Crowd::SingleSignOn:
|
68
|
+
* crowd_authenticated? - Returns whether the user is already authenticated.
|
69
|
+
* crowd_authenticate(user_name, password) - Authenticates the user with the given user name and password and marks the user as authenticated on success.
|
70
|
+
* crowd_authenticate!(user_name, password) - Same as #crowd_authenticate, but raises an AuthenticationException on failure.
|
71
|
+
* crowd_current_user_display_name - Returns the current users display name.
|
72
|
+
* crowd_current_user - Returns the current user, as seen by crowd.
|
73
|
+
* crowd_token - Returns the crowd token or nil.
|
74
|
+
* crowd_log_out - Logs the user out
|
75
|
+
|
76
|
+
== Note on Patches/Pull Requests
|
77
|
+
|
78
|
+
* Fork the project.
|
79
|
+
* Make your feature addition or bug fix.
|
80
|
+
* Add tests for it. This is important so I don't break it in a
|
81
|
+
future version unintentionally.
|
82
|
+
* Commit, do not mess with rakefile, version, or history.
|
83
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
84
|
+
* Send me a pull request. Bonus points for topic branches.
|
85
|
+
|
86
|
+
== Copyright
|
87
|
+
|
88
|
+
Copyright (c) 2010 Stefan Wille. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "crowd_rails"
|
8
|
+
gem.summary = %Q{Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails}
|
9
|
+
gem.description = %Q{Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails}
|
10
|
+
gem.email = "post @nospam@ stefanwille.com"
|
11
|
+
gem.homepage = "http://github.com/stefanwille/crowd_rails"
|
12
|
+
gem.authors = ["Stefan Wille"]
|
13
|
+
gem.add_dependency "crowd-stefanwille", "= 0.5.11"
|
14
|
+
# Silence a warning about missing rubyforge_project
|
15
|
+
gem.rubyforge_project = "nowarning"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
def version
|
24
|
+
File.exist?('VERSION') ? File.read('VERSION') : ""
|
25
|
+
end
|
26
|
+
|
27
|
+
task :push => [:test, :build] do
|
28
|
+
system("gem push pkg/crowd_rails-#{version}.gem")
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'rake/testtask'
|
32
|
+
Rake::TestTask.new(:test) do |test|
|
33
|
+
test.libs << 'lib' << 'test'
|
34
|
+
test.pattern = 'test/**/test_*.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'rcov/rcovtask'
|
40
|
+
Rcov::RcovTask.new do |test|
|
41
|
+
test.libs << 'test'
|
42
|
+
test.pattern = 'test/**/test_*.rb'
|
43
|
+
test.verbose = true
|
44
|
+
end
|
45
|
+
rescue LoadError
|
46
|
+
task :rcov do
|
47
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
task :test => :check_dependencies
|
52
|
+
|
53
|
+
task :default => :test
|
54
|
+
|
55
|
+
require 'rake/rdoctask'
|
56
|
+
Rake::RDocTask.new do |rdoc|
|
57
|
+
rdoc.rdoc_dir = 'rdoc'
|
58
|
+
rdoc.title = "crowd_rails #{version}"
|
59
|
+
rdoc.rdoc_files.include('README*')
|
60
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
61
|
+
end
|
62
|
+
|
data/VERSION
ADDED
data/crowd_rails.gemspec
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{crowd_rails}
|
8
|
+
s.version = "0.5.11"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Stefan Wille"]
|
12
|
+
s.date = %q{2010-07-27}
|
13
|
+
s.description = %q{Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails}
|
14
|
+
s.email = %q{post @nospam@ stefanwille.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"crowd_rails.gemspec",
|
27
|
+
"lib/crowd_rails.rb",
|
28
|
+
"lib/single_sign_on.rb",
|
29
|
+
"test/helper.rb"
|
30
|
+
]
|
31
|
+
s.homepage = %q{http://github.com/stefanwille/crowd_rails}
|
32
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
33
|
+
s.require_paths = ["lib"]
|
34
|
+
s.rubyforge_project = %q{nowarning}
|
35
|
+
s.rubygems_version = %q{1.3.7}
|
36
|
+
s.summary = %q{Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails}
|
37
|
+
s.test_files = [
|
38
|
+
"test/helper.rb"
|
39
|
+
]
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_runtime_dependency(%q<crowd-stefanwille>, ["= 0.5.11"])
|
47
|
+
else
|
48
|
+
s.add_dependency(%q<crowd-stefanwille>, ["= 0.5.11"])
|
49
|
+
end
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<crowd-stefanwille>, ["= 0.5.11"])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
data/lib/crowd_rails.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'single_sign_on')
|
@@ -0,0 +1,183 @@
|
|
1
|
+
class Crowd
|
2
|
+
|
3
|
+
# The single sign on (SSO) functionality for Atlassian Crowd as a mixin module.
|
4
|
+
#
|
5
|
+
# To use this module, include it in your Rails ApplicationController class.
|
6
|
+
# The module uses controller methods such as cookies, session, params.
|
7
|
+
#
|
8
|
+
# Author:: Stefan Wille
|
9
|
+
# Copyright:: Copyright (c) 2010 Stefan Wille
|
10
|
+
# License:: BSD
|
11
|
+
|
12
|
+
module SingleSignOn
|
13
|
+
|
14
|
+
# Returns whether the user is already authenticated.
|
15
|
+
def crowd_authenticated?
|
16
|
+
logger.info "Crowd: All cookies: #{cookies.inspect}"
|
17
|
+
|
18
|
+
token = crowd_token
|
19
|
+
if token.blank?
|
20
|
+
logger.info "Crowd: No token"
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
|
24
|
+
if crowd_authentication_cached?
|
25
|
+
logger.info "Crowd: Authentication is cached"
|
26
|
+
return true
|
27
|
+
else
|
28
|
+
logger.info "Crowd: Authentication is not cached"
|
29
|
+
end
|
30
|
+
|
31
|
+
if Crowd.is_valid_principal_token?(token, crowd_validation_factors)
|
32
|
+
logger.info "Crowd: Token is valid"
|
33
|
+
crowd_mark_session_as_authenticated(token)
|
34
|
+
return true
|
35
|
+
else
|
36
|
+
logger.info "Crowd: Token is invalid"
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Authenticates the user with the given user name and password and
|
42
|
+
# marks the user as authenticated on success.
|
43
|
+
#
|
44
|
+
# Returns the crowd token on success, false on failure.
|
45
|
+
|
46
|
+
def crowd_authenticate(user_name, password)
|
47
|
+
crowd_authenticate!(user_name, password)
|
48
|
+
rescue Crowd::AuthenticationException => e
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
# Same as #crowd_authenticate, but raises an AuthenticationException on failure.
|
53
|
+
|
54
|
+
def crowd_authenticate!(user_name, password)
|
55
|
+
logger.info "Crowd: Authenticating user #{user_name}"
|
56
|
+
token = Crowd.authenticate_principal(user_name, password, crowd_validation_factors)
|
57
|
+
crowd_mark_session_as_authenticated(token)
|
58
|
+
logger.info "Crowd: Authentication successful, token #{token}"
|
59
|
+
token
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns the current users display name.
|
63
|
+
|
64
|
+
def crowd_current_user_display_name
|
65
|
+
user = crowd_current_user
|
66
|
+
user && user[:attributes][:displayName]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the current user, as seen by crowd.
|
70
|
+
|
71
|
+
def crowd_current_user
|
72
|
+
crowd_token && Crowd.find_principal_by_token(crowd_token)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the crowd token or nil.
|
76
|
+
|
77
|
+
def crowd_token
|
78
|
+
logger.info "params token: #{params[Crowd.crowd_cookie_tokenkey]}"
|
79
|
+
logger.info "cookies token: #{cookies[Crowd.crowd_cookie_tokenkey]}"
|
80
|
+
logger.info "session token: #{session[Crowd.crowd_session_tokenkey]}"
|
81
|
+
token = params[Crowd.crowd_cookie_tokenkey] || cookies[Crowd.crowd_cookie_tokenkey] || session[Crowd.crowd_session_tokenkey]
|
82
|
+
logger.info "token = #{token}"
|
83
|
+
token
|
84
|
+
end
|
85
|
+
|
86
|
+
# Marks the user as unauthenticated
|
87
|
+
|
88
|
+
def crowd_log_out
|
89
|
+
logger.info "Crowd: log out"
|
90
|
+
crowd_update_token(nil)
|
91
|
+
crowd_clear_cache
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# Returns the client's validation factors.
|
97
|
+
# Validation factors are essential for interoperation with Atlassian's client library!
|
98
|
+
|
99
|
+
def crowd_validation_factors
|
100
|
+
validation_factors = { 'remote_address' => crowd_remote_address }
|
101
|
+
|
102
|
+
if Crowd.crowd_validation_factors_need_user_agent
|
103
|
+
validation_factors['User-Agent'] = crowd_user_agent
|
104
|
+
end
|
105
|
+
|
106
|
+
forwarded_for = request.env['X-Forwarded-For']
|
107
|
+
if forwarded_for.present? && forwarded_for != request.remote_ip
|
108
|
+
validation_factors['X-Forwarded-For'] = forwarded_for
|
109
|
+
end
|
110
|
+
|
111
|
+
logger.info "Crowd validation_factors: #{validation_factors.inspect}"
|
112
|
+
|
113
|
+
validation_factors
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns the client's IP address.
|
117
|
+
|
118
|
+
def crowd_remote_address
|
119
|
+
# For localhost, Crowd wants the IPv6 address.
|
120
|
+
(request.remote_ip == '127.0.0.1' || request.remote_ip == '0.0.0.0') ? '0:0:0:0:0:0:0:1%0' : request.remote_ip
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
# Returns the client's user agent.
|
125
|
+
|
126
|
+
def crowd_user_agent
|
127
|
+
request.env['HTTP_USER_AGENT']
|
128
|
+
end
|
129
|
+
|
130
|
+
# Whether a successful authentication is in cache.
|
131
|
+
|
132
|
+
def crowd_authentication_cached?
|
133
|
+
last_validation = session[Crowd.crowd_session_lastvalidation]
|
134
|
+
|
135
|
+
if last_validation.present? && crowd_caching_enabled?
|
136
|
+
time_diff = crowd_time_diff_in_minutes(Time.now, last_validation)
|
137
|
+
return time_diff < Crowd.crowd_session_validationinterval
|
138
|
+
else
|
139
|
+
return false
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Marks the session as successfully authenticated and sets the SSO cookie.
|
144
|
+
|
145
|
+
def crowd_mark_session_as_authenticated(token)
|
146
|
+
crowd_update_token(token)
|
147
|
+
if crowd_caching_enabled?
|
148
|
+
logger.info "Crowd: Caching authentication"
|
149
|
+
session[Crowd.crowd_session_lastvalidation] = Time.now
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def crowd_update_token(token)
|
154
|
+
session[Crowd.crowd_session_tokenkey] = token
|
155
|
+
cookies[Crowd.crowd_cookie_tokenkey] = { :value => token, :domain => crowd_cookie_domain, :path => "/", :secure => Crowd.get_cookie_info.secure }
|
156
|
+
end
|
157
|
+
|
158
|
+
def crowd_clear_cache
|
159
|
+
session[Crowd.crowd_session_lastvalidation] = nil
|
160
|
+
end
|
161
|
+
|
162
|
+
def crowd_cookie_domain
|
163
|
+
cookie_domain = Crowd.get_cookie_info.domain
|
164
|
+
if cookie_domain
|
165
|
+
cookie_domain
|
166
|
+
else
|
167
|
+
request.domain ? '.' + request.domain : nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns the difference between two timestamps in minutes.
|
172
|
+
def crowd_time_diff_in_minutes(first_time, second_time)
|
173
|
+
(first_time - second_time).round / 1.minute
|
174
|
+
end
|
175
|
+
|
176
|
+
# Whether caching of successful authentication is enabled.
|
177
|
+
def crowd_caching_enabled?
|
178
|
+
Crowd.crowd_session_validationinterval > 0
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crowd_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 11
|
10
|
+
version: 0.5.11
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Stefan Wille
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-27 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: crowd-stefanwille
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - "="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 29
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 5
|
33
|
+
- 11
|
34
|
+
version: 0.5.11
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails
|
38
|
+
email: post @nospam@ stefanwille.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- LICENSE
|
45
|
+
- README.rdoc
|
46
|
+
files:
|
47
|
+
- .document
|
48
|
+
- .gitignore
|
49
|
+
- LICENSE
|
50
|
+
- README.rdoc
|
51
|
+
- Rakefile
|
52
|
+
- VERSION
|
53
|
+
- crowd_rails.gemspec
|
54
|
+
- lib/crowd_rails.rb
|
55
|
+
- lib/single_sign_on.rb
|
56
|
+
- test/helper.rb
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: http://github.com/stefanwille/crowd_rails
|
59
|
+
licenses: []
|
60
|
+
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options:
|
63
|
+
- --charset=UTF-8
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 3
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
requirements: []
|
85
|
+
|
86
|
+
rubyforge_project: nowarning
|
87
|
+
rubygems_version: 1.3.7
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: Single Sign On for Atlassian Crowd 2.0 with Ruby on Rails
|
91
|
+
test_files:
|
92
|
+
- test/helper.rb
|