merge_params 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3c1c70a888ac373aa3469a2f5c9363f40b201fdd
4
+ data.tar.gz: 465b22de3bebaef210a4ee8a5e94de389f38a099
5
+ SHA512:
6
+ metadata.gz: e63a767704dd575d3376bff60cc895b182b43c88f8c549394b7dbeec777964d040b83a57dd8eee5326e6c534978859a70d44eac3bf4bca2fdcf234f711f6b80c
7
+ data.tar.gz: 3e57322d8275102875e4f313ad240dba635302f4fabb9d601d1c26d92fa59845f2039f7448e05819dd6ff01424b3af6dbfceba58790b3bebc514bf9a7ab24e20
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.4.1
7
+ before_install: gem install bundler -v 1.17.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in merge_params.gemspec
6
+ gemspec
data/License ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2018 Tyler Rick
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4
+ associated documentation files (the "Software"), to deal in the Software without restriction,
5
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
6
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
7
+ furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial
10
+ portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/Readme.md ADDED
@@ -0,0 +1,84 @@
1
+ # MergeParams
2
+
3
+ ## Why do we need it?
4
+
5
+ Have you ever wanted to take the current route and change just one parameter in the route to
6
+ generate a new route?
7
+
8
+ For example, maybe you've tried to do something like this:
9
+
10
+ ```ruby
11
+ redirect_to url_for(params.merge(thing_id: thing.id));
12
+ ```
13
+
14
+ or this:
15
+
16
+ ```ruby
17
+ link_to 'Download as CSV', params.merge(format: :csv)
18
+ ```
19
+
20
+ If you have tried that, and you are on Rails 5.0 or later, then you have probably run into this
21
+ error:
22
+
23
+ Attempting to generate a URL from non-sanitized request parameters! An attacker can
24
+ inject malicious data into the generated URL, such as changing the host. Whitelist and sanitize
25
+ passed parameters to be secure.
26
+
27
+ (See also: https://github.com/rails/rails/issues/26289)
28
+
29
+ ## How do I use it?
30
+
31
+ Anywhere you would be tempted to do `params.merge(hash)`, just replace with `merge_params(hash)` or `merge_url_for(hash)`. For example:
32
+
33
+ ```ruby
34
+ link_to 'Download as CSV', merge_params(format: :csv)
35
+ ```
36
+
37
+ ```ruby
38
+ redirect_to merge_url_for(thing_id: thing.id);
39
+ ```
40
+
41
+ ## Is it guaranteed to be safe?
42
+
43
+ No. While a best effort has been made to ensure unsafe params are not used to generate a URL, we may
44
+ have overlooked something. Please review the code and the tests (coming soon) and open an issue if
45
+ you find any security holes in this approach.
46
+
47
+ ## Other helpers
48
+
49
+ Unlike `url_for_merge`, which tries to generate a route from the given params, sometimes you just
50
+ want to add the given params to the "end" of the URL as part of the query string:
51
+
52
+ ```ruby
53
+ add_params(key: 'value')
54
+ # => "/current_path?key=value
55
+
56
+ add_params({key: 'value'}, '/other_url')
57
+ # => "/other_url?key=value
58
+ ```
59
+
60
+ ## Installation
61
+
62
+ Add this line to your application's Gemfile:
63
+
64
+ ```ruby
65
+ gem 'merge_params'
66
+ ```
67
+
68
+ Add this line to your `ApplicationController` (or whichever controller you want to have the
69
+ helpers):
70
+
71
+ ```ruby
72
+ include MergeParams::Helpers
73
+ ```
74
+
75
+ The helpers will be also be added with `helper_method` so that they are available for use in view
76
+ templates as well.
77
+
78
+ ## Similar projects
79
+
80
+ - [uri_query_merger](https://libraries.io/github/jordanmaguire/uri_query_merger)
81
+
82
+ ## Contributing
83
+
84
+ Bug reports and pull requests are welcome on GitHub at https://github.com/TylerRick/merge_params.
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "merge_params"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,8 @@
1
+ require 'active_support'
2
+
3
+ require 'merge_params/version'
4
+ require 'merge_params/helpers'
5
+
6
+ module MergeParams
7
+ autoload :Helpers, 'merge_params/helpers'
8
+ end
@@ -0,0 +1,97 @@
1
+ require 'uri'
2
+
3
+ module MergeParams::Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ # request.parameters but with symbolized keys.
7
+ def request_params
8
+ request.parameters.symbolize_keys
9
+ end
10
+
11
+ # request.parameters (which also includes POST params) but with only those keys that would
12
+ # normally be passed in a query string (without :controller, :action, :format) and with symbolized
13
+ # keys.
14
+ def query_params_from_request_params
15
+ request.parameters.symbolize_keys.
16
+ except(*request.path_parameters.symbolize_keys.keys)
17
+ end
18
+
19
+ # Returns a hash of params from the query string (https://en.wikipedia.org/wiki/Query_string),
20
+ # with symbolized keys.
21
+ def query_params
22
+ request.query_parameters.symbolize_keys
23
+ end
24
+
25
+ # Params that can safely be passed to url_for to build a route. (Used by merge_url_for.)
26
+ #
27
+ # We exclude RESERVED_OPTIONS such as :host because such options should only come from your app
28
+ # code. Allowing :host to be set via query params, for example, means a bad actor could cause
29
+ # links that go to a different site entirely:
30
+ #
31
+ # # Request for /things?host=somehackingsite.ru
32
+ # url_for(params) => "http://somehackingsite.ru/things"
33
+ #
34
+ # Similarly, the :controller and :action keys of `params` *never* come from the query string, but
35
+ # from `path_parameters`. (TODO: So why not just use params.except(...)?)
36
+ #
37
+ # TODO: Why not allow :format from params? To force people to use .:format? But doesn't that also
38
+ # come through as params?
39
+ #
40
+ # (And we don't even need to pass the path_parameters on to url_for because url_for already
41
+ # includes those (from :_recall)
42
+ #
43
+ def params_for_url_for
44
+ params.to_unsafe_h.symbolize_keys.except(
45
+ *ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS,
46
+ :controller,
47
+ :action,
48
+ :format
49
+ )
50
+ end
51
+
52
+ # Safely merges the given params with the params from the current request
53
+ def merge_params(new_params = {})
54
+ params_for_url_for.merge(new_params)
55
+ end
56
+
57
+ # Safely merges the given params with the params from the current request, then generates a route
58
+ # from the merged params.
59
+ def merge_url_for(new_params = {})
60
+ url = url_for(merge_params(new_params))
61
+
62
+ # Now pass along in the *query string* any params that we couldn't pass to url_for because they
63
+ # were reserved options.
64
+ query_params_already_added = parse_nested_query(URI(url).query || '')
65
+ query_params_to_add = query_params.except(*query_params_already_added.keys)
66
+ add_params(query_params_to_add, url)
67
+ end
68
+
69
+ # Adds params to the query string
70
+ # (Unlike url_for_merge, which tries to generate a route from the params.)
71
+ # TODO: Should URL be first like https://libraries.io/github/jordanmaguire/uri_query_merger ?
72
+ # UriQueryMerger.new("http://www.google.com?other=1", {jordan: "rules"}).merge
73
+ # Can we make it work that way when a URL is supplied buth otherwise let the params be the first
74
+ # and only argument (to optimize for that more common use case)?
75
+ def add_params(params = {}, url = request.fullpath)
76
+ uri = URI(url)
77
+ params = parse_nested_query(uri.query || '').merge(params)
78
+ uri.query = Rack::Utils.build_nested_query(params)
79
+ uri.to_s
80
+ end
81
+
82
+ included do
83
+ helper_method(
84
+ :request_params,
85
+ :params_for_url_for,
86
+ :merge_params,
87
+ :merge_url_for,
88
+ :add_params
89
+ ) if respond_to?(:helper_method)
90
+ end
91
+
92
+ private
93
+
94
+ def parse_nested_query(query)
95
+ Rack::Utils.parse_nested_query(query || '').symbolize_keys
96
+ end
97
+ end
@@ -0,0 +1,5 @@
1
+ module MergeParams
2
+ def self.version
3
+ "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,36 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "merge_params/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "merge_params"
7
+ spec.version = MergeParams.version
8
+ spec.authors = ["Tyler Rick"]
9
+ spec.email = ["tyler@tylerrick.com"]
10
+ spec.license = "MIT"
11
+
12
+ spec.summary = %q{Safely merge params for use with url_for or for the query string}
13
+ spec.description = spec.summary
14
+ spec.homepage = "http://github.com/TylerRick/merge_params"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ spec.metadata["changelog_uri"] = "TODO: Put your gem's Changelog.md URL here."
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.required_ruby_version = ">= 2.3.0"
30
+ spec.add_dependency "activesupport", [">= 4.2", "< 5.3"]
31
+ spec.add_dependency "actionpack", [">= 4.2", "< 5.3"]
32
+
33
+ spec.add_development_dependency "bundler", "~> 1.17"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rspec", "~> 3.0"
36
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: merge_params
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Rick
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-11-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.3'
33
+ - !ruby/object:Gem::Dependency
34
+ name: actionpack
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '4.2'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '5.3'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '4.2'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '5.3'
53
+ - !ruby/object:Gem::Dependency
54
+ name: bundler
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.17'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.17'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '10.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '10.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.0'
95
+ description: Safely merge params for use with url_for or for the query string
96
+ email:
97
+ - tyler@tylerrick.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - ".gitignore"
103
+ - ".rspec"
104
+ - ".travis.yml"
105
+ - Gemfile
106
+ - License
107
+ - Rakefile
108
+ - Readme.md
109
+ - bin/console
110
+ - bin/setup
111
+ - lib/merge_params.rb
112
+ - lib/merge_params/helpers.rb
113
+ - lib/merge_params/version.rb
114
+ - merge_params.gemspec
115
+ homepage: http://github.com/TylerRick/merge_params
116
+ licenses:
117
+ - MIT
118
+ metadata:
119
+ homepage_uri: http://github.com/TylerRick/merge_params
120
+ source_code_uri: http://github.com/TylerRick/merge_params
121
+ changelog_uri: 'TODO: Put your gem''s Changelog.md URL here.'
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: 2.3.0
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.6.11
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Safely merge params for use with url_for or for the query string
142
+ test_files: []