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 => [:set_home, :account, :go_public, :make_friend, :remove_friend, :upload_image, :delete_image]
8 before_filter :check_database_readable, :except => [:api_details, :api_gpx_files]
9 before_filter :check_database_writable, :only => [:login, :new, :set_home, :account, :go_public, :make_friend, :remove_friend, :upload_image, :delete_image]
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 => [:activate, :deactivate, :hide, :unhide, :delete]
15 before_filter :lookup_this_user, :only => [:activate, :deactivate, :hide, :unhide, :delete]
17 filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation
20 @title = t 'user.new.title'
22 if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
23 render :action => 'new'
25 @user = User.new(params[:user])
28 @user.data_public = true
29 @user.description = "" if @user.description.nil?
30 @user.creation_ip = request.remote_ip
31 @user.languages = request.user_preferred_languages
34 flash[:notice] = t 'user.new.flash create success message'
35 Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer]))
36 redirect_to :action => 'login'
38 render :action => 'new'
44 @title = t 'user.account.title'
45 @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
47 #The redirect from the OpenID provider reenters here again
48 #and we need to pass the parameters through to the
49 #open_id_authentication function
50 if params[:open_id_complete]
55 if params[:user] and params[:user][:display_name] and params[:user][:description]
56 if params[:user][:email] != @user.email
57 @user.new_email = params[:user][:email]
60 @user.display_name = params[:user][:display_name]
62 if params[:user][:pass_crypt].length > 0 or params[:user][:pass_crypt_confirmation].length > 0
63 @user.pass_crypt = params[:user][:pass_crypt]
64 @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
66 if (params[:user][:openid_url].length == 0)
67 #Clearing doesn't need OpenID validation, so we can set it here.
68 @user.openid_url = nil
71 @user.description = params[:user][:description]
72 @user.languages = params[:user][:languages].split(",")
73 @user.home_lat = params[:user][:home_lat]
74 @user.home_lon = params[:user][:home_lon]
79 if params[:user][:email] == @user.new_email
80 flash.now[:notice] = t 'user.account.flash update success confirm needed'
81 Notifier.deliver_email_confirm(@user, @user.tokens.create)
83 flash.now[:notice] = t 'user.account.flash update success'
87 if (params[:user][:openid_url].length > 0)
89 @norm_openid_url = OpenIdAuthentication.normalize_identifier(params[:user][:openid_url])
90 if (@norm_openid_url != @user.openid_url)
91 #If the OpenID has changed, we want to check that it is a valid OpenID and one
92 #the user has control over before saving the openID as a password equivalent for
94 openid_verify(@norm_openid_url)
97 flash.now[:error] = t 'user.login.openid invalid'
103 def openid_specialcase_mapping(openid_url)
104 #Special case gmail.com, as it is pontentially a popular OpenID provider and unlike
105 #yahoo.com, where it works automatically, Google have hidden their OpenID endpoint
106 #somewhere obscure making it less userfriendly.
107 if (openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/) )
108 return 'https://www.google.com/accounts/o8/id'
114 def openid_verify(openid_url)
115 authenticate_with_open_id(openid_url) do |result, identity_url|
116 if result.successful?
117 #We need to use the openid url passed back from the OpenID provider
118 #rather than the one supplied by the user, as these can be different.
119 #e.g. one can simply enter yahoo.com in the login box, i.e. no user specific url
120 #only once it comes back from the OpenID provider do we know the unique address for
122 @user.openid_url = identity_url
124 flash.now[:notice] = t 'user.account.flash update success'
126 else if result.missing?
127 mapped_id = openid_specialcase_mapping(openid_url)
129 openid_verify(mapped_id)
131 flash.now[:error] = t 'user.login.openid missing provider'
133 else if result.invalid?
134 flash.now[:error] = t 'user.login.openid invalid'
136 flash.now[:error] = t 'user.login.auth failure'
145 if params[:user][:home_lat] and params[:user][:home_lon]
146 @user.home_lat = params[:user][:home_lat].to_f
147 @user.home_lon = params[:user][:home_lon].to_f
149 flash[:notice] = t 'user.set_home.flash success'
150 redirect_to :controller => 'user', :action => 'account'
156 @user.data_public = true
158 flash[:notice] = t 'user.go_public.flash success'
159 redirect_to :controller => 'user', :action => 'account', :display_name => @user.display_name
163 @title = t 'user.lost_password.title'
165 if params[:user] and params[:user][:email]
166 user = User.find_by_email(params[:user][:email], :conditions => {:visible => true})
169 token = user.tokens.create
170 Notifier.deliver_lost_password(user, token)
171 flash.now[:notice] = t 'user.lost_password.notice email on way'
173 flash.now[:error] = t 'user.lost_password.notice email cannot find'
179 @title = t 'user.reset_password.title'
182 token = UserToken.find_by_token(params[:token])
188 @user.pass_crypt = params[:user][:pass_crypt]
189 @user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
191 @user.email_valid = true
195 flash[:notice] = t 'user.reset_password.flash changed'
196 redirect_to :action => 'login'
200 flash[:error] = t 'user.reset_password.flash token bad'
201 redirect_to :action => 'lost_password'
207 @title = t 'user.new.title'
209 # The user is logged in already, so don't show them the signup page, instead
210 # send them to the home page
211 redirect_to :controller => 'site', :action => 'index' if session[:user]
213 @nickname = params['nickname']
214 @email = params['email']
219 #The redirect from the OpenID provider reenters here again
220 #and we need to pass the parameters through to the
221 # open_id_authentication function
222 if params[:open_id_complete]
223 open_id_authentication('')
227 if params[:user] and session[:user].nil?
229 if !params[:user][:openid_url].empty?
230 open_id_authentication(params[:user][:openid_url])
232 email_or_display_name = params[:user][:email]
233 pass = params[:user][:password]
234 user = User.authenticate(:username => email_or_display_name, :password => pass)
236 session[:user] = user.id
237 elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true)
238 flash.now[:error] = t 'user.login.account not active'
240 flash.now[:error] = t 'user.login.auth failure'
246 # The user is logged in, if the referer param exists, redirect them to that
247 # unless they've also got a block on them, in which case redirect them to
248 # the block so they can clear it.
249 user = User.find(session[:user])
250 block = user.blocked_on_view
252 redirect_to block, :referrer => params[:referrer]
253 elsif params[:referer]
254 redirect_to params[:referer]
256 redirect_to :controller => 'site', :action => 'index'
261 @title = t 'user.login.title'
264 def open_id_authentication(openid_url)
265 #TODO: only ask for nickname and email, if we don't already have a user for that openID, in which case
266 #email and nickname are already filled out. I don't know how to do that with ruby syntax though, as we
267 #don't want to duplicate the do block
268 #On the other hand it also doesn't matter too much if we ask every time, as the OpenID provider should
269 #remember these results, and shouldn't repromt the user for these data each time.
270 authenticate_with_open_id(openid_url, :return_to => request.protocol + request.host_with_port + '/login?referer=' + params[:referer], :optional => [:nickname, :email]) do |result, identity_url, registration|
271 if result.successful?
272 #We need to use the openid url passed back from the OpenID provider
273 #rather than the one supplied by the user, as these can be different.
274 #e.g. one can simply enter yahoo.com in the login box, i.e. no user specific url
275 #only once it comes back from the OpenID provider do we know the unique address for
277 user = User.find_by_openid_url(identity_url)
279 if user.visible? and user.active?
280 session[:user] = user.id
283 flash.now[:error] = t 'user.login.account not active'
286 #We don't have a user registered to this OpenID. Redirect to the create account page
287 #with username and email filled in if they have been given by the OpenID provider through
288 #the simple registration protocol
289 redirect_to :controller => 'user', :action => 'new', :nickname => registration['nickname'], :email => registration['email']
291 else if result.missing?
292 #Try and apply some heuristics to make common cases more userfriendly
293 mapped_id = openid_specialcase_mapping(openid_url)
295 open_id_authentication(mapped_id)
297 flash.now[:error] = t 'user.login.openid missing provider'
299 else if result.invalid?
300 flash.now[:error] = t 'user.login.openid invalid'
302 flash.now[:error] = t 'user.login.auth failure'
311 token = UserToken.find_by_token(session[:token])
315 session[:token] = nil
319 redirect_to params[:referer]
321 redirect_to :controller => 'site', :action => 'index'
326 if params[:confirm_action]
327 token = UserToken.find_by_token(params[:confirm_string])
328 if token and !token.user.active?
331 @user.email_valid = true
333 referer = token.referer
335 flash[:notice] = t 'user.confirm.success'
336 session[:user] = @user.id
340 redirect_to :action => 'account', :display_name => @user.display_name
343 flash.now[:error] = t 'user.confirm.failure'
349 if params[:confirm_action]
350 token = UserToken.find_by_token(params[:confirm_string])
351 if token and token.user.new_email?
353 @user.email = @user.new_email
354 @user.new_email = nil
356 @user.email_valid = true
359 flash[:notice] = t 'user.confirm_email.success'
360 session[:user] = @user.id
361 redirect_to :action => 'account', :display_name => @user.display_name
363 flash.now[:error] = t 'user.confirm_email.failure'
369 @user.image = params[:user][:image]
371 redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
377 redirect_to :controller => 'user', :action => 'view', :display_name => @user.display_name
381 doc = OSM::API.new.get_xml_doc
382 @user.traces.each do |trace|
383 doc.root << trace.to_xml_node() if trace.public? or trace.user == @user
385 render :text => doc.to_s, :content_type => "text/xml"
389 @this_user = User.find_by_display_name(params[:display_name])
392 (@this_user.visible? or (@user and @user.administrator?))
393 @title = @this_user.display_name
395 @title = t 'user.no_such_user.title'
396 @not_found_user = params[:display_name]
397 render :action => 'no_such_user', :status => :not_found
402 if params[:display_name]
403 name = params[:display_name]
404 new_friend = User.find_by_display_name(name, :conditions => {:visible => true})
406 friend.user_id = @user.id
407 friend.friend_user_id = new_friend.id
408 unless @user.is_friends_with?(new_friend)
410 flash[:notice] = t 'user.make_friend.success', :name => name
411 Notifier.deliver_friend_notification(friend)
413 friend.add_error(t('user.make_friend.failed', :name => name))
416 flash[:warning] = t 'user.make_friend.already_a_friend', :name => name
419 redirect_to :controller => 'user', :action => 'view'
424 if params[:display_name]
425 name = params[:display_name]
426 friend = User.find_by_display_name(name, :conditions => {:visible => true})
427 if @user.is_friends_with?(friend)
428 Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
429 flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
431 flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name
434 redirect_to :controller => 'user', :action => 'view'
439 # activate a user, allowing them to log in
441 @this_user.update_attributes(:active => true)
442 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
446 # deactivate a user, preventing them from logging in
448 @this_user.update_attributes(:active => false)
449 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
453 # hide a user, marking them as logically deleted
455 @this_user.update_attributes(:visible => false)
456 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
460 # unhide a user, clearing the logically deleted flag
462 @this_user.update_attributes(:visible => true)
463 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
467 # delete a user, marking them as deleted and removing personal data
470 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
474 # require that the user is a administrator, or fill out a helpful error message
475 # and return them to the user page.
476 def require_administrator
477 unless @user.administrator?
478 flash[:error] = t('user.filter.not_an_administrator')
479 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
484 # ensure that there is a "this_user" instance variable
486 @this_user = User.find_by_display_name(params[:display_name])
487 rescue ActiveRecord::RecordNotFound
488 redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user