From: Tom Hughes Date: Tue, 11 May 2010 20:22:43 +0000 (+0100) Subject: Merge branch 'master' into openid X-Git-Tag: live~6343 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/64f373dc598e9c672e1575622f2fc76c29655b8d Merge branch 'master' into openid Conflicts: app/controllers/user_controller.rb app/views/user/new.html.erb config/locales/en.yml public/stylesheets/common.css --- 64f373dc598e9c672e1575622f2fc76c29655b8d diff --cc app/controllers/user_controller.rb index 0144f69b6,e07b65af7..0459d9a53 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@@ -18,55 -18,45 +18,82 @@@ class UserController < ApplicationContr cache_sweeper :user_sweeper, :only => [:account, :set_status, :delete] - def save + def terms @title = t 'user.new.title' - @user = User.new(params[:user]) - + @legale = params[:legale] || OSM.IPToCountry(request.remote_ip) || APP_CONFIG['default_legale'] + @text = OSM.legal_text_for_country(@legale) - if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"}) - render :action => 'new' - else - if params[:open_id_complete] - # 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| - create_user(user) - end - else - session[:referer] = params[:referer] + if request.xhr? + render :update do |page| + page.replace_html "contributorTerms", :partial => "terms" + end - elsif @user.invalid? - render :action => 'new' ++ elsif params[:open_id_complete] ++ # 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) + - @user = User.new(params[: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] + - @user.status = "pending" - @user.data_public = true - @user.description = "" if @user.description.nil? - @user.creation_ip = request.remote_ip - @user.languages = request.user_preferred_languages ++ @user = User.new(params[:user]) ++ @user.openid_url = nil + - if 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 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.valid? - if params[:user][:openid_url].nil? or - params[:user][:openid_url].empty? - # No OpenID so just save - create_user(@user) - else - # Verify OpenID before saving - session[:new_user] = @user - openid_verify(params[:user][:openid_url], @user) - end ++ if @user.valid? ++ if params[:user][:openid_url].nil? or ++ params[:user][:openid_url].empty? ++ # No OpenID so just move on to the terms ++ render :action => 'terms' ++ else ++ # Verify OpenID before moving on ++ session[:new_user] = @user ++ openid_verify(params[:user][:openid_url], @user) + end ++ else ++ # Something is wrong, so rerender the form ++ render :action => 'new' + end + end + end + + def save + @title = t 'user.new.title' - # Render the signup page unless we have already been - # redirected or have managed to save the user - if response.location.nil? and @user.new_record? - render :action => "new" + 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') + else + @user = User.new(params[:user]) + + @user.status = "pending" + @user.data_public = true + @user.description = "" if @user.description.nil? + @user.creation_ip = request.remote_ip + @user.languages = request.user_preferred_languages + @user.terms_agreed = Time.now.getutc + + if @user.save + flash[:notice] = t 'user.new.flash create success message' - Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer])) ++ Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => session.delete(:referer))) + redirect_to :action => 'login' + else + render :action => 'new' end end end @@@ -368,176 -374,6 +395,164 @@@ 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) + failed_login t('user.login.account suspended') + 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_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 failed_login t('user.login.account suspended') + 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? + # Try and apply some heuristics to make common cases more user friendly + if openid_url = openid_alternate_url(openid_url) + openid_authentication(openid_url) + else + failed_login t('user.login.openid missing provider') + end + 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_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? + # Try and apply some heuristics to make common cases more user friendly + if openid_url = openid_alternate_url(openid_url) + openid_verify(openid_url, user) + 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 + + ## + # special case some common OpenID providers by applying heuristics + # to try and come up with an alternate URL if the supplied one fails + def openid_alternate_url(openid_url) + # 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. + if openid_url.match(/(.*)gmail.com(\/?)$/) or openid_url.match(/(.*)googlemail.com(\/?)$/) + return 'https://www.google.com/accounts/o8/id' + else + return nil + 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 + - ## - # save a new user - def create_user(user) - if user.save - flash[:notice] = t 'user.new.flash create success message' - - Notifier.deliver_signup_confirm(user, user.tokens.create(:referer => session.delete(:referer))) - - redirect_to :action => 'login' - end - 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. diff --cc app/views/user/new.html.erb index 992ec9be1,66d8826c2..83a4d39e4 --- a/app/views/user/new.html.erb +++ b/app/views/user/new.html.erb @@@ -8,85 -10,29 +8,83 @@@ <% else %> -

<%= t 'user.new.fill_form' %> -

+

<%= t 'user.new.fill_form' %>

-

<%= t 'user.new.license_agreement' %>

- <%= error_messages_for 'user' %> - <% form_tag :action => 'save' do %> + <% form_tag :action => 'terms' 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.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 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}) %>
 
+ <%= hidden_field_tag('referer', h(@referer)) unless @referer.nil? %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - ++ + +
<%= t 'user.new.email address' %><%= text_field(:user, :email, { :size => 50, :maxlength => 255, :tabindex => 1, :value => params[:email] }) %>
<%= t 'user.new.confirm email address' %><%= text_field(:user, :email_confirmation, { :size => 50, :maxlength => 255, :tabindex => 2, :value => params[:email] }) %>
<%= t 'user.new.not displayed publicly' %>
 
<%= t 'user.new.display name' %><%= text_field(:user, :display_name, { :size => 30, :maxlength => 255, :tabindex => 3, :value => params[:nickname] }) %>
<%= t 'user.new.display name description' %>
 
<%= t 'user.new.openid', :logo => openid_logo %><%= text_field(:user, :openid_url, { :size => 50, :maxlength => 255, :tabindex => 4, :value => params[:openid], :class => "openid_url" }) %>
 
<%= t 'user.new.password' %><%= password_field(:user, :pass_crypt, { :size => 30, :maxlength => 255, :tabindex => 5 }) %>
<%= t 'user.new.confirm password' %><%= password_field(:user, :pass_crypt_confirmation, { :size => 30, :maxlength => 255, :tabindex => 6 }) %>
+ <%= link_to_function(t('user.new.use openid', :logo => openid_logo)) { |page| page.hide 'openid_prompt'; page.show 'openid_spacer', 'openid_url', 'openid_note' } %> + <%= t 'user.new.openid no password' %> +
 
<%= submit_tag t('user.new.signup'), :tabindex => 6 %><%= submit_tag t('user.new.continue'), :tabindex => 6 %>
<% end %> +<%= + update_page_tag do |page| + if params[:openid] + page[:openid_prompt].hide + else + page[:openid_spacer].hide + page[:openid_url].hide + page[:openid_note].hide + end + end +%> + <%= javascript_include_tag 'https://ethnio.com/remotes/62786' %> <% end %> diff --cc app/views/user/terms.html.erb index 000000000,049e07ca7..ae801bc11 mode 000000,100644..100644 --- a/app/views/user/terms.html.erb +++ b/app/views/user/terms.html.erb @@@ -1,0 -1,46 +1,47 @@@ +

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

+ +

<%= t 'user.terms.press accept button' %>

+ + + <% form_tag :action => 'terms' do %> +

+ <%= t 'user.terms.legale_select' %> + <% [['france', 'FR'], ['italy', 'IT'], ['rest_of_world', 'GB']].each do |name,legale| %> + <%= + radio_button_tag 'legale', legale, @legale == legale, + :onchange => remote_function( + :before => update_page do |page| + page.replace_html 'contributorTerms', image_tag('searching.gif') + end, + :url => {:legale => legale} + ) + %> + <%= label_tag "legale_#{legale}", t('user.terms.legale_names.' + name) %> + <% end %> +

+ <% end %> + +
+ <%= render :partial => "terms" %> +
+ + <% form_tag({:action => "save"}, { :id => "termsForm" }) do %> +

+ + <%= check_box('user', 'consider_pd') %> + (<%= link_to(t('user.terms.consider_pd_why'), t('user.terms.consider_pd_why_url'), :target => :new)%>) +

+

+ <%= hidden_field_tag('referer', h(params[:referer])) unless params[:referer].nil? %> + <%= 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') %> +

+ <%= submit_tag(t('user.terms.decline'), :name => "decline", :id => "decline") %> + <%= submit_tag(t('user.terms.agree'), :name => "agree", :id => "agree") %> +
+

+ <% end %> diff --cc config/locales/en.yml index 7e6592165,5abae7222..cc2dc5e98 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@@ -1548,23 -1523,25 +1548,38 @@@ en not displayed publicly: 'Not displayed publicly (see privacy policy)' 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: | +

Your OpenID is not associated with a OpenStreetMap account yet.

+ - signup: Signup + continue: Continue 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." + terms: + heading: "Contributor terms" + press accept button: "Please read the agreement below and press the agree button to create your account." + consider_pd: "I consider my contributions to be in the Public Domain" + consider_pd_why: "what's this?" + consider_pd_why_url: http://wiki.openstreetmap.org/wiki/Why_would_I_want_my_contributions_to_be_public_domain + agree: Agree + declined: "http://wiki.openstreetmap.org/wiki/Contributor_Terms_Declined" + decline: "Decline" + legale_select: "Please select your country of residence:" + legale_button: "Go" + legale_names: + france: "France" + italy: "Italy" + rest_of_world: "Rest of the world" no_such_user: title: "No such user" heading: "The user {{user}} does not exist" diff --cc db/migrate/053_add_open_id_authentication_tables.rb index 7dfff209d,000000000..7dfff209d mode 100644,000000..100644 --- a/db/migrate/053_add_open_id_authentication_tables.rb +++ b/db/migrate/053_add_open_id_authentication_tables.rb diff --cc public/stylesheets/common.css index 0282e47f3,2590c2d5f..9d4ecb445 --- a/public/stylesheets/common.css +++ b/public/stylesheets/common.css @@@ -583,37 -583,47 +583,78 @@@ hr margin-top: 10px; } +/* Rules for the login form */ + +.loginBox { + float: left; + border-style: solid; + border-width: 1px; + padding-left: 10px; + padding-right: 10px; + padding-bottom: 10px; +} + +.loginBox table { + width: 100%; +} + +.loginBox img { + border: 0; +} + +.loginBox #openid_buttons img { + vertical-align: middle; +} + +.loginBox input[type="submit"] { + float: right; +} + +#openid_buttons { + margin-bottom: 20px; +} + + /* Rules for the account confirmation page */ + + div#contributorTerms { + border: 1px solid black; + padding: 4px; + overflow: auto; + width: 80%; + height: 60%; + } + + div#contributorTerms p#first { + margin-top: 0px; + } + + div#contributorTerms p#last { + margin-bottom: 0px; + } + + div#contributorTerms ol { + margin-bottom: 0px; + } + + div#contributorTerms img { + display: block; + margin-left: auto; + margin-right: auto; + margin-top: 10%; + } + + form#termsForm { + width: 80%; + } + + form#termsForm div#buttons { + float: right; + } + + form#termsForm input#agree { + margin-left: 50px; + } + /* Rules for the account settings page */ #accountForm td {