api_valve 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|