rack_session_manipulation 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -3
- data/lib/rack_session_manipulation.rb +1 -18
- data/lib/rack_session_manipulation/capybara.rb +13 -7
- data/lib/rack_session_manipulation/config.rb +23 -1
- data/lib/rack_session_manipulation/json_encoder.rb +25 -0
- data/lib/rack_session_manipulation/middleware.rb +12 -9
- data/lib/rack_session_manipulation/version.rb +1 -1
- data/rack_session_manipulation.gemspec +2 -0
- metadata +17 -3
- data/lib/rack_session_manipulation/utilities.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dbcb62e888d972acb2dd24eb5a7a735381d58752
|
4
|
+
data.tar.gz: 9d540498faedaf7581331dd70623a95a617acb92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30df0e975654195180fd191c52e9fa945f081014c00407e4da3064d979683afad96430b27afd2f74bd34c75ca437cc6428fd9079698fb6460427d8cf82b45089
|
7
|
+
data.tar.gz: 4aec3d4ced2064f6aef2456d805e3473985a60abed1bff6a6add1a60597d7688cfaac2b21c6533e9d4143d3d62f3a6fa9c11b7de93c40d000f764c837e3ddff0
|
data/README.md
CHANGED
@@ -15,7 +15,13 @@ isolation without the dependency of the rest of your application.
|
|
15
15
|
This is not intended to replace full set of 'behavior' tests, but can be used
|
16
16
|
to speed up getting to a 'Given' state in place of helpers that previously
|
17
17
|
would be forced to walk through your entire application stack to establish the
|
18
|
-
target state. That walkthrough is valuable but can be redundant and unecessary
|
18
|
+
target state. That walkthrough is valuable but can be redundant and unecessary
|
19
|
+
when they are only used to setup other tests.
|
20
|
+
|
21
|
+
RackSessionManipulation strives to be a lightweight and safe, while having a
|
22
|
+
high quality code base following the best ruby practices.
|
23
|
+
|
24
|
+
## Security Notice
|
19
25
|
|
20
26
|
This middleware should never be used in production as it allows arbitrary
|
21
27
|
tampering of encrypted server-side session information without any form of
|
@@ -23,6 +29,14 @@ authentication. Use in production can lead to abuses such as user
|
|
23
29
|
impersonation, privilege escalation, and private information exposure depending
|
24
30
|
on what the application stores in the session.
|
25
31
|
|
32
|
+
## Alternatives
|
33
|
+
|
34
|
+
There is a very similar rack middleware [RackSessionAccess][1] that
|
35
|
+
accomplishes more or less the same task. I wasn't particularly fond of how that
|
36
|
+
gem solved the updating of state using multiple requests, and marshalled
|
37
|
+
objects as well as unecessary use of builder. The approach seemed more
|
38
|
+
complicated, slower and more dangerous than necessary.
|
39
|
+
|
26
40
|
## Installation
|
27
41
|
|
28
42
|
Add this line to your application's Gemfile:
|
@@ -43,9 +57,25 @@ Or install it yourself as:
|
|
43
57
|
|
44
58
|
## Contributing
|
45
59
|
|
46
|
-
|
60
|
+
I welcome new ideas, bug fixes and comments from anyone and strive to take no
|
61
|
+
longer than a week to respond to issues, PRs, or various comments.
|
62
|
+
|
63
|
+
All code submitted through PRs will be licensed under this project's MIT
|
64
|
+
license, if this is a problem please instead open an issue before making your
|
65
|
+
changes indicating this and I depending on the request I may make the requested
|
66
|
+
changes myself or attempt to convince about the usage of this license. I want
|
67
|
+
to avoid a multi-license code base that may impede any individual's usage of
|
68
|
+
this code.
|
69
|
+
|
70
|
+
With all that said, if you'd like to contribute please follow the standard
|
71
|
+
contribution guide:
|
72
|
+
|
73
|
+
1. Review the [Contributor Code of Conduct][2]
|
47
74
|
2. Fork it ( https://github.com/sstelfox/rack_session_manipulation/fork )
|
48
75
|
3. Create your feature branch (`git checkout -b my-new-feature`)
|
49
76
|
4. Commit your changes (`git commit -am 'Add some feature'`)
|
50
77
|
5. Push to the branch (`git push origin my-new-feature`)
|
51
|
-
6. Create a new Pull Request
|
78
|
+
6. Create a new Pull Request against this repo's develop branch
|
79
|
+
|
80
|
+
[1]: https://github.com/railsware/rack_session_access
|
81
|
+
[2]: CODE_OF_CONDUCT.md
|
@@ -1,28 +1,11 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
require 'rack_session_manipulation/config'
|
4
|
+
require 'rack_session_manipulation/json_encoder'
|
4
5
|
require 'rack_session_manipulation/middleware'
|
5
|
-
require 'rack_session_manipulation/utilities'
|
6
6
|
require 'rack_session_manipulation/version'
|
7
7
|
|
8
8
|
# RackSessionManipulation is rack middleware designed to expose internal
|
9
9
|
# session information to be read and modified from within tests.
|
10
10
|
module RackSessionManipulation
|
11
|
-
extend RackSessionManipulation::Utilities
|
12
|
-
|
13
|
-
# Keeps a globally accessible instance of a configuration object. This will
|
14
|
-
# initialize a new Config object the first time this is called (using a
|
15
|
-
# random path for the session access path).
|
16
|
-
#
|
17
|
-
# @return [RackSessionManipulation::Config]
|
18
|
-
def self.config
|
19
|
-
@config ||= RackSessionManipulation::Config.new(random_path_prefix)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Allows block DSL style configuration of the global configuration instance.
|
23
|
-
#
|
24
|
-
# @yield [RackSessionManipulation::Config]
|
25
|
-
def self.configure
|
26
|
-
yield(config)
|
27
|
-
end
|
28
11
|
end
|
@@ -5,16 +5,16 @@ module RackSessionManipulation
|
|
5
5
|
module Capybara
|
6
6
|
# Provides a mechanism to completely reset the server's session to a fresh
|
7
7
|
# blank slate.
|
8
|
-
def
|
9
|
-
driver_method_fallback(:delete,
|
8
|
+
def session_reset
|
9
|
+
driver_method_fallback(:delete, session_manipulation_config.path, {})
|
10
10
|
end
|
11
11
|
|
12
12
|
# Retrieve a hash containing the entire state of the current session.
|
13
13
|
#
|
14
14
|
# @return [Hash] Hash of the session
|
15
15
|
def session
|
16
|
-
driver.get(
|
17
|
-
|
16
|
+
driver.get(session_manipulation_config.path)
|
17
|
+
session_manipulation_config.encoder.decode(driver.response.body)
|
18
18
|
end
|
19
19
|
|
20
20
|
# Updates the state of the current session. An important thing to note
|
@@ -28,8 +28,14 @@ module RackSessionManipulation
|
|
28
28
|
#
|
29
29
|
# @param [Hash] hash Data to be set / updated within the current session.
|
30
30
|
def session=(hash)
|
31
|
-
data = {
|
32
|
-
|
31
|
+
data = {
|
32
|
+
'session_data' => session_manipulation_config.encoder.encode(hash)
|
33
|
+
}
|
34
|
+
driver_method_fallback(:put, session_manipulation_config.path, data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def session_manipulation_config
|
38
|
+
@rsm_config ||= Config.new
|
33
39
|
end
|
34
40
|
|
35
41
|
protected
|
@@ -53,7 +59,7 @@ module RackSessionManipulation
|
|
53
59
|
return
|
54
60
|
end
|
55
61
|
|
56
|
-
|
62
|
+
dat.merge!('_method' => method.to_s.upcase)
|
57
63
|
driver.respond_to?(:post) ? driver.post(path, dat) : driver.get(path, dat)
|
58
64
|
end
|
59
65
|
end
|
@@ -1,5 +1,27 @@
|
|
1
|
+
require 'rack_session_manipulation/json_encoder'
|
2
|
+
|
1
3
|
# Parent namespace for the Rack Session Manipulation middleware.
|
2
4
|
module RackSessionManipulation
|
5
|
+
# Various default configuration options for the middleware.
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
encoder: RackSessionManipulation::JSONEncoder,
|
8
|
+
path: '/rsm_session_path'
|
9
|
+
}
|
10
|
+
|
3
11
|
# A data storage structure for holding configuration related information.
|
4
|
-
Config
|
12
|
+
class Config
|
13
|
+
attr_accessor :encoder, :path
|
14
|
+
|
15
|
+
# Setup the configuration object with the provided options, falling back on
|
16
|
+
# the configured defaults.
|
17
|
+
#
|
18
|
+
# @param [Hash<Symbol=>Object>] options Override the default configuration
|
19
|
+
# options with the provided parameters.
|
20
|
+
def initialize(options = {})
|
21
|
+
options = DEFAULT_OPTIONS.merge(options)
|
22
|
+
|
23
|
+
self.encoder = options[:encoder]
|
24
|
+
self.path = options[:path]
|
25
|
+
end
|
26
|
+
end
|
5
27
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Parent namespace for the Rack Session Manipulation middleware.
|
2
|
+
module RackSessionManipulation
|
3
|
+
# The stock encoder for session data. Encodes and decodes everything to/from
|
4
|
+
# JSON payloads.
|
5
|
+
module JSONEncoder
|
6
|
+
class << self
|
7
|
+
# Decoder for session state into a standard Ruby hash using JSON.
|
8
|
+
#
|
9
|
+
# @param [String] encoded_data JSON encoded session data
|
10
|
+
# @return [Hash] Hash version of the session data
|
11
|
+
def decode(encoded_data)
|
12
|
+
JSON.parse(encoded_data)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Encoder for session state using JSON.
|
16
|
+
#
|
17
|
+
# @param [Hash] obj An object that can be serialized using JSON,
|
18
|
+
# generally this is a hash.
|
19
|
+
# @return [String] The encoded data.
|
20
|
+
def encode(obj)
|
21
|
+
JSON.generate(obj)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -3,6 +3,8 @@ module RackSessionManipulation
|
|
3
3
|
# Rack middleware that handles the accessing and modification of session
|
4
4
|
# state.
|
5
5
|
class Middleware
|
6
|
+
attr_reader :app, :config, :routes
|
7
|
+
|
6
8
|
# Primary entry point of this middleware. Every request that makes it this
|
7
9
|
# far into the stack will be parsed and when it matches something this
|
8
10
|
# middleware is designed to handle it will stop the chain and process it
|
@@ -16,7 +18,7 @@ module RackSessionManipulation
|
|
16
18
|
request = Rack::Request.new(env)
|
17
19
|
|
18
20
|
action = get_action(request)
|
19
|
-
action.nil? ?
|
21
|
+
action.nil? ? app.call(env) : send(action, request)
|
20
22
|
end
|
21
23
|
|
22
24
|
# Setup the middleware with the primary application passed in, anything we
|
@@ -24,8 +26,11 @@ module RackSessionManipulation
|
|
24
26
|
#
|
25
27
|
# @param [Object#call] app A rack application that implements the #call
|
26
28
|
# method.
|
27
|
-
|
29
|
+
# @param [Hash<Symbol=>Object>] opts Configuration options for the
|
30
|
+
# middleware.
|
31
|
+
def initialize(app, opts = {})
|
28
32
|
@app = app
|
33
|
+
@config = Config.new(opts)
|
29
34
|
@routes = {
|
30
35
|
'DELETE' => :reset,
|
31
36
|
'GET' => :retrieve,
|
@@ -33,8 +38,6 @@ module RackSessionManipulation
|
|
33
38
|
}
|
34
39
|
end
|
35
40
|
|
36
|
-
protected
|
37
|
-
|
38
41
|
# Look up what HTTP method was used for this request. In the event the
|
39
42
|
# client doesn't support all HTTP methods, the standard '_method' parameter
|
40
43
|
# fall back is made available to override the method actually used.
|
@@ -63,8 +66,8 @@ module RackSessionManipulation
|
|
63
66
|
# @return [Symbol,Nil] Name of method to use or nil if this middleware
|
64
67
|
# should pass the request on to the app.
|
65
68
|
def get_action(request)
|
66
|
-
return unless request.path ==
|
67
|
-
|
69
|
+
return unless request.path == config.path
|
70
|
+
routes[extract_method(request)]
|
68
71
|
end
|
69
72
|
|
70
73
|
# A helper mechanism to consistently generate common headers client will
|
@@ -95,7 +98,7 @@ module RackSessionManipulation
|
|
95
98
|
# @return [Array<Fixnum, Hash, String>]
|
96
99
|
def retrieve(request)
|
97
100
|
session_hash = request.env['rack.session'].to_hash
|
98
|
-
content =
|
101
|
+
content = config.encoder.encode(session_hash)
|
99
102
|
|
100
103
|
[200, headers(content.length), content]
|
101
104
|
end
|
@@ -108,11 +111,11 @@ module RackSessionManipulation
|
|
108
111
|
# @return [Array<Fixnum, Hash, String>]
|
109
112
|
def update(request)
|
110
113
|
session_data = request.params['session_data']
|
111
|
-
|
114
|
+
config.encoder.decode(session_data).each do |k, v|
|
112
115
|
request.env['rack.session'][k] = v
|
113
116
|
end
|
114
117
|
|
115
|
-
loc_hdr = { 'Location' =>
|
118
|
+
loc_hdr = { 'Location' => config.path }
|
116
119
|
[303, headers(0).merge(loc_hdr), '']
|
117
120
|
rescue JSON::ParserError
|
118
121
|
[400, headers(0), '']
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack_session_manipulation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Stelfox
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,8 +212,8 @@ files:
|
|
198
212
|
- lib/rack_session_manipulation.rb
|
199
213
|
- lib/rack_session_manipulation/capybara.rb
|
200
214
|
- lib/rack_session_manipulation/config.rb
|
215
|
+
- lib/rack_session_manipulation/json_encoder.rb
|
201
216
|
- lib/rack_session_manipulation/middleware.rb
|
202
|
-
- lib/rack_session_manipulation/utilities.rb
|
203
217
|
- lib/rack_session_manipulation/version.rb
|
204
218
|
- rack_session_manipulation.gemspec
|
205
219
|
homepage: https://github.com/sstelfox/rack_session_manipulation
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# Parent namespace for the Rack Session Manipulation middleware.
|
2
|
-
module RackSessionManipulation
|
3
|
-
# Various utility methods that will be module level functions for the parent
|
4
|
-
# namespace module.
|
5
|
-
module Utilities
|
6
|
-
# Helper method for decoding the session state into a standard Ruby hash.
|
7
|
-
# This data is exposed as JSON, and is parsed as such.
|
8
|
-
#
|
9
|
-
# @param [String] encoded_data JSON encoded session data
|
10
|
-
# @return [Hash] Hash version of the session data
|
11
|
-
def decode(encoded_data)
|
12
|
-
JSON.parse(encoded_data)
|
13
|
-
end
|
14
|
-
|
15
|
-
# Helper method for encoding modified session state for the middleware. The
|
16
|
-
# middleware expects JSON so this is just a thin wrapper for encoding to
|
17
|
-
# JSON.
|
18
|
-
#
|
19
|
-
# @param [Hash] obj An object that can be serialized using JSON, generally
|
20
|
-
# this is a hash.
|
21
|
-
# @return [String] The encoded data.
|
22
|
-
def encode(obj)
|
23
|
-
JSON.generate(obj)
|
24
|
-
end
|
25
|
-
|
26
|
-
# SecureRandom raises a NotImplementedError if no random device is
|
27
|
-
# available in that case fallback on Kernel.rand. Shamelessly stolen from
|
28
|
-
# the Sinatra session secret generation code.
|
29
|
-
#
|
30
|
-
# @return [String]
|
31
|
-
def random_path_prefix
|
32
|
-
num = begin
|
33
|
-
require 'securerandom'
|
34
|
-
SecureRandom.random_number(2**128 - 1)
|
35
|
-
rescue LoadError, NotImplementedError
|
36
|
-
Kernel.rand(2**128 - 1)
|
37
|
-
end
|
38
|
-
format('/%032x', num)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|