diff --git a/app/controllers/login_controller.rb b/app/controllers/login_controller.rb index a9b7e8be..8dc6a3bd 100644 --- a/app/controllers/login_controller.rb +++ b/app/controllers/login_controller.rb @@ -6,114 +6,45 @@ class LoginController < ApplicationController skip_before_filter :login_required before_filter :login_optional before_filter :get_current_user - open_id_consumer if openid_enabled? def login - @page_title = "TRACKS::Login" - @openid_url = cookies[:openid_url] if openid_enabled? - case request.method - when :post - if @user = User.authenticate(params['user_login'], params['user_password']) - session['user_id'] = @user.id - # If checkbox on login page checked, we don't expire the session after 1 hour - # of inactivity and we remember this user for future browser sessions - session['noexpiry'] = params['user_noexpiry'] - msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." - notify :notice, "Login successful: session #{msg}" - cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE } - unless should_expire_sessions? - @user.remember_me - cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE } + if openid_enabled? && using_open_id? + login_openid + else + @page_title = "TRACKS::Login" + case request.method + when :post + if @user = User.authenticate(params['user_login'], params['user_password']) + session['user_id'] = @user.id + # If checkbox on login page checked, we don't expire the session after 1 hour + # of inactivity and we remember this user for future browser sessions + session['noexpiry'] = params['user_noexpiry'] + msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." + notify :notice, "Login successful: session #{msg}" + cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE } + unless should_expire_sessions? + @user.remember_me + cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE } + end + redirect_back_or_home + return + else + @login = params['user_login'] + notify :warning, "Login unsuccessful" end - redirect_back_or_home - return - else - @login = params['user_login'] - notify :warning, "Login unsuccessful" - end - when :get - if User.no_users_yet? - redirect_to :controller => 'users', :action => 'new' - return - end - end - respond_to do |format| - format.html - format.m { render :action => 'login_mobile.html.erb', :layout => 'mobile' } + when :get + if User.no_users_yet? + redirect_to :controller => 'users', :action => 'new' + return + end + end + respond_to do |format| + format.html + format.m { render :action => 'login_mobile.html.erb', :layout => 'mobile' } + end end end - def begin - # If the URL was unusable (either because of network conditions, - # a server error, or that the response returned was not an OpenID - # identity page), the library will return HTTP_FAILURE or PARSE_ERROR. - # Let the user know that the URL is unusable. - case open_id_response.status - when OpenID::SUCCESS - session['openid_url'] = params[:openid_url] - session['user_noexpiry'] = params[:user_noexpiry] - # The URL was a valid identity URL. Now we just need to send a redirect - # to the server using the redirect_url the library created for us. - - # redirect to the server - respond_to do |format| - format.html { redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), open_id_complete_url) } - format.m { redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), formatted_open_id_complete_url(:format => 'm')) } - end - else - notify :warning, "Unable to find openid server for #{openid_url}" - redirect_to_login - end - end - - def complete - openid_url = session['openid_url'] - if openid_url.blank? - notify :error, "expected an openid_url" - end - - case open_id_response.status - when OpenID::FAILURE - # In the case of failure, if info is non-nil, it is the - # URL that we were verifying. We include it in the error - # message to help the user figure out what happened. - if open_id_response.identity_url - msg = "Verification of #{openid_url}(#{open_id_response.identity_url}) failed. " - else - msg = "Verification failed. " - end - notify :error, open_id_response.msg.to_s + msg - - when OpenID::SUCCESS - # Success means that the transaction completed without - # error. If info is nil, it means that the user cancelled - # the verification. - @user = User.find_by_open_id_url(openid_url) - unless (@user.nil?) - session['user_id'] = @user.id - session['noexpiry'] = session['user_noexpiry'] - msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." - notify :notice, "You have successfully verified #{openid_url} as your identity. Login successful: session #{msg}" - cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE } - unless should_expire_sessions? - @user.remember_me - cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE } - end - cookies[:openid_url] = { :value => openid_url, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE } - redirect_back_or_home - else - notify :warning, "You have successfully verified #{openid_url} as your identity, but you do not have a Tracks account. Please ask your administrator to sign you up." - end - - when OpenID::CANCEL - notify :warning, "Verification cancelled." - - else - notify :warning, "Unknown response status: #{open_id_response.status}" - end - redirect_to_login unless performed? - end - def logout @user.forget_me if logged_in? cookies.delete :auth_token @@ -156,5 +87,31 @@ class LoginController < ApplicationController def should_expire_sessions? session['noexpiry'] != "on" end - + + protected + + def login_openid + # If checkbox on login page checked, we don't expire the session after 1 hour + # of inactivity and we remember this user for future browser sessions + session['noexpiry'] ||= params['user_noexpiry'] + authenticate_with_open_id do |result, identity_url| + if result.successful? + if @user = User.find_by_identity_url(identity_url) + session['user_id'] = @user.id + msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire." + notify :notice, "Login successful: session #{msg}" + cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE } + unless should_expire_sessions? + @user.remember_me + cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE } + end + redirect_back_or_home + else + notify :warning, "Sorry, no user by that identity URL exists (#{identity_url})" + end + else + notify :warning, result.message + end + end + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 860f31cc..bad67adb 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,10 +1,4 @@ class UsersController < ApplicationController - - if openid_enabled? - open_id_consumer - before_filter :begin_open_id_auth, :only => :update_auth_type - end - before_filter :admin_login_required, :only => [ :index, :show, :destroy ] skip_before_filter :login_required, :only => [ :new, :create ] prepend_before_filter :login_optional, :only => [ :new, :create ] @@ -153,18 +147,25 @@ class UsersController < ApplicationController end def update_auth_type - if (params[:user][:auth_type] == 'open_id') && openid_enabled? - case open_id_response.status - when OpenID::SUCCESS - # The URL was a valid identity URL. Now we just need to send a redirect - # to the server using the redirect_url the library created for us. - session['openid_url'] = params[:openid_url] - - # redirect to the server - redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), url_for(:action => 'complete')) + if (params[:open_id_complete] || (params[:user][:auth_type] == 'open_id')) && openid_enabled? + authenticate_with_open_id do |result, identity_url| + if result.successful? + # Success means that the transaction completed without + # error. If info is nil, it means that the user cancelled + # the verification. + @user.auth_type = 'open_id' + @user.identity_url = identity_url + if @user.save + notify :notice, "You have successfully verified #{identity_url} as your identity and set your authentication type to Open ID." + else + debugger + notify :warning, "You have successfully verified #{identity_url} as your identity but there was a problem saving your authentication preferences." + end + redirect_to preferences_path else - notify :warning, "Unable to find openid server for #{openid_url}" + notify :warning, result.message redirect_to :action => 'change_auth_type' + end end return end @@ -178,47 +179,6 @@ class UsersController < ApplicationController end end - def complete - return unless openid_enabled? - openid_url = session['openid_url'] - if openid_url.blank? - notify :error, "expected an openid_url" - end - case open_id_response.status - when OpenID::FAILURE - # In the case of failure, if info is non-nil, it is the - # URL that we were verifying. We include it in the error - # message to help the user figure out what happened. - if open_id_response.identity_url - msg = "Verification of #{openid_url}(#{open_id_response.identity_url}) failed. " - else - msg = "Verification failed. " - end - notify :error, open_id_response.msg.to_s + msg - - when OpenID::SUCCESS - # Success means that the transaction completed without - # error. If info is nil, it means that the user cancelled - # the verification. - @user.auth_type = 'open_id' - @user.open_id_url = openid_url - if @user.save - notify :notice, "You have successfully verified #{openid_url} as your identity and set your authentication type to Open ID." - else - notify :warning, "You have successfully verified #{openid_url} as your identity but there was a problem saving your authentication preferences." - end - redirect_to preferences_path - - when OpenID::CANCEL - notify :warning, "Verification cancelled." - - else - notify :warning, "Unknown response status: #{open_id_response.status}" - end - redirect_to :action => 'change_auth_type' unless performed? - end - - def refresh_token @user.generate_token @user.save! diff --git a/app/models/user.rb b/app/models/user.rb index 33a9e4bc..0330cead 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -116,11 +116,11 @@ class User < ActiveRecord::Base validates_confirmation_of :password validates_length_of :login, :within => 3..80 validates_uniqueness_of :login, :on => :create - validates_presence_of :open_id_url, :if => :using_openid? + validates_presence_of :identity_url, :if => :using_openid? before_create :crypt_password, :generate_token before_update :crypt_password - before_save :normalize_open_id_url + before_save :normalize_identity_url #for will_paginate plugin cattr_accessor :per_page @@ -145,9 +145,9 @@ class User < ActiveRecord::Base return nil end - def self.find_by_open_id_url(raw_open_id_url) - normalized_open_id_url = normalize_open_id_url(raw_open_id_url) - find(:first, :conditions => ['open_id_url = ?', normalized_open_id_url]) + def self.find_by_identity_url(raw_identity_url) + normalized_identity_url = OpenIdAuthentication.normalize_url(raw_identity_url) + find(:first, :conditions => ['identity_url = ?', normalized_identity_url]) end def self.no_users_yet? @@ -235,15 +235,8 @@ protected crypted_password == sha1(pass) end - def normalize_open_id_url - return if open_id_url.nil? - self.open_id_url = self.class.normalize_open_id_url(open_id_url) + def normalize_identity_url + return if identity_url.nil? + self.identity_url = OpenIdAuthentication.normalize_url(identity_url) end - - def self.normalize_open_id_url(raw_open_id_url) - normalized = raw_open_id_url - normalized = "http://#{raw_open_id_url}" unless raw_open_id_url =~ /\:\/\// - normalized.downcase.chomp('/') - end - end diff --git a/app/views/login/login.html.erb b/app/views/login/login.html.erb index 039fdc59..7c76f964 100644 --- a/app/views/login/login.html.erb +++ b/app/views/login/login.html.erb @@ -36,7 +36,7 @@ <% if show_openid_form %>