1 class UserController < ApplicationController
2 layout 'site', :except => :api_details
4 before_filter :authorize, :only => [:api_details, :api_gpx_files]
5 before_filter :authorize_web, :except => [:api_details, :api_gpx_files]
6 before_filter :set_locale, :except => [:api_details, :api_gpx_files]
7 before_filter :require_user, :only => [:account, :go_public, :make_friend, :remove_friend]
8 before_filter :check_database_readable, :except => [:api_details, :api_gpx_files]
9 before_filter :check_database_writable, :only => [:login, :new, :account, :go_public, :make_friend, :remove_friend]
10 before_filter :check_api_readable, :only => [:api_details, :api_gpx_files]
11 before_filter :require_allow_read_prefs, :only => [:api_details]
12 before_filter :require_allow_read_gpx, :only => [:api_gpx_files]
13 before_filter :require_cookies, :only => [:login, :confirm]
14 before_filter :require_administrator, :only => [:set_status, :delete, :list]
15 before_filter :lookup_this_user, :only => [:set_status, :delete]
17 filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation
19 cache_sweeper :user_sweeper, :only => [:account, :set_status, :delete]
22 @title = t 'user.new.title'
23 @legale = params[:legale] || OSM.IPToCountry(request.remote_ip) || APP_CONFIG['default_legale']
24 @text = OSM.legal_text_for_country(@legale)
27 render :update do |page|
28 page.replace_html "contributorTerms", :partial => "terms"
30 elsif params[:open_id_complete]
31 # The redirect from the OpenID provider reenters here
32 # again and we need to pass the parameters through to
33 # the open_id_authentication function
34 @user = session.delete(:new_user)
36 openid_verify(nil, @user) do |user|
39 if @user.openid_url.nil? or @user.invalid?
40 render :action => 'new'
42 render :action => 'terms'
45 session[:referer] = params[:referer]
47 @user = User.new(params[:user])
48 @user.openid_url = nil
50 if params[:user][:openid_url] and @user.pass_crypt.empty?
51 # We are creating an account with OpenID and no password
52 # was specified so create a random one
53 @user.pass_crypt = ActiveSupport::SecureRandom.base64(16)
54 @user.pass_crypt_confirmation = @user.pass_crypt
58 if params[:user][:openid_url].nil? or
59 params[:user][:openid_url].empty?
60 # No OpenID so just move on to the terms
61 render :action => 'terms'
63 # Verify OpenID before moving on
64 session[:new_user] = @user
65 openid_verify(params[:user][:openid_url], @user)
68 # Something is wrong, so rerender the form
69 render :action => 'new'
75 @title = t 'user.new.title'
77 if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
78 render :action => 'new'
79 elsif params[:decline]
80 redirect_to t('user.terms.declined')
82 @user = User.new(params[:user])
84 @user.status = "pending"
85 @user.data_public = true
86 @user.description = "" if @user.description.nil?
87 @user.creation_ip = request.remote_ip
88 @user.languages = request.user_preferred_languages
89 @user.terms_agreed = Time.now.getutc
92 flash[:notice] = t 'user.new.flash create success message'
93 Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => session.delete(:referer)))
94 redirect_to :action => 'login'
96 render :action => 'new'
102 @title = t 'user.account.title'
103 @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
105 if params[:open_id_complete]
106 # The redirect from the OpenID provider reenters here
107 # again and we need to pass the parameters through to
108 # the open_id_authentication function
109 @user = session.delete(:new_user)
110 openid_verify(nil, @user) do |user|
113 elsif params[:user] and params[:user][:display_name] and params[:user][:description]
114 @user.display_name = params[:user][:display_name]
115 @user.new_email = params[:user][:new_email]
117 if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
118 @user.pass_crypt = params[:user][:pass_crypt]
119 @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
122 @user.description = params[:user][:description]
123 @user.languages = params[:user][:languages].split(",")
125 case params[:image_action]
126 when "new" then @user.image = params[:user][:image]
127 when "delete" then @user.image = nil
130 @user.home_lat = params[:user][:home_lat]
131 @user.home_lon = params[:user][:home_lon]
133 @user.openid_url = nil if params[:user][:openid_url].empty?
135 if params[:user][:openid_url].length > 0 and
136 params[:user][:openid_url] != @user.openid_url
137 # If the OpenID has changed, we want to check that it is a
138 # valid OpenID and one the user has control over before saving
139 # it as a password equivalent for the user.
140 session[:new_user] = @user
141 openid_verify(params[:user][:openid_url], @user)
149 @user.data_public = true
151 flash[:notice] = t 'user.go_public.flash success'
152 redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
156 @title = t 'user.lost_password.title'
158 if params[:user] and params[:user][:email]
159 user = User.find_by_email(params[:user][:email], :conditions => {:status => ["pending", "active", "confirmed"]})
162 token = user.tokens.create
163 Notifier.deliver_lost_password(user, token)
164 flash[:notice] = t 'user.lost_password.notice email on way'
165 redirect_to :action => 'login'
167 flash.now[:error] = t 'user.lost_password.notice email cannot find'
173 @title = t 'user.reset_password.title'
176 token = UserToken.find_by_token(params[:token])
182 @user.pass_crypt = params[:user][:pass_crypt]
183 @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
184 @user.status = "active" if @user.status == "pending"
185 @user.email_valid = true
189 flash[:notice] = t 'user.reset_password.flash changed'
190 redirect_to :action => 'login'
194 flash[:error] = t 'user.reset_password.flash token bad'
195 redirect_to :action => 'lost_password'
201 @title = t 'user.new.title'
202 @referer = params[:referer] || session[:referer]
205 # The user is logged in already, so don't show them the signup
206 # page, instead send them to the home page
207 redirect_to :controller => 'site', :action => 'index'
208 elsif not params['openid'].nil?
209 flash.now[:notice] = t 'user.new.openid association'
215 session[:remember_me] ||= params[:remember_me]
216 session[:referer] ||= params[:referer]
218 if using_open_id?(params[:openid_url])
219 openid_authentication(params[:openid_url])
221 password_authentication(params[:username], params[:password])
224 @title = t 'user.login.title'
229 @title = t 'user.logout.title'
231 if params[:session] == request.session_options[:id]
233 token = UserToken.find_by_token(session[:token])
237 session[:token] = nil
240 session_expires_automatically
242 redirect_to params[:referer]
244 redirect_to :controller => 'site', :action => 'index'
250 if params[:confirm_action]
251 token = UserToken.find_by_token(params[:confirm_string])
252 if token and !token.user.active?
254 @user.status = "active"
255 @user.email_valid = true
257 referer = token.referer
259 flash[:notice] = t 'user.confirm.success'
260 session[:user] = @user.id
264 redirect_to :action => 'account', :display_name => @user.display_name
267 flash.now[:error] = t 'user.confirm.failure'
273 if params[:confirm_action]
274 token = UserToken.find_by_token(params[:confirm_string])
275 if token and token.user.new_email?
277 @user.email = @user.new_email
278 @user.new_email = nil
279 @user.email_valid = true
281 flash[:notice] = t 'user.confirm_email.success'
283 flash[:errors] = @user.errors
286 session[:user] = @user.id
287 redirect_to :action => 'account', :display_name => @user.display_name
289 flash.now[:error] = t 'user.confirm_email.failure'
295 doc = OSM::API.new.get_xml_doc
296 @user.traces.each do |trace|
297 doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
299 render :text => doc.to_s, :content_type => "text/xml"
303 @this_user = User.find_by_display_name(params[:display_name])
306 (@this_user.visible? or (@user and @user.administrator?))
307 @title = @this_user.display_name
309 @title = t 'user.no_such_user.title'
310 @not_found_user = params[:display_name]
311 render :action => 'no_such_user', :status => :not_found
316 if params[:display_name]
317 name = params[:display_name]
318 new_friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
320 friend.user_id = @user.id
321 friend.friend_user_id = new_friend.id
322 unless @user.is_friends_with?(new_friend)
324 flash[:notice] = t 'user.make_friend.success', :name => name
325 Notifier.deliver_friend_notification(friend)
327 friend.add_error(t('user.make_friend.failed', :name => name))
330 flash[:warning] = t 'user.make_friend.already_a_friend', :name => name
334 redirect_to params[:referer]
336 redirect_to :controller => 'user', :action => 'view'
342 if params[:display_name]
343 name = params[:display_name]
344 friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
345 if @user.is_friends_with?(friend)
346 Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
347 flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
349 flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name
353 redirect_to params[:referer]
355 redirect_to :controller => 'user', :action => 'view'
361 # sets a user's status
363 @this_user.update_attributes(:status => params[:status])
364 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
368 # delete a user, marking them as deleted and removing personal data
371 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
375 # display a list of users matching specified criteria
378 ids = params[:user].keys.collect { |id| id.to_i }
380 User.update_all("status = 'confirmed'", :id => ids) if params[:confirm]
381 User.update_all("status = 'deleted'", :id => ids) if params[:hide]
383 redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
385 conditions = Hash.new
386 conditions[:status] = params[:status] if params[:status]
387 conditions[:creation_ip] = params[:ip] if params[:ip]
389 @user_pages, @users = paginate(:users,
390 :conditions => conditions,
399 # handle password authentication
400 def password_authentication(username, password)
401 if user = User.authenticate(:username => username, :password => password)
402 successful_login(user)
403 elsif User.authenticate(:username => username, :password => password, :pending => true)
404 failed_login t('user.login.account not active')
405 elsif User.authenticate(:username => username, :password => password, :suspended => true)
406 failed_login t('user.login.account suspended')
408 failed_login t('user.login.auth failure')
413 # handle OpenID authentication
414 def openid_authentication(openid_url)
415 # If we don't appear to have a user for this URL then ask the
416 # provider for some extra information to help with signup
417 if openid_url and User.find_by_openid_url(openid_url)
420 optional = [:nickname, :email]
423 # Start the authentication
424 authenticate_with_open_id(openid_url, :optional => optional) do |result, identity_url, registration|
425 if result.successful?
426 # We need to use the openid url passed back from the OpenID provider
427 # rather than the one supplied by the user, as these can be different.
429 # For example, you can simply enter yahoo.com in the login box rather
430 # than a user specific url. Only once it comes back from the provider
431 # provider do we know the unique address for the user.
432 if user = User.find_by_openid_url(identity_url)
434 when "pending" then failed_login t('user.login.account not active')
435 when "active", "confirmed" then successful_login(user)
436 when "suspended" then failed_login t('user.login.account suspended')
437 else failed_login t('user.login.auth failure')
440 # We don't have a user registered to this OpenID, so redirect
441 # to the create account page with username and email filled
442 # in if they have been given by the OpenID provider through
443 # the simple registration protocol.
444 redirect_to :controller => 'user', :action => 'new', :nickname => registration['nickname'], :email => registration['email'], :openid => identity_url
446 elsif result.missing?
447 # Try and apply some heuristics to make common cases more user friendly
448 if openid_url = openid_alternate_url(openid_url)
449 openid_authentication(openid_url)
451 failed_login t('user.login.openid missing provider')
453 elsif result.invalid?
454 failed_login t('user.login.openid invalid')
456 failed_login t('user.login.auth failure')
462 # verify an OpenID URL
463 def openid_verify(openid_url, user)
464 user.openid_url = openid_url
466 authenticate_with_open_id(openid_url) do |result, identity_url|
467 if result.successful?
468 # We need to use the openid url passed back from the OpenID provider
469 # rather than the one supplied by the user, as these can be different.
471 # For example, you can simply enter yahoo.com in the login box rather
472 # than a user specific url. Only once it comes back from the provider
473 # provider do we know the unique address for the user.
474 user.openid_url = identity_url
476 elsif result.missing?
477 # Try and apply some heuristics to make common cases more user friendly
478 if openid_url = openid_alternate_url(openid_url)
479 openid_verify(openid_url, user)
481 flash.now[:error] = t 'user.login.openid missing provider'
483 elsif result.invalid?
484 flash.now[:error] = t 'user.login.openid invalid'
486 flash.now[:error] = t 'user.login.auth failure'
492 # special case some common OpenID providers by applying heuristics
493 # to try and come up with an alternate URL if the supplied one fails
494 def openid_alternate_url(openid_url)
495 # Special case gmail.com as it is potentially a popular OpenID
496 # provider and, unlike yahoo.com, where it works automatically, Google
497 # have hidden their OpenID endpoint somewhere obscure this making it
498 # somewhat less user friendly.
499 if openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/)
500 return 'https://www.google.com/accounts/o8/id'
507 # process a successful login
508 def successful_login(user)
509 session[:user] = user.id
511 session_expires_after 1.month if session[:remember_me]
513 if user.blocked_on_view
514 redirect_to user.blocked_on_view, :referer => params[:referer]
515 elsif session[:referer]
516 redirect_to session[:referer]
518 redirect_to :controller => 'site', :action => 'index'
521 session.delete(:remember_me)
522 session.delete(:referer)
526 # process a failed login
527 def failed_login(message)
528 flash[:error] = message
530 redirect_to :action => 'login', :referer => session[:referer]
532 session.delete(:remember_me)
533 session.delete(:referer)
537 # update a user's details
538 def update_user(user)
542 if user.new_email.nil? or user.new_email.empty?
543 flash.now[:notice] = t 'user.account.flash update success'
545 flash.now[:notice] = t 'user.account.flash update success confirm needed'
548 Notifier.deliver_email_confirm(user, user.tokens.create)
550 # Ignore errors sending email
557 # require that the user is a administrator, or fill out a helpful error message
558 # and return them to the user page.
559 def require_administrator
560 if @user and not @user.administrator?
561 flash[:error] = t('user.filter.not_an_administrator')
563 if params[:display_name]
564 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
566 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
569 redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
574 # ensure that there is a "this_user" instance variable
576 @this_user = User.find_by_display_name(params[:display_name])
577 rescue ActiveRecord::RecordNotFound
578 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user