rack_session_manipulation 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|