From 14f2067a1eb8918c5f9a8897f376bffe587d137c Mon Sep 17 00:00:00 2001 From: lukemelia Date: Mon, 16 Apr 2007 02:19:20 +0000 Subject: [PATCH] Fix #498 (cannot login using mobile interface) by introducing a login page specialized for mobile devices. To support this, I added named routes for the login paths and pulled up the mobile content negotiation code to the ApplicationController. git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@531 a4c988fc-2ded-0310-b66e-134b36920a42 --- tracks/app/controllers/application.rb | 41 ++++++++++++++++++++-- tracks/app/controllers/login_controller.rb | 26 +++++++++++--- tracks/app/controllers/todos_controller.rb | 39 +------------------- tracks/app/views/layouts/standard.rhtml | 2 +- tracks/app/views/todos/index_mobile.rhtml | 2 +- tracks/config/routes.rb | 14 ++++++-- tracks/lib/login_system.rb | 6 ++-- 7 files changed, 76 insertions(+), 54 deletions(-) diff --git a/tracks/app/controllers/application.rb b/tracks/app/controllers/application.rb index 87de1415..00a77bc0 100644 --- a/tracks/app/controllers/application.rb +++ b/tracks/app/controllers/application.rb @@ -14,11 +14,12 @@ class ApplicationController < ActionController::Base helper :application include LoginSystem - layout 'standard' + layout proc{ |controller| controller.mobile? ? "mobile" : "standard" } before_filter :set_session_expiration prepend_before_filter :login_required - + prepend_before_filter :enable_mobile_content_negotiation + after_filter :restore_content_type_for_mobile after_filter :set_charset include ActionView::Helpers::TextHelper @@ -115,6 +116,37 @@ class ApplicationController < ActionController::Base def build_default_project_context_name_map(projects) Hash[*projects.reject{ |p| p.default_context.nil? }.map{ |p| [p.name, p.default_context.name] }.flatten].to_json end + + # Here's the concept behind this "mobile content negotiation" hack: + # In addition to the main, AJAXy Web UI, Tracks has a lightweight + # low-feature 'mobile' version designed to be suitablef or use + # from a phone or PDA. It makes some sense that tne pages of that + # mobile version are simply alternate representations of the same + # Todo resources. The implementation goal was to treat mobile + # as another format and be able to use respond_to to render both + # versions. Unfortunately, I ran into a lot of trouble simply + # registering a new mime type 'text/html' with format :m because + # :html already is linked to that mime type and the new + # registration was forcing all html requests to be rendered in + # the mobile view. The before_filter and after_filter hackery + # below accomplishs that implementation goal by using a 'fake' + # mime type during the processing and then setting it to + # 'text/html' in an 'after_filter' -LKM 2007-04-01 + def mobile? + return params[:format] == 'm' || response.content_type == MOBILE_CONTENT_TYPE + end + + def enable_mobile_content_negotiation + if mobile? + request.accepts.unshift(Mime::Type::lookup(MOBILE_CONTENT_TYPE)) + end + end + + def restore_content_type_for_mobile + if mobile? + response.content_type = 'text/html' + end + end protected @@ -126,7 +158,10 @@ class ApplicationController < ActionController::Base end def redirect_back_or_home - redirect_back_or_default home_url + respond_to do |format| + format.html { redirect_back_or_default home_url } + format.m { redirect_back_or_default mobile_url } + end end def boolean_param(param_name) diff --git a/tracks/app/controllers/login_controller.rb b/tracks/app/controllers/login_controller.rb index abef4a15..da55c577 100644 --- a/tracks/app/controllers/login_controller.rb +++ b/tracks/app/controllers/login_controller.rb @@ -1,6 +1,6 @@ class LoginController < ApplicationController - layout 'login' + layout 'login' skip_before_filter :set_session_expiration skip_before_filter :login_required before_filter :get_current_user @@ -20,6 +20,7 @@ class LoginController < ApplicationController notify :notice, "Login successful: session #{msg}" cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year } redirect_back_or_home + return else @login = params['user_login'] notify :warning, "Login unsuccessful" @@ -27,8 +28,13 @@ class LoginController < ApplicationController 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.rhtml', :layout => 'mobile' } + end end def begin @@ -44,10 +50,13 @@ class LoginController < ApplicationController # to the server using the redirect_url the library created for us. # redirect to the server - redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), url_for(:action => 'complete')) + 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 :action => 'login' + redirect_to_login end end @@ -92,14 +101,14 @@ class LoginController < ApplicationController else notify :warning, "Unknown response status: #{open_id_response.status}" end - redirect_to :action => 'login' unless performed? + redirect_to_login unless performed? end def logout session['user_id'] = nil reset_session notify :notice, "You have been logged out of Tracks." - redirect_to :action => "login" + redirect_to_login end def check_expiry @@ -122,6 +131,13 @@ class LoginController < ApplicationController private + def redirect_to_login + respond_to do |format| + format.html { redirect_to login_path } + format.m { redirect_to formatted_login_path(:format => 'm') } + end + end + def should_expire_sessions? session['noexpiry'] != "on" end diff --git a/tracks/app/controllers/todos_controller.rb b/tracks/app/controllers/todos_controller.rb index 54db5389..1224624d 100644 --- a/tracks/app/controllers/todos_controller.rb +++ b/tracks/app/controllers/todos_controller.rb @@ -7,13 +7,8 @@ class TodosController < ApplicationController append_before_filter :init, :except => [ :destroy, :completed, :completed_archive, :check_deferred ] append_before_filter :get_todo_from_params, :only => [ :edit, :toggle_check, :show, :update, :destroy ] - prepend_before_filter :enable_mobile_content_negotiation - after_filter :restore_content_type_for_mobile - session :off, :only => :index, :if => Proc.new { |req| is_feed_request(req) } - layout proc{ |controller| controller.mobile? ? "mobile" : "standard" } - def index @projects = @user.projects.find(:all, :include => [ :todos ]) @contexts = @user.contexts.find(:all, :include => [ :todos ]) @@ -317,39 +312,7 @@ class TodosController < ApplicationController end - # Here's the concept behind this "mobile content negotiation" hack: - # In addition to the main, AJAXy Web UI, Tracks has a lightweight - # low-feature 'mobile' version designed to be suitablef or use - # from a phone or PDA. It makes some sense that tne pages of that - # mobile version are simply alternate representations of the same - # Todo resources. The implementation goal was to treat mobile - # as another format and be able to use respond_to to render both - # versions. Unfortunately, I ran into a lot of trouble simply - # registering a new mime type 'text/html' with format :m because - # :html already is linked to that mime type and the new - # registration was forcing all html requests to be rendered in - # the mobile view. The before_filter and after_filter hackery - # below accomplishs that implementation goal by using a 'fake' - # mime type during the processing and then setting it to - # 'text/html' in an 'after_filter' -LKM 2007-04-01 - def mobile? - return params[:format] == 'm' || response.content_type == MOBILE_CONTENT_TYPE - end - - def enable_mobile_content_negotiation - if mobile? - request.accepts.unshift(Mime::Type::lookup(MOBILE_CONTENT_TYPE)) - end - end - - def restore_content_type_for_mobile - if mobile? - response.content_type = 'text/html' - end - end - - private - + private def get_todo_from_params @todo = @user.todos.find(params['id']) diff --git a/tracks/app/views/layouts/standard.rhtml b/tracks/app/views/layouts/standard.rhtml index 7498b664..1b45f717 100644 --- a/tracks/app/views/layouts/standard.rhtml +++ b/tracks/app/views/layouts/standard.rhtml @@ -35,7 +35,7 @@ page.select('.notes').each { |e| e.toggle } end -%> |  - <%= link_to "Logout (#{@user.display_name}) »", :controller => "login", :action=>"logout"%> + <%= link_to "Logout (#{@user.display_name}) »", logout_path %>