+ def make_friend
+ if params[:display_name]
+ name = params[:display_name]
+ new_friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
+ friend = Friend.new
+ friend.user_id = @user.id
+ friend.friend_user_id = new_friend.id
+ unless @user.is_friends_with?(new_friend)
+ if friend.save
+ flash[:notice] = t 'user.make_friend.success', :name => name
+ Notifier.deliver_friend_notification(friend)
+ else
+ friend.add_error(t('user.make_friend.failed', :name => name))
+ end
+ else
+ flash[:warning] = t 'user.make_friend.already_a_friend', :name => name
+ end
+
+ if params[:referer]
+ redirect_to params[:referer]
+ else
+ redirect_to :controller => 'user', :action => 'view'
+ end
+ end
+ end
+
+ def remove_friend
+ if params[:display_name]
+ name = params[:display_name]
+ friend = User.find_by_display_name(name, :conditions => {:status => ["active", "confirmed"]})
+ if @user.is_friends_with?(friend)
+ Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{friend.id}"
+ flash[:notice] = t 'user.remove_friend.success', :name => friend.display_name
+ else
+ flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name
+ end
+
+ if params[:referer]
+ redirect_to params[:referer]
+ else
+ redirect_to :controller => 'user', :action => 'view'
+ end
+ end
+ end
+
+ ##
+ # sets a user's status
+ def set_status
+ @this_user.update_attributes(:status => params[:status])
+ redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+ end
+
+ ##
+ # delete a user, marking them as deleted and removing personal data
+ def delete
+ @this_user.delete
+ redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+ end
+
+ ##
+ # display a list of users matching specified criteria
+ def list
+ if request.post?
+ ids = params[:user].keys.collect { |id| id.to_i }
+
+ User.update_all("status = 'confirmed'", :id => ids) if params[:confirm]
+ User.update_all("status = 'deleted'", :id => ids) if params[:hide]
+
+ redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
+ else
+ conditions = Hash.new
+ conditions[:status] = params[:status] if params[:status]
+ conditions[:creation_ip] = params[:ip] if params[:ip]
+
+ @user_pages, @users = paginate(:users,
+ :conditions => conditions,
+ :order => :id,
+ :per_page => 50)
+ end
+ end
+
+private
+
+ ##
+ # handle password authentication
+ def password_authentication(username, password)
+ if user = User.authenticate(:username => username, :password => password)
+ successful_login(user)
+ elsif User.authenticate(:username => username, :password => password, :pending => true)
+ failed_login t('user.login.account not active')
+ elsif User.authenticate(:username => username, :password => password, :suspended => true)
+ webmaster = link_to t('user.login.webmaster'), "mailto:webmaster@openstreetmap.org"
+ failed_login t('user.login.account suspended', :webmaster => webmaster)
+ else
+ failed_login t('user.login.auth failure')
+ end
+ end
+
+ ##
+ # handle OpenID authentication
+ def openid_authentication(openid_url)
+ # If we don't appear to have a user for this URL then ask the
+ # provider for some extra information to help with signup
+ if openid_url and User.find_by_openid_url(openid_url)
+ optional = nil
+ else
+ optional = [:nickname, :email]
+ end
+
+ # Start the authentication
+ authenticate_with_open_id(openid_expand_url(openid_url), :optional => optional) do |result, identity_url, registration|
+ if result.successful?
+ # We need to use the openid url passed back from the OpenID provider
+ # rather than the one supplied by the user, as these can be different.
+ #
+ # For example, you can simply enter yahoo.com in the login box rather
+ # than a user specific url. Only once it comes back from the provider
+ # provider do we know the unique address for the user.
+ if user = User.find_by_openid_url(identity_url)
+ case user.status
+ when "pending" then
+ failed_login t('user.login.account not active')
+ when "active", "confirmed" then
+ successful_login(user)
+ when "suspended" then
+ webmaster = link_to t('user.login.webmaster'), "mailto:webmaster@openstreetmap.org"
+ failed_login t('user.login.account suspended', :webmaster => webmaster)
+ else
+ failed_login t('user.login.auth failure')
+ end
+ else
+ # We don't have a user registered to this OpenID, so redirect
+ # to the create account page with username and email filled
+ # in if they have been given by the OpenID provider through
+ # the simple registration protocol.
+ redirect_to :controller => 'user', :action => 'new', :nickname => registration['nickname'], :email => registration['email'], :openid => identity_url
+ end
+ elsif result.missing?
+ failed_login t('user.login.openid missing provider')
+ elsif result.invalid?
+ failed_login t('user.login.openid invalid')
+ else
+ failed_login t('user.login.auth failure')
+ end
+ end
+ end
+
+ ##
+ # verify an OpenID URL
+ def openid_verify(openid_url, user)
+ user.openid_url = openid_url
+
+ authenticate_with_open_id(openid_expand_url(openid_url)) do |result, identity_url|
+ if result.successful?
+ # We need to use the openid url passed back from the OpenID provider
+ # rather than the one supplied by the user, as these can be different.
+ #
+ # For example, you can simply enter yahoo.com in the login box rather
+ # than a user specific url. Only once it comes back from the provider
+ # provider do we know the unique address for the user.
+ user.openid_url = identity_url
+ yield user
+ elsif result.missing?
+ flash.now[:error] = t 'user.login.openid missing provider'
+ elsif result.invalid?
+ flash.now[:error] = t 'user.login.openid invalid'
+ else
+ flash.now[:error] = t 'user.login.auth failure'
+ end
+ end
+ end
+
+ ##
+ # special case some common OpenID providers by applying heuristics to
+ # try and come up with the correct URL based on what the user entered
+ def openid_expand_url(openid_url)
+ if openid_url.nil?
+ return nil
+ elsif openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/)
+ # Special case gmail.com as it is potentially a popular OpenID
+ # provider and, unlike yahoo.com, where it works automatically, Google
+ # have hidden their OpenID endpoint somewhere obscure this making it
+ # somewhat less user friendly.
+ return 'https://www.google.com/accounts/o8/id'
+ else
+ return openid_url
+ end
+ end
+
+ ##
+ # process a successful login
+ def successful_login(user)
+ session[:user] = user.id
+
+ session_expires_after 1.month if session[:remember_me]
+
+ if user.blocked_on_view
+ redirect_to user.blocked_on_view, :referer => params[:referer]
+ elsif session[:referer]
+ redirect_to session[:referer]
+ else
+ redirect_to :controller => 'site', :action => 'index'
+ end
+
+ session.delete(:remember_me)
+ session.delete(:referer)
+ end
+
+ ##
+ # process a failed login
+ def failed_login(message)
+ flash[:error] = message
+
+ redirect_to :action => 'login', :referer => session[:referer]
+
+ session.delete(:remember_me)
+ session.delete(:referer)
+ end
+
+ ##
+ # update a user's details
+ def update_user(user)
+ if user.save
+ set_locale
+
+ if user.new_email.nil? or user.new_email.empty?
+ flash.now[:notice] = t 'user.account.flash update success'
+ else
+ flash.now[:notice] = t 'user.account.flash update success confirm needed'
+
+ begin
+ Notifier.deliver_email_confirm(user, user.tokens.create)
+ rescue
+ # Ignore errors sending email
+ end
+ end
+ end
+ end
+
+ ##
+ # require that the user is a administrator, or fill out a helpful error message
+ # and return them to the user page.
+ def require_administrator
+ if @user and not @user.administrator?
+ flash[:error] = t('user.filter.not_an_administrator')
+
+ if params[:display_name]
+ redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name]
+ else
+ redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
+ end
+ elsif not @user
+ redirect_to :controller => 'user', :action => 'login', :referer => request.request_uri
+ end
+ end
+
+ ##
+ # ensure that there is a "this_user" instance variable
+ def lookup_this_user
+ @this_user = User.find_by_display_name(params[:display_name])
+ rescue ActiveRecord::RecordNotFound
+ redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user
+ end