Merge branch 'master' into openid
authorTom Hughes <tom@compton.nu>
Sat, 21 May 2011 11:14:56 +0000 (12:14 +0100)
committerTom Hughes <tom@compton.nu>
Sat, 21 May 2011 11:14:56 +0000 (12:14 +0100)
Conflicts:
app/controllers/user_controller.rb
app/views/user/terms.html.erb
test/fixtures/users.yml

1  2 
app/controllers/user_controller.rb
app/views/user/account.html.erb
app/views/user/terms.html.erb
config/locales/en.yml
config/locales/is.yml
public/stylesheets/common.css
public/stylesheets/small.css
test/fixtures/users.yml
test/integration/user_blocks_test.rb

@@@ -24,25 -25,9 +25,25 @@@ class UserController < ApplicationContr
  
      if request.xhr?
        render :update do |page|
-         page.replace_html "contributorTerms", :partial => "terms", :locals => { :has_decline => params[:has_decline] }
+         page.replace_html "contributorTerms", :partial => "terms"
        end
 +    elsif using_open_id?
 +      # The redirect from the OpenID provider reenters here
 +      # again and we need to pass the parameters through to
 +      # the open_id_authentication function
 +      @user = session.delete(:new_user)
 +
 +      openid_verify(nil, @user) do |user|
 +      end
 +
 +      if @user.openid_url.nil? or @user.invalid?
 +        render :action => 'new'
 +      else
 +        render :action => 'terms'
 +      end
      else
 +      session[:referer] = params[:referer]
 +
        @title = t 'user.terms.title'
        @user = User.new(params[:user]) if params[:user]
  
        @user.creation_ip = request.remote_ip
        @user.languages = request.user_preferred_languages
        @user.terms_agreed = Time.now.getutc
+       @user.terms_seen = true
+       
        if @user.save
          flash[:notice] = t 'user.new.flash create success message', :email => @user.email
 -        Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer]))
 +        Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => session.delete(:referer)))
          session[:token] = @user.tokens.create.token
-         redirect_to :action => 'login'
+         redirect_to :action => 'login', :referer => params[:referer]
        else
-         render :action => 'new'
+         render :action => 'new', :referer => params[:referer]
        end
      end
    end
  
  private
  
 +  ##
 +  # handle password authentication
 +  def password_authentication(username, password)
 +    if user = User.authenticate(:username => username, :password => password)
 +      successful_login(user)
 +    elsif user = User.authenticate(:username => username, :password => password, :pending => true)
 +      failed_login t('user.login.account not active', :reconfirm => url_for(:action => 'confirm_resend', :display_name => user.display_name))
 +    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)
 +      required = nil
 +    else
 +      required = [:nickname, :email, "http://axschema.org/namePerson/friendly", "http://axschema.org/contact/email"]
 +    end
 +
 +    # Start the authentication
 +    authenticate_with_open_id(openid_expand_url(openid_url), :required => required) do |result, identity_url, sreg, ax|
 +      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.
 +          nickname = sreg["nickname"] || ax["http://axschema.org/namePerson/friendly"]
 +          email = sreg["email"] || ax["http://axschema.org/contact/email"]
 +          redirect_to :controller => 'user', :action => 'new', :nickname => nickname, :email => 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
-     if user.blocked_on_view
-       redirect_to user.blocked_on_view, :referer => params[:referer]
-     elsif session[:referer]
-       redirect_to session[:referer]
 +    session_expires_after 1.month if session[:remember_me]
 +
-       redirect_to :controller => 'site', :action => 'index'
++    target = params[:referer] || url_for(:controller => :site, :action => :index)
++
++    # The user is logged in, so decide where to send them:
++    #
++    # - If they haven't seen the contributor terms, send them there.
++    # - If they have a block on them, show them that.
++    # - If they were referred to the login, send them back there.
++    # - Otherwise, send them to the home page.
++    if REQUIRE_TERMS_SEEN and not user.terms_seen
++      redirect_to :controller => :user, :action => :terms, :referer => target
++    elsif user.blocked_on_view
++      redirect_to user.blocked_on_view, :referer => target
 +    else
++      redirect_to target
 +    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.
Simple merge
        <%= hidden_field('user', 'display_name') %>
        <%= hidden_field('user', 'pass_crypt') %>
        <%= hidden_field('user', 'pass_crypt_confirmation') %>
 +      <%= hidden_field('user', 'openid_url') %>
      <% end %>
      <div id="buttons">
-       <% if @user.new_record? %>
-         <%= submit_tag(t('user.terms.decline'), :name => "decline", :id => "decline") %>
-       <% end %>
+       <%= submit_tag(t('user.terms.decline'), :name => "decline", :id => "decline") %>
        <%= submit_tag(t('user.terms.agree'), :name => "agree", :id => "agree") %>
      </div>
    </p>
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -68,13 -73,14 +73,24 @@@ administrator_user
    creation_time: "2008-05-01 01:23:45"
    display_name: administrator
    data_public: true
 -  terms_seen: true
  
openid_user:
terms_not_seen_user:
    id: 7
+   email: not_agreed@example.com
+   status: active
+   pass_crypt: <%= Digest::MD5.hexdigest('test') %>
+   creation_time: "2011-03-22 00:23:45"
+   display_name: not_agreed
+   data_public: true
+   terms_seen: false
++
++openid_user:
++  id: 8
 +  email: openid-user@example.com
 +  status: active
 +  pass_crypt: <%= Digest::MD5.hexdigest('test') %>
 +  creation_time: "2008-05-01 01:23:45"
 +  display_name: openIDuser
 +  data_public: true
 +  openid_url: http://localhost:1123/john.doe?openid.success=true
++  terms_seen: true
@@@ -38,11 -38,8 +38,8 @@@ class UserBlocksTest < ActionController
  
      # revoke the ban
      get '/login'
-     assert_response :redirect
-     assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
-     follow_redirect!
      assert_response :success
 -    post '/login', {'user[email]' => moderator.email, 'user[password]' => "test", :referer => "/blocks/#{block.id}/revoke"}
 +    post '/login', {'username' => moderator.email, 'password' => "test", :referer => "/blocks/#{block.id}/revoke"}
      assert_response :redirect
      follow_redirect!
      assert_response :success