]> git.openstreetmap.org Git - rails.git/commitdiff
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

index 1193ec9106b151887fb7518bd727184bd19276ef,97b0de73c79fdf4d85676069df17a816a6989fd3..a066c1c63b3c6f812264c56b4106a0f6f20e1472
@@@ -1,6 -1,7 +1,7 @@@
  class UserController < ApplicationController
-   layout 'site', :except => :api_details
+   layout :choose_layout
  
+   before_filter :disable_terms_redirect, :only => [:terms, :save, :logout, :api_details]
    before_filter :authorize, :only => [:api_details, :api_gpx_files]
    before_filter :authorize_web, :except => [:api_details, :api_gpx_files]
    before_filter :set_locale, :except => [:api_details, :api_gpx_files]
  
      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]
  
 +      if params[:user] and params[:user][:openid_url] and @user.pass_crypt.empty?
 +        # We are creating an account with OpenID and no password
 +        # was specified so create a random one
 +        @user.pass_crypt = ActiveSupport::SecureRandom.base64(16) 
 +        @user.pass_crypt_confirmation = @user.pass_crypt 
 +      end
 +
        if @user
          if @user.invalid?
            if @user.new_record?
 +            # Something is wrong with a new user, so rerender the form
              render :action => :new
            else
 +            # Error in existing user, so go to account settings
              flash[:errors] = @user.errors
              redirect_to :action => :account, :display_name => @user.display_name
            end
          elsif @user.terms_agreed?
 +          # Already agreed to terms, so just show settings
            redirect_to :action => :account, :display_name => @user.display_name
 +        elsif params[:user] and params[:user][:openid_url]
 +          # Verify OpenID before moving on
 +          session[:new_user] = @user
 +          openid_verify(params[:user][:openid_url], @user)
          end
        else
 +        # Not logged in, so redirect to the login page
          redirect_to :action => :login, :referer => request.request_uri
        end
      end
      if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"})
        render :action => 'new'
      elsif params[:decline]
-       redirect_to t('user.terms.declined')
+       if @user
+         @user.terms_seen = true
+         if @user.save
+           flash[:notice] = t 'user.new.terms declined', :url => t('user.new.terms declined url')
+         end
+         if params[:referer]
+           redirect_to params[:referer]
+         else
+           redirect_to :action => :account, :display_name => @user.display_name
+         end
+       else
+         redirect_to t('user.terms.declined')
+       end
      elsif @user
        if !@user.terms_agreed?
          @user.consider_pd = params[:user][:consider_pd]
          @user.terms_agreed = Time.now.getutc
+         @user.terms_seen = true
          if @user.save
            flash[:notice] = t 'user.new.terms accepted'
          end
        end
  
-       redirect_to :action => :account, :display_name => @user.display_name
+       if params[:referer]
+         redirect_to params[:referer]
+       else
+         redirect_to :action => :account, :display_name => @user.display_name
+       end
      else
        @user = User.new(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
          @user.preferred_editor = params[:user][:preferred_editor]
        end
  
 -      if @user.save
 -        set_locale
 -
 -        if @user.new_email.nil? or @user.new_email.empty?
 -          flash[:notice] = t 'user.account.flash update success'
 -        else
 -          flash[:notice] = t 'user.account.flash update success confirm needed'
 +      @user.openid_url = nil if params[:user][:openid_url].empty?
  
 -          begin
 -            Notifier.deliver_email_confirm(@user, @user.tokens.create)
 -          rescue
 -            # Ignore errors sending email
 -          end
 -        end
 -
 -        redirect_to :action => "account", :display_name => @user.display_name
 +      if params[:user][:openid_url].length > 0 and
 +         params[:user][:openid_url] != @user.openid_url
 +        # If the OpenID has changed, we want to check that it is a
 +        # valid OpenID and one the user has control over before saving
 +        # it as a password equivalent for the user.
 +        session[:new_user] = @user
 +        openid_verify(params[:user][:openid_url], @user)
 +      else
 +        update_user(@user)
 +      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|
 +        update_user(user)
        end
      else
        if flash[:errors]
  
    def new
      @title = t 'user.new.title'
 -
 -    # The user is logged in already, so don't show them the signup
 -    # page, instead send them to the home page
 -    redirect_to :controller => 'site', :action => 'index' if session[:user]
 +    @referer = params[:referer] || session[:referer]
 +
 +    if session[:user]
 +      # The user is logged in already, so don't show them the signup
 +      # page, instead send them to the home page
 +      redirect_to :controller => 'site', :action => 'index'
 +    elsif not params['openid'].nil?
 +      flash.now[:notice] = t 'user.new.openid association'
 +    end
    end
  
    def login
 -    @title = t 'user.login.title'
 +    if params[:username] or using_open_id?
 +      session[:remember_me] ||= params[:remember_me]
 +      session[:referer] ||= params[:referer]
  
 -    if params[:user]
 -      email_or_display_name = params[:user][:email]
 -      pass = params[:user][:password]
 -      user = User.authenticate(:username => email_or_display_name, :password => pass)
 -
 -      if user
 -        session[:user] = user.id
 -        session_expires_after 1.month if params[:remember_me]
 -
 -        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
 -      elsif user = User.authenticate(:username => email_or_display_name, :password => pass, :pending => true)
 -        flash.now[:error] = t 'user.login.account not active', :reconfirm => url_for(:action => 'confirm_resend', :display_name => user.display_name)
 -      elsif User.authenticate(:username => email_or_display_name, :password => pass, :suspended => true)
 -        webmaster = link_to t('user.login.webmaster'), "mailto:webmaster@openstreetmap.org"
 -        flash.now[:error] = t 'user.login.account suspended', :webmaster => webmaster
 +      if using_open_id?
 +        openid_authentication(params[:openid_url])
        else
 -        flash.now[:error] = t 'user.login.auth failure'
 +        password_authentication(params[:username], params[:password])
        end
      elsif flash[:notice].nil?
        flash.now[:notice] =  t 'user.login.notice'
  
  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.
    rescue ActiveRecord::RecordNotFound
      redirect_to :controller => 'user', :action => 'view', :display_name => params[:display_name] unless @this_user
    end
+   ##
+   # Choose the layout to use. See
+   # https://rails.lighthouseapp.com/projects/8994/tickets/5371-layout-with-onlyexcept-options-makes-other-actions-render-without-layouts
+   def choose_layout
+     oauth_url = url_for(:controller => :oauth, :action => :oauthorize, :only_path => true)
+     if [ 'api_details' ].include? action_name
+       nil
+     elsif params[:referer] and URI.parse(params[:referer]).path == oauth_url
+       'slim'
+     else
+       'site'
+     end
+   end
+   ##
+   #
+   def disable_terms_redirect
+     # this is necessary otherwise going to the user terms page, when 
+     # having not agreed already would cause an infinite redirect loop.
+     # it's .now so that this doesn't propagate to other pages.
+     flash.now[:skip_terms] = true
+   end
  end
index 161f8f4f9882290bbfed9bcdba59f20075e9c993,abece879f7622bb2362c36372b69f17acf5cfe73..16f3ad7d39ed00b2e559d0864514637bc202a081
      <td><%= f.password_field :pass_crypt_confirmation, {:value => '', :size => 30, :maxlength => 255, :autocomplete => :off} %></td>
    </tr>
  
 +  <tr>
 +    <td class="fieldName" ><%= t 'user.account.openid.openid' %></td>
 +    <td><%= f.text_field :openid_url, {:class => "openid_url"} %> <span class="minorNote">(<a href="<%= t 'user.account.openid.link' %>" target="_new"><%= t 'user.account.openid.link text' %></a>)</span></td>
 +  </tr>
 +
    <tr>
      <td class="fieldName" valign="top"><%= t 'user.account.public editing.heading' %></td>
      <td>
  
    <tr id="homerow" <% unless @user.home_lat and @user.home_lon %> class="nohome" <%end%> >
      <td class="fieldName"><%= t 'user.account.home location' %></td>
-     <td><em class="message"><%= t 'user.account.no home location' %></em><span class="location"><%= t 'user.account.latitude' %> <%= f.text_field :home_lat, :size => 20, :id => "home_lat" %><%= t 'user.account.longitude' %><%= f.text_field :home_lon, :size => 20, :id => "home_lon" %></span></td>
+     <td><em class="message"><%= t 'user.account.no home location' %></em><span class="location"><%= t 'user.account.latitude' %> <%= f.text_field :home_lat, :size => 20, :id => "home_lat" %> <%= t 'user.account.longitude' %><%= f.text_field :home_lon, :size => 20, :id => "home_lon" %></span></td>
    </tr>
  
    <tr>
  </table>
  <% end %>
  
- <%= render :partial => 'map' %>
+ <%= render :partial => 'map', :locals => { :setting_location => true,  :show_other_users => false } %>
  
  <% unless @user.data_public? %>
  <a name="public"></a>
index 3e93ff20c6dacfda9d9a6a75c7df281137814836,5160716d16abf14aa713daf5639933e30fee6934..ded9b4db681edde57f9fcf9c868fdb13466c781a
@@@ -13,7 -13,7 +13,7 @@@
              :before => update_page do |page|
                page.replace_html 'contributorTerms', image_tag('searching.gif')
              end,
-             :url => {:legale => legale, :has_decline => @user.new_record?}
+             :url => {:legale => legale}
            )
        %>
        <%= label_tag "legale_#{legale}", t('user.terms.legale_names.' + name) %>
@@@ -22,7 -22,7 +22,7 @@@
  <% end %>
  
  <div id="contributorTerms">
-   <%= render :partial => "terms", :locals => { :has_decline => @user.new_record? }  %>
+   <%= render :partial => "terms" %>
  </div>
  
  <% form_tag({:action => "save"}, { :id => "termsForm" }) do %>
    </p>
    <p>
      <%= hidden_field_tag('referer', h(params[:referer])) unless params[:referer].nil? %>
 -    <% if params[:user] %>
 +    <% if @user.new_record? %>
        <%= hidden_field('user', 'email') %>
        <%= hidden_field('user', 'email_confirmation') %>
        <%= 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>
diff --combined config/locales/en.yml
index 1fa2831ead11a07eb64a181785e08bff883d8426,8fb88491425f07f4cf00822c69c41434b891cd62..1509ba91733bde6c21dd2b85b20536f6822d8af2
@@@ -141,6 -141,8 +141,8 @@@ en
      common_details:
        edited_at: "Edited at:"
        edited_by: "Edited by:"
+       deleted_at: "Deleted at:"
+       deleted_by: "Deleted by:"
        version: "Version:"
        in_changeset: "In changeset:"
        changeset_comment: "Comment:"
        zoom_or_select: "Zoom in or select an area of the map to view"
        drag_a_box: "Drag a box on the map to select an area"
        manually_select: "Manually select a different area"
+       hide_areas: "Hide areas"
+       show_areas: "Show areas"
        loaded_an_area_with_num_features: "You have loaded an area which contains [[num_features]] features. In general, some browsers may not cope well with displaying this quantity of data. Generally, browsers work best at displaying less than 100 features at a time: doing anything else may make your browser slow/unresponsive. If you are sure you want to display this data, you may do so by clicking the button below."
        load_data: "Load Data"
        unable_to_load_size: "Unable to load: Bounding box size of [[bbox_size]] is too large (must be smaller than {{max_bbox_size}})"
      community_blogs_title: "Blogs from members of the OpenStreetMap community"
      foundation: Foundation
      foundation_title: The OpenStreetMap Foundation
+     sotm2011: 'Come to the 2011 OpenStreetMap Conference, The State of the Map, September 9-11th in Denver!'
      license:
        alt: CC by-sa 2.0
        title: OpenStreetMap data is licensed under the Creative Commons Attribution-Share Alike 2.0 Generic License
            Resources Canada), CanVec (&copy; Department of Natural
            Resources Canada), and StatCan (Geography Division,
            Statistics Canada).</li>
+           <li><strong>France</strong>: Contains data sourced from
+           Direction Générale des Impôts.</li>
            <li><strong>New Zealand</strong>: Contains data sourced from
            Land Information New Zealand. Crown Copyright reserved.</li>
            <li><strong>Poland</strong>: Contains data from <a
        anon_edits_link_text: "Find out why this is the case."
        flash_player_required: 'You need a Flash player to use Potlatch, the OpenStreetMap Flash editor. You can <a href="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">download Flash Player from Adobe.com</a>. <a href="http://wiki.openstreetmap.org/wiki/Editing">Several other options</a> are also available for editing OpenStreetMap.'
        potlatch_unsaved_changes: "You have unsaved changes. (To save in Potlatch, you should deselect the current way or point, if editing in live mode, or click save if you have a save button.)"
+       potlatch2_not_configured: "Potlatch 2 has not been configured - please see http://wiki.openstreetmap.org/wiki/The_Rails_Port#Potlatch_2 for more information"
        potlatch2_unsaved_changes: "You have unsaved changes. (To save in Potlatch 2, you should click save.)"
        no_iframe_support: "Your browser doesn't support HTML iframes, which are necessary for this feature."
      sidebar:
        help: "Help"
        help_url: "http://wiki.openstreetmap.org/wiki/Upload"
      trace_header:
-       your_traces: "See just your traces"
        upload_trace: "Upload a trace"
        see_all_traces: "See all traces"
-       see_your_traces: "See all your traces"
+       see_your_traces: "See your traces"
        traces_waiting: "You have {{count}} traces waiting for upload. Please consider waiting for these to finish before uploading any more, so as not to block the queue for other users."
      trace_optionals:
        tags: "Tags"
        cookies_needed: "You appear to have cookies disabled - please enable cookies in your browser before continuing."
      setup_user_auth:
        blocked: "Your access to the API has been blocked. Please log-in to the web interface to find out more."
+       need_to_see_terms: "Your access to the API is temporarily suspended. Please log-in to the web interface to view the Contributor Terms. You do not need to agree, but you must view them."
    oauth:
      oauthorize:
        request_access: "The application {{app_name}} is requesting access to your account. Please check whether you would like the application to have the following capabilities. You may choose as many or as few as you like."
      login:
        title: "Login"
        heading: "Login"
 -      please login: "Please login or {{create_user_link}}."
 -      create_account: "create an account"
        email or username: "Email Address or Username:"
        password: "Password:"
 +      openid: "{{logo}} OpenID:"
        remember: "Remember me:"
        lost password link: "Lost your password?"
        login_button: "Login"
        register now: Register now
 -      already have: Already have an OpenStreetMap account? Please login.
 +      with username: "Already have an OpenStreetMap account? Please login with your username and password:"
 +      with openid: "Alternatively please use your OpenID to login:"
        new to osm: New to OpenStreetMap?
        to make changes: To make changes to the OpenStreetMap data, you must have an account.
        create account minute: Create an account. It only takes a minute.
        webmaster: webmaster
        auth failure: "Sorry, could not log in with those details."
        notice: "<a href=\"http://www.osmfoundation.org/wiki/License/We_Are_Changing_The_License\">Find out more about OpenStreetMap's upcoming license change</a> (<a href=\"http://wiki.openstreetmap.org/wiki/ODbL/We_Are_Changing_The_License\">translations</a>) (<a href=\"http://wiki.openstreetmap.org/wiki/Talk:ODbL/Upcoming\">discussion</a>)"
 +      openid missing provider: "Sorry, could not contact your OpenID provider"
 +      openid invalid: "Sorry, your OpenID seems to be malformed"
 +      openid_logo_alt: "Log in with an OpenID"
 +      openid_providers:
 +        openid:
 +          title: Login with an OpenID URL
 +          alt: Login with an OpenID URL
 +        yahoo:
 +          title: Login with a Yahoo! OpenID
 +          alt: Login with a Yahoo! OpenID
 +        google:
 +          title: Login with a Google OpenID
 +          alt: Login with a Google OpenID
 +        myopenid:
 +          title: Login with a myOpenID OpenID
 +          alt: Login with a myOpenID OpenID
 +        wordpress:
 +          title: Login with a Wordpress.com OpenID
 +          alt: Login with a Wordpress.com OpenID
 +        myspace:
 +          title: Login with a MySpace OpenID
 +          alt: Login with a MySpace OpenID
      logout:
        title: "Logout"
        heading: "Logout from OpenStreetMap"
        not displayed publicly: 'Not displayed publicly (see <a href="http://wiki.openstreetmap.org/wiki/Privacy_Policy" title="wiki privacy policy including section on email addresses">privacy policy</a>)'
        display name: "Display Name:"
        display name description: "Your publicly displayed username. You can change this later in the preferences."
 +      openid: "{{logo}} OpenID:"
        password: "Password:"
        confirm password: "Confirm Password:"
 +      use openid: "Alternatively, use {{logo}} OpenID to login"
 +      openid no password: "With OpenID a password is not required, but some extra tools or server may still need one."
 +      openid association: |
 +        <p>Your OpenID is not associated with a OpenStreetMap account yet.</p>
 +        <ul>
 +          <li>If you are new to OpenStreetMap, please create a new account using the form below.</li>
 +          <li>
 +            If you already have an account, you can login to your account
 +            using your username and password and then associate the account
 +            with your OpenID in your user settings.
 +          </li>
 +        </ul> 
        continue: Continue
        flash create success message: "Thanks for signing up. We've sent a confirmation note to {{email}} and as soon as you confirm your account you'll be able to get mapping.<br /><br />If you use an antispam system which sends confirmation requests then please make sure you whitelist webmaster@openstreetmap.org as we are unable to reply to any confirmation requests."
        terms accepted: "Thanks for accepting the new contributor terms!"
+       terms declined: "We are sorry that you have decided to not accept the new Contributor Terms. For more information, please see <a href=\"{{url}}\">this wiki page</a>."
+       terms declined url: http://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined
      terms:
        title: "Contributor terms"
        heading: "Contributor terms"
        agree: Agree
        declined: "http://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined"
        decline: "Decline"
+       you need to accept or decline: "Please read and then either accept or decline the new Contributor Terms to continue."
        legale_select: "Please select your country of residence:"
        legale_names:
          france: "France"
        current email address: "Current Email Address:"
        new email address: "New Email Address:"
        email never displayed publicly: "(never displayed publicly)"
 +      openid:
 +        openid: "OpenID:"
 +        link: "http://wiki.openstreetmap.org/wiki/OpenID"
 +        link text: "what is this?"
        public editing:
          heading: "Public editing:"
          enabled: "Enabled. Not anonymous and can edit data."
diff --combined config/locales/is.yml
index be2f08452827372e2a041eb3907a27a029f0b9fd,bf033ac8a8776b0454cb2514559eae5c5dd662f5..505973def8dadbd0d019f52c8962e8bc4b324e10
@@@ -1,6 -1,6 +1,6 @@@
  # Messages for Icelandic (Íslenska)
  # Exported from translatewiki.net
- # Export driver: syck
+ # Export driver: syck-pecl
  # Author: Ævar Arnfjörð Bjarmason
  is: 
    activerecord: 
        current email address: "Núverandi netfang:"
        delete image: Eyða þessari mynd
        email never displayed publicly: (aldrei sýnt opinberlega)
 +      openid:
 +        link text: "hvað er openID?"
        flash update success: Stillingarnar þínar voru uppfærðar.
        flash update success confirm needed: Stillingarnar þínar voru uppfærðar. Póstur var sendur á netfangið þitt sem þú þarft að bregðast við til að netfangið þitt verði staðfest.
        home location: "Staðsetning:"
        remember: "Muna innskráninguna:"
        title: Innskrá
        webmaster: vefstjóra
 +      openid_heading: "Innskráning með OpenID:"
 +      username_heading: "Innskráning með OpenStreetMap aðgang:"
 +      openid_logo_alt: "Innskrá með OpenID"
 +      openid_providers:
 +        openid:
 +          title: Innskrá með OpenID slóð
 +          alt: Innskrá með OpenID slóð
 +        yahoo:
 +          title: Innsrká með Yahoo! OpenID
 +          alt: Innsrká með Yahoo! OpenID
 +        google:
 +          title: Innsrká með Google OpenID
 +          alt: Innsrká með Google OpenID
 +        myopenid:
 +          title: Innsrká með myOpenID OpenID
 +          alt: Innsrká með myOpenID OpenID
 +        wordpress:
 +          title: Innsrká með Wordpress.com OpenID
 +          alt: Innsrká með Wordpress.com OpenID
 +        myspace:
 +          title: Innsrká með MySpace OpenID
 +          alt: Innsrká með MySpace OpenID
      logout: 
        heading: Útskrá
        logout_button: Útskrá
        no_auto_account_create: Því miður getum við eki búið til reikning fyrir þig sjálfkrafa.
        not displayed publicly: Ekki sýnt opinberlega (sjá <a href="http://wiki.openstreetmap.org/index.php?uselang=is&title=Privacy_Policy" title="Meðferð persónuupplýsinga, þ.á.m. netfanga">meðferð persónuupplýsinga</a>)
        password: "Lykilorð:"
 +      openID associate: "Tengja OpenID við þennan aðgang"
 +      openID: "OpenID:"
 +      openID description: '(Valfrjálst) Ef þú ert með <a href="http://wiki.openstreetmap.org/wiki/openID">OpenID</a> getur þú tengt það við nýja aðganginn þinn.'
 +      openID nopassword: "Með OpenID þarft þú ekki að gefa upp lykilorð við innskráningu. Í stað þess notar þú OpenID."
 +      openID association: |
 +        Þetta OpenID er ekki tengt við neinn OpenStreetMap aðgang.
 +        <ul>
 +          <li>Ef þú ert ekki með OpenStreetMap aðgang getur þú búið til nýjan aðgang hér fyrir neðan.</li>
 +          <li>
 +            Ef þú ert þegar með aðgang skaltu innskrá þig með
 +            honum. Svo getur þú tengt OpenID við aðganginn þinn á
 +            stillingarsíðunni.
 +          </li>
 +        </ul> 
 +      signup: Nýskrá
        title: Nýskrá
      no_such_user: 
        body: Það er ekki til notandi með nafninu {{user}}. Kannski slóstu nafnið rangt inn eða fylgdir ógildum tengli.
index 3051f52d16663b0f868efef0e54644f8073d4fe2,1ea7a5bd29553dbabb83ab3791911e6c69cfbd35..18c7917f32d2b65ad42983babf3e533938f6c1a3
@@@ -10,6 -10,10 +10,10 @@@ body 
    padding: 0px;
  }
  
+ body.slim {
+   background-color: #f0f0f0;
+ }
  /* Rules for links */
  
  a {
@@@ -63,6 -67,12 +67,12 @@@ hr 
    margin: 0px;
  }
  
+ /* Rules for the site name */
+ #small-title {
+   display: none;
+ }
  /* Rules for the introductory text displayed in the left sidebar to new users */
  
  #intro {
  /* Rules for SOTM advert */
  
  #sotm {
-   width: 170px;
+   width: 180px;
+   min-width: 180px;
+   margin: 5px;
    padding: 0px;
+   border: 0px;
+   background: #fff;
  }
  
  /*
    text-align: left;
  }
  
+ #slim_container {
+   width: 100%;
+ }
+ #slim_container_content {
+   max-width: 50em;
+   background-color: #FFFFFF;
+   margin: 10px auto;
+   padding: 3px;
+   border-radius: 25px;
+   -moz-border-radius: 25px;
+   border: 1px solid #e6e6e6;
+ }
+ #slim_content {
+   margin: 10px;
+   margin-top: 90px;
+   max-width: 50em;
+ }
+ #slim_header {
+   margin: 10px;
+   position: absolute;
+   top: 0px;
+ }
+ #slim_header img {
+   vertical-align: middle;
+   margin-right: 5px;
+   margin-bottom: 5px;
+ }
  /* Rules for the changeset list shown by the history tab etc */
  
- #changeset_list, #keyvalue {
-   width: 100%;
+ #changeset_list_container {
+   position: relative;
+ }
+ #changeset_list {
+   width: 50%;
    font-size: small;
    text-align: left;
    border-collapse: collapse;
    border-width: 0px;
+   margin-top: 1px;
+   margin-bottom: 1px;
+ }
+ #changeset_list td {
+   vertical-align: top;
+   padding: 3px;
  }
  
  #changeset_list .date {
    white-space: nowrap;
  }
  
- #changeset_list.th {
-   font-weight: bold;
+ #changeset_list .selected {
+   background-color: rgb(255, 255, 160);
+   background-color: rgba(255, 255, 85, 0.5);
+ }
+ #changeset_list_map {
+   float: right;
+   position: absolute;
+   top: 0px;
+   bottom: 0px;
+   right: 0px;
+   width: 49%;
+   min-height: 400px;
+   border: solid 1px black;
  }
  
  /* Rules for the data browser */
    margin-left: 10px;
  }
  
+ table.browse_details th {
+   white-space: nowrap;
+ }
  #browse_map {
    float: right;
    width: 250px;
  
  /* Rules for the login page */
  
- #login_wrapper {
-   float: left; /* ensures the child divs are the same size, and only as wide as they need to be */
- }
  #login_wrapper div {
    margin: 5px;
    padding: 15px;
  }
  
  #login_login {
-   background-color: #f0f0f0;
+   background-color: #f5f5ff;
+   border: 1px solid #f3f3ff;
+   border-radius: 15px;
+   -moz-border-radius: 15px;
  }
  
  #login_login h1 {
    margin-top: 5px;
  }
  
 +#login_openid_buttons img {
 +  border: 0;
 +}
 +
  #login_signup form.button-to div {
    margin: 0px;
    padding: 0px;
@@@ -667,7 -735,11 +739,11 @@@ div#contributorTerms 
    padding: 4px;
    overflow: auto;
    width: 80%;
-   height: 60%;
+   height: 400px;
+ }
+ div#slim_content div#contributorTerms {
+   width: auto;
  }
  
  div#contributorTerms p#first {
@@@ -691,6 -763,11 +767,11 @@@ div#contributorTerms img 
  
  form#termsForm {
    width: 80%;
+   margin-bottom: 3em;
+ }
+ div#slim_content form#termsForm {
+   width: auto;
  }
  
  form#termsForm div#buttons {
@@@ -842,11 -919,6 +923,11 @@@ input[type="submit"] 
    border: 1px solid black;
  }
  
 +input.openid_url { 
 +  background: url('../images/openid_input.png') repeat-y left white;
 +  padding-left: 16px;
 +}
 +
  /* Rules for user images */
  
  img.user_image {
@@@ -889,10 -961,3 +970,10 @@@ abbr.geo 
  .table1 { 
    background: #fff;
  }
 +
 +/* Rules for OpenID logo */
 +
 +.openid_logo {
 +  vertical-align: text-bottom;
 +  border: 0;
 +}
index c709bcba9b05c9f91929b0242bd878cc8dd43f9e,f4d51c868453d43c9e9edc781b262f8d9ab908d0..76fea4fccc3034b1f90216ab0e035365a66b3588
@@@ -22,7 -22,7 +22,7 @@@ h1 
  {
    height: 14px;
    margin: 0px;
-   padding-left: 10px;
+   padding-left: 3px;
    padding-top: 5px;
    margin-top: 18px;
    background: url('../images/tab_bottom.gif') repeat-x bottom;
    margin-right: 1px;
  }
  
+ /* Rules for the site name - shown when left sidebar is hidden */
+ #small-title {
+   font-size: 12px;
+   line-height: 14px;
+   height: 16px;
+   display: block;
+   position: absolute;
+   top: 0;
+   padding: 2px;
+   width: 110px; /* TODO: find better fix for overlap */
+   background-color: #fff;
+   z-index: 100;
+ }
+ #small-title img {
+   position: absolute;
+ }
+ #small-title h1 {
+   position: absolute;
+   left: 18px;
+   font-size: 12px;
+   margin: 2px;
+ }
  /* Rules for greeting bar in the top right corner */
  
  #greeting {
  
  /* Rules for the login form */
  
 -#loginForm input#user_email {
 +.loginBox {
 +  width: 90%;
 +}
 +
 +.loginBox input#user_email {
 +  width: 100%;
 +  max-width: 18em;
 +}
 +
 +.loginBox input#user_password {
    width: 100%;
    max-width: 18em;
  }
  
 -#loginForm input#user_password {
 +.loginBox input#user_openid_url {
    width: 100%;
    max-width: 18em;
  }
+ /* Rules for the profile page */
+ .user_map {
+   width: 100% !important;
+   height: 300px !important;
+ }
+ /* Rules for the user settings page */
+ #user_new_email {
+   width: 60% !important;
+ }
+ #user_description, #user_preferred_editor {
+   width: 90% !important;
+ }
+ .minorNote {
+   display: block;
+ }
+ /* Rules for the browse pages */
+ #browse_navigation {
+   width: 100% !important;
+   margin-top: 0 !important;
+ }
+ #small_map, #browse_map {
+   width: 100% !important;
+ }
+ #changeset_list tr {
+   display: block;
+   clear: left;
+   width: 100%;
+ }
+ #changeset_list th {
+   display: none;
+ }
+ #changeset_list td {
+   display: block;
+   float: left;
+   padding-right: 10px;
+ }
+ #changeset_list td.comment, #changeset_list td.area {
+   width: 96%;
+   clear: left;
+ }
+ /* Rules for the diary entries pages */
+ #diary_entry_title, #diary_entry_body, #diary_entry_language_code, #diary_comment_body {
+   width: 100% !important;
+ }
+ #usemap {
+   display: block;
+ }
+ /* Rules for the messaging pages */
+ #message_title, #message_body {
+   width: 100% !important;
+ }
diff --combined test/fixtures/users.yml
index 9802783fd0da0b7dfece5ca063f7ec3013497ad2,98517fd2aa86f9b24134f0ce560027349c93324a..360738c220fa4e0334c252b4424fb61d2d2d17f6
@@@ -11,6 -11,7 +11,7 @@@ normal_user
    home_lat: 12.1
    home_lon: 12.1
    home_zoom: 3
+   terms_seen: true
    
  public_user:
    id: 2
@@@ -24,6 -25,7 +25,7 @@@
    home_lat: 12
    home_lon: 12
    home_zoom: 12
+   terms_seen: true
    
  inactive_user:
    id: 3
@@@ -37,6 -39,7 +39,7 @@@
    home_lat: 123.4
    home_lon: 12.34
    home_zoom: 15
+   terms_seen: true
    
  second_public_user:
    id: 4
@@@ -50,6 -53,7 +53,7 @@@
    home_lat: 89
    home_lon: 87
    home_zoom: 12
+   terms_seen: true
  
  moderator_user:
    id: 5
@@@ -59,6 -63,7 +63,7 @@@
    creation_time: "2008-05-01 01:23:45"
    display_name: moderator
    data_public: true
+   terms_seen: true
  
  administrator_user:
    id: 6
    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
index 942a94302de8ec4195f2afdb46a0545aa3573af6,b4ca49022ec056c8b6fbccb6b283e5a4082b3640..7003d769251c2a97dbe0578a35bf627e60255c41
@@@ -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