authlogic_crowd 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +26 -0
- data/Gemfile +4 -0
- data/README.rdoc +14 -0
- data/Rakefile +21 -0
- data/authlogic_crowd.gemspec +47 -0
- data/lib/authlogic_crowd/acts_as_authentic.rb +134 -0
- data/lib/authlogic_crowd/acts_as_authentic_callbacks.rb +26 -0
- data/lib/authlogic_crowd/session.rb +285 -0
- data/lib/authlogic_crowd/session_callbacks.rb +19 -0
- data/lib/authlogic_crowd/version.rb +3 -0
- data/lib/authlogic_crowd.rb +9 -0
- data/test/helper.rb +13 -0
- data/test/test_authlogic_crowd.rb +7 -0
- metadata +162 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## PROJECT::GENERAL
|
17
|
+
coverage
|
18
|
+
rdoc
|
19
|
+
doc
|
20
|
+
pkg
|
21
|
+
.bundle
|
22
|
+
.idea
|
23
|
+
.yardoc
|
24
|
+
|
25
|
+
## PROJECT::SPECIFIC
|
26
|
+
Gemfile.lock
|
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
= authlogic_crowd
|
2
|
+
|
3
|
+
Incomplete Authlogic plugin for Atlassian Crowd ( do not use )
|
4
|
+
Description goes here.
|
5
|
+
|
6
|
+
== Note on Patches/Pull Requests
|
7
|
+
|
8
|
+
* Fork the project.
|
9
|
+
* Make your feature addition or bug fix.
|
10
|
+
* Add tests for it. This is important so I don't break it in a
|
11
|
+
future version unintentionally.
|
12
|
+
* Commit, do not mess with rakefile, version, or history.
|
13
|
+
(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)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'bundler'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
desc 'Run tests for InheritedResources.'
|
8
|
+
Rake::TestTask.new(:test) do |t|
|
9
|
+
t.pattern = 'test/**/*_test.rb'
|
10
|
+
t.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Generate documentation for InheritedResources.'
|
14
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'InheritedResources'
|
17
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
18
|
+
rdoc.rdoc_files.include('README.rdoc')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
$:.push File.expand_path("../lib",__FILE__)
|
2
|
+
require 'authlogic_crowd/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = %q{authlogic_crowd}
|
6
|
+
s.version = AuthlogicCrowd::VERSION.dup
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
s.authors = ["Paul Strong"]
|
10
|
+
s.description = %q{Authlogic Crowd}
|
11
|
+
s.email = %q{paul@thestrongfamily.org}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"README.rdoc"
|
14
|
+
]
|
15
|
+
s.files = %w(
|
16
|
+
.document
|
17
|
+
.gitignore
|
18
|
+
Gemfile
|
19
|
+
README.rdoc
|
20
|
+
Rakefile
|
21
|
+
authlogic_crowd.gemspec
|
22
|
+
lib/authlogic_crowd.rb
|
23
|
+
lib/authlogic_crowd/acts_as_authentic.rb
|
24
|
+
lib/authlogic_crowd/acts_as_authentic_callbacks.rb
|
25
|
+
lib/authlogic_crowd/session.rb
|
26
|
+
lib/authlogic_crowd/session_callbacks.rb
|
27
|
+
lib/authlogic_crowd/version.rb
|
28
|
+
test/helper.rb
|
29
|
+
test/test_authlogic_crowd.rb
|
30
|
+
)
|
31
|
+
s.test_files = %w(
|
32
|
+
test/helper.rb
|
33
|
+
test/test_authlogic_crowd.rb
|
34
|
+
)
|
35
|
+
s.homepage = %q{http://github.com/lapluviosilla/authlogic_crowd}
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.7}
|
38
|
+
s.summary = %q{Atlassian Crowd support for Authlogic}
|
39
|
+
|
40
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
41
|
+
s.add_development_dependency(%q<fcoury-matchy>, [">= 0"])
|
42
|
+
s.add_development_dependency(%q<rr>, [">= 0"])
|
43
|
+
s.add_runtime_dependency(%q<authlogic>, [">= 2.1.3", "< 3.0.0"])
|
44
|
+
s.add_runtime_dependency(%q<simple_crowd>, [">= 1.0.0"])
|
45
|
+
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module ActsAsAuthentic
|
3
|
+
# Adds in the neccesary modules for acts_as_authentic to include and also disabled password validation if
|
4
|
+
# OpenID is being used.
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval do
|
7
|
+
extend Config
|
8
|
+
add_acts_as_authentic_module(Methods, :prepend)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
module Config
|
12
|
+
|
13
|
+
# **REQUIRED**
|
14
|
+
#
|
15
|
+
# Specify your crowd service url.
|
16
|
+
# @param [String] url to use when calling Crowd
|
17
|
+
def crowd_service_url(url=nil)
|
18
|
+
rw_config(:crowd_service_url, url, "http://localhost:8095/crowd/services/SecurityServer")
|
19
|
+
end
|
20
|
+
alias_method :crowd_service_url=, :crowd_service_url
|
21
|
+
|
22
|
+
# **REQUIRED**
|
23
|
+
#
|
24
|
+
# Specify your crowd app name.
|
25
|
+
# @param [String] name of app to use when calling Crowd
|
26
|
+
def crowd_app_name(name=nil)
|
27
|
+
rw_config(:crowd_app_name, name, nil)
|
28
|
+
end
|
29
|
+
alias_method :crowd_app_name=, :crowd_app_name
|
30
|
+
|
31
|
+
# **REQUIRED**
|
32
|
+
#
|
33
|
+
# Specify your crowd app password.
|
34
|
+
# @param [String] password Plain-text password for crowd app validation
|
35
|
+
def crowd_app_password(password=nil)
|
36
|
+
rw_config(:crowd_app_password, password, nil)
|
37
|
+
end
|
38
|
+
alias_method :crowd_app_password=, :crowd_app_password
|
39
|
+
|
40
|
+
def crowd_user_token_field(value = nil)
|
41
|
+
rw_config(:crowd_user_token_field, value, :crowd_user_token)
|
42
|
+
end
|
43
|
+
alias_method :crowd_user_token_field=, :crowd_user_token_field
|
44
|
+
|
45
|
+
end
|
46
|
+
module Methods
|
47
|
+
def self.included(klass)
|
48
|
+
klass.class_eval do
|
49
|
+
validate_on_create :must_have_unique_crowd_login
|
50
|
+
|
51
|
+
# TODO: Cleanup and refactor into callbacks
|
52
|
+
def create
|
53
|
+
if using_crowd? && !crowd_record
|
54
|
+
crowd_user = self.create_crowd_user
|
55
|
+
if crowd_user
|
56
|
+
# Crowd is going to store password so clear them from local object
|
57
|
+
self.clear_passwords
|
58
|
+
result = super
|
59
|
+
# Delete crowd user if local creation failed
|
60
|
+
crowd_client.delete_user crowd_user.user unless result
|
61
|
+
if result
|
62
|
+
user_token = crowd_client.create_user_token crowd_user.username
|
63
|
+
session_class.crowd_user_token = user_token unless
|
64
|
+
session_class.controller && session_class.controller.session[:"crowd.token_key"]
|
65
|
+
end
|
66
|
+
return result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
super
|
70
|
+
end
|
71
|
+
validates_length_of_password_field_options validates_length_of_password_field_options.merge(:on => :create)
|
72
|
+
validates_confirmation_of_password_field_options validates_confirmation_of_password_field_options.merge(:on => :create)
|
73
|
+
validates_length_of_password_confirmation_field_options validates_length_of_password_confirmation_field_options.merge(:on => :create)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_accessor :crowd_record
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def create_crowd_user
|
82
|
+
return unless self.login && @password
|
83
|
+
self.crowd_record = SimpleCrowd::User.new({:username => self.login})
|
84
|
+
sync_on_create
|
85
|
+
crowd_client.add_user self.crowd_record, @password
|
86
|
+
end
|
87
|
+
|
88
|
+
def clear_passwords
|
89
|
+
@password = nil
|
90
|
+
@password_changed = false
|
91
|
+
send("#{self.class.crypted_password_field}=", nil) if self.class.crypted_password_field
|
92
|
+
send("#{self.class.password_salt_field}=", nil) if self.class.password_salt_field
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def must_have_unique_crowd_login
|
98
|
+
login = send(self.class.login_field)
|
99
|
+
crowd_user = crowd_client.find_user_by_name(login)
|
100
|
+
errors.add(self.class.login_field, "is already taken") unless crowd_user.nil? || !errors.on(self.class.login_field).nil?
|
101
|
+
end
|
102
|
+
|
103
|
+
def crowd_client
|
104
|
+
@crowd_client ||= SimpleCrowd::Client.new(crowd_config)
|
105
|
+
end
|
106
|
+
def load_crowd_app_token
|
107
|
+
cached_token = Rails.cache.read('crowd_app_token')
|
108
|
+
crowd_client.app_token = cached_token unless cached_token.nil?
|
109
|
+
Rails.cache.write('crowd_app_token', crowd_client.app_token) unless cached_token == crowd_client.app_token
|
110
|
+
end
|
111
|
+
def crowd_cookie_info
|
112
|
+
unless @crowd_cookie_info
|
113
|
+
cached_info = Rails.cache.read('crowd_cookie_info')
|
114
|
+
@crowd_cookie_info ||= cached_info || crowd_client.get_cookie_info
|
115
|
+
Rails.cache.write('crowd_cookie_info', @crowd_cookie_info) unless cached_info == @crowd_cookie_info
|
116
|
+
end
|
117
|
+
@crowd_cookie_info
|
118
|
+
end
|
119
|
+
def crowd_config
|
120
|
+
{:service_url => self.class.crowd_service_url,
|
121
|
+
:app_name => self.class.crowd_app_name,
|
122
|
+
:app_password => self.class.crowd_app_password}
|
123
|
+
end
|
124
|
+
|
125
|
+
def using_crowd?
|
126
|
+
!(self.class.crowd_app_name.nil? || self.class.crowd_app_password.nil? || self.class.crowd_service_url.nil?)
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate_password_with_crowd?
|
130
|
+
#!using_crowd? && require_password?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module ActsAsAuthenticCallbacks
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
add_acts_as_authentic_module(Methods, :prepend)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
module Methods
|
9
|
+
METHODS = [
|
10
|
+
"sync_on_create"
|
11
|
+
]
|
12
|
+
def self.included(base)
|
13
|
+
base.send :include, ActiveSupport::Callbacks
|
14
|
+
base.define_callbacks *METHODS
|
15
|
+
end
|
16
|
+
private
|
17
|
+
METHODS.each do |method|
|
18
|
+
class_eval <<-"end_eval", __FILE__, __LINE__
|
19
|
+
def #{method}
|
20
|
+
run_callbacks(:#{method}) { |result, object| result == false }
|
21
|
+
end
|
22
|
+
end_eval
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module Session
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
extend Config
|
6
|
+
include Methods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
module Config
|
10
|
+
|
11
|
+
# Single Signout (defaults to true)
|
12
|
+
# @param [Boolean] value
|
13
|
+
def crowd_sso(value=nil)
|
14
|
+
rw_config(:crowd_sso, value, true)
|
15
|
+
end
|
16
|
+
alias_method :crowd_sso=, :crowd_sso
|
17
|
+
|
18
|
+
def crowd_sso?
|
19
|
+
crowd_sso
|
20
|
+
end
|
21
|
+
|
22
|
+
# Auto Register is enabled by default.
|
23
|
+
# Add this in your Session object if you need to disable auto-registration via crowd
|
24
|
+
def auto_register(value=true)
|
25
|
+
auto_register_value(value)
|
26
|
+
end
|
27
|
+
def auto_register_value(value=nil)
|
28
|
+
rw_config(:auto_register,value,true)
|
29
|
+
end
|
30
|
+
alias_method :auto_register=,:auto_register
|
31
|
+
|
32
|
+
def crowd_user_token= token
|
33
|
+
session_user_token = controller && controller.session[:"crowd.token_key"]
|
34
|
+
cookie_user_token = crowd_sso? && controller && controller.cookies[:"crowd.token_key"]
|
35
|
+
cached_info = Rails.cache.read('crowd_cookie_info')
|
36
|
+
@crowd_client ||= SimpleCrowd::Client.new({
|
37
|
+
:service_url => klass.crowd_service_url,
|
38
|
+
:app_name => klass.crowd_app_name,
|
39
|
+
:app_password => klass.crowd_app_password})
|
40
|
+
crowd_cookie_info ||= cached_info || @crowd_client.get_cookie_info
|
41
|
+
controller.session[:"crowd.token_key"] = token unless session_user_token == token || !controller
|
42
|
+
controller.cookies[:"crowd.token_key"] = {:domain => crowd_cookie_info[:domain],
|
43
|
+
:secure => crowd_cookie_info[:secure],
|
44
|
+
:value => token} unless cookie_user_token == token || !crowd_sso? || !controller
|
45
|
+
end
|
46
|
+
def crowd_user_token
|
47
|
+
controller && (controller.params["crowd.token_key"] || controller.cookies[:"crowd.token_key"] || controller.session[:"crowd.token_key"])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
module Methods
|
51
|
+
def self.included(klass)
|
52
|
+
klass.class_eval do
|
53
|
+
attr_accessor :new_registration
|
54
|
+
validate :validate_by_crowd, :if => :authenticating_with_crowd?
|
55
|
+
persist :validate_by_crowd, :if => :authenticating_with_crowd?
|
56
|
+
after_create :sync_with_crowd, :if => :authenticating_with_crowd?
|
57
|
+
before_destroy :logout_of_crowd, :if => [:authenticating_with_crowd?, :sso?]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Temporary storage of crowd record for syncing purposes
|
62
|
+
attr_accessor :crowd_record
|
63
|
+
|
64
|
+
# Determines if the authenticated user is also a new registration.
|
65
|
+
# For use in the session controller to help direct the most appropriate action to follow.
|
66
|
+
def new_registration?
|
67
|
+
new_registration || !new_registration.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Determines if the authenticated user has a complete registration (no validation errors)
|
71
|
+
# For use in the session controller to help direct the most appropriate action to follow.
|
72
|
+
def registration_complete?
|
73
|
+
attempted_record && attempted_record.valid?
|
74
|
+
end
|
75
|
+
|
76
|
+
def auto_register?
|
77
|
+
self.class.auto_register_value
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
# Determines whether to use crowd to authenticate and validate the current request
|
83
|
+
# For now we assume the app wants to use Crowd exclusively.
|
84
|
+
# Use crowd authentication if tokens are present or if login/password is available but not valid or is blank in db
|
85
|
+
# TODO: Add flexibility regarding multiple authentication methods and identity mapping
|
86
|
+
def authenticating_with_crowd?
|
87
|
+
errors.empty? &&
|
88
|
+
!klass.crowd_app_name.blank? &&
|
89
|
+
!klass.crowd_app_password.blank? &&
|
90
|
+
((login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)) ||
|
91
|
+
controller && (controller.cookies[:"crowd.token_key"] || controller.session[:"crowd.token_key"] || controller.params["crowd.token_key"]))
|
92
|
+
end
|
93
|
+
|
94
|
+
def authenticating_with_password?
|
95
|
+
!authenticating_with_crowd? && login_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
96
|
+
end
|
97
|
+
|
98
|
+
def sso?
|
99
|
+
self.class.crowd_sso
|
100
|
+
end
|
101
|
+
|
102
|
+
# def credentials
|
103
|
+
# if authenticating_with_crowd?
|
104
|
+
# details = {}
|
105
|
+
# details[login_field.to_sym] = send(login_field)
|
106
|
+
# details[password_field.to_sym] = "<protected>"
|
107
|
+
# details[crowd_user_token_field.to_sym] = send(crowd_user_token_field)
|
108
|
+
# details
|
109
|
+
# else
|
110
|
+
# super
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
|
114
|
+
def credentials=(value)
|
115
|
+
super
|
116
|
+
values = value.is_a?(Array) ? value : [value]
|
117
|
+
if values.first.is_a?(Hash)
|
118
|
+
values.first.with_indifferent_access.slice(login_field, password_field).each do |field, value|
|
119
|
+
next if value.blank?
|
120
|
+
send("#{field}=", value)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
# Main session validation using Crowd user token.
|
128
|
+
# Uses simple_crowd to verify the user token on the configured crowd server
|
129
|
+
# If no *local* user is found and auto_register is enabled (default) then automatically create *local* user for them
|
130
|
+
# TODO: Cleanup and figure out reason for duplicate calls
|
131
|
+
def validate_by_crowd
|
132
|
+
begin
|
133
|
+
load_crowd_app_token
|
134
|
+
login = send(login_field) || (unauthorized_record && unauthorized_record.login)
|
135
|
+
password = send("protected_#{password_field}")
|
136
|
+
params_user_token = controller && controller.params["crowd.token_key"]
|
137
|
+
session_user_token = controller && controller.session[:"crowd.token_key"]
|
138
|
+
cookie_user_token = sso? && controller && controller.cookies[:"crowd.token_key"]
|
139
|
+
user_token = crowd_user_token
|
140
|
+
crowd_user = nil
|
141
|
+
|
142
|
+
# Lets see if the user passed in an email or a login using the db
|
143
|
+
if !login.blank? && self.unauthorized_record.nil?
|
144
|
+
self.unauthorized_record = klass.respond_to?(:login_or_email_equals) ?
|
145
|
+
klass.send(:login_or_email_equals, login).first :
|
146
|
+
klass.send("find_by_#{login_field}", login)
|
147
|
+
# If passed in login equals the user email then get the REAL login used by crowd instead
|
148
|
+
login = unauthorized_record.login if !unauthorized_record.nil? && login = unauthorized_record.email
|
149
|
+
end
|
150
|
+
|
151
|
+
if user_token && crowd_client.is_valid_user_token?(user_token)
|
152
|
+
elsif login && password
|
153
|
+
# Authenticate if we don't have token
|
154
|
+
user_token = crowd_client.authenticate_user login, password rescue nil
|
155
|
+
|
156
|
+
# Try one last time to login with crowd email field instead of login
|
157
|
+
if user_token.nil? && self.unauthorized_record.nil? && login =~ Authlogic::Regex.email
|
158
|
+
crowd_user ||= crowd_client.find_user_by_email(login)
|
159
|
+
if crowd_user
|
160
|
+
login = crowd_user.username
|
161
|
+
user_token = crowd_client.authenticate_user login, password rescue nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
else
|
165
|
+
user_token = nil
|
166
|
+
end
|
167
|
+
|
168
|
+
raise "No user token" if user_token.blank?
|
169
|
+
|
170
|
+
login = crowd_client.find_username_by_token user_token unless login &&
|
171
|
+
(!cookie_user_token || session_user_token == cookie_user_token) &&
|
172
|
+
(!params_user_token || session_user_token == params_user_token)
|
173
|
+
send("#{login_field}=", login)
|
174
|
+
|
175
|
+
self.class.crowd_user_token = user_token
|
176
|
+
|
177
|
+
if !self.unauthorized_record.nil? && self.unauthorized_record.login == login
|
178
|
+
self.attempted_record = self.unauthorized_record
|
179
|
+
else
|
180
|
+
self.attempted_record = self.unauthorized_record = klass.send(:"find_by_#{login_field}", login)
|
181
|
+
end
|
182
|
+
|
183
|
+
if !attempted_record
|
184
|
+
# If auto_register enabled then create new user with crowd info
|
185
|
+
if auto_register?
|
186
|
+
crowd_user ||= crowd_client.find_user_by_token user_token
|
187
|
+
self.attempted_record = klass.new :login => crowd_user.username, :email => crowd_user.email
|
188
|
+
self.new_registration = true
|
189
|
+
self.attempted_record.crowd_record = crowd_user
|
190
|
+
self.crowd_record = crowd_user
|
191
|
+
sync
|
192
|
+
self.attempted_record.save_without_session_maintenance
|
193
|
+
else
|
194
|
+
errors.add_to_base("We did not find any accounts with that login. Enter your details and create an account.")
|
195
|
+
return false
|
196
|
+
end
|
197
|
+
end
|
198
|
+
rescue Exception => e
|
199
|
+
errors.add_to_base("Authentication failed. Please try again")
|
200
|
+
# Don't know why it doesn't work the first time,
|
201
|
+
# but if we nil the session key here then the session doesn't get deleted
|
202
|
+
# Leaving the token triggers the validation a second time and successfully destroys the session
|
203
|
+
# REMOVED AS HACK
|
204
|
+
# Hack to fix user_credentials not being deleted on session destroy
|
205
|
+
|
206
|
+
if controller
|
207
|
+
controller.session[:"crowd.token_key"] = nil
|
208
|
+
unless (send(login_field) || (unauthorized_record && unauthorized_record.login) && send("protected_#{password_field}"))
|
209
|
+
# Hack to try and check session without recreating it. (we only want to destroy it if it exists already)
|
210
|
+
# This is to avoid a infinite recursive session creation bug we had a while back
|
211
|
+
curr_klass = klass
|
212
|
+
curr_session = controller.instance_eval { @current_user_session }
|
213
|
+
curr_session.destroy if curr_session
|
214
|
+
controller.session.clear
|
215
|
+
end
|
216
|
+
# Delete by klass name instead of generic user
|
217
|
+
controller.cookies.delete :"#{klass.name.underscore}_credentials"
|
218
|
+
controller.cookies.delete :"crowd.token_key", :domain => crowd_cookie_info[:domain] if sso?
|
219
|
+
end
|
220
|
+
false
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def sync_with_crowd
|
225
|
+
# If it's a new registration then the crowd data was just pulled, so skip syncing on login
|
226
|
+
unless new_registration? || !self.attempted_record
|
227
|
+
login = send(login_field) || (!attempted_record.nil? && attempted_record.login)
|
228
|
+
user_token = controller && (controller.params["crowd.token_key"] || controller.cookies[:"crowd.token_key"] || controller.session[:"crowd.token_key"])
|
229
|
+
crowd_user = if login
|
230
|
+
crowd_client.find_user_by_name login
|
231
|
+
elsif user_token
|
232
|
+
crowd_client.find_user_by_token user_token
|
233
|
+
end
|
234
|
+
if crowd_user && before_sync
|
235
|
+
self.crowd_record = crowd_user
|
236
|
+
# Callbacks to sync data
|
237
|
+
sync
|
238
|
+
self.attempted_record.save
|
239
|
+
after_sync
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Single Sign-out
|
245
|
+
def logout_of_crowd
|
246
|
+
# Send an invalidate call for single signout
|
247
|
+
# Apparently there is no way of knowing if this was successful or not.
|
248
|
+
crowd_client.invalidate_user_token crowd_user_token unless crowd_user_token.nil?
|
249
|
+
# Remove cookie and session
|
250
|
+
if controller
|
251
|
+
controller.session[:"crowd.token_key"] = nil
|
252
|
+
controller.cookies.delete :"crowd.token_key", :domain => crowd_cookie_info[:domain] if sso?
|
253
|
+
controller.cookies.delete :"#{klass.name.underscore}_credentials"
|
254
|
+
end
|
255
|
+
true
|
256
|
+
end
|
257
|
+
|
258
|
+
|
259
|
+
def crowd_user_token
|
260
|
+
self.class.crowd_user_token
|
261
|
+
end
|
262
|
+
def crowd_client
|
263
|
+
@crowd_client ||= SimpleCrowd::Client.new(crowd_config)
|
264
|
+
end
|
265
|
+
def load_crowd_app_token
|
266
|
+
cached_token = Rails.cache.read('crowd_app_token')
|
267
|
+
crowd_client.app_token = cached_token unless cached_token.nil?
|
268
|
+
Rails.cache.write('crowd_app_token', crowd_client.app_token) unless cached_token == crowd_client.app_token
|
269
|
+
end
|
270
|
+
def crowd_cookie_info
|
271
|
+
unless @crowd_cookie_info
|
272
|
+
cached_info = Rails.cache.read('crowd_cookie_info')
|
273
|
+
@crowd_cookie_info ||= cached_info || crowd_client.get_cookie_info
|
274
|
+
Rails.cache.write('crowd_cookie_info', @crowd_cookie_info) unless cached_info == @crowd_cookie_info
|
275
|
+
end
|
276
|
+
@crowd_cookie_info
|
277
|
+
end
|
278
|
+
def crowd_config
|
279
|
+
{:service_url => klass.crowd_service_url,
|
280
|
+
:app_name => klass.crowd_app_name,
|
281
|
+
:app_password => klass.crowd_app_password}
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module SessionCallbacks
|
3
|
+
METHODS = [
|
4
|
+
"before_sync", "sync", "after_sync"
|
5
|
+
]
|
6
|
+
def self.included(base)
|
7
|
+
base.send :include, ActiveSupport::Callbacks
|
8
|
+
base.define_callbacks *METHODS
|
9
|
+
end
|
10
|
+
private
|
11
|
+
METHODS.each do |method|
|
12
|
+
class_eval <<-"end_eval", __FILE__, __LINE__
|
13
|
+
def #{method}
|
14
|
+
run_callbacks(:#{method}) { |result, object| result == false }
|
15
|
+
end
|
16
|
+
end_eval
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "authlogic_crowd/acts_as_authentic"
|
2
|
+
require "authlogic_crowd/session"
|
3
|
+
require "authlogic_crowd/session_callbacks"
|
4
|
+
require "authlogic_crowd/acts_as_authentic_callbacks"
|
5
|
+
|
6
|
+
ActiveRecord::Base.send(:include, AuthlogicCrowd::ActsAsAuthentic)
|
7
|
+
ActiveRecord::Base.send(:include, AuthlogicCrowd::ActsAsAuthenticCallbacks)
|
8
|
+
Authlogic::Session::Base.send(:include, AuthlogicCrowd::Session)
|
9
|
+
Authlogic::Session::Base.send(:include, AuthlogicCrowd::SessionCallbacks)
|
data/test/helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'matchy'
|
5
|
+
require 'rr'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
require 'authlogic_crowd'
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
include RR::Adapters::TestUnit
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: authlogic_crowd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Paul Strong
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-07-11 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: thoughtbot-shoulda
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: fcoury-matchy
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rr
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: authlogic
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 13
|
72
|
+
segments:
|
73
|
+
- 2
|
74
|
+
- 1
|
75
|
+
- 3
|
76
|
+
version: 2.1.3
|
77
|
+
- - <
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 7
|
80
|
+
segments:
|
81
|
+
- 3
|
82
|
+
- 0
|
83
|
+
- 0
|
84
|
+
version: 3.0.0
|
85
|
+
type: :runtime
|
86
|
+
version_requirements: *id004
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: simple_crowd
|
89
|
+
prerelease: false
|
90
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
hash: 23
|
96
|
+
segments:
|
97
|
+
- 1
|
98
|
+
- 0
|
99
|
+
- 0
|
100
|
+
version: 1.0.0
|
101
|
+
type: :runtime
|
102
|
+
version_requirements: *id005
|
103
|
+
description: Authlogic Crowd
|
104
|
+
email: paul@thestrongfamily.org
|
105
|
+
executables: []
|
106
|
+
|
107
|
+
extensions: []
|
108
|
+
|
109
|
+
extra_rdoc_files:
|
110
|
+
- README.rdoc
|
111
|
+
files:
|
112
|
+
- .document
|
113
|
+
- .gitignore
|
114
|
+
- Gemfile
|
115
|
+
- README.rdoc
|
116
|
+
- Rakefile
|
117
|
+
- authlogic_crowd.gemspec
|
118
|
+
- lib/authlogic_crowd.rb
|
119
|
+
- lib/authlogic_crowd/acts_as_authentic.rb
|
120
|
+
- lib/authlogic_crowd/acts_as_authentic_callbacks.rb
|
121
|
+
- lib/authlogic_crowd/session.rb
|
122
|
+
- lib/authlogic_crowd/session_callbacks.rb
|
123
|
+
- lib/authlogic_crowd/version.rb
|
124
|
+
- test/helper.rb
|
125
|
+
- test/test_authlogic_crowd.rb
|
126
|
+
has_rdoc: true
|
127
|
+
homepage: http://github.com/lapluviosilla/authlogic_crowd
|
128
|
+
licenses: []
|
129
|
+
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
|
133
|
+
require_paths:
|
134
|
+
- lib
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
hash: 3
|
141
|
+
segments:
|
142
|
+
- 0
|
143
|
+
version: "0"
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
hash: 3
|
150
|
+
segments:
|
151
|
+
- 0
|
152
|
+
version: "0"
|
153
|
+
requirements: []
|
154
|
+
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 1.6.2
|
157
|
+
signing_key:
|
158
|
+
specification_version: 3
|
159
|
+
summary: Atlassian Crowd support for Authlogic
|
160
|
+
test_files:
|
161
|
+
- test/helper.rb
|
162
|
+
- test/test_authlogic_crowd.rb
|