activerecord-session_store 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +48 -7
- data/lib/action_dispatch/session/active_record_store.rb +41 -27
- data/lib/active_record/session_store.rb +22 -20
- data/lib/active_record/session_store/session.rb +31 -11
- data/lib/active_record/session_store/sql_bypass.rb +11 -7
- data/lib/active_record/session_store/version.rb +1 -1
- data/lib/generators/active_record/session_migration_generator.rb +4 -0
- data/lib/generators/active_record/templates/migration.rb +1 -1
- data/lib/tasks/database.rake +8 -4
- metadata +16 -51
- data/lib/action_dispatch/session/legacy_support.rb +0 -51
- data/lib/active_record/session_store/extension/logger_silencer.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e3618fed7f080158309e682f1906af4d056b65fdbf687c7f562677cecaf17d05
|
4
|
+
data.tar.gz: 314cfae6877c80c6d73512f082765f083b733fcb5eb532b490b89033f37fd3aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd976a3e033d38632598f9ab5f47eee88c9e72fd624c470f385976361eba83b58e9b0e44241a7ce994f76b79ed3b71f142ce0d6547b10a04d5af4ed75812596d
|
7
|
+
data.tar.gz: 273a6fbec6eb0a9426d66963ee8008f91281a454fa8722d52a1f1179c1f39c68bf6a37e25ecd5db2c2031a8f344c5375121d52c8fc02fb3595654b1015057178
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -18,12 +18,23 @@ Run the migration generator:
|
|
18
18
|
|
19
19
|
rails generate active_record:session_migration
|
20
20
|
|
21
|
+
Run the migration:
|
22
|
+
|
23
|
+
rake db:migrate
|
24
|
+
|
21
25
|
Then, set your session store in `config/initializers/session_store.rb`:
|
22
26
|
|
23
27
|
```ruby
|
24
28
|
Rails.application.config.session_store :active_record_store, :key => '_my_app_session'
|
25
29
|
```
|
26
30
|
|
31
|
+
To avoid your sessions table expanding without limit as it will store expired and
|
32
|
+
potentially sensitive session data, it is strongly recommended in production
|
33
|
+
environments to schedule the `db:sessions:trim` rake task to run daily.
|
34
|
+
Running `bin/rake db:sessions:trim` will delete all sessions that have not
|
35
|
+
been updated in the last 30 days. The 30 days cutoff can be changed using the
|
36
|
+
`SESSION_DAYS_TRIM_THRESHOLD` environment variable.
|
37
|
+
|
27
38
|
Configuration
|
28
39
|
--------------
|
29
40
|
|
@@ -31,7 +42,8 @@ The default assumes a `sessions` tables with columns:
|
|
31
42
|
|
32
43
|
* `id` (numeric primary key),
|
33
44
|
* `session_id` (string, usually varchar; maximum length is 255), and
|
34
|
-
* `data` (text or
|
45
|
+
* `data` (text, longtext, json or jsonb); careful if your session data exceeds
|
46
|
+
65KB).
|
35
47
|
|
36
48
|
The `session_id` column should always be indexed for speedy lookups.
|
37
49
|
Session data is marshaled to the `data` column in Base64 format.
|
@@ -53,11 +65,14 @@ having a separate `id` column if you don't want it. However, you must
|
|
53
65
|
set `session.model.id = session.session_id` by hand! A before filter
|
54
66
|
on ApplicationController is a good place.
|
55
67
|
|
56
|
-
The serializer may be
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
but write as JSON.
|
68
|
+
The serializer may be class responding to `#load(value)` and `#dump(value)`, or
|
69
|
+
a symbol of `marshal`, `json`, `hybrid` or `null`. `marshal` is the default and
|
70
|
+
uses the built-in Marshal methods coupled with Base64 encoding. `json` does
|
71
|
+
what it says on the tin, using the `parse()` and `generate()` methods of the
|
72
|
+
JSON module. `hybrid` will read either type but write as JSON. `null` will
|
73
|
+
not perform serialization, leaving that up to the ActiveRecord database
|
74
|
+
adapter. This allows you to take advantage of the native JSON capabilities of
|
75
|
+
your database.
|
61
76
|
|
62
77
|
Since the default class is a simple Active Record, you get timestamps
|
63
78
|
for free if you add `created_at` and `updated_at` datetime columns to
|
@@ -94,7 +109,33 @@ MyLogger.send :include, ActiveRecord::SessionStore::Extension::LoggerSilencer
|
|
94
109
|
This silencer is being used to silence the logger and not leaking private
|
95
110
|
information into the log, and it is required for security reason.
|
96
111
|
|
97
|
-
|
112
|
+
CVE-2015-9284 mitigation
|
113
|
+
--------------
|
114
|
+
|
115
|
+
Sessions that were created by Active Record Session Store version 1.x are
|
116
|
+
affected by [CVE-2019-25025]. This means an attacker can perform a timing
|
117
|
+
attack against the session IDs stored in the database.
|
118
|
+
|
119
|
+
[CVE-2019-25025]: https://github.com/advisories/GHSA-cvw2-xj8r-mjf7
|
120
|
+
|
121
|
+
After upgrade to version 2.0.0, you should run [`db:sessions:upgrade`] rake task
|
122
|
+
to upgrade all existing session records in your database to the secured version.
|
123
|
+
|
124
|
+
[`db:sessions:upgrade`]: https://github.com/rails/activerecord-session_store/blob/master/lib/tasks/database.rake#L22
|
125
|
+
|
126
|
+
```console
|
127
|
+
$ rake db:sessions:upgrade
|
128
|
+
```
|
129
|
+
|
130
|
+
This rake task is idempotent and can be run multiple times, and session data of
|
131
|
+
users will remain intact.
|
132
|
+
|
133
|
+
Please see [#151] for more details.
|
134
|
+
|
135
|
+
[#151]: https://github.com/rails/activerecord-session_store/pull/151
|
136
|
+
|
137
|
+
Contributing to Active Record Session Store
|
138
|
+
--------------
|
98
139
|
|
99
140
|
Active Record Session Store is work of many contributors. You're encouraged to submit pull requests, propose features and discuss issues.
|
100
141
|
|
@@ -52,26 +52,22 @@ module ActionDispatch
|
|
52
52
|
#
|
53
53
|
# The example SqlBypass class is a generic SQL session store. You may
|
54
54
|
# use it as a basis for high-performance database-specific stores.
|
55
|
-
class ActiveRecordStore < ActionDispatch::Session::
|
55
|
+
class ActiveRecordStore < ActionDispatch::Session::AbstractSecureStore
|
56
56
|
# The class used for session storage. Defaults to
|
57
57
|
# ActiveRecord::SessionStore::Session
|
58
58
|
cattr_accessor :session_class
|
59
59
|
|
60
60
|
SESSION_RECORD_KEY = 'rack.session.record'
|
61
|
-
|
62
|
-
ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS
|
63
|
-
else
|
64
|
-
ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY
|
65
|
-
end
|
61
|
+
ENV_SESSION_OPTIONS_KEY = Rack::RACK_SESSION_OPTIONS
|
66
62
|
|
67
63
|
private
|
68
64
|
def get_session(request, sid)
|
69
|
-
logger.
|
70
|
-
unless sid and session =
|
65
|
+
logger.silence do
|
66
|
+
unless sid and session = get_session_with_fallback(sid)
|
71
67
|
# If the sid was nil or if there is no pre-existing session under the sid,
|
72
68
|
# force the generation of a new sid and associate a new session associated with the new sid
|
73
69
|
sid = generate_sid
|
74
|
-
session = @@session_class.new(:session_id => sid, :data => {})
|
70
|
+
session = @@session_class.new(:session_id => sid.private_id, :data => {})
|
75
71
|
end
|
76
72
|
request.env[SESSION_RECORD_KEY] = session
|
77
73
|
[sid, session.data]
|
@@ -79,8 +75,8 @@ module ActionDispatch
|
|
79
75
|
end
|
80
76
|
|
81
77
|
def write_session(request, sid, session_data, options)
|
82
|
-
logger.
|
83
|
-
record = get_session_model(request, sid)
|
78
|
+
logger.silence do
|
79
|
+
record, sid = get_session_model(request, sid)
|
84
80
|
record.data = session_data
|
85
81
|
return false unless record.save
|
86
82
|
|
@@ -96,9 +92,9 @@ module ActionDispatch
|
|
96
92
|
end
|
97
93
|
|
98
94
|
def delete_session(request, session_id, options)
|
99
|
-
logger.
|
95
|
+
logger.silence do
|
100
96
|
if sid = current_session_id(request)
|
101
|
-
if model =
|
97
|
+
if model = get_session_with_fallback(sid)
|
102
98
|
data = model.data
|
103
99
|
model.destroy
|
104
100
|
end
|
@@ -110,7 +106,7 @@ module ActionDispatch
|
|
110
106
|
new_sid = generate_sid
|
111
107
|
|
112
108
|
if options[:renew]
|
113
|
-
new_model = @@session_class.new(:session_id => new_sid, :data => data)
|
109
|
+
new_model = @@session_class.new(:session_id => new_sid.private_id, :data => data)
|
114
110
|
new_model.save
|
115
111
|
request.env[SESSION_RECORD_KEY] = new_model
|
116
112
|
end
|
@@ -120,11 +116,11 @@ module ActionDispatch
|
|
120
116
|
end
|
121
117
|
|
122
118
|
def get_session_model(request, id)
|
123
|
-
logger.
|
124
|
-
model =
|
125
|
-
|
119
|
+
logger.silence do
|
120
|
+
model = get_session_with_fallback(id)
|
121
|
+
unless model
|
126
122
|
id = generate_sid
|
127
|
-
model = @@session_class.new(:session_id => id, :data => {})
|
123
|
+
model = @@session_class.new(:session_id => id.private_id, :data => {})
|
128
124
|
model.save
|
129
125
|
end
|
130
126
|
if request.env[ENV_SESSION_OPTIONS_KEY][:id].nil?
|
@@ -132,23 +128,41 @@ module ActionDispatch
|
|
132
128
|
else
|
133
129
|
request.env[SESSION_RECORD_KEY] ||= model
|
134
130
|
end
|
135
|
-
model
|
131
|
+
[model, id]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_session_with_fallback(sid)
|
136
|
+
if sid && !self.class.private_session_id?(sid.public_id)
|
137
|
+
if (secure_session = @@session_class.find_by_session_id(sid.private_id))
|
138
|
+
secure_session
|
139
|
+
elsif (insecure_session = @@session_class.find_by_session_id(sid.public_id))
|
140
|
+
insecure_session.session_id = sid.private_id # this causes the session to be secured
|
141
|
+
insecure_session
|
142
|
+
end
|
136
143
|
end
|
137
144
|
end
|
138
145
|
|
139
146
|
def find_session(request, id)
|
140
|
-
model = get_session_model(request, id)
|
141
|
-
[
|
147
|
+
model, id = get_session_model(request, id)
|
148
|
+
[id, model.data]
|
149
|
+
end
|
150
|
+
|
151
|
+
module NilLogger
|
152
|
+
def self.silence
|
153
|
+
yield
|
154
|
+
end
|
142
155
|
end
|
143
156
|
|
144
157
|
def logger
|
145
|
-
ActiveRecord::Base.logger ||
|
158
|
+
ActiveRecord::Base.logger || NilLogger
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.private_session_id?(session_id)
|
162
|
+
# user tried to retrieve a session by a private key?
|
163
|
+
session_id =~ /\A\d+::/
|
146
164
|
end
|
165
|
+
|
147
166
|
end
|
148
167
|
end
|
149
168
|
end
|
150
|
-
|
151
|
-
if ActiveRecord::VERSION::MAJOR == 4
|
152
|
-
require 'action_dispatch/session/legacy_support'
|
153
|
-
ActionDispatch::Session::ActiveRecordStore.send(:include, ActionDispatch::Session::LegacySupport)
|
154
|
-
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
require 'active_record'
|
1
2
|
require 'active_record/session_store/version'
|
2
3
|
require 'action_dispatch/session/active_record_store'
|
3
|
-
require "active_record/session_store/extension/logger_silencer"
|
4
4
|
require 'active_support/core_ext/hash/keys'
|
5
5
|
require 'multi_json'
|
6
6
|
|
7
7
|
module ActiveRecord
|
8
8
|
module SessionStore
|
9
|
+
autoload :Session, 'active_record/session_store/session'
|
10
|
+
|
9
11
|
module ClassMethods # :nodoc:
|
10
12
|
mattr_accessor :serializer
|
11
13
|
|
@@ -18,20 +20,12 @@ module ActiveRecord
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def drop_table!
|
21
|
-
|
22
|
-
connection.schema_cache.clear_data_source_cache!(table_name)
|
23
|
-
else
|
24
|
-
connection.schema_cache.clear_table_cache!(table_name)
|
25
|
-
end
|
23
|
+
connection.schema_cache.clear_data_source_cache!(table_name)
|
26
24
|
connection.drop_table table_name
|
27
25
|
end
|
28
26
|
|
29
27
|
def create_table!
|
30
|
-
|
31
|
-
connection.schema_cache.clear_data_source_cache!(table_name)
|
32
|
-
else
|
33
|
-
connection.schema_cache.clear_table_cache!(table_name)
|
34
|
-
end
|
28
|
+
connection.schema_cache.clear_data_source_cache!(table_name)
|
35
29
|
connection.create_table(table_name) do |t|
|
36
30
|
t.string session_id_column, :limit => 255
|
37
31
|
t.text data_column_name
|
@@ -47,6 +41,8 @@ module ActiveRecord
|
|
47
41
|
JsonSerializer
|
48
42
|
when :hybrid then
|
49
43
|
HybridSerializer
|
44
|
+
when :null then
|
45
|
+
NullSerializer
|
50
46
|
else
|
51
47
|
self.serializer
|
52
48
|
end
|
@@ -91,18 +87,24 @@ module ActiveRecord
|
|
91
87
|
value.start_with?(MARSHAL_SIGNATURE)
|
92
88
|
end
|
93
89
|
end
|
90
|
+
|
91
|
+
# Defer serialization to the ActiveRecord database adapter
|
92
|
+
class NullSerializer
|
93
|
+
def self.load(value)
|
94
|
+
value
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.dump(value)
|
98
|
+
value
|
99
|
+
end
|
100
|
+
end
|
94
101
|
end
|
95
102
|
end
|
96
103
|
end
|
97
104
|
|
98
|
-
|
105
|
+
ActiveSupport.on_load(:active_record) do
|
106
|
+
require 'active_record/session_store/session'
|
107
|
+
end
|
108
|
+
|
99
109
|
require 'active_record/session_store/sql_bypass'
|
100
110
|
require 'active_record/session_store/railtie' if defined?(Rails)
|
101
|
-
|
102
|
-
ActionDispatch::Session::ActiveRecordStore.session_class = ActiveRecord::SessionStore::Session
|
103
|
-
Logger.send :include, ActiveRecord::SessionStore::Extension::LoggerSilencer
|
104
|
-
|
105
|
-
begin
|
106
|
-
require "syslog/logger"
|
107
|
-
Syslog::Logger.send :include, ActiveRecord::SessionStore::Extension::LoggerSilencer
|
108
|
-
rescue LoadError; end
|
@@ -17,13 +17,6 @@ module ActiveRecord
|
|
17
17
|
before_save :serialize_data!
|
18
18
|
before_save :raise_on_session_data_overflow!
|
19
19
|
|
20
|
-
# This method is defiend in `protected_attributes` gem. We can't check for
|
21
|
-
# `attr_accessible` as Rails also define this and raise `RuntimeError`
|
22
|
-
# telling you to use the gem.
|
23
|
-
if respond_to?(:accessible_attributes)
|
24
|
-
attr_accessible :session_id, :data
|
25
|
-
end
|
26
|
-
|
27
20
|
class << self
|
28
21
|
def data_column_size_limit
|
29
22
|
@data_column_size_limit ||= columns_hash[data_column_name].limit
|
@@ -45,8 +38,8 @@ module ActiveRecord
|
|
45
38
|
# Reset column info since it may be stale.
|
46
39
|
reset_column_information
|
47
40
|
if columns_hash['sessid']
|
48
|
-
def self.find_by_session_id(
|
49
|
-
find_by_sessid(
|
41
|
+
def self.find_by_session_id(session_id)
|
42
|
+
find_by_sessid(session_id)
|
50
43
|
end
|
51
44
|
|
52
45
|
define_method(:session_id) { sessid }
|
@@ -78,9 +71,32 @@ module ActiveRecord
|
|
78
71
|
@data
|
79
72
|
end
|
80
73
|
|
74
|
+
# This method was introduced when addressing CVE-2019-16782
|
75
|
+
# (see https://github.com/rack/rack/security/advisories/GHSA-hrqr-hxpp-chr3).
|
76
|
+
# Sessions created on version <= 1.1.3 were guessable via a timing attack.
|
77
|
+
# To secure sessions created on those old versions, this method can be called
|
78
|
+
# on all existing sessions in the database. Users will not lose their session
|
79
|
+
# when this is done.
|
80
|
+
def secure!
|
81
|
+
session_id_column = if self.class.columns_hash['sessid']
|
82
|
+
:sessid
|
83
|
+
else
|
84
|
+
:session_id
|
85
|
+
end
|
86
|
+
raw_session_id = read_attribute(session_id_column)
|
87
|
+
if ActionDispatch::Session::ActiveRecordStore.private_session_id?(raw_session_id)
|
88
|
+
# is already private, nothing to do
|
89
|
+
else
|
90
|
+
session_id_object = Rack::Session::SessionId.new(raw_session_id)
|
91
|
+
update_column(session_id_column, session_id_object.private_id)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
81
95
|
private
|
82
96
|
def serialize_data!
|
83
|
-
|
97
|
+
unless loaded?
|
98
|
+
throw :abort
|
99
|
+
end
|
84
100
|
write_attribute(@@data_column_name, self.class.serialize(data))
|
85
101
|
end
|
86
102
|
|
@@ -88,7 +104,9 @@ module ActiveRecord
|
|
88
104
|
# larger than the data storage column. Raises
|
89
105
|
# ActionController::SessionOverflowError.
|
90
106
|
def raise_on_session_data_overflow!
|
91
|
-
|
107
|
+
unless loaded?
|
108
|
+
throw :abort
|
109
|
+
end
|
92
110
|
limit = self.class.data_column_size_limit
|
93
111
|
if limit and read_attribute(@@data_column_name).size > limit
|
94
112
|
raise ActionController::SessionOverflowError
|
@@ -97,3 +115,5 @@ module ActiveRecord
|
|
97
115
|
end
|
98
116
|
end
|
99
117
|
end
|
118
|
+
|
119
|
+
ActionDispatch::Session::ActiveRecordStore.session_class = ActiveRecord::SessionStore::Session
|
@@ -60,15 +60,16 @@ module ActiveRecord
|
|
60
60
|
|
61
61
|
# Look up a session by id and deserialize its data if found.
|
62
62
|
def find_by_session_id(session_id)
|
63
|
-
if record = connection.select_one("SELECT #{connection.quote_column_name(data_column)} AS data FROM #{@@table_name} WHERE #{connection.quote_column_name(@@session_id_column)}=#{connection.quote(session_id
|
64
|
-
new(:session_id => session_id, :serialized_data => record['data'])
|
63
|
+
if record = connection.select_one("SELECT #{connection.quote_column_name(data_column)} AS data FROM #{@@table_name} WHERE #{connection.quote_column_name(@@session_id_column)}=#{connection.quote(session_id)}")
|
64
|
+
new(:session_id => session_id, :retrieved_by => session_id, :serialized_data => record['data'])
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
delegate :connection, :connection=, :connection_pool, :connection_pool=, :to => self
|
70
70
|
|
71
|
-
attr_reader :
|
71
|
+
attr_reader :new_record
|
72
|
+
attr_accessor :session_id
|
72
73
|
alias :new_record? :new_record
|
73
74
|
|
74
75
|
attr_writer :data
|
@@ -77,7 +78,8 @@ module ActiveRecord
|
|
77
78
|
# telling us to postpone deserializing until the data is requested.
|
78
79
|
# We need to handle a normal data attribute in case of a new record.
|
79
80
|
def initialize(attributes)
|
80
|
-
@session_id
|
81
|
+
@session_id = attributes[:session_id]
|
82
|
+
@retrieved_by = attributes[:retrieved_by]
|
81
83
|
@data = attributes[:data]
|
82
84
|
@serialized_data = attributes[:serialized_data]
|
83
85
|
@new_record = @serialized_data.nil?
|
@@ -122,8 +124,10 @@ module ActiveRecord
|
|
122
124
|
else
|
123
125
|
connect.update <<-end_sql, 'Update session'
|
124
126
|
UPDATE #{table_name}
|
125
|
-
SET
|
126
|
-
|
127
|
+
SET
|
128
|
+
#{connect.quote_column_name(data_column)}=#{connect.quote(serialized_data)},
|
129
|
+
#{connect.quote_column_name(session_id_column)}=#{connect.quote(@session_id)}
|
130
|
+
WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(@retrieved_by)}
|
127
131
|
end_sql
|
128
132
|
end
|
129
133
|
end
|
@@ -134,7 +138,7 @@ module ActiveRecord
|
|
134
138
|
connect = connection
|
135
139
|
connect.delete <<-end_sql, 'Destroy session'
|
136
140
|
DELETE FROM #{table_name}
|
137
|
-
WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id
|
141
|
+
WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
|
138
142
|
end_sql
|
139
143
|
end
|
140
144
|
end
|
data/lib/tasks/database.rake
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
namespace 'db:sessions' do
|
2
2
|
desc "Creates a sessions migration for use with ActiveRecord::SessionStore"
|
3
3
|
task :create => [:environment, 'db:load_config'] do
|
4
|
-
raise 'Task unavailable to this database (no migration support)' unless ActiveRecord::Base.connection.supports_migrations?
|
5
4
|
Rails.application.load_generators
|
6
|
-
require '
|
7
|
-
|
5
|
+
require 'generators/active_record/session_migration_generator'
|
6
|
+
ActiveRecord::Generators::SessionMigrationGenerator.start [ ENV['MIGRATION'] || 'add_sessions_table' ]
|
8
7
|
end
|
9
8
|
|
10
9
|
desc "Clear the sessions table"
|
11
10
|
task :clear => [:environment, 'db:load_config'] do
|
12
|
-
ActiveRecord::Base.connection.execute "
|
11
|
+
ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{ActiveRecord::SessionStore::Session.table_name}"
|
13
12
|
end
|
14
13
|
|
15
14
|
desc "Trim old sessions from the table (default: > 30 days)"
|
@@ -19,4 +18,9 @@ namespace 'db:sessions' do
|
|
19
18
|
where("updated_at < ?", cutoff_period).
|
20
19
|
delete_all
|
21
20
|
end
|
21
|
+
|
22
|
+
desc "Upgrade current sessions in the database to the secure version"
|
23
|
+
task :upgrade => [:environment, 'db:load_config'] do
|
24
|
+
ActionDispatch::Session::ActiveRecordStore.session_class.find_each(&:secure!)
|
25
|
+
end
|
22
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-session_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,67 +16,49 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '5.1'
|
19
|
+
version: 5.2.4.1
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '5.1'
|
26
|
+
version: 5.2.4.1
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: actionpack
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
31
|
- - ">="
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
40
|
-
- - "<"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '5.1'
|
33
|
+
version: 5.2.4.1
|
43
34
|
type: :runtime
|
44
35
|
prerelease: false
|
45
36
|
version_requirements: !ruby/object:Gem::Requirement
|
46
37
|
requirements:
|
47
38
|
- - ">="
|
48
39
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
50
|
-
- - "<"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '5.1'
|
40
|
+
version: 5.2.4.1
|
53
41
|
- !ruby/object:Gem::Dependency
|
54
42
|
name: railties
|
55
43
|
requirement: !ruby/object:Gem::Requirement
|
56
44
|
requirements:
|
57
45
|
- - ">="
|
58
46
|
- !ruby/object:Gem::Version
|
59
|
-
version:
|
60
|
-
- - "<"
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: '5.1'
|
47
|
+
version: 5.2.4.1
|
63
48
|
type: :runtime
|
64
49
|
prerelease: false
|
65
50
|
version_requirements: !ruby/object:Gem::Requirement
|
66
51
|
requirements:
|
67
52
|
- - ">="
|
68
53
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
- - "<"
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
version: '5.1'
|
54
|
+
version: 5.2.4.1
|
73
55
|
- !ruby/object:Gem::Dependency
|
74
56
|
name: rack
|
75
57
|
requirement: !ruby/object:Gem::Requirement
|
76
58
|
requirements:
|
77
59
|
- - ">="
|
78
60
|
- !ruby/object:Gem::Version
|
79
|
-
version:
|
61
|
+
version: 2.0.8
|
80
62
|
- - "<"
|
81
63
|
- !ruby/object:Gem::Version
|
82
64
|
version: '3'
|
@@ -86,7 +68,7 @@ dependencies:
|
|
86
68
|
requirements:
|
87
69
|
- - ">="
|
88
70
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
71
|
+
version: 2.0.8
|
90
72
|
- - "<"
|
91
73
|
- !ruby/object:Gem::Version
|
92
74
|
version: '3'
|
@@ -124,21 +106,7 @@ dependencies:
|
|
124
106
|
- - ">="
|
125
107
|
- !ruby/object:Gem::Version
|
126
108
|
version: '0'
|
127
|
-
|
128
|
-
name: appraisal
|
129
|
-
requirement: !ruby/object:Gem::Requirement
|
130
|
-
requirements:
|
131
|
-
- - "~>"
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: 2.1.0
|
134
|
-
type: :development
|
135
|
-
prerelease: false
|
136
|
-
version_requirements: !ruby/object:Gem::Requirement
|
137
|
-
requirements:
|
138
|
-
- - "~>"
|
139
|
-
- !ruby/object:Gem::Version
|
140
|
-
version: 2.1.0
|
141
|
-
description:
|
109
|
+
description:
|
142
110
|
email: david@loudthinking.com
|
143
111
|
executables: []
|
144
112
|
extensions: []
|
@@ -148,9 +116,7 @@ files:
|
|
148
116
|
- MIT-LICENSE
|
149
117
|
- README.md
|
150
118
|
- lib/action_dispatch/session/active_record_store.rb
|
151
|
-
- lib/action_dispatch/session/legacy_support.rb
|
152
119
|
- lib/active_record/session_store.rb
|
153
|
-
- lib/active_record/session_store/extension/logger_silencer.rb
|
154
120
|
- lib/active_record/session_store/railtie.rb
|
155
121
|
- lib/active_record/session_store/session.rb
|
156
122
|
- lib/active_record/session_store/sql_bypass.rb
|
@@ -163,7 +129,7 @@ homepage: https://github.com/rails/activerecord-session_store
|
|
163
129
|
licenses:
|
164
130
|
- MIT
|
165
131
|
metadata: {}
|
166
|
-
post_install_message:
|
132
|
+
post_install_message:
|
167
133
|
rdoc_options:
|
168
134
|
- "--main"
|
169
135
|
- README.md
|
@@ -173,16 +139,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
173
139
|
requirements:
|
174
140
|
- - ">="
|
175
141
|
- !ruby/object:Gem::Version
|
176
|
-
version:
|
142
|
+
version: 2.2.2
|
177
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
144
|
requirements:
|
179
145
|
- - ">="
|
180
146
|
- !ruby/object:Gem::Version
|
181
147
|
version: '0'
|
182
148
|
requirements: []
|
183
|
-
|
184
|
-
|
185
|
-
signing_key:
|
149
|
+
rubygems_version: 3.1.4
|
150
|
+
signing_key:
|
186
151
|
specification_version: 4
|
187
152
|
summary: An Action Dispatch session store backed by an Active Record class.
|
188
153
|
test_files: []
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module ActionDispatch
|
2
|
-
module Session
|
3
|
-
module LegacySupport
|
4
|
-
EnvWrapper = Struct.new(:env)
|
5
|
-
|
6
|
-
def self.included(klass)
|
7
|
-
[
|
8
|
-
:get_session,
|
9
|
-
:get_session_model,
|
10
|
-
:write_session,
|
11
|
-
:delete_session,
|
12
|
-
:find_session
|
13
|
-
].each do |m|
|
14
|
-
klass.send(:alias_method, "#{m}_rails5".to_sym, m)
|
15
|
-
klass.send(:remove_method, m)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def get_session(env, sid)
|
20
|
-
request = EnvWrapper.new(env)
|
21
|
-
get_session_rails5(request, sid)
|
22
|
-
end
|
23
|
-
|
24
|
-
def set_session(env, sid, session_data, options)
|
25
|
-
request = EnvWrapper.new(env)
|
26
|
-
write_session_rails5(request, sid, session_data, options)
|
27
|
-
end
|
28
|
-
|
29
|
-
def destroy_session(env, session_id, options)
|
30
|
-
request = EnvWrapper.new(env)
|
31
|
-
if sid = current_session_id(request.env)
|
32
|
-
get_session_model(request, sid).destroy
|
33
|
-
request.env[self.class::SESSION_RECORD_KEY] = nil
|
34
|
-
end
|
35
|
-
generate_sid unless options[:drop]
|
36
|
-
end
|
37
|
-
|
38
|
-
def get_session_model(request, sid)
|
39
|
-
if request.env[self.class::ENV_SESSION_OPTIONS_KEY][:id].nil?
|
40
|
-
request.env[self.class::SESSION_RECORD_KEY] = find_session(sid)
|
41
|
-
else
|
42
|
-
request.env[self.class::SESSION_RECORD_KEY] ||= find_session(sid)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def find_session(id)
|
47
|
-
self.class.session_class.find_by_session_id(id) || self.class.session_class.new(:session_id => id, :data => {})
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require "thread"
|
2
|
-
require "active_support/core_ext/class/attribute_accessors"
|
3
|
-
require "active_support/core_ext/module/aliasing"
|
4
|
-
require "active_support/core_ext/module/attribute_accessors"
|
5
|
-
require "active_support/concern"
|
6
|
-
|
7
|
-
module ActiveRecord
|
8
|
-
module SessionStore
|
9
|
-
module Extension
|
10
|
-
module LoggerSilencer
|
11
|
-
extend ActiveSupport::Concern
|
12
|
-
|
13
|
-
included do
|
14
|
-
cattr_accessor :silencer
|
15
|
-
self.silencer = true
|
16
|
-
alias_method :level_without_threadsafety, :level
|
17
|
-
alias_method :level, :level_with_threadsafety
|
18
|
-
alias_method :add_without_threadsafety, :add
|
19
|
-
alias_method :add, :add_with_threadsafety
|
20
|
-
end
|
21
|
-
|
22
|
-
def thread_level
|
23
|
-
Thread.current[thread_hash_level_key]
|
24
|
-
end
|
25
|
-
|
26
|
-
def thread_level=(level)
|
27
|
-
Thread.current[thread_hash_level_key] = level
|
28
|
-
end
|
29
|
-
|
30
|
-
def level_with_threadsafety
|
31
|
-
thread_level || level_without_threadsafety
|
32
|
-
end
|
33
|
-
|
34
|
-
def add_with_threadsafety(severity, message = nil, progname = nil, &block)
|
35
|
-
if (defined?(@logdev) && @logdev.nil?) || (severity || UNKNOWN) < level
|
36
|
-
true
|
37
|
-
else
|
38
|
-
add_without_threadsafety(severity, message, progname, &block)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Silences the logger for the duration of the block.
|
43
|
-
def silence_logger(temporary_level = Logger::ERROR)
|
44
|
-
if silencer
|
45
|
-
begin
|
46
|
-
self.thread_level = temporary_level
|
47
|
-
yield self
|
48
|
-
ensure
|
49
|
-
self.thread_level = nil
|
50
|
-
end
|
51
|
-
else
|
52
|
-
yield self
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
for severity in Logger::Severity.constants
|
57
|
-
class_eval <<-EOT, __FILE__, __LINE__ + 1
|
58
|
-
def #{severity.downcase}? # def debug?
|
59
|
-
Logger::#{severity} >= level # DEBUG >= level
|
60
|
-
end # end
|
61
|
-
EOT
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def thread_hash_level_key
|
67
|
-
@thread_hash_level_key ||= :"ThreadSafeLogger##{object_id}@level"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class NilLogger
|
73
|
-
def self.silence_logger
|
74
|
-
yield
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|