mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-20 17:20:12 +01:00
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
This commit is contained in:
parent
fd5b871839
commit
14f2067a1e
7 changed files with 76 additions and 54 deletions
|
|
@ -14,11 +14,12 @@ class ApplicationController < ActionController::Base
|
||||||
helper :application
|
helper :application
|
||||||
include LoginSystem
|
include LoginSystem
|
||||||
|
|
||||||
layout 'standard'
|
layout proc{ |controller| controller.mobile? ? "mobile" : "standard" }
|
||||||
|
|
||||||
before_filter :set_session_expiration
|
before_filter :set_session_expiration
|
||||||
prepend_before_filter :login_required
|
prepend_before_filter :login_required
|
||||||
|
prepend_before_filter :enable_mobile_content_negotiation
|
||||||
|
after_filter :restore_content_type_for_mobile
|
||||||
after_filter :set_charset
|
after_filter :set_charset
|
||||||
|
|
||||||
include ActionView::Helpers::TextHelper
|
include ActionView::Helpers::TextHelper
|
||||||
|
|
@ -116,6 +117,37 @@ class ApplicationController < ActionController::Base
|
||||||
Hash[*projects.reject{ |p| p.default_context.nil? }.map{ |p| [p.name, p.default_context.name] }.flatten].to_json
|
Hash[*projects.reject{ |p| p.default_context.nil? }.map{ |p| [p.name, p.default_context.name] }.flatten].to_json
|
||||||
end
|
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
|
protected
|
||||||
|
|
||||||
def admin_login_required
|
def admin_login_required
|
||||||
|
|
@ -126,7 +158,10 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirect_back_or_home
|
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
|
end
|
||||||
|
|
||||||
def boolean_param(param_name)
|
def boolean_param(param_name)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ class LoginController < ApplicationController
|
||||||
notify :notice, "Login successful: session #{msg}"
|
notify :notice, "Login successful: session #{msg}"
|
||||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year }
|
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year }
|
||||||
redirect_back_or_home
|
redirect_back_or_home
|
||||||
|
return
|
||||||
else
|
else
|
||||||
@login = params['user_login']
|
@login = params['user_login']
|
||||||
notify :warning, "Login unsuccessful"
|
notify :warning, "Login unsuccessful"
|
||||||
|
|
@ -27,8 +28,13 @@ class LoginController < ApplicationController
|
||||||
when :get
|
when :get
|
||||||
if User.no_users_yet?
|
if User.no_users_yet?
|
||||||
redirect_to :controller => 'users', :action => 'new'
|
redirect_to :controller => 'users', :action => 'new'
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.m { render :action => 'login_mobile.rhtml', :layout => 'mobile' }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def begin
|
def begin
|
||||||
|
|
@ -44,10 +50,13 @@ class LoginController < ApplicationController
|
||||||
# to the server using the redirect_url the library created for us.
|
# to the server using the redirect_url the library created for us.
|
||||||
|
|
||||||
# redirect to the server
|
# 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
|
else
|
||||||
notify :warning, "Unable to find openid server for <q>#{openid_url}</q>"
|
notify :warning, "Unable to find openid server for <q>#{openid_url}</q>"
|
||||||
redirect_to :action => 'login'
|
redirect_to_login
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -92,14 +101,14 @@ class LoginController < ApplicationController
|
||||||
else
|
else
|
||||||
notify :warning, "Unknown response status: #{open_id_response.status}"
|
notify :warning, "Unknown response status: #{open_id_response.status}"
|
||||||
end
|
end
|
||||||
redirect_to :action => 'login' unless performed?
|
redirect_to_login unless performed?
|
||||||
end
|
end
|
||||||
|
|
||||||
def logout
|
def logout
|
||||||
session['user_id'] = nil
|
session['user_id'] = nil
|
||||||
reset_session
|
reset_session
|
||||||
notify :notice, "You have been logged out of Tracks."
|
notify :notice, "You have been logged out of Tracks."
|
||||||
redirect_to :action => "login"
|
redirect_to_login
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_expiry
|
def check_expiry
|
||||||
|
|
@ -122,6 +131,13 @@ class LoginController < ApplicationController
|
||||||
|
|
||||||
private
|
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?
|
def should_expire_sessions?
|
||||||
session['noexpiry'] != "on"
|
session['noexpiry'] != "on"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,8 @@ class TodosController < ApplicationController
|
||||||
append_before_filter :init, :except => [ :destroy, :completed, :completed_archive, :check_deferred ]
|
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 ]
|
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) }
|
session :off, :only => :index, :if => Proc.new { |req| is_feed_request(req) }
|
||||||
|
|
||||||
layout proc{ |controller| controller.mobile? ? "mobile" : "standard" }
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@projects = @user.projects.find(:all, :include => [ :todos ])
|
@projects = @user.projects.find(:all, :include => [ :todos ])
|
||||||
@contexts = @user.contexts.find(:all, :include => [ :todos ])
|
@contexts = @user.contexts.find(:all, :include => [ :todos ])
|
||||||
|
|
@ -317,40 +312,8 @@ class TodosController < ApplicationController
|
||||||
|
|
||||||
end
|
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
|
def get_todo_from_params
|
||||||
@todo = @user.todos.find(params['id'])
|
@todo = @user.todos.find(params['id'])
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
page.select('.notes').each { |e| e.toggle }
|
page.select('.notes').each { |e| e.toggle }
|
||||||
end
|
end
|
||||||
-%> |
|
-%> |
|
||||||
<%= link_to "Logout (#{@user.display_name}) »", :controller => "login", :action=>"logout"%>
|
<%= link_to "Logout (#{@user.display_name}) »", logout_path %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="navcontainer">
|
<div id="navcontainer">
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
<hr />
|
<hr />
|
||||||
<%= render :partial => 'mobile_actions' %>
|
<%= render :partial => 'mobile_actions' %>
|
||||||
<hr />
|
<hr />
|
||||||
<%= link_to "Logout", :controller => 'login', :action => 'logout' %>
|
<%= link_to "Logout", formatted_logout_path(:format => 'm') %>
|
||||||
|
|
@ -2,8 +2,16 @@ ActionController::Routing::Routes.draw do |map|
|
||||||
UJS::routes
|
UJS::routes
|
||||||
|
|
||||||
# Login Routes
|
# Login Routes
|
||||||
map.connect 'login', :controller => 'login', :action => 'login'
|
map.with_options :controller => 'login' do |login|
|
||||||
map.connect 'logout', :controller => 'login', :action => 'logout'
|
login.login 'login', :action => 'login'
|
||||||
|
login.formatted_login 'login.:format', :action => 'login'
|
||||||
|
login.logout 'logout', :action => 'logout'
|
||||||
|
login.formatted_logout 'logout.:format', :action => 'logout'
|
||||||
|
login.open_id_begin 'begin', :action => 'begin'
|
||||||
|
login.formatted_open_id_begin 'begin.:format', :action => 'begin'
|
||||||
|
login.open_id_complete 'complete', :action => 'complete'
|
||||||
|
login.formatted_open_id_complete 'complete.:format', :action => 'complete'
|
||||||
|
end
|
||||||
|
|
||||||
map.resources :users,
|
map.resources :users,
|
||||||
:member => {:change_password => :get, :update_password => :post,
|
:member => {:change_password => :get, :update_password => :post,
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,8 @@ module LoginSystem
|
||||||
# a popup window might just close itself for instance
|
# a popup window might just close itself for instance
|
||||||
def access_denied
|
def access_denied
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to :controller=>"login", :action =>"login" }
|
format.html { redirect_to login_path }
|
||||||
format.m { redirect_to :controller=>"login", :action =>"login" }
|
format.m { redirect_to formatted_login_path(:format => 'm') }
|
||||||
format.js { render :partial => 'login/redirect_to_login' }
|
format.js { render :partial => 'login/redirect_to_login' }
|
||||||
format.xml { basic_auth_denied }
|
format.xml { basic_auth_denied }
|
||||||
format.rss { basic_auth_denied }
|
format.rss { basic_auth_denied }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue