api_valve 0.6.1 → 0.7.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/lib/api_valve.rb +10 -10
- data/lib/api_valve/forwarder.rb +4 -8
- data/lib/api_valve/forwarder/request.rb +6 -5
- data/lib/api_valve/forwarder/response.rb +6 -2
- data/lib/api_valve/middleware.rb +4 -3
- data/lib/api_valve/middleware/permission_check.rb +36 -0
- data/lib/api_valve/permission_handler.rb +25 -0
- data/lib/api_valve/proxy.rb +14 -85
- data/lib/api_valve/proxy/builder.rb +72 -0
- data/lib/api_valve/{runner.rb → proxy/runner.rb} +1 -1
- data/lib/api_valve/route_set.rb +32 -27
- metadata +6 -4
- data/lib/api_valve/forwarder/permission_handler.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 975b9612ff292d9330c8ee255ec3584f83f5daa8fe2e2a65cf3af0ed7f000eed
|
4
|
+
data.tar.gz: c3d75f806fad96a5ca9f871973a4b458e1da812e0c8bb0e4480c887dc12c77b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4454093eb9d930218a252d6e05c6bcfa573172660c34c1a7bfba91ad085df92bc6ed8fc2d02714fb39a32960a493c30518609c6bb3a3d77efc8b2e44daf0d08
|
7
|
+
data.tar.gz: 8a7c8e8ba52346c4c65b2a6dcaa0f95592d880de6c68745b1a4259f68ab4fc2c0e16fef4f75ecb7c1f9d56dd70d0d491a8ff421622b4d7ed34e6b848e3aa5feb
|
data/lib/api_valve.rb
CHANGED
@@ -12,16 +12,16 @@ require 'multi_json'
|
|
12
12
|
require 'logger'
|
13
13
|
|
14
14
|
module ApiValve
|
15
|
-
autoload :Benchmarking,
|
16
|
-
autoload :Cascade,
|
17
|
-
autoload :Error,
|
18
|
-
autoload :ErrorResponder,
|
19
|
-
autoload :Forwarder,
|
20
|
-
autoload :Middleware,
|
21
|
-
autoload :Logger,
|
22
|
-
autoload :
|
23
|
-
autoload :
|
24
|
-
autoload :
|
15
|
+
autoload :Benchmarking, 'api_valve/benchmarking'
|
16
|
+
autoload :Cascade, 'api_valve/cascade'
|
17
|
+
autoload :Error, 'api_valve/error'
|
18
|
+
autoload :ErrorResponder, 'api_valve/error_responder'
|
19
|
+
autoload :Forwarder, 'api_valve/forwarder'
|
20
|
+
autoload :Middleware, 'api_valve/middleware'
|
21
|
+
autoload :Logger, 'api_valve/logger'
|
22
|
+
autoload :PermissionHandler, 'api_valve/permission_handler'
|
23
|
+
autoload :Proxy, 'api_valve/proxy'
|
24
|
+
autoload :RouteSet, 'api_valve/route_set'
|
25
25
|
|
26
26
|
include ActiveSupport::Configurable
|
27
27
|
|
data/lib/api_valve/forwarder.rb
CHANGED
@@ -4,9 +4,8 @@ module ApiValve
|
|
4
4
|
# options, and called from the router.
|
5
5
|
|
6
6
|
class Forwarder
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
autoload :Response, 'api_valve/forwarder/response'
|
7
|
+
autoload :Request, 'api_valve/forwarder/request'
|
8
|
+
autoload :Response, 'api_valve/forwarder/response'
|
10
9
|
|
11
10
|
include Benchmarking
|
12
11
|
|
@@ -25,7 +24,6 @@ module ApiValve
|
|
25
24
|
# request and response.
|
26
25
|
def call(original_request, local_options = {})
|
27
26
|
request = build_request(original_request, request_options.deep_merge(local_options))
|
28
|
-
request.check_permissions!
|
29
27
|
response = build_response(original_request, run_request(request), response_options)
|
30
28
|
response.rack_response
|
31
29
|
end
|
@@ -50,13 +48,11 @@ module ApiValve
|
|
50
48
|
end
|
51
49
|
|
52
50
|
def request_options
|
53
|
-
|
54
|
-
(@options[:request] || {}).merge(@options.slice(:permission_handler))
|
51
|
+
(@options[:request] || {})
|
55
52
|
end
|
56
53
|
|
57
54
|
def response_options
|
58
|
-
|
59
|
-
(@options[:response] || {}).merge(@options.slice(:permission_handler) || {})
|
55
|
+
(@options[:response] || {})
|
60
56
|
end
|
61
57
|
|
62
58
|
def run_request(request)
|
@@ -5,8 +5,6 @@ module ApiValve
|
|
5
5
|
# request is forwarded
|
6
6
|
|
7
7
|
class Forwarder::Request
|
8
|
-
include Forwarder::PermissionHandler::RequestIntegration
|
9
|
-
|
10
8
|
attr_reader :original_request, :options
|
11
9
|
|
12
10
|
WHITELISTED_HEADERS = %w(
|
@@ -25,9 +23,6 @@ module ApiValve
|
|
25
23
|
@options = options.with_indifferent_access
|
26
24
|
end
|
27
25
|
|
28
|
-
# Called by forwarder before actual request is executed
|
29
|
-
delegate :check_permissions!, to: :permission_handler
|
30
|
-
|
31
26
|
# HTTP method to use when forwarding. Must return sym.
|
32
27
|
# Returns original request method
|
33
28
|
def method
|
@@ -72,6 +67,12 @@ module ApiValve
|
|
72
67
|
@url_params ||= Rack::Utils.parse_nested_query(original_request.query_string)
|
73
68
|
end
|
74
69
|
|
70
|
+
protected
|
71
|
+
|
72
|
+
def permission_handler
|
73
|
+
original_request.env['permission_handler']
|
74
|
+
end
|
75
|
+
|
75
76
|
private
|
76
77
|
|
77
78
|
def forwarded_headers
|
@@ -9,8 +9,6 @@ module ApiValve
|
|
9
9
|
# to the original caller
|
10
10
|
|
11
11
|
class Forwarder::Response
|
12
|
-
include Forwarder::PermissionHandler::RequestIntegration
|
13
|
-
|
14
12
|
attr_reader :original_request, :original_response, :options
|
15
13
|
|
16
14
|
WHITELISTED_HEADERS = %w(
|
@@ -31,6 +29,12 @@ module ApiValve
|
|
31
29
|
[status, headers, [body]]
|
32
30
|
end
|
33
31
|
|
32
|
+
protected
|
33
|
+
|
34
|
+
def permission_handler
|
35
|
+
original_request.env['permission_handler']
|
36
|
+
end
|
37
|
+
|
34
38
|
private
|
35
39
|
|
36
40
|
def status
|
data/lib/api_valve/middleware.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module ApiValve
|
2
2
|
class Middleware
|
3
|
-
autoload :ErrorHandling,
|
4
|
-
autoload :Logging,
|
5
|
-
autoload :
|
3
|
+
autoload :ErrorHandling, 'api_valve/middleware/error_handling'
|
4
|
+
autoload :Logging, 'api_valve/middleware/logging'
|
5
|
+
autoload :PermissionCheck, 'api_valve/middleware/permission_check'
|
6
|
+
autoload :Router, 'api_valve/middleware/router'
|
6
7
|
|
7
8
|
Item = Struct.new(:klass, :proc)
|
8
9
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class ApiValve::Middleware
|
2
|
+
class PermissionCheck
|
3
|
+
def initialize(app, options = {})
|
4
|
+
@app = app
|
5
|
+
@options = options
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
env['permission_handler'] = @handler
|
10
|
+
if handler(env).allowed?
|
11
|
+
@app.call(env)
|
12
|
+
else
|
13
|
+
message = handler(env).message
|
14
|
+
ApiValve.logger.info { message }
|
15
|
+
render_error ApiValve::Error::Forbidden.new message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def handler(env)
|
22
|
+
env['permission_handler'] ||= handler_klass.new(
|
23
|
+
env,
|
24
|
+
@options.merge(env['api_valve.router.route'].options[:permission_handler] || {})
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def handler_klass
|
29
|
+
@options[:klass] || ApiValve::PermissionHandler
|
30
|
+
end
|
31
|
+
|
32
|
+
def render_error(error)
|
33
|
+
self.class.const_get(ApiValve.error_responder).new(error).call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ApiValve
|
2
|
+
class PermissionHandler
|
3
|
+
def initialize(env, options = {})
|
4
|
+
@env = env
|
5
|
+
@options = options.with_indifferent_access
|
6
|
+
end
|
7
|
+
|
8
|
+
# Run permission checks
|
9
|
+
# Simple implementation is always true. Override in your implementation.
|
10
|
+
def allowed?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns string message why access was denied
|
15
|
+
# Rendered on the API.
|
16
|
+
# Override in your implementation.
|
17
|
+
def message
|
18
|
+
'Insufficient permissions'
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
attr_reader :env, :options
|
24
|
+
end
|
25
|
+
end
|
data/lib/api_valve/proxy.rb
CHANGED
@@ -1,69 +1,17 @@
|
|
1
1
|
module ApiValve
|
2
2
|
class Proxy
|
3
|
-
|
3
|
+
autoload :Builder, 'api_valve/proxy/builder'
|
4
|
+
autoload :Runner, 'api_valve/proxy/runner'
|
4
5
|
|
5
|
-
|
6
|
+
extend Builder
|
7
|
+
|
8
|
+
FORWARDER_OPTIONS = %w(endpoint request response).freeze
|
6
9
|
|
7
10
|
class_attribute :permission_handler, :request, :response
|
8
|
-
self.permission_handler =
|
11
|
+
self.permission_handler = PermissionHandler
|
9
12
|
self.request = Forwarder::Request
|
10
13
|
self.response = Forwarder::Response
|
11
14
|
|
12
|
-
class << self
|
13
|
-
# Creates a n instance from a config hash and takes optional block
|
14
|
-
# which is executed in scope of the proxy
|
15
|
-
def build(config)
|
16
|
-
block = Proc.new if block_given? # capture the yield
|
17
|
-
from_hash(config).tap do |proxy|
|
18
|
-
proxy.instance_eval(&block) if block
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def from_config(file_name = nil)
|
23
|
-
file_name ||= name.underscore
|
24
|
-
path = find_config(file_name)
|
25
|
-
raise "Config not found for #{name.underscore}(.yml|.yml.erb) in #{ApiValve.config_paths.inspect}" unless path
|
26
|
-
|
27
|
-
yaml = File.read(path)
|
28
|
-
yaml = ERB.new(yaml, nil, '-').result if path.fnmatch? '*.erb'
|
29
|
-
from_yaml yaml
|
30
|
-
end
|
31
|
-
|
32
|
-
def from_yaml(string)
|
33
|
-
from_hash YAML.load(string) # rubocop:disable Security/YAMLLoad
|
34
|
-
end
|
35
|
-
|
36
|
-
def from_hash(config)
|
37
|
-
config = config.with_indifferent_access
|
38
|
-
forwarder = Forwarder.new(forwarder_config(config))
|
39
|
-
new(forwarder).tap do |proxy|
|
40
|
-
Array.wrap(config[:use]).each { |mw| proxy.use mw }
|
41
|
-
proxy.build_routes_from_config config[:routes]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def find_config(file_name)
|
48
|
-
ApiValve.config_paths.each do |dir|
|
49
|
-
path = dir.join("#{file_name}.yml")
|
50
|
-
return path if path.exist?
|
51
|
-
|
52
|
-
path = dir.join("#{file_name}.yml.erb")
|
53
|
-
return path if path.exist?
|
54
|
-
end
|
55
|
-
nil
|
56
|
-
end
|
57
|
-
|
58
|
-
def forwarder_config(config)
|
59
|
-
{
|
60
|
-
permission_handler: {klass: permission_handler},
|
61
|
-
request: {klass: request},
|
62
|
-
response: {klass: response}
|
63
|
-
}.with_indifferent_access.deep_merge config.slice(*FORWARDER_OPTIONS)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
15
|
attr_reader :request, :forwarder, :middleware, :route_set
|
68
16
|
|
69
17
|
alias router route_set
|
@@ -84,38 +32,19 @@ module ApiValve
|
|
84
32
|
delegate :add_route, to: :route_set
|
85
33
|
delegate :use, to: :middleware
|
86
34
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
method ||= 'any' # no method defined means all methods
|
93
|
-
if route_config['raise']
|
94
|
-
deny method, path_regexp, with: route_config['raise']
|
95
|
-
else
|
96
|
-
forward method, path_regexp, request_override
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def forward(methods, path_regexp = nil, request_override = {})
|
102
|
-
Array.wrap(methods).each do |method|
|
103
|
-
route_set.public_send(method, path_regexp, proc { |request, match_data|
|
104
|
-
forwarder.call request, {'match_data' => match_data}.merge(request_override || {})
|
105
|
-
})
|
106
|
-
end
|
35
|
+
def forward(methods, path_regexp = nil, options = {})
|
36
|
+
options = options.with_indifferent_access
|
37
|
+
route_set.append(methods, path_regexp, options.except(:request), proc { |request, match_data|
|
38
|
+
forwarder.call request, {'match_data' => match_data}.merge(options[:request] || {}).with_indifferent_access
|
39
|
+
})
|
107
40
|
end
|
108
41
|
|
109
|
-
def forward_all
|
110
|
-
|
111
|
-
forwarder.call request, 'match_data' => match_data
|
112
|
-
end
|
42
|
+
def forward_all(options = {})
|
43
|
+
forward(RouteSet::METHODS, nil, options)
|
113
44
|
end
|
114
45
|
|
115
46
|
def deny(methods, path_regexp = nil, with: 'Error::Forbidden')
|
116
|
-
|
117
|
-
route_set.public_send(method, path_regexp, ->(*_args) { raise ApiValve.const_get(with) })
|
118
|
-
end
|
47
|
+
route_set.append(methods, path_regexp, {}, ->(*_args) { raise ApiValve.const_get(with) })
|
119
48
|
end
|
120
49
|
|
121
50
|
protected
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ApiValve
|
2
|
+
class Proxy
|
3
|
+
module Builder
|
4
|
+
# Creates a n instance from a config hash and takes optional block
|
5
|
+
# which is executed in scope of the proxy
|
6
|
+
def build(config)
|
7
|
+
block = Proc.new if block_given? # capture the yield
|
8
|
+
from_hash(config).tap do |proxy|
|
9
|
+
proxy.instance_eval(&block) if block
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_config(file_name = nil)
|
14
|
+
file_name ||= name.underscore
|
15
|
+
path = find_config(file_name)
|
16
|
+
raise "Config not found for #{name.underscore}(.yml|.yml.erb) in #{ApiValve.config_paths.inspect}" unless path
|
17
|
+
|
18
|
+
yaml = File.read(path)
|
19
|
+
yaml = ERB.new(yaml, nil, '-').result if path.fnmatch? '*.erb'
|
20
|
+
from_yaml yaml
|
21
|
+
end
|
22
|
+
|
23
|
+
def from_yaml(string)
|
24
|
+
from_hash YAML.load(string) # rubocop:disable Security/YAMLLoad
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_hash(config)
|
28
|
+
config = config.with_indifferent_access
|
29
|
+
forwarder = Forwarder.new(forwarder_config(config))
|
30
|
+
new(forwarder).tap do |proxy|
|
31
|
+
Array.wrap(config[:use]).each { |mw| proxy.use mw }
|
32
|
+
add_routes_from_config proxy, config[:routes]
|
33
|
+
proxy.use Middleware::PermissionCheck, config[:permission_handler] if config[:permission_handler]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def add_routes_from_config(proxy, routes_config)
|
40
|
+
return proxy.forward_all unless routes_config
|
41
|
+
|
42
|
+
routes_config.each do |route_config|
|
43
|
+
method, path_regexp = *route_config.values_at('method', 'path')
|
44
|
+
method ||= 'any' # no method defined means all methods
|
45
|
+
if route_config['raise']
|
46
|
+
proxy.deny method, path_regexp, with: route_config['raise']
|
47
|
+
else
|
48
|
+
proxy.forward method, path_regexp, route_config.except('method', 'path')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_config(file_name)
|
54
|
+
ApiValve.config_paths.each do |dir|
|
55
|
+
path = dir.join("#{file_name}.yml")
|
56
|
+
return path if path.exist?
|
57
|
+
|
58
|
+
path = dir.join("#{file_name}.yml.erb")
|
59
|
+
return path if path.exist?
|
60
|
+
end
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def forwarder_config(config)
|
65
|
+
{
|
66
|
+
request: {klass: request},
|
67
|
+
response: {klass: response}
|
68
|
+
}.with_indifferent_access.deep_merge config.slice(*FORWARDER_OPTIONS)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/api_valve/route_set.rb
CHANGED
@@ -2,7 +2,7 @@ module ApiValve
|
|
2
2
|
class RouteSet
|
3
3
|
METHODS = %i(get post put patch delete head).freeze
|
4
4
|
|
5
|
-
Route = Struct.new(:regexp, :block) do
|
5
|
+
Route = Struct.new(:regexp, :options, :block) do
|
6
6
|
delegate :call, to: :block
|
7
7
|
|
8
8
|
def match(path_info)
|
@@ -24,7 +24,7 @@ module ApiValve
|
|
24
24
|
raise 'URL not supported' if request.path_info.include?('/../')
|
25
25
|
|
26
26
|
match_data = nil
|
27
|
-
route = @routes && @routes[request.request_method.downcase
|
27
|
+
route = @routes && @routes[request.request_method.downcase].find do |r|
|
28
28
|
(match_data = r.match(request.path_info))
|
29
29
|
end
|
30
30
|
raise Error::NotRouted, 'Endpoint not found' unless route
|
@@ -32,50 +32,55 @@ module ApiValve
|
|
32
32
|
[route, match_data]
|
33
33
|
end
|
34
34
|
|
35
|
-
def delete(path = nil, prok = nil)
|
36
|
-
|
35
|
+
def delete(path = nil, options = {}, prok = nil)
|
36
|
+
push :delete, path, options, prok || Proc.new
|
37
37
|
end
|
38
38
|
|
39
|
-
def get(path = nil, prok = nil)
|
40
|
-
|
39
|
+
def get(path = nil, options = {}, prok = nil)
|
40
|
+
push :get, path, options, prok || Proc.new
|
41
41
|
end
|
42
42
|
|
43
|
-
def head(path = nil, prok = nil)
|
44
|
-
|
43
|
+
def head(path = nil, options = {}, prok = nil)
|
44
|
+
push :head, path, options, prok || Proc.new
|
45
45
|
end
|
46
46
|
|
47
|
-
def patch(path = nil, prok = nil)
|
48
|
-
|
47
|
+
def patch(path = nil, options = {}, prok = nil)
|
48
|
+
push :patch, path, options, prok || Proc.new
|
49
49
|
end
|
50
50
|
|
51
|
-
def post(path = nil, prok = nil)
|
52
|
-
|
51
|
+
def post(path = nil, options = {}, prok = nil)
|
52
|
+
push :post, path, options, prok || Proc.new
|
53
53
|
end
|
54
54
|
|
55
|
-
def put(path = nil, prok = nil)
|
56
|
-
|
55
|
+
def put(path = nil, options = {}, prok = nil)
|
56
|
+
push :put, path, options, prok || Proc.new
|
57
57
|
end
|
58
58
|
|
59
|
-
def any(path = nil, prok = nil)
|
60
|
-
append METHODS, path, prok || Proc.new
|
59
|
+
def any(path = nil, options = {}, prok = nil)
|
60
|
+
append METHODS, path, options, prok || Proc.new
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
64
|
-
prok
|
65
|
-
Array.wrap(methods).each do |method|
|
66
|
-
@routes[method] << Route.new(regexp, prok)
|
67
|
-
end
|
63
|
+
def push(methods, regexp, options = {}, prok = nil)
|
64
|
+
add_route :push, methods, regexp, options, prok || Proc.new
|
68
65
|
end
|
69
66
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
67
|
+
alias append push
|
68
|
+
|
69
|
+
def unshift(methods, regexp = nil, options = {}, prok = nil)
|
70
|
+
add_route :unshift, methods, regexp, options, prok || Proc.new
|
75
71
|
end
|
76
72
|
|
77
73
|
def reset_routes
|
78
|
-
@routes = Hash[METHODS.map { |v| [v, []] }].freeze
|
74
|
+
@routes = Hash[METHODS.map { |v| [v, []] }].with_indifferent_access.freeze
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def add_route(how, methods, regexp, options, prok)
|
80
|
+
methods = METHODS if methods.to_s == 'any'
|
81
|
+
Array.wrap(methods).each do |method|
|
82
|
+
@routes[method].public_send how, Route.new(regexp, options, prok)
|
83
|
+
end
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_valve
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mkon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -198,17 +198,19 @@ files:
|
|
198
198
|
- lib/api_valve/error.rb
|
199
199
|
- lib/api_valve/error_responder.rb
|
200
200
|
- lib/api_valve/forwarder.rb
|
201
|
-
- lib/api_valve/forwarder/permission_handler.rb
|
202
201
|
- lib/api_valve/forwarder/request.rb
|
203
202
|
- lib/api_valve/forwarder/response.rb
|
204
203
|
- lib/api_valve/logger.rb
|
205
204
|
- lib/api_valve/middleware.rb
|
206
205
|
- lib/api_valve/middleware/error_handling.rb
|
207
206
|
- lib/api_valve/middleware/logging.rb
|
207
|
+
- lib/api_valve/middleware/permission_check.rb
|
208
208
|
- lib/api_valve/middleware/router.rb
|
209
|
+
- lib/api_valve/permission_handler.rb
|
209
210
|
- lib/api_valve/proxy.rb
|
211
|
+
- lib/api_valve/proxy/builder.rb
|
212
|
+
- lib/api_valve/proxy/runner.rb
|
210
213
|
- lib/api_valve/route_set.rb
|
211
|
-
- lib/api_valve/runner.rb
|
212
214
|
homepage: https://github.com/mkon/api_valve
|
213
215
|
licenses:
|
214
216
|
- MIT
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module ApiValve
|
2
|
-
# This class is responsible to decide if a request is allowed or not, and can
|
3
|
-
# be extended with more ACL related features, for example returning a list of
|
4
|
-
# attributes that can be read or written.
|
5
|
-
|
6
|
-
class Forwarder::PermissionHandler
|
7
|
-
InsufficientPermissions = Class.new(Error::Forbidden)
|
8
|
-
|
9
|
-
module RequestIntegration
|
10
|
-
private
|
11
|
-
|
12
|
-
def permission_handler
|
13
|
-
permission_handler_klass.instance(original_request, permission_handler_options)
|
14
|
-
end
|
15
|
-
|
16
|
-
def permission_handler_klass
|
17
|
-
permission_handler_options[:klass] || Forwarder::PermissionHandler
|
18
|
-
end
|
19
|
-
|
20
|
-
def permission_handler_options
|
21
|
-
options[:permission_handler] || {}
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :request, :options
|
26
|
-
|
27
|
-
delegate :env, to: :request
|
28
|
-
|
29
|
-
# Returns an instance of the PermissionHandler, cached in the request env
|
30
|
-
# This allows re-use of the PermissionHandler by both Request and Response instances
|
31
|
-
def self.instance(request, options)
|
32
|
-
request.env['permission_handler'] ||= new(request, options)
|
33
|
-
end
|
34
|
-
|
35
|
-
def initialize(request, options = {})
|
36
|
-
@request = request
|
37
|
-
@options = options
|
38
|
-
end
|
39
|
-
|
40
|
-
# Run permission checks
|
41
|
-
# Simple implementation is always true. Override in your implementation.
|
42
|
-
# For example raise ApiValve::Error::Forbidden in certain conditions
|
43
|
-
def check_permissions!
|
44
|
-
true
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|