X-Git-Url: https://git.openstreetmap.org./rails.git/blobdiff_plain/ca558c692ebecfcf5f7ebb464d4592718f445038..45f12aa99e9f9634b5494c9f56a5a92168c62305:/app/controllers/user_controller.rb diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index e661aa1e2..3a4b00920 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -15,28 +15,85 @@ class UserController < ApplicationController before_filter :lookup_this_user, :only => [:activate, :deactivate, :hide, :unhide, :delete] filter_parameter_logging :password, :pass_crypt, :pass_crypt_confirmation - + def save @title = t 'user.new.title' if Acl.find_by_address(request.remote_ip, :conditions => {:k => "no_account_creation"}) render :action => 'new' else - @user = User.new(params[:user]) - - @user.visible = true - @user.data_public = true - @user.description = "" if @user.description.nil? - @user.creation_ip = request.remote_ip - @user.languages = request.user_preferred_languages - - if @user.save - flash[:notice] = t 'user.new.flash create success message' - Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer])) - redirect_to :action => 'login' - else - render :action => 'new' - end + #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 + @user.data_public = true + @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' + Notifier.deliver_signup_confirm(@user, @user.tokens.create(:referer => params[:referer])) + redirect_to :action => 'login' + else + render :action => 'new' + end end end @@ -48,7 +105,8 @@ class UserController < ApplicationController #and we need to pass the parameters through to the #open_id_authentication function if params[:open_id_complete] - openid_verify('') + openid_verify('', false) + @user.save return end @@ -85,18 +143,19 @@ class UserController < ApplicationController 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) - end - rescue - flash.now[:error] = t 'user.login.openid invalid' - end + 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 + end end @@ -111,7 +170,7 @@ class UserController < ApplicationController return nil end - def openid_verify(openid_url) + 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 @@ -119,24 +178,20 @@ class UserController < ApplicationController #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 - if @user.save - flash.now[:notice] = t 'user.account.flash update success' - end - else if result.missing? - mapped_id = openid_specialcase_mapping(openid_url) - if mapped_id - openid_verify(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 + 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 @@ -212,6 +267,7 @@ class UserController < ApplicationController @nickname = params['nickname'] @email = params['email'] + @openID = params['openid'] end def login @@ -226,7 +282,7 @@ class UserController < ApplicationController if params[:user] and session[:user].nil? - if !params[:user][:openid_url].empty? + if !params[:user][:openid_url].nil? and !params[:user][:openid_url].empty? open_id_authentication(params[:user][:openid_url]) else email_or_display_name = params[:user][:email] @@ -286,7 +342,7 @@ class UserController < ApplicationController #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'] + 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