Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 469
- Log:
Major spam event on 2016-04-12 - I'm not playing anymore. Block those domains.
- Author:
- rool
- Date:
- Tue Apr 12 09:36:09 +0100 2016
- Size:
- 18779 Bytes
1 | ####################################################################### |
2 | # File: account_controller.rb # |
3 | # (C) Hipposoft 2006-2011 # |
4 | # # |
5 | # Purpose: Hub account management. # |
6 | # # |
7 | # Author: A.D.Hodgkinson # |
8 | # # |
9 | # History: 31-Jan-2011 (ADH): Comment header added; prior history # |
10 | # not recorded. # |
11 | ####################################################################### |
12 | |
13 | class AccountController < ApplicationController |
14 | |
15 | layout 'default.html.erb' |
16 | |
17 | # Cache the logged in and out PNG images in RAM; they're only small. |
18 | |
19 | @@logged_in_image = File.read("#{RAILS_ROOT}/public/images/icons/logged_in.png") |
20 | @@logged_out_image = File.read("#{RAILS_ROOT}/public/images/icons/logged_out.png") |
21 | |
22 | # Action permissions for this class as a class variable, exposed |
23 | # to the public through a class method. |
24 | |
25 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ |
26 | :change_password => [ :admin, :webmaster, :privileged, :normal ], |
27 | :change_details => [ :admin, :webmaster, :privileged, :normal ], |
28 | :delete => [ :admin, :webmaster, :privileged, :normal ], |
29 | :delete_confirm => [ :admin, :webmaster, :privileged, :normal ], |
30 | :list => [ :admin, :webmaster, :privileged ], |
31 | :enumerate => [ :admin, :webmaster ], |
32 | :show => [ :admin, :webmaster ], |
33 | :edit_roles => [ :admin ], |
34 | :destroy => [ :admin ] |
35 | }) |
36 | |
37 | def AccountController.hubssolib_permissions |
38 | @@hubssolib_permissions |
39 | end |
40 | |
41 | # HTTPS enforcement for all methods, except the login indicator; if someone |
42 | # is on an HTTP page, the login indicator needs to be fetched by HTTP too so |
43 | # it can show "logged out" as the secure-only cookies won't get sent. It is |
44 | # very confusing to be on an HTTP page, apparently fetching the indicator by |
45 | # HTTP, only to have the image fetch quietly redirect behind the scenes, go |
46 | # to HTTPS, and say you're logged in - when everyone else thinks you're not. |
47 | |
48 | before_filter :hubssolib_ensure_https, :except => :login_indication |
49 | |
50 | # The "proper" login method |
51 | # |
52 | def login |
53 | @title = 'Log in' |
54 | return unless request.post? |
55 | |
56 | @email = params[:email] |
57 | self.hubssolib_current_user = from_real_user(User.authenticate(@email, params[:password])) |
58 | |
59 | if (self.hubssolib_current_user and self.hubssolib_current_user != :false) |
60 | hubssolib_set_last_used(Time.now.utc) |
61 | |
62 | privileges = hubssolib_get_user_roles.to_human_s.downcase |
63 | hubssolib_set_flash( |
64 | :notice, |
65 | "Logged in successfully. Welcome, #{hubssolib_get_user_name}. " << |
66 | "You have #{privileges} privileges." |
67 | ) |
68 | |
69 | hubssolib_redirect_back_or_default(:controller => 'tasks', :action => nil) |
70 | else |
71 | hubssolib_set_flash(:alert, 'Incorrect e-mail address or password.') |
72 | end |
73 | end |
74 | |
75 | # Log out the user and redirect to the Tasks controller. |
76 | # |
77 | def logout |
78 | @title = 'Log out' |
79 | hubssolib_log_out() |
80 | hubssolib_set_flash(:attention, 'You are now logged out.') |
81 | redirect_to :controller => 'tasks', :action => nil |
82 | end |
83 | |
84 | def signup |
85 | @title = 'Sign up' |
86 | return unless request.post? |
87 | |
88 | # Bulk assignment from the params hash is safe because the User object |
89 | # contains nothing that won't be overwritten anyway or isn't already |
90 | # protected by attr_accessible in the User model. |
91 | |
92 | @user = User.new(params[:user]) |
93 | |
94 | if ( @user.email.downcase.ends_with?( '.kr' ) || @user.email.downcase.ends_with?( '.cn' ) ) |
95 | hubssolib_set_flash(:attention, 'Due to overwhelming spam volumes from some locations, self-signups for those locations are blocked. Please contact ROOL for assistence.') |
96 | redirect_to :controller => 'tasks', :action => nil |
97 | return |
98 | end |
99 | |
100 | # Are there any users yet? If not, grant this user admin permissions. |
101 | # Administrators are for just this application; whether or not admin |
102 | # privileges affect other applications depends on the level of external |
103 | # SSO integration. |
104 | |
105 | if (User.count.zero?) |
106 | |
107 | @user.roles = HubSsoLib::Roles.new(true).to_s |
108 | @user.save! |
109 | @user.activate |
110 | self.hubssolib_current_user = from_real_user(@user) |
111 | |
112 | hubssolib_set_flash( |
113 | :notice, |
114 | 'Thanks for signing up. You are now the system administrator ' << |
115 | 'and your account has been automatically activated.' |
116 | ) |
117 | |
118 | else |
119 | |
120 | # Have to do the captcha verification explicitly before trying to save |
121 | # the model, as verification is not done as part of validation and we |
122 | # don't want to successfully save a model only to find that the captcha |
123 | # text is incorrect. |
124 | |
125 | raise ActiveRecord::RecordInvalid.new(@user) if not verify_recaptcha( |
126 | :model => @user, |
127 | :message => "The \"prove you're a human\" response did not match the reCaptcha challenge images" |
128 | ) |
129 | |
130 | @user.roles = HubSsoLib::Roles.new(false).to_s |
131 | @user.save! |
132 | |
133 | hubssolib_set_flash( |
134 | :notice, |
135 | 'Thanks for signing up. Your site account must be activated ' << |
136 | 'before you can use it - please check your e-mail account ' << |
137 | 'for a message which tells you what you should do next.' |
138 | ) |
139 | |
140 | end |
141 | |
142 | redirect_to :controller => 'tasks', :action => nil |
143 | |
144 | rescue ActiveRecord::RecordInvalid |
145 | render :action => 'signup' |
146 | end |
147 | |
148 | def activate |
149 | activation_code = params[:activation_code] || params[:id] |
150 | |
151 | unless activation_code.nil? |
152 | @user = User.find_by_activation_code(activation_code) |
153 | |
154 | if @user and @user.activate |
155 | self.hubssolib_current_user = from_real_user(@user) |
156 | |
157 | hubssolib_set_flash( |
158 | :notice, |
159 | "Your #{INSTITUTION_NAME_LONG} web site account is now active." |
160 | ) |
161 | |
162 | hubssolib_redirect_back_or_default(:controller => 'tasks', :action => nil) |
163 | else |
164 | hubssolib_set_flash( |
165 | :alert, |
166 | "Unable to activate your #{INSTITUTION_NAME_LONG} web site account. " << |
167 | 'Is the activation code correct, or has it already been used? ' << |
168 | "If in doubt please try to sign up again. Contact #{INSTITUTION_NAME_SHORT} if you " << |
169 | 'keep having trouble.' |
170 | ) |
171 | |
172 | redirect_to :controller => 'account', :action => 'signup' |
173 | end |
174 | else |
175 | redirect_to :controller => 'account', :action => 'signup' |
176 | end |
177 | end |
178 | |
179 | def change_password |
180 | @title = 'Change password' |
181 | return unless request.post? |
182 | |
183 | user = to_real_user(self.hubssolib_current_user) |
184 | |
185 | if User.authenticate(user.email, params[:old_password]) |
186 | if (params[:password] == params[:password_confirmation]) |
187 | user.password_confirmation = params[:password_confirmation] |
188 | user.password = params[:password] |
189 | save_password_and_set_flash(user) |
190 | self.hubssolib_current_user = from_real_user(user) |
191 | |
192 | redirect_to :controller => 'tasks', :action => nil |
193 | else |
194 | set_password_mismatch_flash |
195 | @old_password = params[:old_password] |
196 | end |
197 | else |
198 | hubssolib_set_flash(:alert, 'Incorrect current password.') |
199 | end |
200 | end |
201 | |
202 | def change_details |
203 | @title = 'Update account details' |
204 | @user = to_real_user(self.hubssolib_current_user) |
205 | @real_name = @user ? @user.real_name || '' : '' |
206 | |
207 | return unless request.post? |
208 | |
209 | if (params[:real_name]) |
210 | @user.real_name = @real_name = params[:real_name] |
211 | @user.save! |
212 | self.hubssolib_current_user = from_real_user(@user) |
213 | |
214 | hubssolib_set_flash(:notice, 'Account details updated successfully.') |
215 | redirect_to :controller => 'tasks', :action => nil |
216 | end |
217 | end |
218 | |
219 | def forgot_password |
220 | @title = 'Forgotten password' |
221 | return unless request.post? |
222 | |
223 | @user = User.find(:first, :conditions => ["LOWER(email) = ?", params[:email].downcase]) |
224 | |
225 | unless @user.nil? |
226 | @user.forgot_password |
227 | @user.save! |
228 | |
229 | hubssolib_set_flash( |
230 | :notice, |
231 | 'An e-mail message which tells you how to reset your ' << |
232 | 'account password has been set to your e-mail address.' |
233 | ) |
234 | |
235 | redirect_to :controller => 'tasks', :action => nil |
236 | else |
237 | hubssolib_set_flash( |
238 | :alert, |
239 | 'No account was found for the given e-mail address.' |
240 | ) |
241 | end |
242 | end |
243 | |
244 | def reset_password |
245 | @title = 'Reset password' |
246 | |
247 | if params[:id].nil? |
248 | hubssolib_redirect_back_or_default(:controller => 'tasks', :action => nil) |
249 | return |
250 | end |
251 | |
252 | @user = User.find_by_password_reset_code(params[:id]) |
253 | |
254 | if (@user.nil?) |
255 | hubssolib_set_flash( |
256 | :alert, |
257 | 'Invalid reset code. Did your e-mail client break up the reset ' << |
258 | 'link so it spanned more than one line? If so, please try again, ' << |
259 | 'copying all of the link in the message however many lines it spans.' |
260 | ) |
261 | |
262 | hubssolib_redirect_back_or_default(:controller => 'tasks', :action => nil) |
263 | return |
264 | end |
265 | |
266 | t = Time.now.utc |
267 | if (t >= (@user.password_reset_code_expires_at || t)) # Allows for 'nil' in expiry field |
268 | hubssolib_set_flash( |
269 | :alert, |
270 | 'The reset code has expired. Please try your reset request again.' |
271 | ) |
272 | redirect_to :controller => 'account', :action => 'forgot_password' |
273 | return |
274 | end |
275 | |
276 | unless params[:password] |
277 | hubssolib_set_flash(:alert, 'Reset your password using the form below.') |
278 | return |
279 | end |
280 | |
281 | if (params[:password] == params[:password_confirmation]) |
282 | @user.password_confirmation = params[:password_confirmation] |
283 | @user.password = params[:password] |
284 | @user.reset_password |
285 | save_password_and_set_flash(@user) |
286 | self.hubssolib_current_user = from_real_user(@user) |
287 | redirect_to :controller => 'tasks', :action => nil |
288 | return |
289 | else |
290 | set_password_mismatch_flash |
291 | return |
292 | end |
293 | end |
294 | |
295 | def delete |
296 | hubssolib_set_flash(:alert, 'Are you sure?') |
297 | title = 'Delete account: Are you sure?' |
298 | end |
299 | |
300 | def delete_confirm |
301 | me = to_real_user(self.hubssolib_current_user) |
302 | hubssolib_log_out() |
303 | me.destroy |
304 | |
305 | hubssolib_clear_flash() |
306 | hubssolib_set_flash(:attention, 'Your account has been deleted.') |
307 | redirect_to :controller => 'tasks', :action => nil |
308 | end |
309 | |
310 | def list |
311 | @title = 'List of user accounts' |
312 | |
313 | # Page zero means 'all'. |
314 | |
315 | if (params.has_key?(:page) && params[:page] == '0' ) |
316 | page = 1 |
317 | per_page = User.count |
318 | else |
319 | page = params[:page] |
320 | per_page = 20 |
321 | end |
322 | |
323 | @users = User.paginate :page => page, |
324 | :per_page => per_page, |
325 | :order => 'created_at DESC' |
326 | end |
327 | |
328 | # Enumerate active users (those users known to the DRb server). |
329 | # |
330 | def enumerate |
331 | @title = 'Active users' |
332 | @users = hubssolib_enumerate_users |
333 | @users = [] if @users.nil? |
334 | |
335 | # Map the user objects returned from the HubSsoLib Gem to |
336 | # internal users. |
337 | |
338 | @users.map! { |user| to_real_user(user) } |
339 | |
340 | # Page number zero is magic; it indicates "all items". |
341 | |
342 | if (params.has_key?(:page) && params[:page] == '0' ) |
343 | page = 1 |
344 | per_page = @users.count |
345 | else |
346 | page = params[:page] |
347 | per_page = 20 |
348 | end |
349 | |
350 | @users = @users.paginate :page => page, |
351 | :per_page => per_page, |
352 | :order => 'created_at DESC' |
353 | end |
354 | |
355 | # Show details of a specific user account. |
356 | # |
357 | def show |
358 | @title = 'User account details' |
359 | @user = User.find(params[:id]) |
360 | @referrer = request.env["HTTP_REFERER"] |
361 | @referrer = nil unless (@referrer && !@referrer.empty?) |
362 | end |
363 | |
364 | def edit_roles |
365 | @title = 'Edit account roles' |
366 | |
367 | # We must have a valid ID |
368 | |
369 | unless (request.post?) and (params[:id]) and (@user = User.find(params[:id])) |
370 | redirect_to :controller => 'tasks', :action => nil |
371 | return |
372 | end |
373 | |
374 | # If 'commit' is present, the form was submitted with details rather than |
375 | # visited from a list or account details view. |
376 | |
377 | return unless (params[:commit]) |
378 | |
379 | # Validate the result |
380 | |
381 | roles = (params[:user] ? params[:user][:roles] : '').to_authenticated_roles |
382 | |
383 | unless (roles.validate) |
384 | hubssolib_set_flash( |
385 | :alert, |
386 | 'Invalid roles chosen. ' << |
387 | 'At least one item in the list must be selected.' |
388 | ) |
389 | else |
390 | @user.roles = roles.to_s |
391 | @user.save! |
392 | |
393 | # Did I update my own roles? |
394 | |
395 | if (hubssolib_get_user_id == @user.id) |
396 | self.hubssolib_current_user = from_real_user(@user) |
397 | end |
398 | |
399 | hubssolib_set_flash(:notice, 'Account roles updated successfully.') |
400 | redirect_to :action => 'show', :id => @user.id |
401 | end |
402 | end |
403 | |
404 | def destroy |
405 | user = User.find(params[:id]) |
406 | |
407 | if (hubssolib_get_user_id == user.id) |
408 | hubssolib_set_flash( |
409 | :alert, |
410 | 'Please use the normal control panel below to delete your own account.' |
411 | ) |
412 | redirect_to root_path |
413 | return |
414 | elsif (user.roles.to_authenticated_roles.include?(:admin)) |
415 | hubssolib_set_flash( |
416 | :alert, |
417 | 'You cannot destroy an administrator account from here! ' << |
418 | 'You can only do that at the control panel when ' << |
419 | 'logged into the account, or at the database level.' |
420 | ) |
421 | else |
422 | user.destroy |
423 | hubssolib_set_flash(:alert, 'The account has been deleted.') |
424 | end |
425 | |
426 | redirect_to :action => 'list' |
427 | end |
428 | |
429 | # The login_indication method is unusual; it returns data for an image, |
430 | # with no-cache parameters set, to indicate whether or not the user is |
431 | # logged in. It does not render a view. |
432 | # |
433 | # The idea is that a caller which caches HTML can include an image tag |
434 | # that points its source data to this method; the image will be updated |
435 | # even if the HTML stays cached. |
436 | # |
437 | def login_indication |
438 | headers['Pragma'] = 'no-cache' |
439 | headers['Cache-Control'] = 'no-cache, must-revalidate' |
440 | |
441 | send_data hubssolib_logged_in? ? @@logged_in_image : @@logged_out_image, |
442 | :type => 'image/png', |
443 | :disposition => 'inline' |
444 | end |
445 | |
446 | # A supporting unusual method is login_conditional, which redirects to |
447 | # the login page if the user is logged out or the tasks page if the user |
448 | # is logged in. It explicitly clears a return-to link, if there is one, |
449 | # so that the user doesn't drop out of Hub. This is useful if the page |
450 | # from which the user came cannot support (for example) the Flash display |
451 | # because of, say, caching. |
452 | # |
453 | def login_conditional |
454 | if (hubssolib_ensure_https) # Redirect back to here using HTTPS, if not already |
455 | hubssolib_store_location(nil) |
456 | |
457 | if (hubssolib_logged_in?) |
458 | redirect_to :controller => 'tasks', :action => nil |
459 | else |
460 | redirect_to :action => 'login' |
461 | end |
462 | end |
463 | end |
464 | |
465 | protected |
466 | |
467 | # Pass a HubSsoLib::User object. Returns an equivalent User Model object. |
468 | # |
469 | def to_real_user(user) |
470 | return nil if user.nil? |
471 | raise 'Incorrect argument class' unless (user.class == HubSsoLib::User or user.class == DRbObject) |
472 | |
473 | # Unpleasant "user_" prefix in HubSsoLib::User field names is to avoid |
474 | # collisions (e.g. of "id") with DRbObject. |
475 | |
476 | real_user = User.find(user.user_id) |
477 | raise 'No equivalent real user' unless real_user |
478 | |
479 | real_user.activated_at = Time.zone.parse(user.user_activated_at) |
480 | real_user.activation_code = user.user_activation_code |
481 | real_user.created_at = Time.zone.parse(user.user_created_at) |
482 | real_user.crypted_password = user.user_crypted_password |
483 | real_user.email = user.user_email |
484 | real_user.member_id = user.user_member_id |
485 | real_user.password_reset_code = user.user_password_reset_code |
486 | real_user.password_reset_code_expires_at = Time.zone.parse(user.user_password_reset_code_expires_at) |
487 | real_user.real_name = user.user_real_name |
488 | real_user.remember_token = user.user_remember_token |
489 | real_user.remember_token_expires_at = Time.zone.parse(user.user_remember_token_expires_at) |
490 | real_user.roles = user.user_roles |
491 | real_user.salt = user.user_salt |
492 | real_user.updated_at = Time.zone.parse(user.user_updated_at) |
493 | |
494 | return real_user |
495 | end |
496 | |
497 | # Pass a User Model object. Returns an equivalent HubSsoLib::User object. |
498 | # |
499 | def from_real_user(real_user) |
500 | return nil if real_user.nil? |
501 | raise 'Incorrect argument class' unless real_user.class == User |
502 | |
503 | user = HubSsoLib::User.new |
504 | |
505 | user.user_activated_at = real_user.activated_at.to_s |
506 | user.user_activation_code = real_user.activation_code |
507 | user.user_created_at = real_user.created_at.to_s |
508 | user.user_crypted_password = real_user.crypted_password |
509 | user.user_email = real_user.email |
510 | user.user_id = real_user.id |
511 | user.user_member_id = real_user.member_id |
512 | user.user_password_reset_code = real_user.password_reset_code |
513 | user.user_password_reset_code_expires_at = real_user.password_reset_code_expires_at.to_s |
514 | user.user_real_name = real_user.real_name |
515 | user.user_remember_token = real_user.remember_token |
516 | user.user_remember_token_expires_at = real_user.remember_token_expires_at.to_s |
517 | user.user_roles = real_user.roles |
518 | user.user_salt = real_user.salt |
519 | user.user_updated_at = real_user.updated_at.to_s |
520 | |
521 | return user |
522 | end |
523 | |
524 | def save_password_and_set_flash(user) |
525 | if ( user.save ) |
526 | hubssolib_set_flash(:notice, 'Your password has been changed.') |
527 | else |
528 | hubssolib_set_flash(:alert, 'Sorry, your password could not be changed.') |
529 | end |
530 | end |
531 | |
532 | def set_password_mismatch_flash |
533 | hubssolib_set_flash( |
534 | :alert, |
535 | 'The new password differed from the password confirmation you entered.' |
536 | ) |
537 | end |
538 | end |