mongo_session_store-rails3 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +32 -0
- data/README.md +128 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/mongo_session_store-rails3.rb +32 -0
- data/lib/mongo_session_store/mongo_mapper_store.rb +20 -0
- data/lib/mongo_session_store/mongo_store.rb +80 -0
- data/lib/mongo_session_store/mongo_store_base.rb +77 -0
- data/lib/mongo_session_store/mongoid_store.rb +34 -0
- data/mongo_session_store-rails3.gemspec +16 -0
- data/perf/benchmark.rb +93 -0
- data/spec/integration_with_devise_spec.rb +84 -0
- data/spec/rails_3.0_app/.gitignore +4 -0
- data/spec/rails_3.0_app/README +256 -0
- data/spec/rails_3.0_app/Rakefile +7 -0
- data/spec/rails_3.0_app/app/controllers/application_controller.rb +3 -0
- data/spec/rails_3.0_app/app/controllers/home_controller.rb +4 -0
- data/spec/rails_3.0_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_3.0_app/app/models/user.rb +8 -0
- data/spec/rails_3.0_app/app/views/devise/confirmations/new.html.erb +12 -0
- data/spec/rails_3.0_app/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/spec/rails_3.0_app/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/spec/rails_3.0_app/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/spec/rails_3.0_app/app/views/devise/passwords/edit.html.erb +16 -0
- data/spec/rails_3.0_app/app/views/devise/passwords/new.html.erb +12 -0
- data/spec/rails_3.0_app/app/views/devise/registrations/edit.html.erb +25 -0
- data/spec/rails_3.0_app/app/views/devise/registrations/new.html.erb +18 -0
- data/spec/rails_3.0_app/app/views/devise/sessions/new.html.erb +17 -0
- data/spec/rails_3.0_app/app/views/devise/shared/_links.erb +25 -0
- data/spec/rails_3.0_app/app/views/devise/unlocks/new.html.erb +12 -0
- data/spec/rails_3.0_app/app/views/home/index.html.erb +10 -0
- data/spec/rails_3.0_app/app/views/layouts/application.html.erb +15 -0
- data/spec/rails_3.0_app/config.ru +4 -0
- data/spec/rails_3.0_app/config/application.rb +47 -0
- data/spec/rails_3.0_app/config/boot.rb +6 -0
- data/spec/rails_3.0_app/config/environment.rb +5 -0
- data/spec/rails_3.0_app/config/environments/development.rb +26 -0
- data/spec/rails_3.0_app/config/environments/production.rb +49 -0
- data/spec/rails_3.0_app/config/environments/test.rb +35 -0
- data/spec/rails_3.0_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_3.0_app/config/initializers/devise.rb +204 -0
- data/spec/rails_3.0_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_3.0_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_3.0_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_3.0_app/config/initializers/session_store.rb +8 -0
- data/spec/rails_3.0_app/config/locales/devise.en.yml +53 -0
- data/spec/rails_3.0_app/config/locales/en.yml +5 -0
- data/spec/rails_3.0_app/config/mongo.yml +18 -0
- data/spec/rails_3.0_app/config/mongoid.yml +20 -0
- data/spec/rails_3.0_app/config/routes.rb +4 -0
- data/spec/rails_3.0_app/lib/tasks/.gitkeep +0 -0
- data/spec/rails_3.0_app/public/404.html +26 -0
- data/spec/rails_3.0_app/public/422.html +26 -0
- data/spec/rails_3.0_app/public/500.html +26 -0
- data/spec/rails_3.0_app/public/favicon.ico +0 -0
- data/spec/rails_3.0_app/public/javascripts/.gitkeep +0 -0
- data/spec/rails_3.0_app/public/javascripts/application.js +0 -0
- data/spec/rails_3.0_app/public/robots.txt +5 -0
- data/spec/rails_3.0_app/public/stylesheets/.gitkeep +0 -0
- data/spec/rails_3.0_app/script/rails +6 -0
- data/spec/rails_3.0_app/vendor/plugins/.gitkeep +0 -0
- data/spec/rails_3.1_app/.gitignore +5 -0
- data/spec/rails_3.1_app/README +261 -0
- data/spec/rails_3.1_app/Rakefile +7 -0
- data/spec/rails_3.1_app/app/assets/javascripts/application.js +7 -0
- data/spec/rails_3.1_app/app/assets/stylesheets/application.css +7 -0
- data/spec/rails_3.1_app/app/controllers/application_controller.rb +3 -0
- data/spec/rails_3.1_app/app/controllers/home_controller.rb +4 -0
- data/spec/rails_3.1_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_3.1_app/app/mailers/.gitkeep +0 -0
- data/spec/rails_3.1_app/app/models/.gitkeep +0 -0
- data/spec/rails_3.1_app/app/models/user.rb +8 -0
- data/spec/rails_3.1_app/app/views/devise/confirmations/new.html.erb +12 -0
- data/spec/rails_3.1_app/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/spec/rails_3.1_app/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
- data/spec/rails_3.1_app/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/spec/rails_3.1_app/app/views/devise/passwords/edit.html.erb +16 -0
- data/spec/rails_3.1_app/app/views/devise/passwords/new.html.erb +12 -0
- data/spec/rails_3.1_app/app/views/devise/registrations/edit.html.erb +25 -0
- data/spec/rails_3.1_app/app/views/devise/registrations/new.html.erb +18 -0
- data/spec/rails_3.1_app/app/views/devise/sessions/new.html.erb +17 -0
- data/spec/rails_3.1_app/app/views/devise/shared/_links.erb +25 -0
- data/spec/rails_3.1_app/app/views/devise/unlocks/new.html.erb +12 -0
- data/spec/rails_3.1_app/app/views/home/index.html.erb +10 -0
- data/spec/rails_3.1_app/app/views/layouts/application.html.erb +15 -0
- data/spec/rails_3.1_app/config.ru +4 -0
- data/spec/rails_3.1_app/config/application.rb +47 -0
- data/spec/rails_3.1_app/config/boot.rb +6 -0
- data/spec/rails_3.1_app/config/environment.rb +5 -0
- data/spec/rails_3.1_app/config/environments/development.rb +27 -0
- data/spec/rails_3.1_app/config/environments/production.rb +54 -0
- data/spec/rails_3.1_app/config/environments/test.rb +39 -0
- data/spec/rails_3.1_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_3.1_app/config/initializers/devise.rb +204 -0
- data/spec/rails_3.1_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_3.1_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_3.1_app/config/initializers/secret_token.rb +7 -0
- data/spec/rails_3.1_app/config/initializers/session_store.rb +8 -0
- data/spec/rails_3.1_app/config/initializers/wrap_parameters.rb +12 -0
- data/spec/rails_3.1_app/config/locales/devise.en.yml +53 -0
- data/spec/rails_3.1_app/config/locales/en.yml +5 -0
- data/spec/rails_3.1_app/config/mongo.yml +18 -0
- data/spec/rails_3.1_app/config/mongoid.yml +20 -0
- data/spec/rails_3.1_app/config/routes.rb +4 -0
- data/spec/rails_3.1_app/lib/tasks/.gitkeep +0 -0
- data/spec/rails_3.1_app/log/.gitkeep +0 -0
- data/spec/rails_3.1_app/public/404.html +26 -0
- data/spec/rails_3.1_app/public/422.html +26 -0
- data/spec/rails_3.1_app/public/500.html +26 -0
- data/spec/rails_3.1_app/public/favicon.ico +0 -0
- data/spec/rails_3.1_app/public/robots.txt +5 -0
- data/spec/rails_3.1_app/script/rails +6 -0
- data/spec/rails_3.1_app/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/rails_3.1_app/vendor/plugins/.gitkeep +0 -0
- data/spec/spec_helper.rb +33 -0
- metadata +318 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
MONGO_VERS = '1.3.1' unless defined? MONGO_VERS
|
4
|
+
|
5
|
+
RAILS_VERS = case ENV['RAILS_VERS']
|
6
|
+
when '3.0'
|
7
|
+
'~>3.0'
|
8
|
+
when '3.1'
|
9
|
+
'>3.1.0.pre'
|
10
|
+
when nil
|
11
|
+
nil
|
12
|
+
else
|
13
|
+
raise "Invalid RAILS_VERS. Available versions are 3.0 and 3.1."
|
14
|
+
end
|
15
|
+
|
16
|
+
gemspec
|
17
|
+
|
18
|
+
group :development, :test do
|
19
|
+
gem 'rake'
|
20
|
+
gem 'mongo_mapper', '>= 0.9.0'
|
21
|
+
gem 'mongoid', '>= 2.0'
|
22
|
+
gem 'mongo', MONGO_VERS
|
23
|
+
gem 'bson_ext', MONGO_VERS
|
24
|
+
|
25
|
+
gem 'system_timer', :platforms => :ruby_18
|
26
|
+
gem 'ruby-debug', :platforms => :ruby_18
|
27
|
+
gem 'ruby-debug19', :platforms => :ruby_19
|
28
|
+
|
29
|
+
RAILS_VERS ? gem('rails', RAILS_VERS) : gem('rails')
|
30
|
+
gem 'rspec-rails'
|
31
|
+
gem 'devise'
|
32
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# MongoSessionStore
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
MongoSessionStore is a collection of Rails-compatible session stores for MongoMapper and Mongoid, but also included is a generic Mongo store that works with any (or no!) Mongo ODM.
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
MongoSessionStore is compatible with Rails 3.0 and 3.1
|
10
|
+
|
11
|
+
In your Gemfile:
|
12
|
+
|
13
|
+
gem "mongo_mapper"
|
14
|
+
gem "mongo_session_store-rails3"
|
15
|
+
|
16
|
+
In the session_store initializer (config/initializers/session_store.rb):
|
17
|
+
|
18
|
+
# MongoMapper
|
19
|
+
MyApp::Application.config.session_store = :mongo_mapper_store
|
20
|
+
|
21
|
+
# Mongoid
|
22
|
+
MyApp::Application.config.session_store = :mongoid_store
|
23
|
+
|
24
|
+
# anything else
|
25
|
+
MyApp::Application.config.session_store = :mongo_store
|
26
|
+
ActionDispatch::Session:MongoStore::Session.database = Mongo::Connection.new.db('my_app_development')
|
27
|
+
|
28
|
+
Note: If you choose to use the :mongo_store you only need to set its database if you aren't using MongoMapper or Mongoid in your project.
|
29
|
+
|
30
|
+
By default, the sessions will be stored in the "sessions" collection in MongoDB. If you want to use a different collection, you can set that in the initializer:
|
31
|
+
|
32
|
+
MongoSessionStore.collection_name = "client_sessions"
|
33
|
+
|
34
|
+
If for some reason you want to query your sessions:
|
35
|
+
|
36
|
+
# MongoMapper
|
37
|
+
ActionDispatch::Session:MongoMapperStore::Session.where(:updated_at.gt => 2.days.ago)
|
38
|
+
|
39
|
+
# Mongoid
|
40
|
+
ActionDispatch::Session:MongoidStore::Session.where(:updated_at.gt => 2.days.ago)
|
41
|
+
|
42
|
+
# Plain old Mongo
|
43
|
+
ActionDispatch::Session:MongoStore::Session.where('updated_at' => { '$gt' => 2.days.ago })
|
44
|
+
|
45
|
+
## Performance
|
46
|
+
|
47
|
+
The following is the benchmark run with bson_ext installed. Without bson_ext, speeds are about 10x slower. The benchmark saves 2000 sessions (~12kb each) and then finds/reloads each one.
|
48
|
+
|
49
|
+
$ ruby perf/benchmark.rb
|
50
|
+
MongoMapperStore...
|
51
|
+
3.65ms per session save
|
52
|
+
2.25ms per session load
|
53
|
+
Total Size: 23648924
|
54
|
+
Object count: 2000
|
55
|
+
Average object size: 11824.462
|
56
|
+
Index sizes: {"_id_"=>172032}
|
57
|
+
MongoidStore...
|
58
|
+
2.59ms per session save
|
59
|
+
1.33ms per session load
|
60
|
+
Total Size: 23648924
|
61
|
+
Object count: 2000
|
62
|
+
Average object size: 11824.462
|
63
|
+
Index sizes: {"_id_"=>172032}
|
64
|
+
MongoStore...
|
65
|
+
1.42ms per session save
|
66
|
+
1.11ms per session load
|
67
|
+
Total Size: 23648924
|
68
|
+
Object count: 2000
|
69
|
+
Average object size: 11824.462
|
70
|
+
Index sizes: {"_id_"=>204800}
|
71
|
+
|
72
|
+
## Development
|
73
|
+
|
74
|
+
To run all the tests:
|
75
|
+
|
76
|
+
rake
|
77
|
+
|
78
|
+
To switch to the Rails 3.0 Gemfile.lock:
|
79
|
+
|
80
|
+
rake use_rails_30
|
81
|
+
|
82
|
+
To switch to the Rails 3.1 Gemfile.lock:
|
83
|
+
|
84
|
+
rake use_rails_31
|
85
|
+
|
86
|
+
To run the tests for a specific store:
|
87
|
+
|
88
|
+
MONGO_SESSION_STORE_ORM=mongo_mapper bundle exec rspec spec
|
89
|
+
MONGO_SESSION_STORE_ORM=mongoid bundle exec rspec spec
|
90
|
+
|
91
|
+
## Previous contributors
|
92
|
+
|
93
|
+
MongoSessionStore started as a fork of the DataMapper session store, modified to work with MongoMapper and Mongoid. Much thanks to all the previous contributors:
|
94
|
+
|
95
|
+
* Nicolas Mérouze
|
96
|
+
* Chris Brickley
|
97
|
+
* Tony Pitale
|
98
|
+
* Nicola Racco
|
99
|
+
* Matt Powell
|
100
|
+
* Ryan Fitzgerald
|
101
|
+
|
102
|
+
## License
|
103
|
+
|
104
|
+
Copyright (c) 2011 Brian Hempel
|
105
|
+
Copyright (c) 2010 Nicolas Mérouze
|
106
|
+
Copyright (c) 2009 Chris Brickley
|
107
|
+
Copyright (c) 2009 Tony Pitale
|
108
|
+
|
109
|
+
Permission is hereby granted, free of charge, to any person
|
110
|
+
obtaining a copy of this software and associated documentation
|
111
|
+
files (the "Software"), to deal in the Software without
|
112
|
+
restriction, including without limitation the rights to use,
|
113
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
114
|
+
copies of the Software, and to permit persons to whom the
|
115
|
+
Software is furnished to do so, subject to the following
|
116
|
+
conditions:
|
117
|
+
|
118
|
+
The above copyright notice and this permission notice shall be
|
119
|
+
included in all copies or substantial portions of the Software.
|
120
|
+
|
121
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
122
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
123
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
124
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
125
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
126
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
127
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
128
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
def run_with_output(command)
|
5
|
+
puts "Running: #{command}"
|
6
|
+
|
7
|
+
Process.wait( fork { exec command } )
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_rails_version(rails_vers)
|
11
|
+
unless File.exists?("Gemfile_Rails_#{rails_vers}.lock")
|
12
|
+
run_with_output "export RAILS_VERS=#{rails_vers}; bundle update rails"
|
13
|
+
run_with_output "cp Gemfile.lock Gemfile_Rails_#{rails_vers}.lock"
|
14
|
+
else
|
15
|
+
run_with_output "rm Gemfile.lock"
|
16
|
+
run_with_output "cp Gemfile_Rails_#{rails_vers}.lock Gemfile.lock"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
task :default => :test_all
|
21
|
+
|
22
|
+
desc 'Test each session store against Rails 3.0 and Rails 3.1'
|
23
|
+
task :test_all do
|
24
|
+
# inspired by http://pivotallabs.com/users/jdean/blog/articles/1728-testing-your-gem-against-multiple-rubies-and-rails-versions-with-rvm
|
25
|
+
|
26
|
+
orms = ['mongo_mapper', 'mongoid', 'mongo']
|
27
|
+
|
28
|
+
set_rails_version('3.0')
|
29
|
+
|
30
|
+
orms.each do |orm|
|
31
|
+
run_with_output "export MONGO_SESSION_STORE_ORM=#{orm}; bundle exec rspec spec"
|
32
|
+
end
|
33
|
+
|
34
|
+
set_rails_version('3.1')
|
35
|
+
|
36
|
+
orms.each do |orm|
|
37
|
+
run_with_output "export MONGO_SESSION_STORE_ORM=#{orm}; bundle exec rspec spec"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Set Rails version to 3.0'
|
42
|
+
task :use_rails_30 do
|
43
|
+
set_rails_version('3.0')
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Set Rails version to 3.1'
|
47
|
+
task :use_rails_31 do
|
48
|
+
set_rails_version('3.1')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.1
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__)
|
4
|
+
|
5
|
+
module MongoSessionStore
|
6
|
+
def self.collection_name=(name)
|
7
|
+
@collection_name = name
|
8
|
+
|
9
|
+
if defined?(ActionDispatch::Session::MongoStore::Session)
|
10
|
+
ActionDispatch::Session::MongoStore::Session.reset_collection
|
11
|
+
end
|
12
|
+
|
13
|
+
if defined?(ActionDispatch::Session::MongoMapperStore::Session)
|
14
|
+
ActionDispatch::Session::MongoMapperStore::Session.set_collection_name(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
if defined?(ActionDispatch::Session::MongoidStore::Session)
|
18
|
+
ActionDispatch::Session::MongoidStore::Session.store_in(name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.collection_name
|
23
|
+
@collection_name
|
24
|
+
end
|
25
|
+
|
26
|
+
# default collection name for all the stores
|
27
|
+
self.collection_name = "sessions"
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'mongo_session_store/mongo_mapper_store'
|
31
|
+
require 'mongo_session_store/mongoid_store'
|
32
|
+
require 'mongo_session_store/mongo_store'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require 'mongo_mapper'
|
3
|
+
require 'mongo_session_store/mongo_store_base'
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
module Session
|
7
|
+
class MongoMapperStore < MongoStoreBase
|
8
|
+
class Session
|
9
|
+
include MongoMapper::Document
|
10
|
+
set_collection_name MongoSessionStore.collection_name
|
11
|
+
key :_id, String
|
12
|
+
key :data, Binary, :default => Marshal.dump({})
|
13
|
+
timestamps!
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'mongo_session_store/mongo_store_base'
|
3
|
+
|
4
|
+
module ActionDispatch
|
5
|
+
module Session
|
6
|
+
class MongoStore < MongoStoreBase
|
7
|
+
class Session
|
8
|
+
attr_accessor :_id, :data, :created_at, :updated_at
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
@_id = options[:_id]
|
12
|
+
@data = options[:data] || BSON::Binary.new(Marshal.dump({}))
|
13
|
+
@created_at = options[:created_at]
|
14
|
+
@updated_at = options[:updated_at]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load(options={})
|
18
|
+
options[:data] = options["data"].to_s if options["data"]
|
19
|
+
new(options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy
|
23
|
+
collection.remove :_id => _id
|
24
|
+
end
|
25
|
+
|
26
|
+
def save
|
27
|
+
@created_at ||= Time.now
|
28
|
+
@updated_at = Time.now
|
29
|
+
|
30
|
+
collection.save(
|
31
|
+
:_id => @_id,
|
32
|
+
:data => BSON::Binary.new(@data),
|
33
|
+
:created_at => @created_at,
|
34
|
+
:updated_at => @updated_at
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def data=(stuff)
|
39
|
+
@data = stuff.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.where(query = {})
|
43
|
+
collection.find(query).map { |doc| load(doc) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.last
|
47
|
+
where.last
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.database
|
51
|
+
if @database
|
52
|
+
@database
|
53
|
+
elsif defined?(MongoMapper)
|
54
|
+
MongoMapper.database
|
55
|
+
elsif defined?(Mongoid)
|
56
|
+
Mongoid.database
|
57
|
+
else
|
58
|
+
raise "MongoStore needs a database, e.g. #{name.to_s}.database = Mongo::Connection.new.db('my_app_development')"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.database=(database)
|
63
|
+
@database = database
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.collection
|
67
|
+
@collection ||= database[MongoSessionStore.collection_name]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reset_collection
|
71
|
+
@collection = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def collection
|
75
|
+
self.class.collection
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module ActionDispatch
|
2
|
+
module Session
|
3
|
+
class MongoStoreBase < AbstractStore
|
4
|
+
|
5
|
+
SESSION_RECORD_KEY = 'rack.session.record'.freeze
|
6
|
+
begin
|
7
|
+
ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
|
8
|
+
rescue NameError
|
9
|
+
# Rack 1.2.x has access to the ENV_SESSION_OPTIONS_KEY
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.session_class
|
13
|
+
self::Session
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def session_class
|
18
|
+
self.class.session_class
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_sid
|
22
|
+
# 20 random bytes in url-safe base64
|
23
|
+
SecureRandom.base64(20).gsub('=','').gsub('+','-').gsub('/','_')
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_session(env, sid)
|
27
|
+
sid ||= generate_sid
|
28
|
+
session = find_session(sid)
|
29
|
+
env[SESSION_RECORD_KEY] = session
|
30
|
+
[sid, unpack(session.data)]
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_session(env, sid, session_data, options = {})
|
34
|
+
record = get_session_model(env, sid)
|
35
|
+
record.data = pack(session_data)
|
36
|
+
# Rack spec dictates that set_session should return true or false
|
37
|
+
# depending on whether or not the session was saved or not.
|
38
|
+
# However, ActionPack seems to want a session id instead.
|
39
|
+
record.save ? sid : false
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_session(id)
|
43
|
+
session_class.where(:_id => id).first || session_class.new(:_id => id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_session_model(env, sid)
|
47
|
+
if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
|
48
|
+
env[SESSION_RECORD_KEY] = find_session(sid)
|
49
|
+
else
|
50
|
+
env[SESSION_RECORD_KEY] ||= find_session(sid)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy_session(env, session_id, options)
|
55
|
+
destroy(env)
|
56
|
+
generate_sid unless options[:drop]
|
57
|
+
end
|
58
|
+
|
59
|
+
def destroy(env)
|
60
|
+
if sid = current_session_id(env)
|
61
|
+
get_session_model(env, sid).destroy
|
62
|
+
env[SESSION_RECORD_KEY] = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def pack(data)
|
67
|
+
Marshal.dump(data)
|
68
|
+
end
|
69
|
+
|
70
|
+
def unpack(packed)
|
71
|
+
return nil unless packed
|
72
|
+
Marshal.load(StringIO.new(packed.to_s))
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'mongoid'
|
3
|
+
require 'mongo_session_store/mongo_store_base'
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
module Session
|
7
|
+
class MongoidStore < MongoStoreBase
|
8
|
+
|
9
|
+
class Session
|
10
|
+
include Mongoid::Document
|
11
|
+
include Mongoid::Timestamps
|
12
|
+
self.collection_name = MongoSessionStore.collection_name
|
13
|
+
|
14
|
+
identity :type => String
|
15
|
+
|
16
|
+
field :data, :type => BSON::Binary, :default => BSON::Binary.new(Marshal.dump({}))
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def pack(data)
|
21
|
+
BSON::Binary.new(Marshal.dump(data))
|
22
|
+
end
|
23
|
+
|
24
|
+
def unpack(packed)
|
25
|
+
return nil unless packed
|
26
|
+
Marshal.load(StringIO.new(packed.to_s))
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
rescue LoadError
|
34
|
+
end
|