authlogic_crowd 0.2.4 → 0.3.0.pre.2
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 -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
|