authlogic_crowd 0.2.4 → 0.3.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -5
- data/Gemfile +3 -0
- data/README.markdown +173 -0
- data/Rakefile +1 -21
- data/authlogic_crowd.gemspec +17 -37
- data/lib/authlogic_crowd.rb +8 -9
- data/lib/authlogic_crowd/acts_as_authentic.rb +185 -138
- data/lib/authlogic_crowd/acts_as_authentic_callbacks.rb +32 -26
- data/lib/authlogic_crowd/crowd_synchronizer.rb +97 -0
- data/lib/authlogic_crowd/session.rb +358 -302
- data/lib/authlogic_crowd/version.rb +1 -1
- metadata +51 -62
- data/README.rdoc +0 -14
- data/lib/authlogic_crowd/session_callbacks.rb +0 -19
- data/test/helper.rb +0 -13
- data/test/test_authlogic_crowd.rb +0 -7
@@ -1,26 +1,32 @@
|
|
1
|
-
module AuthlogicCrowd
|
2
|
-
module ActsAsAuthenticCallbacks
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module ActsAsAuthenticCallbacks
|
3
|
+
METHODS = [
|
4
|
+
# Fired when a local record is synced from a crowd record (usually on login)
|
5
|
+
"before_sync_from_crowd", "sync_from_crowd", "after_sync_from_crowd",
|
6
|
+
|
7
|
+
# Fired when a new local record is created by crowd (usually because a
|
8
|
+
# user logged in using crowd credentials)
|
9
|
+
"before_create_from_crowd", "after_create_from_crowd",
|
10
|
+
|
11
|
+
# Fired when a local record is synced to a crowd record (usually when creating a local record)
|
12
|
+
"before_sync_to_crowd", "sync_to_crowd", "after_sync_to_crowd",
|
13
|
+
|
14
|
+
# Fired when a creating a new crowd record (usually because a new local
|
15
|
+
# record was created)
|
16
|
+
"before_create_crowd_record", "after_create_crowd_record",
|
17
|
+
]
|
18
|
+
|
19
|
+
def self.included(klass)
|
20
|
+
klass.define_callbacks *METHODS
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
METHODS.each do |method|
|
25
|
+
class_eval <<-"end_eval", __FILE__, __LINE__
|
26
|
+
def #{method}
|
27
|
+
run_callbacks(:#{method}) { |result, object| result == false }
|
28
|
+
end
|
29
|
+
end_eval
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module AuthlogicCrowd
|
2
|
+
class CrowdSynchronizer
|
3
|
+
|
4
|
+
attr_accessor :klass, :crowd_client, :local_record
|
5
|
+
|
6
|
+
def initialize(klass, crowd_client, local_record=nil, crowd_record=nil)
|
7
|
+
self.klass = klass
|
8
|
+
self.crowd_client = crowd_client
|
9
|
+
self.local_record = local_record if local_record
|
10
|
+
self.crowd_record = crowd_record if crowd_record
|
11
|
+
@syncing = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def local_record=(val)
|
15
|
+
@local_record = val
|
16
|
+
@local_record.crowd_synchronizer = self if @local_record
|
17
|
+
@local_record.crowd_record = @crowd_record if @local_record && @crowd_record
|
18
|
+
end
|
19
|
+
|
20
|
+
def crowd_record
|
21
|
+
@crowd_record ||= @local_record.crowd_record if @local_record
|
22
|
+
@crowd_record
|
23
|
+
end
|
24
|
+
|
25
|
+
def crowd_record=(val)
|
26
|
+
@crowd_record = val
|
27
|
+
@local_record.crowd_record = @crowd_record if @local_record
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_crowd_record
|
31
|
+
if local_record.before_create_crowd_record
|
32
|
+
self.crowd_record = SimpleCrowd::User.new({:username => local_record.send(klass.login_field)})
|
33
|
+
if sync_to_crowd(true)
|
34
|
+
local_record.after_create_crowd_record
|
35
|
+
return crowd_record
|
36
|
+
end
|
37
|
+
end
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def sync_to_crowd(new_record=false)
|
42
|
+
return unless local_record && crowd_record
|
43
|
+
return if @syncing
|
44
|
+
|
45
|
+
if local_record.before_sync_to_crowd
|
46
|
+
@syncing = true
|
47
|
+
begin
|
48
|
+
local_record.sync_to_crowd
|
49
|
+
if new_record || crowd_record.dirty? || local_record.crowd_password_changed?
|
50
|
+
if new_record
|
51
|
+
crowd_client.add_user crowd_record, local_record.crowd_password
|
52
|
+
else
|
53
|
+
crowd_client.update_user crowd_record
|
54
|
+
if local_record.crowd_password_changed? && local_record.crowd_password
|
55
|
+
crowd_client.update_user_credential crowd_record.username, local_record.crowd_password
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
@syncing = false
|
61
|
+
end
|
62
|
+
local_record.after_sync_to_crowd
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_record_from_crowd
|
69
|
+
self.local_record = klass.new
|
70
|
+
if local_record.before_create_from_crowd
|
71
|
+
local_record.send(:"#{klass.login_field}=", crowd_record.username) if local_record.respond_to?(:"#{klass.login_field}=")
|
72
|
+
sync_from_crowd
|
73
|
+
if local_record.save_without_session_maintenance
|
74
|
+
local_record.after_create_from_crowd
|
75
|
+
return local_record
|
76
|
+
end
|
77
|
+
end
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def sync_from_crowd
|
82
|
+
return unless local_record && crowd_record
|
83
|
+
return if @syncing
|
84
|
+
|
85
|
+
if local_record.before_sync_from_crowd
|
86
|
+
@syncing = true
|
87
|
+
begin
|
88
|
+
local_record.sync_from_crowd
|
89
|
+
local_record.save_without_session_maintenance if local_record.changed?
|
90
|
+
ensure
|
91
|
+
@syncing = false
|
92
|
+
end
|
93
|
+
local_record.after_sync_from_crowd
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -1,302 +1,358 @@
|
|
1
|
-
module AuthlogicCrowd
|
2
|
-
module Session
|
3
|
-
def self.included(klass)
|
4
|
-
klass.class_eval do
|
5
|
-
extend Config
|
6
|
-
include
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
#
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
user_token =
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
1
|
+
module AuthlogicCrowd
|
2
|
+
module Session
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
extend Config
|
6
|
+
include InstanceMethods
|
7
|
+
|
8
|
+
attr_accessor :new_registration
|
9
|
+
|
10
|
+
persist :persist_by_crowd, :if => :authenticating_with_crowd?
|
11
|
+
validate :validate_by_crowd, :if => [:authenticating_with_crowd?, :needs_crowd_validation?]
|
12
|
+
before_destroy :logout_of_crowd, :if => :authenticating_with_crowd?
|
13
|
+
after_create(:if => :authenticating_with_crowd?, :unless => :new_registration?) do |s|
|
14
|
+
synchronizer = s.crowd_synchronizer
|
15
|
+
synchronizer.local_record = s.record
|
16
|
+
synchronizer.crowd_record = s.crowd_record
|
17
|
+
synchronizer.sync_from_crowd
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Configuration for the crowd feature.
|
23
|
+
module Config
|
24
|
+
|
25
|
+
# How often should Crowd re-authorize (in seconds). Default is 0 (always re-authorize)
|
26
|
+
def crowd_auth_every(value = nil)
|
27
|
+
rw_config(:crowd_auth_every, value, 0)
|
28
|
+
end
|
29
|
+
alias_method :crowd_auth_every=, :crowd_auth_every
|
30
|
+
|
31
|
+
# Should a new local record be created for existing Crowd users with no
|
32
|
+
# matching local record?
|
33
|
+
# Default is true.
|
34
|
+
# Add this in your Session object if you need to disable auto-registration via crowd
|
35
|
+
def auto_register(value=true)
|
36
|
+
auto_register_value(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def auto_register_value(value=nil)
|
40
|
+
rw_config(:auto_register,value,true)
|
41
|
+
end
|
42
|
+
alias_method :auto_register=, :auto_register
|
43
|
+
end
|
44
|
+
|
45
|
+
module InstanceMethods
|
46
|
+
|
47
|
+
def initialize(*args)
|
48
|
+
super
|
49
|
+
@valid_crowd_user = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
# Determines if the authenticated user is also a new registration.
|
53
|
+
# For use in the session controller to help direct the most appropriate action to follow.
|
54
|
+
def new_registration?
|
55
|
+
new_registration || !new_registration.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def auto_register?
|
59
|
+
self.class.auto_register_value
|
60
|
+
end
|
61
|
+
|
62
|
+
def crowd_record
|
63
|
+
if @valid_crowd_user[:user_token] && !@valid_crowd_user.has_key?(:record)
|
64
|
+
@valid_crowd_user[:record] = crowd_client.find_user_by_token(@valid_crowd_user[:user_token])
|
65
|
+
end
|
66
|
+
|
67
|
+
@valid_crowd_user[:record]
|
68
|
+
end
|
69
|
+
|
70
|
+
def crowd_client
|
71
|
+
@crowd_client ||= klass.crowd_client
|
72
|
+
end
|
73
|
+
|
74
|
+
def crowd_synchronizer
|
75
|
+
@crowd_synchronizer ||= klass.crowd_synchronizer(crowd_client)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def authenticating_with_crowd?
|
81
|
+
klass.using_crowd? && (authenticated_by_crowd? || has_crowd_user_token? || has_crowd_credentials?)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Use the Crowd to "log in" the user using the crowd.token_key
|
85
|
+
# cookie/parameter. If the token_key is valid and returns a valid Crowd
|
86
|
+
# user, the find_by_login_method is called to find the appropriate local
|
87
|
+
# user/record.
|
88
|
+
#
|
89
|
+
# If no *local* record is found and auto_register is enabled (default)
|
90
|
+
# then automatically create *local* record for them.
|
91
|
+
#
|
92
|
+
# This method enables a Crowd user to log in without having to explicity
|
93
|
+
# log in to this app. Once a Crowd user has authenticated with this app
|
94
|
+
# via this method, future requests usually use the Authlogic::Session
|
95
|
+
# module to persist/find users.
|
96
|
+
def persist_by_crowd
|
97
|
+
clear_crowd_auth_cache
|
98
|
+
return false unless has_crowd_user_token? && valid_crowd_user_token? && crowd_username
|
99
|
+
self.unauthorized_record = find_or_create_record_from_crowd
|
100
|
+
valid?
|
101
|
+
rescue SimpleCrowd::CrowdError => e
|
102
|
+
Rails.logger.warn "CROWD[#{__method__}]: Unexpected error. #{e}"
|
103
|
+
return false
|
104
|
+
end
|
105
|
+
|
106
|
+
# Validates the current record/user with Crowd. This validates the
|
107
|
+
# crowd.token_key cookie/parameter and/or explicit credentials.
|
108
|
+
#
|
109
|
+
# If a crowd.token_key exists and matches a previously authenticated
|
110
|
+
# token_key, this method will only verify the token with crowd if the
|
111
|
+
# last authorization was more than crowd_auth_every seconds ago (see
|
112
|
+
# the crowd_auth_every config option).
|
113
|
+
def validate_by_crowd
|
114
|
+
# Credentials trump a crowd.token_key.
|
115
|
+
# We don't even attempt to authenticated from the token key if
|
116
|
+
# credentials are present.
|
117
|
+
if has_crowd_credentials?
|
118
|
+
# HACK: Remove previous login/password errors since we are going to
|
119
|
+
# try to validate them with crowd
|
120
|
+
errors.instance_variable_get('@errors').delete(login_field.to_s)
|
121
|
+
errors.instance_variable_get('@errors').delete(password_field.to_s)
|
122
|
+
|
123
|
+
if valid_crowd_credentials?
|
124
|
+
self.attempted_record = find_or_create_record_from_crowd
|
125
|
+
unless self.attempted_record
|
126
|
+
errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid"))
|
127
|
+
end
|
128
|
+
else
|
129
|
+
errors.add(login_field, I18n.t('error_messages.login_not_found', :default => "is not valid")) if !@valid_crowd_user[:username]
|
130
|
+
errors.add(password_field, I18n.t('error_messages.password_invalid', :default => "is not valid")) if @valid_crowd_user[:username]
|
131
|
+
end
|
132
|
+
|
133
|
+
elsif has_crowd_user_token?
|
134
|
+
unless valid_crowd_user_token? && valid_crowd_username?
|
135
|
+
errors.add_to_base(I18n.t('error_messages.crowd_invalid_user_token', :default => "invalid user token"))
|
136
|
+
end
|
137
|
+
|
138
|
+
elsif authenticated_by_crowd?
|
139
|
+
destroy
|
140
|
+
errors.add_to_base(I18n.t('error_messages.crowd_missing_using_token', :default => "missing user token"))
|
141
|
+
end
|
142
|
+
|
143
|
+
unless self.attempted_record.valid?
|
144
|
+
errors.add_to_base('record is not valid')
|
145
|
+
end
|
146
|
+
|
147
|
+
if errors.count == 0
|
148
|
+
# Set crowd.token_key cookie
|
149
|
+
save_crowd_cookie
|
150
|
+
|
151
|
+
# Cache crowd authorization to make future requests faster (if
|
152
|
+
# crowd_auth_every config is enabled)
|
153
|
+
cache_crowd_auth
|
154
|
+
end
|
155
|
+
rescue SimpleCrowd::CrowdError => e
|
156
|
+
Rails.logger.warn "CROWD[#{__method__}]: Unexpected error. #{e}"
|
157
|
+
errors.add_to_base("Crowd error: #{e}")
|
158
|
+
end
|
159
|
+
|
160
|
+
# Validate the crowd.token_key (if one exists)
|
161
|
+
# Uses simple_crowd to verify the user token on the configured crowd server.
|
162
|
+
# This only checks that the token is valid with Crowd. It does not check
|
163
|
+
# that the token belongs to a valid local user/record.
|
164
|
+
def valid_crowd_user_token?
|
165
|
+
unless @valid_crowd_user.has_key?(:user_token)
|
166
|
+
@valid_crowd_user[:user_token] = nil
|
167
|
+
user_token = crowd_user_token
|
168
|
+
if user_token
|
169
|
+
if crowd_client.is_valid_user_token?(user_token)
|
170
|
+
@valid_crowd_user[:user_token] = user_token
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
!!@valid_crowd_user[:user_token]
|
175
|
+
end
|
176
|
+
|
177
|
+
# Validate username/password using Crowd.
|
178
|
+
# Uses simple_crowd to verify credentials on the configured crowd server.
|
179
|
+
def valid_crowd_credentials?
|
180
|
+
login = send(login_field)
|
181
|
+
password = send("protected_#{password_field}")
|
182
|
+
return false unless login && password
|
183
|
+
|
184
|
+
unless @valid_crowd_user.has_key?(:credentials)
|
185
|
+
@valid_crowd_user[:user_token] = nil
|
186
|
+
|
187
|
+
# Authenticate using login/password
|
188
|
+
user_token = crowd_fetch {crowd_client.authenticate_user(login, password)}
|
189
|
+
if user_token
|
190
|
+
@valid_crowd_user[:user_token] = user_token
|
191
|
+
@valid_crowd_user[:username] = login
|
192
|
+
else
|
193
|
+
# See if the login exists
|
194
|
+
crecord = @valid_crowd_user[:record] = crowd_fetch {crowd_client.find_user_by_name(login)}
|
195
|
+
@valid_crowd_user[:username] = crecord ? crecord.username : nil
|
196
|
+
end
|
197
|
+
|
198
|
+
# Attempt to find user with crowd email field instead of principal name
|
199
|
+
if !@valid_crowd_user[:username] && login =~ Authlogic::Regex.email
|
200
|
+
crecord = @valid_crowd_user[:record] = crowd_fetch {crowd_client.find_user_by_email(login)}
|
201
|
+
if crecord
|
202
|
+
user_token = crowd_fetch {crowd_client.authenticate_user(crecord.username, password)}
|
203
|
+
@valid_crowd_user[:username] = crecord.username
|
204
|
+
@valid_crowd_user[:user_token] = user_token if user_token
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
@valid_crowd_user[:credentials] = !!@valid_crowd_user[:user_token]
|
209
|
+
end
|
210
|
+
|
211
|
+
@valid_crowd_user[:credentials]
|
212
|
+
end
|
213
|
+
|
214
|
+
# Validate the crowd username against the current record
|
215
|
+
def valid_crowd_username?
|
216
|
+
record_login = send(login_field) || (unauthorized_record && unauthorized_record.login)
|
217
|
+
|
218
|
+
# Use the last username if available to reduce crowd calls
|
219
|
+
if @valid_crowd_user[:user_token] && @valid_crowd_user[:user_token] == controller.session[:"crowd.last_user_token"]
|
220
|
+
crowd_login = controller.session[:"crowd.last_username"]
|
221
|
+
end
|
222
|
+
crowd_login = crowd_username unless crowd_login
|
223
|
+
|
224
|
+
crowd_login && crowd_login == record_login
|
225
|
+
end
|
226
|
+
|
227
|
+
def crowd_username
|
228
|
+
if @valid_crowd_user[:user_token] && !@valid_crowd_user.has_key?(:username)
|
229
|
+
crecord = crowd_record
|
230
|
+
@valid_crowd_user[:username] = crecord ? crecord.username : nil
|
231
|
+
end
|
232
|
+
|
233
|
+
@valid_crowd_user[:username]
|
234
|
+
end
|
235
|
+
|
236
|
+
def cache_crowd_auth
|
237
|
+
if @valid_crowd_user[:user_token]
|
238
|
+
controller.session[:"crowd.last_auth"] = Time.now
|
239
|
+
controller.session[:"crowd.last_user_token"] = @valid_crowd_user[:user_token].dup
|
240
|
+
controller.session[:"crowd.last_username"] = @valid_crowd_user[:username].dup if @valid_crowd_user[:username]
|
241
|
+
Rails.logger.debug "CROWD: Cached crowd authorization (#{controller.session[:"crowd.last_username"]}). Next authorization at #{Time.now + self.class.crowd_auth_every}." if self.class.crowd_auth_every.to_i > 0
|
242
|
+
else
|
243
|
+
clear_crowd_auth_cache
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Clear cached crowd information
|
248
|
+
def clear_crowd_auth_cache
|
249
|
+
controller.session.delete_if {|key, val| ["crowd.last_user_token", "crowd.last_auth", "crowd.last_username"].include?(key.to_s)}
|
250
|
+
end
|
251
|
+
|
252
|
+
def save_crowd_cookie
|
253
|
+
if @valid_crowd_user[:user_token] && @valid_crowd_user[:user_token] != crowd_user_token
|
254
|
+
controller.params.delete("crowd.token_key")
|
255
|
+
controller.cookies[:"crowd.token_key"] = {
|
256
|
+
:domain => crowd_cookie_info[:domain],
|
257
|
+
:secure => crowd_cookie_info[:secure],
|
258
|
+
:value => @valid_crowd_user[:user_token],
|
259
|
+
}
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def destroy_crowd_cookie
|
264
|
+
controller.cookies.delete(:"crowd.token_key", :domain => crowd_cookie_info[:domain])
|
265
|
+
end
|
266
|
+
|
267
|
+
# When the crowd_auth_every config option is set and the user is logged
|
268
|
+
# in via crowd, validation can be skipped in certain cases (token_key
|
269
|
+
# matches last token_key and last authorization was less than
|
270
|
+
# crowd_auth_every seconds).
|
271
|
+
def needs_crowd_validation?
|
272
|
+
res = true
|
273
|
+
if !has_crowd_credentials? && authenticated_by_crowd? && self.class.crowd_auth_every.to_i > 0
|
274
|
+
last_user_token = controller.session[:"crowd.last_user_token"]
|
275
|
+
last_auth = controller.session[:"crowd.last_auth"]
|
276
|
+
if last_user_token
|
277
|
+
if !crowd_user_token
|
278
|
+
Rails.logger.debug "CROWD: Re-authorization required. Crowd token does not exist."
|
279
|
+
elsif last_user_token != crowd_user_token
|
280
|
+
Rails.logger.debug "CROWD: Re-authorization required. Crowd token does match cached token."
|
281
|
+
elsif last_auth && last_auth <= self.class.crowd_auth_every.ago
|
282
|
+
Rails.logger.debug "CROWD: Re-authorization required. Last authorization was at #{last_auth}."
|
283
|
+
elsif !last_auth
|
284
|
+
Rails.logger.debug "CROWD: Re-authorization required. Unable to determine last authorization time."
|
285
|
+
else
|
286
|
+
Rails.logger.debug "CROWD: Authenticating from cache. Next authorization at #{last_auth + self.class.crowd_auth_every}."
|
287
|
+
res = false
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
res
|
292
|
+
end
|
293
|
+
|
294
|
+
def find_or_create_record_from_crowd
|
295
|
+
return nil unless crowd_username
|
296
|
+
record = search_for_record(find_by_login_method, crowd_username)
|
297
|
+
|
298
|
+
if !record && auto_register?
|
299
|
+
synchronizer = crowd_synchronizer
|
300
|
+
synchronizer.crowd_record = crowd_record
|
301
|
+
record = synchronizer.create_record_from_crowd
|
302
|
+
self.new_registration if record
|
303
|
+
end
|
304
|
+
|
305
|
+
record
|
306
|
+
end
|
307
|
+
|
308
|
+
# Logout of crowd and remove the crowd cookie.
|
309
|
+
def logout_of_crowd
|
310
|
+
if crowd_user_token
|
311
|
+
# Send an invalidate call for single signout
|
312
|
+
# Apparently there is no way of knowing if this was successful or not.
|
313
|
+
begin
|
314
|
+
crowd_client.invalidate_user_token(crowd_user_token)
|
315
|
+
rescue SimpleCrowd::CrowdError => e
|
316
|
+
Rails.logger.debug "CROWD: logout_of_crowd #{e.message}"
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
controller.params.delete("crowd.token_key")
|
321
|
+
destroy_crowd_cookie
|
322
|
+
clear_crowd_auth_cache
|
323
|
+
true
|
324
|
+
end
|
325
|
+
|
326
|
+
def crowd_user_token
|
327
|
+
controller && (controller.params["crowd.token_key"] || controller.cookies[:"crowd.token_key"])
|
328
|
+
end
|
329
|
+
|
330
|
+
def authenticated_by_crowd?
|
331
|
+
!!controller.session[:"crowd.last_user_token"]
|
332
|
+
end
|
333
|
+
|
334
|
+
def has_crowd_user_token?
|
335
|
+
!!crowd_user_token
|
336
|
+
end
|
337
|
+
|
338
|
+
def has_crowd_credentials?
|
339
|
+
login_field && password_field && (!send(login_field).nil? || !send("protected_#{password_field}").nil?)
|
340
|
+
end
|
341
|
+
|
342
|
+
def crowd_cookie_info
|
343
|
+
@crowd_cookie_info ||= crowd_client.get_cookie_info
|
344
|
+
end
|
345
|
+
|
346
|
+
# Executes the given block, returning nil if a SimpleCrowd::CrowdError
|
347
|
+
# ocurrs.
|
348
|
+
def crowd_fetch
|
349
|
+
begin
|
350
|
+
yield
|
351
|
+
rescue SimpleCrowd::CrowdError => e
|
352
|
+
Rails.logger.debug "CROWD[#{caller[0][/`.*'/][1..-2]}]: #{e.message}"
|
353
|
+
nil
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|