From: Tom Hughes Date: Mon, 19 Apr 2010 23:41:03 +0000 (+0100) Subject: Merge branch 'master' into openid X-Git-Tag: live~7012 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/d36fab2913d10bef4eae2cee7c34875f20311af9?hp=-c Merge branch 'master' into openid Conflicts: app/controllers/user_controller.rb app/views/user/login.html.erb config/locales/en.yml --- d36fab2913d10bef4eae2cee7c34875f20311af9 diff --combined app/controllers/user_controller.rb index 97e184b59,9551ac6d8..428a8b90c --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@@ -24,18 -24,6 +24,18 @@@ class UserController < ApplicationContr if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"}) render :action => 'new' else + #The redirect from the OpenID provider reenters here again + #and we need to pass the parameters through to the + #open_id_authentication function a second time + if params[:open_id_complete] + openid_verify('', true) + #We have set the user.openid_url to nil beforehand. If it hasn't + #been set to a new valid openid_url, it means the openid couldn't be validated + if @user.nil? or @user.openid_url.nil? + render :action => 'new' + return + end + else @user = User.new(params[:user]) @user.visible = true @@@ -43,52 -31,6 +43,52 @@@ @user.description = "" if @user.description.nil? @user.creation_ip = request.remote_ip @user.languages = request.user_preferred_languages + #Set the openid_url to nil as for one it is used + #to check if the openid could be validated and secondly + #to not get dupplicate conflicts for an empty openid + @user.openid_url = nil + +if (!params[:user][:openid_url].nil? and params[:user][:openid_url].length > 0) + if @user.pass_crypt.length == 0 + #if the password is empty, but we have a openid + #then generate a random passowrd to disable + #loging in via password + @user.pass_crypt = ActiveSupport::SecureRandom.base64(16) + @user.pass_crypt_confirmation = @user.pass_crypt + end + #Validate all of the other fields before + #redirecting to the openid provider + if !@user.valid? + render :action => 'new' + else + #TODO: Is it a problem to store the user variable with respect to password safty in the session variables? + #Store the user variable in the session for it to be accessible when redirecting back from the openid provider + session[:new_usr] = @user + begin + @norm_openid_url = OpenIdAuthentication.normalize_identifier(params[:user][:openid_url]) + rescue + flash.now[:error] = t 'user.login.openid invalid' + render :action => 'new' + return + end + #Verify that the openid provided is valid and that the user is the owner of the id + openid_verify(@norm_openid_url, true) + #openid_verify can return in two ways: + #Either it returns with a redirect to the openid provider who then freshly + #redirects back to this url if the openid is valid, or if the openid is not plausible + #and no provider for it could be found it just returns + #we want to just let the redirect through + if response.headers["Location"].nil? + render :action => 'new' + end + end + #At this point there was either an error and the page has been rendered, + #or there is a redirect to the openid provider and the rest of the method + #gets executed whenn this method gets reentered after redirecting back + #from the openid provider + return + end + end if @user.save flash[:notice] = t 'user.new.flash create success message' @@@ -104,15 -46,6 +104,15 @@@ @title = t 'user.account.title' @tokens = @user.oauth_tokens.find :all, :conditions => 'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null' + #The redirect from the OpenID provider reenters here again + #and we need to pass the parameters through to the + #open_id_authentication function + if params[:open_id_complete] + openid_verify('', false) + @user.save + return + end + if params[:user] and params[:user][:display_name] and params[:user][:description] @user.display_name = params[:user][:display_name] @user.new_email = params[:user][:new_email] @@@ -148,21 -81,6 +148,21 @@@ end end end + + if (params[:user][:openid_url].length > 0) + begin + @norm_openid_url = OpenIdAuthentication.normalize_identifier(params[:user][:openid_url]) + if (@norm_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 the openID as a password equivalent for + #the user. + openid_verify(@norm_openid_url, false) + end + rescue + flash.now[:error] = t 'user.login.openid invalid' + end + end + else if flash[:errors] flash[:errors].each do |attr,msg| @@@ -173,88 -91,6 +173,90 @@@ end end + def openid_specialcase_mapping(openid_url) + #Special case gmail.com, as it is pontentially a popular OpenID provider and unlike + #yahoo.com, where it works automatically, Google have hidden their OpenID endpoint + #somewhere obscure making it less userfriendly. + if (openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/) ) + return 'https://www.google.com/accounts/o8/id' + end + + return nil + end + + def openid_verify(openid_url,account_create) + authenticate_with_open_id(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. + #e.g. one can simply enter yahoo.com in the login box, i.e. no user specific url + #only once it comes back from the OpenID provider do we know the unique address for + #the user. + @user = session[:new_usr] unless @user #this is used for account creation when the user is not yet in the database + @user.openid_url = identity_url + elsif result.missing? + mapped_id = openid_specialcase_mapping(openid_url) + if mapped_id + openid_verify(mapped_id, account_create) + else + flash.now[:error] = t 'user.login.openid missing provider' + end + elsif result.invalid? + flash.now[:error] = t 'user.login.openid invalid' + else + flash.now[:error] = t 'user.login.auth failure' + end + end + end + + def open_id_authentication(openid_url) + #TODO: only ask for nickname and email, if we don't already have a user for that openID, in which case + #email and nickname are already filled out. I don't know how to do that with ruby syntax though, as we + #don't want to duplicate the do block + #On the other hand it also doesn't matter too much if we ask every time, as the OpenID provider should + #remember these results, and shouldn't repromt the user for these data each time. + 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| + 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. + #e.g. one can simply enter yahoo.com in the login box, i.e. no user specific url + #only once it comes back from the OpenID provider do we know the unique address for + #the user. + user = User.find_by_openid_url(identity_url) + if user + if user.visible? and user.active? + session[:user] = user.id + session_expires_after 1.month if session[:remember] + else + user = nil + flash.now[:error] = t 'user.login.account not active' + end + else + #We don't have a user registered to this OpenID. 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 + else if result.missing? + #Try and apply some heuristics to make common cases more userfriendly + mapped_id = openid_specialcase_mapping(openid_url) + if mapped_id + open_id_authentication(mapped_id) + else + flash.now[:error] = t 'user.login.openid missing provider' + end + else if result.invalid? + flash.now[:error] = t 'user.login.openid invalid' + else + flash.now[:error] = t 'user.login.auth failure' + end + end + end + end ++ ++ user + end + def go_public @user.data_public = true @user.save @@@ -310,76 -146,59 +312,74 @@@ 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 + # 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] + + @nickname = params['nickname'] + @email = params['email'] + @openID = params['openid'] end def login + @title = t 'user.login.title' - #The redirect from the OpenID provider reenters here again - 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] - - # The user is logged in, if the referer param exists, redirect - # them to that unless they've also got a block on them, in - # which case redirect them to the block so they can clear it. - if user.blocked_on_view - redirect_to user.blocked_on_view, :referrer => params[:referrer] - elsif params[:referer] - redirect_to params[:referer] ++ #The redirect from the OpenID provider reenters here again + #and we need to pass the parameters through to the + # open_id_authentication function + if params[:open_id_complete] - open_id_authentication('') - end - - if params[:user] and session[:user].nil? - if !params[:user][:openid_url].nil? and !params[:user][:openid_url].empty? - session[:remember] = params[:remember_me] - open_id_authentication(params[:user][:openid_url]) ++ user = open_id_authentication('') ++ elsif params[:user] ++ if !params[:user][:openid_url].nil? and !params[:user][:openid_url].empty? ++ session[:remember] = params[:remember_me] ++ user = open_id_authentication(params[:user][:openid_url]) + else - 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] - elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true) - flash.now[:error] = t 'user.login.account not active' - else - flash.now[:error] = t 'user.login.auth failure' - end - end ++ email_or_display_name = params[:user][:email] ++ pass = params[:user][:password] ++ ++ if user = User.authenticate(:username => email_or_display_name, :password => pass) ++ session[:user] = user.id ++ session_expires_after 1.month if params[:remember_me] ++ elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true) ++ flash.now[:error] = t 'user.login.account not active' + else - redirect_to :controller => 'site', :action => 'index' ++ flash.now[:error] = t 'user.login.auth failure' + end - elsif User.authenticate(:username => email_or_display_name, :password => pass, :inactive => true) - flash.now[:error] = t 'user.login.account not active' ++ end + end + - if session[:user] - # The user is logged in, if the referer param exists, redirect them to that - # unless they've also got a block on them, in which case redirect them to - # the block so they can clear it. - user = User.find(session[:user]) - block = user.blocked_on_view - if block - redirect_to block, :referrer => params[:referrer] ++ if user ++ # The user is logged in, if the referer param exists, redirect ++ # them to that unless they've also got a block on them, in ++ # which case redirect them to the block so they can clear it. ++ if user.blocked_on_view ++ redirect_to user.blocked_on_view, :referrer => params[:referrer] + elsif params[:referer] + redirect_to params[:referer] else - flash.now[:error] = t 'user.login.auth failure' + redirect_to :controller => 'site', :action => 'index' end - return end - - @title = t 'user.login.title' end def logout - if session[:token] - token = UserToken.find_by_token(session[:token]) - if token - token.destroy + @title = t 'user.logout.title' + + if params[:session] == request.session_options[:id] + if session[:token] + token = UserToken.find_by_token(session[:token]) + if token + token.destroy + end + session[:token] = nil + end + session[:user] = nil + session_expires_automatically + if params[:referer] + redirect_to params[:referer] + else + redirect_to :controller => 'site', :action => 'index' end - session[:token] = nil - end - session[:user] = nil - session_expires_automatically - if params[:referer] - redirect_to params[:referer] - else - redirect_to :controller => 'site', :action => 'index' end end @@@ -468,7 -287,11 +468,11 @@@ flash[:warning] = t 'user.make_friend.already_a_friend', :name => name end - redirect_to :controller => 'user', :action => 'view' + if params[:referer] + redirect_to params[:referer] + else + redirect_to :controller => 'user', :action => 'view' + end end end @@@ -483,7 -306,11 +487,11 @@@ flash[:error] = t 'user.remove_friend.not_a_friend', :name => friend.display_name end - redirect_to :controller => 'user', :action => 'view' + if params[:referer] + redirect_to params[:referer] + else + redirect_to :controller => 'user', :action => 'view' + end end end diff --combined app/models/user.rb index 1a4769544,f02c9a5cd..09e1a7d35 --- a/app/models/user.rb +++ b/app/models/user.rb @@@ -22,7 -22,6 +22,7 @@@ class User < ActiveRecord::Bas validates_confirmation_of :pass_crypt#, :message => ' must match the confirmation password' validates_uniqueness_of :display_name, :allow_nil => true validates_uniqueness_of :email + validates_uniqueness_of :openid_url, :allow_nil => true validates_length_of :pass_crypt, :within => 8..255 validates_length_of :display_name, :within => 3..255, :allow_nil => true validates_email_format_of :email @@@ -86,7 -85,7 +86,7 @@@ end def languages - attribute_present?(:languages) ? read_attribute(:languages).split(",") : [] + attribute_present?(:languages) ? read_attribute(:languages).split(/ *, */) : [] end def languages=(languages) diff --combined app/views/user/account.html.erb index c20f3526c,85e9aebef..badcc1249 --- a/app/views/user/account.html.erb +++ b/app/views/user/account.html.erb @@@ -6,6 -6,7 +6,6 @@@ <%= t 'user.new.display name' %> <%= f.text_field :display_name %> - <%= t 'user.account.current email address' %> <%= @user.email %> <%= t 'user.account.email never displayed publicly' %> @@@ -18,17 -19,13 +18,17 @@@ <%= t 'user.new.password' %> - <%= f.password_field :pass_crypt, {:value => '', :size => 30, :maxlength => 255} %> + <%= f.password_field :pass_crypt, {:value => '', :size => 30, :maxlength => 255, :autocomplete => :off} %> <%= t 'user.new.confirm password' %> - <%= f.password_field :pass_crypt_confirmation, {:value => '', :size => 30, :maxlength => 255} %> + <%= f.password_field :pass_crypt_confirmation, {:value => '', :size => 30, :maxlength => 255, :autocomplete => :off} %> + + <%= t 'user.account.openid.openid' %> + <%= f.text_field :openid_url %> (<%= t 'user.account.openid.link text' %>) + <%= t 'user.account.public editing.heading' %> @@@ -58,11 -55,11 +58,11 @@@ <% if @user.image.nil? %> <%= hidden_field_tag "image_action", "new" %> - <%= t 'user.account.new image' %>
<%= file_column_field "user", "image" %> + <%= t 'user.account.new image' %>
<%= file_column_field "user", "image" %>
<%= t 'user.account.image size hint' %> <% else %> - +
- + @@@ -72,7 -69,7 +72,7 @@@ - +
<%= image_tag url_for_file_column(@user, "image") %><%= image_tag url_for_file_column(@user, "image"), :class => "user_image" %> <%= radio_button_tag "image_action", "keep", true %> <%= t 'user.account.keep image' %>
<%= radio_button_tag "image_action", "new" %><%= t 'user.account.replace image' %>
<%= file_column_field "user", "image", :onchange => "$('image_action_new').checked = true" %>
<%= t 'user.account.replace image' %>
<%= file_column_field "user", "image", :onchange => "$('image_action_new').checked = true" %>
<%= t 'user.account.image size hint' %>
<% end %> @@@ -88,7 -85,7 +88,7 @@@

<%= t 'user.account.update home location on click' %> checked="checked" <% end %> id="updatehome" />

-
+
@@@ -99,7 -96,7 +99,7 @@@ <% end %> - <%= render :partial => 'friend_map' %> + <%= render :partial => 'map' %> <% unless @user.data_public? %> diff --combined app/views/user/login.html.erb index 269bbc0cc,cf7f4a819..46e7f7b8b --- a/app/views/user/login.html.erb +++ b/app/views/user/login.html.erb @@@ -1,17 -1,14 +1,16 @@@ -

<%= t 'user.login.heading' %>

+

<%= t 'user.login.heading' %>

<%= t 'user.login.please login', :create_user_link => link_to(t('user.login.create_account'), :controller => 'user', :action => 'new', :referer => params[:referer]) %>

<% form_tag :action => 'login' do %> <%= hidden_field_tag('referer', h(params[:referer])) %> - - - - - - - - + - - - - ++ ++ ++ ++ ++ ++
<%= t 'user.login.email or username' %><%= text_field('user', 'email',{:size => 28, :maxlength => 255, :tabindex => 1}) %>
<%= t 'user.login.password' %><%= password_field('user', 'password',{:size => 28, :maxlength => 255, :tabindex => 2}) %> (<%= link_to t('user.login.lost password link'), :controller => 'user', :action => 'lost_password' %>)

<%= t 'user.login.alternatively' %>

<%= t 'user.login.openid' %><%= text_field('user', 'openid_url',{:size => 28, :maxlength => 255, :tabindex => 3}) %> (<%= t 'user.account.openid.link text' %>)
 
 
<%= check_box_tag "remember_me", "yes", false, :tabindex => 3 %><%= submit_tag t('user.login.login_button'), :tabindex => 3 %>
<%= t 'user.login.email or username' %><%= text_field('user', 'email',{:value => "", :size => 28, :maxlength => 255, :tabindex => 1}) %>
<%= t 'user.login.password' %><%= password_field('user', 'password',{:value => "", :size => 28, :maxlength => 255, :tabindex => 2}) %> (<%= link_to t('user.login.lost password link'), :controller => 'user', :action => 'lost_password' %>)
<%= check_box_tag "remember_me", "yes", false, :tabindex => 3 %>
 
<%= submit_tag t('user.login.login_button'), :tabindex => 3 %>
<%= t 'user.login.password' %><%= password_field('user', 'password',{:value => "", :size => 28, :maxlength => 255, :tabindex => 2}) %> (<%= link_to t('user.login.lost password link'), :controller => 'user', :action => 'lost_password' %>)

<%= t 'user.login.alternatively' %>

<%= t 'user.login.openid' %><%= text_field('user', 'openid_url',{:size => 28, :maxlength => 255, :tabindex => 3}) %> (<%= t 'user.account.openid.link text' %>)
 
 
<%= check_box_tag "remember_me", "yes", false, :tabindex => 3 %><%= submit_tag t('user.login.login_button'), :tabindex => 3 %>
<% end %> diff --combined app/views/user/new.html.erb index 3059a0bc0,bd85664c0..d2c939bad --- a/app/views/user/new.html.erb +++ b/app/views/user/new.html.erb @@@ -21,22 -21,21 +21,24 @@@ <% form_tag :action => 'save' do %> <%= hidden_field_tag('referer', h(params[:referer])) unless params[:referer].nil? %> - + - + - + + + +
<%= t 'user.new.email address' %><%= text_field('user', 'email',{:size => 50, :maxlength => 255, :tabindex => 1}) %>
<%= t 'user.new.email address' %><%= text_field('user', 'email',{:size => 50, :maxlength => 255, :tabindex => 1, :value => @email}) %>
<%= t 'user.new.confirm email address' %><%= text_field('user', 'email_confirmation',{:size => 50, :maxlength => 255, :tabindex => 2}) %>
<%= t 'user.new.not displayed publicly' %>
 
<%= t 'user.new.display name' %><%= text_field('user', 'display_name',{:size => 30, :maxlength => 255, :tabindex => 3}) %>
<%= t 'user.new.display name' %><%= text_field('user', 'display_name',{:size => 30, :maxlength => 255, :tabindex => 3, :value => @nickname}) %>
<%= t 'user.new.display name description' %>
 
<%= t 'user.new.password' %><%= password_field('user', 'pass_crypt',{:size => 30, :maxlength => 255, :tabindex => 4}) %>
<%= t 'user.new.confirm password' %><%= password_field('user', 'pass_crypt_confirmation',{:size => 30, :maxlength => 255, :tabindex => 5}) %>
 
<%= t 'user.new.openID' %><%= text_field('user', 'openid_url',{:size => 50, :maxlength => 255, :tabindex => 6, :value => @openID}) %>
<%= t 'user.new.openID description' %>
 
<% end %> + <%= javascript_include_tag 'https://ethnio.com/remotes/62786' %> + <% end %> diff --combined config/environment.rb index 70a1ddbd5,539af83b2..01115ba97 --- a/config/environment.rb +++ b/config/environment.rb @@@ -52,8 -52,8 +52,9 @@@ Rails::Initializer.run do |config config.gem 'rmagick', :lib => 'RMagick' config.gem 'oauth', :version => '>= 0.3.6' config.gem 'httpclient' + config.gem 'ruby-openid', :lib => 'openid', :version => '>=2.0.4' config.gem 'SystemTimer', :version => '>= 1.1.3', :lib => 'system_timer' + config.gem 'sanitize' # Only load the plugins named here, in the order given. By default, all plugins # in vendor/plugins are loaded in alphabetical order. diff --combined config/locales/en.yml index b358cf8d3,8699d600c..2df80cd1d --- a/config/locales/en.yml +++ b/config/locales/en.yml @@@ -1,6 -1,9 +1,9 @@@ en: html: dir: ltr + time: + formats: + friendly: "%e %B %Y at %H:%M" activerecord: # Translates all the model names, which is used in error handling on the web site models: @@@ -76,10 -79,6 +79,6 @@@ with_id: "{{id}}" with_version: "{{id}}, v{{version}}" with_name: "{{name}} ({{id}})" - map: - view: View - edit: Edit - coordinates: "Coordinates:" browse: changeset: title: "Changeset" @@@ -328,7 -327,7 +327,7 @@@ heading: "The user {{user}} does not exist" body: "Sorry, there is no user with the name {{user}}. Please check your spelling, or maybe the link you clicked is wrong." diary_entry: - posted_by: "Posted by {{link_user}} at {{created}} in {{language_link}}" + posted_by: "Posted by {{link_user}} on {{created}} in {{language_link}}" comment_link: Comment on this entry reply_link: Reply to this entry comment_count: @@@ -338,9 -337,13 +337,13 @@@ hide_link: Hide this entry confirm: Confirm diary_comment: - comment_from: "Comment from {{link_user}} at {{comment_created_at}}" + comment_from: "Comment from {{link_user}} on {{comment_created_at}}" hide_link: Hide this comment confirm: Confirm + location: + location: "Location:" + view: "View" + edit: "Edit" feed: user: title: "OpenStreetMap diary entries for {{user}}" @@@ -938,7 -941,8 +941,8 @@@ friend_notification: subject: "[OpenStreetMap] {{user}} added you as a friend" had_added_you: "{{user}} has added you as a friend on OpenStreetMap." - see_their_profile: "You can see their profile at {{userurl}} and add them as a friend too if you wish." + see_their_profile: "You can see their profile at {{userurl}}." + befriend_them: "You can also add them as a friend at {{befriendurl}}." gpx_notification: greeting: "Hi," your_gpx_file: "It looks like your GPX file" @@@ -1035,9 -1039,13 +1039,13 @@@ message_sent: "Message sent" limit_exceeded: "You have sent a lot of messages recently. Please wait a while before trying to send any more." no_such_user: - title: "No such user or message" - heading: "No such user or message" - body: "Sorry there is no user or message with that name or id" + title: "No such user" + heading: "No such user" + body: "Sorry there is no user with that name." + no_such_message: + title: "No such message" + heading: "No such message" + body: "Sorry there is no message with that id." outbox: title: "Outbox" my_inbox: "My {{inbox_link}}" @@@ -1049,6 -1057,8 +1057,8 @@@ date: "Date" no_sent_messages: "You have no sent messages yet. Why not get in touch with some of the {{people_mapping_nearby_link}}?" people_mapping_nearby: "people mapping nearby" + reply: + wrong_user: "You are logged in as `{{user}}' but the message you have asked to reply to was not sent to that user. Please login as the correct user in order to reply." read: title: "Read message" reading_your_messages: "Reading your messages" @@@ -1061,6 -1071,7 +1071,7 @@@ reading_your_sent_messages: "Reading your sent messages" to: "To" back_to_outbox: "Back to outbox" + wrong_user: "You are logged in as `{{user}}' but the message you have asked to read to was not sent by or to that user. Please login as the correct user in order to read it." sent_message_summary: delete_button: "Delete" mark: @@@ -1183,7 -1194,7 +1194,7 @@@ heading: "Editing trace {{name}}" filename: "Filename:" download: "download" - uploaded_at: "Uploaded at:" + uploaded_at: "Uploaded:" points: "Points:" start_coord: "Start coordinate:" map: "map" @@@ -1224,7 -1235,7 +1235,7 @@@ pending: "PENDING" filename: "Filename:" download: "download" - uploaded: "Uploaded at:" + uploaded: "Uploaded:" points: "Points:" start_coordinates: "Start coordinate:" map: "map" @@@ -1351,15 -1362,15 +1362,20 @@@ create_account: "create an account" email or username: "Email Address or Username:" password: "Password:" + openid: "OpenID:" + openid description: "Use your OpenID to login" + alternatively: "Alternatively" + remember: "Remember me:" lost password link: "Lost your password?" login_button: "Login" account not active: "Sorry, your account is not active yet.
Please click on the link in the account confirmation email to activate your account." auth failure: "Sorry, could not log in with those details." + openid missing provider: "Sorry, could not contact your OpenID provider" + openid invalid: "Sorry, your OpenID seems misformed" + logout: + title: "Logout" + heading: "Logout from OpenStreetMap" + logout_button: "Logout" lost_password: title: "Lost password" heading: "Forgotten Password?" @@@ -1390,8 -1401,6 +1406,8 @@@ display name description: "Your publicly displayed username. You can change this later in the preferences." password: "Password:" confirm password: "Confirm Password:" + openID: "OpenID:" + openID description: '(Optional) If you have an OpenID you can associate it with this account to login' signup: Signup flash create success message: "User was successfully created. Check your email for a confirmation note, and you will be mapping in no time :-)

Please note that you will not be able to login until you've received and confirmed your email address.

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." no_such_user: @@@ -1404,6 -1413,7 +1420,7 @@@ my edits: my edits my traces: my traces my settings: my settings + oauth settings: oauth settings blocks on me: blocks on me blocks by me: blocks by me send message: send message @@@ -1418,16 -1428,14 +1435,14 @@@ created from: "Created from:" description: Description user location: User location - no home location: "No home location has been set." - if set location: "If you set your location, a pretty map and stuff will appear below. You can set your home location on your {{settings_link}} page." + if set location: "If you set your location, a pretty map and stuff will appear here. You can set your home location on your {{settings_link}} page." settings_link_text: settings your friends: Your friends no friends: You have not added any friends yet. km away: "{{count}}km away" m away: "{{count}}m away" - nearby users: "Nearby users:" - no nearby users: "There are no users who admit to mapping nearby yet." - my_oauth_details: "View my OAuth details" + nearby users: "Other nearby users" + no nearby users: "There are no other users who admit to mapping nearby yet." role: administrator: "This user is an administrator" moderator: "This user is a moderator" @@@ -1446,19 -1454,16 +1461,20 @@@ unhide_user: "unhide this user" delete_user: "delete this user" confirm: "Confirm" - friend_map: - your location: Your location - nearby mapper: "Nearby mapper: [[nearby_user]]" + popup: + your location: "Your location" + nearby mapper: "Nearby mapper" + friend: "Friend" account: title: "Edit account" my settings: My settings 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." @@@ -1476,6 -1481,7 +1492,7 @@@ keep image: "Keep the current image" delete image: "Remove the current image" replace image: "Replace the current image" + image size hint: "(square images at least 100x100 work best)" home location: "Home Location:" no home location: "You have not entered your home location." latitude: "Latitude:"