diff options
-rw-r--r-- | app/controllers/application.rb | 60 | ||||
-rw-r--r-- | app/controllers/user_controller.rb | 9 | ||||
-rw-r--r-- | app/views/user/_signin.rhtml | 5 | ||||
-rw-r--r-- | config/environment.rb | 20 | ||||
-rw-r--r-- | config/general-example | 5 | ||||
-rw-r--r-- | db/migrate/058_remove_sessions.rb | 16 | ||||
-rw-r--r-- | db/schema.rb | 12 | ||||
-rwxr-xr-x | script/delete-old-sessions | 1 | ||||
-rw-r--r-- | todo.txt | 5 |
9 files changed, 99 insertions, 34 deletions
diff --git a/app/controllers/application.rb b/app/controllers/application.rb index dd762480c..4c3f6e114 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -6,23 +6,59 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: application.rb,v 1.48 2008-06-10 15:12:02 francis Exp $ +# $Id: application.rb,v 1.49 2008-06-12 13:43:29 francis Exp $ class ApplicationController < ActionController::Base - # Standard hearders, footers and navigation for whole site + # Standard headers, footers and navigation for whole site layout "default" - # Pick a unique cookie name to distinguish our session data from others' - session :session_key => '_foi_session_id' + # Set cookie expiry according to "remember me" checkbox, as per "An easier + # and more flexible hack" on this page: + # http://wiki.rubyonrails.org/rails/pages/HowtoChangeSessionOptions + before_filter :session_remember_me + def session_remember_me + # Reset the "sliding window" session expiry time. + if session[:remember_me] + expire_time = 1.month.from_now + # "Why is session[:force_new_cookie] set to Time.now? In order for the “sliding window” + # concept to work, a fresh cookie must be sent with every response. Rails only + # sends a cookie when the session data has changed so using a value like Time.now + # ensures that it changes every time. What I have actually found is that some + # internal voodoo causes the session data to change slightly anyway but it’s best + # to be sure!" + session[:force_new_cookie] = Time.now + else + expire_time = nil + end + # if statement here is so test code runs + if session.instance_variable_get(:@dbman) + session.instance_variable_get(:@dbman).instance_variable_get(:@cookie_options)['expires'] = expire_time + end + end - # Override default error handler + # Override default error handler, for production sites. def rescue_action_in_public(exception) - # do something based on exception + # Make sure expiry time for session is set (before_filters are + # otherwise missed by this override) + session_remember_me + + # Display user appropriate error message @exception_backtrace = exception.backtrace.join("\n") @exception_class = exception.class.to_s render :template => "general/exception_caught.rhtml", :status => 404 end + + # For development sites. + alias original_rescue_action_locally rescue_action_locally + def rescue_action_locally(exception) + # Make sure expiry time for session is set (before_filters are + # otherwise missed by this override) + session_remember_me + + # Display default, detailed error for developers + original_rescue_action_locally(exception) + end def local_request? false @@ -87,8 +123,11 @@ class ApplicationController < ActionController::Base # Do a POST redirect. This is a nasty hack - we store the posted values in # the session, and when the GET redirect with "?post_redirect=1" happens, # load them in. - def do_post_redirect(uri, params) - session[:post_redirect_params] = params + def do_post_redirect(post_redirect) + uri = post_redirect.uri + + session[:post_redirect_token] = post_redirect.token + # XXX what is the built in Ruby URI munging function that can do this # choice of & vs. ? more elegantly than this dumb if statement? if uri.include?("?") @@ -110,8 +149,9 @@ class ApplicationController < ActionController::Base # If we are in a faked redirect to POST request, then set post params. before_filter :check_in_post_redirect def check_in_post_redirect - if params[:post_redirect] and session[:post_redirect_params] - params.update(session[:post_redirect_params]) + if params[:post_redirect] and session[:post_redirect_token] + post_redirect = PostRedirect.find_by_token(session[:post_redirect_token]) + params.update(post_redirect.post_params) end end diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 73fbce9d6..af2f572ba 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -4,7 +4,7 @@ # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ # -# $Id: user_controller.rb,v 1.46 2008-05-12 10:57:43 francis Exp $ +# $Id: user_controller.rb,v 1.47 2008-06-12 13:43:29 francis Exp $ class UserController < ApplicationController # Show page about a set of users with same url name @@ -45,7 +45,8 @@ class UserController < ApplicationController if @user_signin.email_confirmed session[:user_id] = @user_signin.id session[:user_circumstance] = nil - do_post_redirect @post_redirect.uri, @post_redirect.post_params + session[:remember_me] = params[:remember_me] ? true : false + do_post_redirect @post_redirect else send_confirmation_mail @user_signin end @@ -96,7 +97,7 @@ class UserController < ApplicationController session[:user_id] = @user.id session[:user_circumstance] = post_redirect.circumstance - do_post_redirect post_redirect.uri, post_redirect.post_params + do_post_redirect post_redirect end # Logout form @@ -166,7 +167,7 @@ class UserController < ApplicationController flash[:notice] = "Your password has been changed." if params[:pretoken] and not params[:pretoken].empty? post_redirect = PostRedirect.find_by_token(params[:pretoken]) - do_post_redirect post_redirect.uri, post_redirect.post_params + do_post_redirect post_redirect else redirect_to user_url(@user) end diff --git a/app/views/user/_signin.rhtml b/app/views/user/_signin.rhtml index aefcde17e..787773d5a 100644 --- a/app/views/user/_signin.rhtml +++ b/app/views/user/_signin.rhtml @@ -19,6 +19,11 @@ <%= link_to "Forgotten your password?", signchange_url + "?pretoken=" + h(params[:token]) %> </p> + <p class="form_note"> + <%= check_box_tag 'remember_me', "1" %> + <label for="remember_me">Remember me</label> + </p> + <div class="form_button"> <%= hidden_field_tag 'token', params[:token], { :id => 'signin_token' } %> <%= submit_tag "Sign in" %> diff --git a/config/environment.rb b/config/environment.rb index d05981b0d..6418de705 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -19,6 +19,10 @@ load "config.rb" load "format.rb" Rails::Initializer.run do |config| + # Load intial mySociety config + MySociety::Config.set_file(File.join(config.root_path, 'config', 'general'), true) + MySociety::Config.load_default + # Settings in config/environments/* take precedence over those specified here # Skip frameworks you're not going to use (only works if using vendor/rails) @@ -34,9 +38,15 @@ Rails::Initializer.run do |config| # (by default production uses :info, the others :debug) # config.log_level = :debug - # Use the database for sessions instead of the file system - # (create the session table with 'rake db:sessions:create') - config.action_controller.session_store = :active_record_store + # Your secret key for verifying cookie session data integrity. + # If you change this key, all old sessions will become invalid! + # Make sure the secret is at least 30 characters and all random, + # no regular words or you'll be exposed to dictionary attacks. + config.action_controller.session = { + :session_key => '_foi_cookie_session', + :secret => MySociety::Config.get("COOKIE_STORE_SESSION_SECRET", 'this default is insecure as code is open source, please override for live sites in config/general; this will do for local development'), + } + config.action_controller.session_store = :cookie_store # Use SQL instead of Active Record's schema dumper when creating the test database. # This is necessary if your schema can't be completely dumped by the schema dumper, @@ -50,10 +60,6 @@ Rails::Initializer.run do |config| config.active_record.default_timezone = :utc # See Rails::Configuration for more options - - # Load intial mySociety config - MySociety::Config.set_file(File.join(config.root_path, 'config', 'general'), true) - MySociety::Config.load_default end # Add new inflection rules using the following format diff --git a/config/general-example b/config/general-example index d7cd0be5d..2a7a0b140 100644 --- a/config/general-example +++ b/config/general-example @@ -19,7 +19,7 @@ * Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. * Email: francis@mysociety.org; WWW: http://www.mysociety.org * - * $Id: general-example,v 1.14 2008-05-18 23:50:05 francis Exp $ + * $Id: general-example,v 1.15 2008-06-12 13:43:30 francis Exp $ * */ @@ -39,4 +39,7 @@ define('OPTION_CONTACT_EMAIL', 'admin@localhost'); define('OPTION_ADMIN_BASE_URL', '/admin/'); define('OPTION_ADMIN_PUBLIC_URL', '/'); // where /stylesheets sits under for admin pages +// Secret key for signing cookie_store sessions +define('OPTION_COOKIE_STORE_SESSION_SECRET', 'your secret key here, make it long and random'); + ?> diff --git a/db/migrate/058_remove_sessions.rb b/db/migrate/058_remove_sessions.rb new file mode 100644 index 000000000..316fcfdda --- /dev/null +++ b/db/migrate/058_remove_sessions.rb @@ -0,0 +1,16 @@ +class RemoveSessions < ActiveRecord::Migration + def self.up + drop_table :sessions + end + + def self.down + create_table :sessions do |t| + t.column :session_id, :string + t.column :data, :text + t.column :updated_at, :datetime + end + + add_index :sessions, :session_id + add_index :sessions, :updated_at + end +end diff --git a/db/schema.rb b/db/schema.rb index 66758a69c..6c71d1ef0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 57) do +ActiveRecord::Schema.define(:version => 58) do create_table "acts_as_xapian_jobs", :force => true do |t| t.string "model", :null => false @@ -118,16 +118,6 @@ ActiveRecord::Schema.define(:version => 57) do t.text "url_name" end - create_table "sessions", :force => true do |t| - t.string "session_id" - t.text "data" - t.datetime "updated_at" - t.datetime "created_at" - end - - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" - create_table "track_things", :force => true do |t| t.integer "tracking_user_id", :null => false t.string "track_query", :null => false diff --git a/script/delete-old-sessions b/script/delete-old-sessions index 0e4c91122..c1354e4f4 100755 --- a/script/delete-old-sessions +++ b/script/delete-old-sessions @@ -3,6 +3,5 @@ LOC=`dirname $0` $LOC/runner 'PostRedirect.delete_old_post_redirects()' -$LOC/runner "ActiveRecord::Base.connection.execute(\"delete from sessions where now() - updated_at > '1 month'\")" @@ -1,3 +1,6 @@ +Cookie: + Delete cronjob + Site move: Install PostgresSQL 8.3 Move database @@ -66,6 +69,8 @@ Needs tagline that v. quickly explains what site is on each page This one is a word doc by itself: http://www.whatdotheyknow.com/request/cost_benefit_analysis_for_real_n +rename delete_old_sessions + Later ===== |