Skip to content

Commit

Permalink
Merge branch 'michalmuskala-allow-session-configuration'
Browse files Browse the repository at this point in the history
  • Loading branch information
jodosha committed Dec 1, 2014
2 parents 033fac2 + 5f6a8f4 commit e6a2794
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 20 deletions.
48 changes: 48 additions & 0 deletions lib/lotus/config/sessions.rb
@@ -0,0 +1,48 @@
require 'lotus/utils/string'

module Lotus
module Config
# Sessions configuration
#
# @since x.x.x
# @api private
class Sessions

RACK_NAMESPACE = 'Rack::Session::%{class_name}'.freeze

def initialize(identifier = nil, options = {}, config = nil)
@identifier = identifier
@options = options
@config = config
end

def enabled?
!!@identifier
end

def options
default_options.merge(@options)
end

def middleware_class
case @identifier
when Symbol
class_name = Utils::String.new(@identifier).classify
RACK_NAMESPACE % { class_name: class_name }
else
@identifier
end
end

private

def default_options
if @config
{ domain: @config.host, secure: @config.scheme == 'https' }
else
{}
end
end
end
end
end
83 changes: 83 additions & 0 deletions lib/lotus/configuration.rb
Expand Up @@ -4,6 +4,7 @@
require 'lotus/config/assets'
require 'lotus/config/routes'
require 'lotus/config/mapping'
require 'lotus/config/sessions'

module Lotus
# Configuration for a Lotus application
Expand Down Expand Up @@ -444,6 +445,88 @@ def cookies(value = nil)
end
end

# Configure sessions
# Enable sessions (disabled by default).
#
# This is part of a DSL, for this reason when this method is called with
# an argument, it will set the corresponding instance variable. When
# called without, it will return the already set value, or the default.
#
# Given Class as identifier it will be used as sessions middleware.
# Given String as identifier it will be resolved as class name and used as
# sessions middleware.
# Given Symbol as identifier it is assumed it's name of the class under
# Rack::Session namespace that will be used as sessions middleware
# (e.g. :cookie for Rack::Session::Cookie).
#
# By default options include domain inferred from host configuration, and
# secure flag inferred from scheme configuration.
#
# @overload sessions(identifier, options)
# Sets the given value.
# @param identifier [Class, String, Symbol] Rack middleware for sessions management
# @param options [Hash] options to pass to sessions middleware
#
# @overload sessions(false)
# Disables sessions
#
# @overload sessions
# Gets the value.
# @return [Lotus::Config::Sessions] sessions configuration
#
# @since x.x.x
#
# @see Lotus::Configuration#host
# @see Lotus::Configuration#scheme
#
# @example Getting the value
# require 'lotus'
#
# module Bookshelf
# class Application < Lotus::Application
# end
# end
#
# Bookshelf::Application.configuration.sessions
# # => #<Lotus::Config::Sessions:0x00000001ca0c28 @enabled=false>
#
# @example Setting the value with symbol
# require 'lotus'
#
# module Bookshelf
# class Application < Lotus::Application
# configure do
# sessions :cookie
# end
# end
# end
#
# Bookshelf::Application.configuration.sessions
# # => #<Lotus::Config::Sessions:0x00000001589458 @enabled=true, @identifier=:cookie, @options={:domain=>"localhost", :secure=>false}>
#
# @example Disabling previusly enabled sessions
# require 'lotus'
#
# module Bookshelf
# class Application < Lotus::Application
# configure do
# sessions :cookie
# sessions false
# end
# end
# end
#
# Bookshelf::Application.configuration.sessions
# # => #<Lotus::Config::Sessions:0x00000002460d78 @enabled=false>
#
def sessions(identifier = nil, options = {})
if identifier.nil?
@sessions ||= Config::Sessions.new
else
@sessions = Config::Sessions.new(identifier, options, self)
end
end

# Application load paths
# The application will recursively load all the Ruby files under these paths.
#
Expand Down
2 changes: 2 additions & 0 deletions lib/lotus/loader.rb
Expand Up @@ -4,6 +4,7 @@
require 'lotus/routes'
require 'lotus/routing/default'
require 'lotus/action/cookies'
require 'lotus/action/session'

module Lotus
# Load an application
Expand Down Expand Up @@ -48,6 +49,7 @@ def _load_controller_framework!
default_format config.default_format

modules { include Lotus::Action::Cookies } if config.cookies
modules { include Lotus::Action::Session } if config.sessions.enabled?
end

application_module.const_set('Controller', controller)
Expand Down
23 changes: 16 additions & 7 deletions lib/lotus/middleware.rb
Expand Up @@ -16,13 +16,7 @@ class Middleware
# @see Lotus::Configuration
def initialize(configuration)
@stack = []

if configuration.assets.enabled?
use Rack::Static, {
urls: configuration.assets.entries,
root: configuration.assets
}
end
@configuration = configuration
end

# Load the middleware stack
Expand All @@ -38,6 +32,7 @@ def initialize(configuration)
def load!(application, namespace)
@namespace = namespace
@builder = ::Rack::Builder.new
load_default_stack
@stack.each { |m, args, block| @builder.use load_middleware(m), *args, &block }
@builder.run application.routes

Expand Down Expand Up @@ -80,5 +75,19 @@ def load_middleware(middleware)
middleware
end
end

# @api private
# @since x.x.x
def load_default_stack
@default_stack_loaded ||= begin
if @configuration.sessions.enabled?
use @configuration.sessions.middleware_class, @configuration.sessions.options
end
if @configuration.assets.enabled?
use Rack::Static, urls: @configuration.assets.entries, root: @configuration.assets.to_s
end
true
end
end
end
end
54 changes: 54 additions & 0 deletions test/config/sessions_test.rb
@@ -0,0 +1,54 @@
require 'test_helper'

describe Lotus::Config::Sessions do
describe '#enabled?' do
it 'is false unless identifier is provided' do
sessions = Lotus::Config::Sessions.new
sessions.wont_be :enabled?
end

it 'is true when identifier is provided' do
sessions = Lotus::Config::Sessions.new('Cookie')
sessions.must_be :enabled?
end
end

describe '#middleware_class' do
describe 'provided with class as identifier' do
before do
SessionMiddleware = Class.new
end

after do
Object.send(:remove_const, :SessionMiddleware)
end

it 'returns class' do
sessions = Lotus::Config::Sessions.new(SessionMiddleware)
sessions.middleware_class.must_equal SessionMiddleware
end
end

describe 'provided with string as identifier' do
it 'returns string' do
sessions = Lotus::Config::Sessions.new('SessionMiddleware')
sessions.middleware_class.must_equal 'SessionMiddleware'
end
end

describe 'provided with symbol as identifier' do
it 'returns symbol as class name under Rack::Session namespace' do
sessions = Lotus::Config::Sessions.new(:some_storage)
sessions.middleware_class.must_equal 'Rack::Session::SomeStorage'
end
end
end

describe '#options' do
it 'returns passed options' do
options = { domain: 'example.com' }
sessions = Lotus::Config::Sessions.new('Cookie', options)
sessions.options.must_equal options
end
end
end
66 changes: 66 additions & 0 deletions test/configuration_test.rb
Expand Up @@ -340,6 +340,72 @@ def to_pathname

end

describe '#sessions' do
describe 'when not previously set' do
it 'is not enabled' do
@configuration.sessions.wont_be :enabled?
end
end

describe 'when set without options' do
before do
@configuration.sessions :cookie
end

it 'is enabled' do
@configuration.sessions.must_be :enabled?
end

it 'returns the configured value for middleware' do
@configuration.sessions.middleware_class.must_equal 'Rack::Session::Cookie'
end

it 'returns default values for options' do
default_options = { domain: @configuration.host, secure: @configuration.scheme == 'https' }
@configuration.sessions.options.must_equal default_options
end
end

describe 'when set with options' do
before do
@configuration.sessions :cookies, secure: true, expire_after: 2592000
end

it 'merges default option values' do
options = @configuration.sessions.options
options[:domain].must_equal @configuration.host
options[:expire_after].must_equal 2592000
options[:secure].must_equal true
end
end

describe 'when already set' do
before do
@configuration.sessions :cookie
end

describe 'if set with new configuration' do
before do
@configuration.sessions 'Rack::Session::Redis'
end

it 'returns it' do
@configuration.sessions.middleware_class.must_equal 'Rack::Session::Redis'
end
end

describe 'if set with false' do
before do
@configuration.sessions false
end

it 'is disabled' do
@configuration.sessions.wont_be :enabled?
end
end
end
end

describe 'assets' do
describe "when not previously set" do
it "is equal to public/ from the root directory" do
Expand Down
44 changes: 44 additions & 0 deletions test/fixtures/sessions/application.rb
@@ -0,0 +1,44 @@
module SessionsApp
class Application < Lotus::Application
configure do
# Activate sessions
sessions :cookie, secret: '1234567890'

routes do
post '/set_session' , to: 'sessions#new'
get '/get_session' , to: 'sessions#show'
delete '/clear_session', to: 'sessions#destroy'
end
end

load!
end


module Controllers::Sessions
include SessionsApp::Controller

action 'New' do
def call(params)
session[:name] = params[:name]
self.body = "Session created for: #{session[:name]}"
end
end

action 'Show' do
def call(params)

self.body = session[:name]
end
end

action 'Destroy' do
def call(params)
name = session[:name]
session.clear
self.body = "Session cleared for: #{name}"
end
end
end

end

0 comments on commit e6a2794

Please sign in to comment.