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/helpers/application_helper.rb b/app/helpers/application_helper.rb index a4147313..549f2fbc 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -8,7 +8,7 @@ module ApplicationHelper # Replicates the link_to method but also checks request.request_uri to find # current page. If that matches the url, the link is marked id = "current" - # + # def navigation_link(name, options = {}, html_options = nil, *parameters_for_method_reference) if html_options html_options = html_options.stringify_keys @@ -29,7 +29,7 @@ module ApplicationHelper # Check due date in comparison to today's date Flag up date appropriately with # a 'traffic light' colour code - # + # def due_date(due) if due == nil return "" @@ -62,7 +62,7 @@ module ApplicationHelper # Check due date in comparison to today's date Flag up date appropriately with # a 'traffic light' colour code Modified method for mobile screen - # + # def due_date_mobile(due) if due == nil return "" @@ -92,7 +92,7 @@ module ApplicationHelper # Returns a count of next actions in the given context or project. The result # is count and a string descriptor, correctly pluralised if there are no # actions or multiple actions - # + # def count_undone_todos_phrase(todos_parent, string="actions") @controller.count_undone_todos_phrase(todos_parent, string) end @@ -143,5 +143,31 @@ module ApplicationHelper page.replace 'flash', "

#{message}

" page.visual_effect :fade, 'flash', :duration => fade_duration end - + + def recurrence_time_span(rt) + case rt.ends_on + when "no_end_date" + return rt.start_from.nil? ? "" : "from " + format_date(rt.start_from) + when "ends_on_number_of_times" + return "for "+rt.number_of_occurences.to_s + " times" + when "ends_on_end_date" + starts = rt.start_from.nil? ? "" : "from " + format_date(rt.start_from) + ends = rt.end_date.nil? ? "" : " until " + format_date(rt.end_date) + return starts+ends + else + raise Exception.new, "unknown recurrence time span selection (#{rt.ends_on})" + end + end + + def recurrence_pattern_as_text(recurring_todo) + rt = recurring_todo.recurring_target_as_text + rp = recurring_todo.recurrence_pattern + # only add space if recurrence_pattern has content + rp = " " + rp if !rp.nil? + rts = recurrence_time_span(recurring_todo) + # only add space if recurrence_time_span has content + rts = " " + rts if !(rts == "") + return rt+rp+rts + end + end diff --git a/app/helpers/recurring_todos_helper.rb b/app/helpers/recurring_todos_helper.rb index 76fcc95e..4ba1a690 100644 --- a/app/helpers/recurring_todos_helper.rb +++ b/app/helpers/recurring_todos_helper.rb @@ -1,30 +1,4 @@ module RecurringTodosHelper - - def recurrence_time_span(rt) - case rt.ends_on - when "no_end_date" - return rt.start_from.nil? ? "" : "from " + format_date(rt.start_from) - when "ends_on_number_of_times" - return "for "+rt.number_of_occurences.to_s + " times" - when "ends_on_end_date" - starts = rt.start_from.nil? ? "" : "from " + format_date(rt.start_from) - ends = rt.end_date.nil? ? "" : " until " + format_date(rt.end_date) - return starts+ends - else - raise Exception.new, "unknown recurrence time span selection (#{self.ends_on})" - end - end - - def recurrence_target(rt) - case rt.target - when 'due_date' - return "due" - when 'show_from_date' - return "show" - else - return "ERROR" - end - end def recurring_todo_tag_list tags_except_starred = @recurring_todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME} diff --git a/app/models/recurring_todo.rb b/app/models/recurring_todo.rb index be4e2414..7d24b7eb 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -295,6 +295,17 @@ class RecurringTodo < ActiveRecord::Base def recurring_target=(t) self.target = t end + + def recurring_target_as_text + case self.target + when 'due_date' + return "due" + when 'show_from_date' + return "show" + else + raise Exception.new, "unexpected value of recurrence target '#{self.target}'" + end + end def recurring_show_days_before=(days) self.show_from_delta=days @@ -361,6 +372,8 @@ class RecurringTodo < ActiveRecord::Base when 'show_from' # so leave due date empty return nil + else + raise Exception.new, "unexpected value of recurrence target '#{self.target}'" end end @@ -476,14 +489,14 @@ class RecurringTodo < ActiveRecord::Base when 0 # specific day of the month if start.mday >= day # there is no next day n in this month, search in next month - # + # # start += n.months - # + # # The above seems to not work. Fiddle with timezone. Looks like we hit a # bug in rails here where 2008-12-01 +0100 plus 1.month becomes # 2008-12-31 +0100. For now, just calculate in UTC and convert back to # local timezone. - # + # # TODO: recheck if future rails versions have this problem too start = Time.utc(start.year, start.month, start.day)+n.months start = Time.zone.local(start.year, start.month, start.day) 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 %>