workarea-basic_auth 1.1.1
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 +7 -0
- data/.editorconfig +20 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +25 -0
- data/CHANGELOG.md +371 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +5 -0
- data/LICENSE +52 -0
- data/README.md +105 -0
- data/Rakefile +60 -0
- data/bin/rails +20 -0
- data/config/initializers/access_control.rb +23 -0
- data/lib/tasks/basic_auth_tasks.rake +4 -0
- data/lib/workarea/basic_auth.rb +23 -0
- data/lib/workarea/basic_auth/engine.rb +8 -0
- data/lib/workarea/basic_auth/middleware.rb +82 -0
- data/lib/workarea/basic_auth/path.rb +37 -0
- data/lib/workarea/basic_auth/railtie.rb +16 -0
- data/lib/workarea/basic_auth/simple_route_set.rb +23 -0
- data/lib/workarea/basic_auth/version.rb +5 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/config/application.rb +17 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +56 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +43 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/workarea.rb +4 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +5 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/db/seeds.rb +2 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/factories/workarea/testing/basic_auth_helper.rb +21 -0
- data/test/lib/workarea/basic_auth/middleware_test.rb +149 -0
- data/test/lib/workarea/basic_auth/path_test.rb +50 -0
- data/test/lib/workarea/basic_auth/simple_route_set_test.rb +64 -0
- data/test/lib/workarea/basic_auth_test.rb +12 -0
- data/test/test_helper.rb +9 -0
- data/workarea-basic_auth.gemspec +39 -0
- metadata +226 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Version of your assets, change this if you want to expire all your assets.
|
4
|
+
Rails.application.config.assets.version = "1.0"
|
5
|
+
|
6
|
+
# Add additional assets to the asset load path
|
7
|
+
# Rails.application.config.assets.paths << Emoji.images_path
|
8
|
+
|
9
|
+
# Precompile additional assets.
|
10
|
+
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
11
|
+
# Rails.application.config.assets.precompile += %w( search.js )
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
|
4
|
+
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
5
|
+
|
6
|
+
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
7
|
+
# Rails.backtrace_cleaner.remove_silencers!
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Add new inflection rules using the following format. Inflections
|
4
|
+
# are locale specific, and you may define rules for as many different
|
5
|
+
# locales as you wish. All of these examples are active by default:
|
6
|
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
7
|
+
# inflect.plural /^(ox)$/i, '\1en'
|
8
|
+
# inflect.singular /^(ox)en/i, '\1'
|
9
|
+
# inflect.irregular 'person', 'people'
|
10
|
+
# inflect.uncountable %w( fish sheep )
|
11
|
+
# end
|
12
|
+
|
13
|
+
# These inflection rules are supported but not enabled by default:
|
14
|
+
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
15
|
+
# inflect.acronym 'RESTful'
|
16
|
+
# end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
#
|
3
|
+
# This file contains migration options to ease your Rails 5.0 upgrade.
|
4
|
+
#
|
5
|
+
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
|
6
|
+
|
7
|
+
# Enable per-form CSRF tokens. Previous versions had false.
|
8
|
+
Rails.application.config.action_controller.per_form_csrf_tokens = true
|
9
|
+
|
10
|
+
# Enable origin-checking CSRF mitigation. Previous versions had false.
|
11
|
+
Rails.application.config.action_controller.forgery_protection_origin_check = true
|
12
|
+
|
13
|
+
# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
|
14
|
+
# Previous versions had false.
|
15
|
+
ActiveSupport.to_time_preserves_timezone = true
|
16
|
+
|
17
|
+
# Require `belongs_to` associations by default. Previous versions had false.
|
18
|
+
# Rails.application.config.active_record.belongs_to_required_by_default = true
|
19
|
+
|
20
|
+
# Configure SSL options to enable HSTS with subdomains. Previous versions had false.
|
21
|
+
Rails.application.config.ssl_options = { hsts: { subdomains: true } }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# This file contains settings for ActionController::ParamsWrapper which
|
4
|
+
# is enabled by default.
|
5
|
+
|
6
|
+
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
7
|
+
ActiveSupport.on_load(:action_controller) do
|
8
|
+
wrap_parameters format: [:json]
|
9
|
+
end
|
10
|
+
|
11
|
+
# To enable root element in JSON for ActiveRecord objects.
|
12
|
+
# ActiveSupport.on_load(:active_record) do
|
13
|
+
# self.include_root_in_json = true
|
14
|
+
# end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
3
|
+
# than English, add the necessary files in this directory.
|
4
|
+
#
|
5
|
+
# To use the locales, use `I18n.t`:
|
6
|
+
#
|
7
|
+
# I18n.t 'hello'
|
8
|
+
#
|
9
|
+
# In views, this is aliased to just `t`:
|
10
|
+
#
|
11
|
+
# <%= t('hello') %>
|
12
|
+
#
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
14
|
+
#
|
15
|
+
# I18n.locale = :es
|
16
|
+
#
|
17
|
+
# This would use the information in config/locales/es.yml.
|
18
|
+
#
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
21
|
+
|
22
|
+
en:
|
23
|
+
hello: "Hello world"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Puma can serve each request in a thread from an internal thread pool.
|
2
|
+
# The `threads` method setting takes two numbers a minimum and maximum.
|
3
|
+
# Any libraries that use thread pools should be configured to match
|
4
|
+
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
5
|
+
# and maximum, this matches the default thread size of Active Record.
|
6
|
+
#
|
7
|
+
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
|
8
|
+
threads threads_count, threads_count
|
9
|
+
|
10
|
+
# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
|
11
|
+
#
|
12
|
+
port ENV.fetch("PORT") { 3000 }
|
13
|
+
|
14
|
+
# Specifies the `environment` that Puma will run in.
|
15
|
+
#
|
16
|
+
environment ENV.fetch("RAILS_ENV") { "development" }
|
17
|
+
|
18
|
+
# Specifies the number of `workers` to boot in clustered mode.
|
19
|
+
# Workers are forked webserver processes. If using threads and workers together
|
20
|
+
# the concurrency of the application would be max `threads` * `workers`.
|
21
|
+
# Workers do not work on JRuby or Windows (both of which do not support
|
22
|
+
# processes).
|
23
|
+
#
|
24
|
+
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
|
25
|
+
|
26
|
+
# Use the `preload_app!` method when specifying a `workers` number.
|
27
|
+
# This directive tells Puma to first boot the application and load code
|
28
|
+
# before forking the application. This takes advantage of Copy On Write
|
29
|
+
# process behavior so workers use less memory. If you use this option
|
30
|
+
# you need to make sure to reconnect any threads in the `on_worker_boot`
|
31
|
+
# block.
|
32
|
+
#
|
33
|
+
# preload_app!
|
34
|
+
|
35
|
+
# The code in the `on_worker_boot` will be called if you are using
|
36
|
+
# clustered mode by specifying a number of `workers`. After each worker
|
37
|
+
# process is booted this block will be run, if you are using `preload_app!`
|
38
|
+
# option you will want to use this block to reconnect to any threads
|
39
|
+
# or connections that may have been created at application boot, Ruby
|
40
|
+
# cannot share connections between processes.
|
41
|
+
#
|
42
|
+
# on_worker_boot do
|
43
|
+
# ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
|
44
|
+
# end
|
45
|
+
|
46
|
+
# Allow puma to be restarted by `rails restart` command.
|
47
|
+
plugin :tmp_restart
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
2
|
+
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
5
|
+
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
8
|
+
# You can use `rails secret` to generate a secure secret key.
|
9
|
+
|
10
|
+
# Make sure the secrets in this file are kept private
|
11
|
+
# if you're sharing your code publicly.
|
12
|
+
|
13
|
+
development:
|
14
|
+
secret_key_base: e3136ca2a4ab2bb5ea181b14ff500ae40db8718fb990d590bfed3774247d430c805c45686322f93e8a746d034fa1fba9ef00a9ce7a35aee9339675ccb0426121
|
15
|
+
|
16
|
+
test:
|
17
|
+
secret_key_base: 8183e0351525142fce68cf619e94c68caa017c9b90c03183d288ee4a32283d77838eb94bc252e5159eabf3e20a77f8df9466b5056e14b59631dfa592b67e9bbd
|
18
|
+
|
19
|
+
# Do not keep production secrets in the repository,
|
20
|
+
# instead read values from the environment.
|
21
|
+
production:
|
22
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
File without changes
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Workarea
|
2
|
+
module Testing
|
3
|
+
module BasicAuthHelper
|
4
|
+
def encode_password(username, password)
|
5
|
+
Base64.encode64("#{username}:#{password}")
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_request(path, method = "GET")
|
9
|
+
Rack::Request.new(
|
10
|
+
Rack::MockRequest.env_for(path, "REQUEST_METHOD" => method)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_response(path, method = "GET")
|
15
|
+
Rack::Response.new(
|
16
|
+
Rack::MockRequest.env_for(path, "REQUEST_METHOD" => method)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module Workarea
|
4
|
+
module BasicAuth
|
5
|
+
class MiddlewareTest < Workarea::TestCase
|
6
|
+
include Workarea::Testing::BasicAuthHelper
|
7
|
+
|
8
|
+
setup :turn_on_basic_auth
|
9
|
+
teardown :turn_off_basic_auth
|
10
|
+
|
11
|
+
def middleware
|
12
|
+
@middleware ||= BasicAuth::Middleware.new(Rails.application)
|
13
|
+
end
|
14
|
+
|
15
|
+
def turn_on_basic_auth
|
16
|
+
Workarea.config.basic_auth.enabled = true
|
17
|
+
Workarea.config.basic_auth.user = "thomas"
|
18
|
+
Workarea.config.basic_auth.pass = "vendetta"
|
19
|
+
Workarea.config.basic_auth.protect_routes = BasicAuth::SimpleRouteSet.new
|
20
|
+
Workarea.config.basic_auth.exclude_routes = BasicAuth::SimpleRouteSet.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def turn_off_basic_auth
|
24
|
+
Workarea.config.basic_auth.enabled = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_unathorized_users_doesnt_do_anything_if_basic_auth_is_disabled
|
28
|
+
Workarea.config.basic_auth.enabled = false
|
29
|
+
|
30
|
+
env = Rack::MockRequest.env_for("/")
|
31
|
+
response = Rack::Response.new(middleware.call(env))
|
32
|
+
|
33
|
+
assert_equal(200, response.status)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_unathorized_users_returns_200_if_route_is_unprotected
|
37
|
+
env = Rack::MockRequest.env_for("/login")
|
38
|
+
get_login = Rack::Response.new(middleware.call(env))
|
39
|
+
|
40
|
+
assert_equal(200, get_login.status)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_unauthorized_users_returns_200_if_ip_is_whitelisted
|
44
|
+
ip_addr = Workarea.config.basic_auth.whitelisted_ips.first.to_s
|
45
|
+
env = Rack::MockRequest.env_for("/login", 'REMOTE_ADDR' => ip_addr)
|
46
|
+
get_login = Rack::Response.new(middleware.call(env))
|
47
|
+
|
48
|
+
assert_equal(200, get_login.status)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_unathorized_users_returns_401_for_all_http_methods_on_a_path_by_default
|
52
|
+
Workarea.config.basic_auth.protect_routes.add("/login")
|
53
|
+
|
54
|
+
env = Rack::MockRequest.env_for("/login")
|
55
|
+
get_login = Rack::MockResponse.new(*middleware.call(env))
|
56
|
+
|
57
|
+
env = Rack::MockRequest.env_for("/login", method: :post)
|
58
|
+
post_login = Rack::MockResponse.new(*middleware.call(env))
|
59
|
+
|
60
|
+
env = Rack::MockRequest.env_for("/login", method: :head)
|
61
|
+
head_login = Rack::MockResponse.new(*middleware.call(env))
|
62
|
+
|
63
|
+
assert_equal(401, get_login.status)
|
64
|
+
assert_equal(401, post_login.status)
|
65
|
+
assert_equal(401, head_login.status)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_unathorized_users_returns_401_for_specific_http_methods_on_a_path
|
69
|
+
Workarea.config.basic_auth.protect_routes.add("/login", :post)
|
70
|
+
|
71
|
+
env = Rack::MockRequest.env_for("/login")
|
72
|
+
get_login = Rack::MockResponse.new(*middleware.call(env))
|
73
|
+
|
74
|
+
env = Rack::MockRequest.env_for("/login", method: :post)
|
75
|
+
post_login = Rack::MockResponse.new(*middleware.call(env))
|
76
|
+
|
77
|
+
assert_equal(200, get_login.status)
|
78
|
+
assert_equal(401, post_login.status)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_unathorized_users_protects_wildcard_routes
|
82
|
+
Workarea.config.basic_auth.protect_routes.add("/*")
|
83
|
+
|
84
|
+
env = Rack::MockRequest.env_for("/login")
|
85
|
+
get_login = Rack::MockResponse.new(*middleware.call(env))
|
86
|
+
|
87
|
+
env = Rack::MockRequest.env_for("/login", method: :post)
|
88
|
+
post_login = Rack::MockResponse.new(*middleware.call(env))
|
89
|
+
|
90
|
+
env = Rack::MockRequest.env_for("/products/my-product")
|
91
|
+
get_product = Rack::MockResponse.new(*middleware.call(env))
|
92
|
+
|
93
|
+
assert_equal(401, get_login.status)
|
94
|
+
assert_equal(401, post_login.status)
|
95
|
+
assert_equal(401, get_product.status)
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_unathorized_users_allows_route_exclusions
|
99
|
+
Workarea.config.basic_auth.protect_routes.add("/*")
|
100
|
+
Workarea.config.basic_auth.exclude_routes.add("/contact")
|
101
|
+
|
102
|
+
env = Rack::MockRequest.env_for("/login")
|
103
|
+
get_login = Rack::MockResponse.new(*middleware.call(env))
|
104
|
+
|
105
|
+
env = Rack::MockRequest.env_for("/contact")
|
106
|
+
get_contact = Rack::MockResponse.new(*middleware.call(env))
|
107
|
+
|
108
|
+
assert_equal(401, get_login.status)
|
109
|
+
assert_equal(200, get_contact.status)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_unathorized_users_works_properly_with_a_health_check
|
113
|
+
Workarea.config.basic_auth.protect_routes.add("/*")
|
114
|
+
Workarea.config.basic_auth.exclude_routes.add("/health_check")
|
115
|
+
|
116
|
+
env = Rack::MockRequest.env_for("/health_check")
|
117
|
+
health_check = Rack::MockResponse.new(*middleware.call(env))
|
118
|
+
|
119
|
+
assert_equal(200, health_check.status)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_authorized_users_lets_authorized_users_access_all_routes
|
123
|
+
Workarea.config.basic_auth.protect_routes.add("/*")
|
124
|
+
|
125
|
+
env = Rack::MockRequest.env_for("/contact")
|
126
|
+
bad = Rack::MockResponse.new(*middleware.call(env))
|
127
|
+
assert_equal(401, bad.status)
|
128
|
+
|
129
|
+
encoded_pass = encode_password("thomas", "vendetta")
|
130
|
+
env_opts = { "HTTP_AUTHORIZATION" => "Basic #{encoded_pass}" }
|
131
|
+
|
132
|
+
env = Rack::MockRequest.env_for("/login", env_opts)
|
133
|
+
good = Rack::MockResponse.new(*middleware.call(env))
|
134
|
+
assert_equal(200, good.status)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_authorized_users_renders_401_with_invalid_credentials
|
138
|
+
Workarea.config.basic_auth.protect_routes.add("/*")
|
139
|
+
|
140
|
+
encoded_pass = encode_password("notavalid", "password")
|
141
|
+
env_opts = { "HTTP_AUTHORIZATION" => "Basic #{encoded_pass}" }
|
142
|
+
|
143
|
+
env = Rack::MockRequest.env_for("/contact", env_opts)
|
144
|
+
bad = Rack::MockResponse.new(*middleware.call(env))
|
145
|
+
assert_equal(401, bad.status)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rack/mock"
|
3
|
+
|
4
|
+
module Workarea
|
5
|
+
module BasicAuth
|
6
|
+
class PathTest < Workarea::TestCase
|
7
|
+
include Workarea::Testing::BasicAuthHelper
|
8
|
+
|
9
|
+
def test_matches_a_pathname_and_all_http_methods_by_default
|
10
|
+
path = Path.new("/products")
|
11
|
+
|
12
|
+
get = build_request("/products")
|
13
|
+
post = build_request("/products", "POST")
|
14
|
+
options = build_request("/products", "OPTIONS")
|
15
|
+
head = build_request("/products", "HEAD")
|
16
|
+
|
17
|
+
bad = build_request("/wat")
|
18
|
+
|
19
|
+
assert path.matches?(get)
|
20
|
+
assert path.matches?(post)
|
21
|
+
assert path.matches?(options)
|
22
|
+
assert path.matches?(head)
|
23
|
+
|
24
|
+
refute path.matches?(bad)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_matches_a_pathname_and_a_specific_request_method
|
28
|
+
path = Path.new("/products", :post, :head)
|
29
|
+
|
30
|
+
get = build_request("/products")
|
31
|
+
post = build_request("/products", "POST")
|
32
|
+
head = build_request("/products", "HEAD")
|
33
|
+
|
34
|
+
refute path.matches?(get)
|
35
|
+
assert path.matches?(post)
|
36
|
+
assert path.matches?(head)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_matches_wildcards
|
40
|
+
path = Path.new("/api/v2/*")
|
41
|
+
|
42
|
+
good = build_request("/api/v2/wat/sup")
|
43
|
+
bad = build_request("/api/v1/wat/sup")
|
44
|
+
|
45
|
+
assert path.matches?(good)
|
46
|
+
refute path.matches?(bad)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|