endpoint-flux 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/.gitignore +36 -0
- data/CONTRIBUTING.md +18 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +37 -0
- data/README.md +607 -0
- data/circle.yml +14 -0
- data/endpoint_flux.gemspec +17 -0
- data/lib/endpoint_flux.rb +20 -0
- data/lib/endpoint_flux/class_loader.rb +58 -0
- data/lib/endpoint_flux/config.rb +85 -0
- data/lib/endpoint_flux/config/interceptor.rb +23 -0
- data/lib/endpoint_flux/config/middleware.rb +38 -0
- data/lib/endpoint_flux/config/rescue_from.rb +28 -0
- data/lib/endpoint_flux/endpoint.rb +81 -0
- data/lib/endpoint_flux/exceptions.rb +10 -0
- data/lib/endpoint_flux/exceptions/base.rb +21 -0
- data/lib/endpoint_flux/exceptions/forbidden.rb +12 -0
- data/lib/endpoint_flux/exceptions/not_found.rb +12 -0
- data/lib/endpoint_flux/exceptions/service_unavailable.rb +12 -0
- data/lib/endpoint_flux/exceptions/unauthorized.rb +12 -0
- data/lib/endpoint_flux/exceptions/validation.rb +13 -0
- data/lib/endpoint_flux/middlewares.rb +8 -0
- data/lib/endpoint_flux/middlewares/authenticator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/authorizator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/decorator/add_status.rb +12 -0
- data/lib/endpoint_flux/middlewares/decorator/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/policy/skip.rb +11 -0
- data/lib/endpoint_flux/middlewares/validator/empty.rb +12 -0
- data/lib/endpoint_flux/rails/concerns/endpoint_controller.rb +32 -0
- data/lib/endpoint_flux/request.rb +15 -0
- data/lib/endpoint_flux/response.rb +30 -0
- data/lib/endpoint_flux/version.rb +3 -0
- data/spec/lib/class_loader_spec.rb +31 -0
- data/spec/lib/config/default_middlewares_spec.rb +21 -0
- data/spec/lib/config/endpoints_namespace_spec.rb +13 -0
- data/spec/lib/config/flow_spec.rb +8 -0
- data/spec/lib/config/interceptor_spec.rb +34 -0
- data/spec/lib/config/middleware_spec.rb +62 -0
- data/spec/lib/config/rescue_from_spec.rb +45 -0
- data/spec/lib/endpoint/flow_spec.rb +43 -0
- data/spec/lib/endpoint/middlewares_spec.rb +110 -0
- data/spec/lib/endpoint/perform_spec.rb +61 -0
- data/spec/lib/endpoint/rescue_from_spec.rb +61 -0
- data/spec/lib/exceptions/forbidden_spec.rb +12 -0
- data/spec/lib/exceptions/not_found_spec.rb +12 -0
- data/spec/lib/exceptions/service_unavailable_spec.rb +12 -0
- data/spec/lib/exceptions/unauthorized_spec.rb +12 -0
- data/spec/lib/exceptions/validation_spec.rb +14 -0
- data/spec/lib/middlewares/authenticator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/authorizator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/decorator/add_status_spec.rb +17 -0
- data/spec/lib/middlewares/decorator/skip_spec.rb +5 -0
- data/spec/lib/middlewares/policy/skip_spec.rb +5 -0
- data/spec/lib/middlewares/shared_examples.rb +19 -0
- data/spec/lib/middlewares/validator/empty_spec.rb +15 -0
- data/spec/lib/response_spec.rb +131 -0
- data/spec/spec_helper.rb +52 -0
- metadata +153 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
module Middlewares
|
2
|
+
require_relative 'middlewares/authenticator/skip'
|
3
|
+
require_relative 'middlewares/authorizator/skip'
|
4
|
+
require_relative 'middlewares/decorator/skip'
|
5
|
+
require_relative 'middlewares/decorator/add_status'
|
6
|
+
require_relative 'middlewares/policy/skip'
|
7
|
+
require_relative 'middlewares/validator/empty'
|
8
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EndpointFlux
|
2
|
+
module Rails
|
3
|
+
module Concerns
|
4
|
+
module EndpointController
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def present(namespace)
|
8
|
+
_, response = endpoint_for(namespace).perform(request_object)
|
9
|
+
|
10
|
+
headers.merge! response.headers
|
11
|
+
render json: response.body
|
12
|
+
end
|
13
|
+
|
14
|
+
def endpoint_for(namespace)
|
15
|
+
return namespace unless ::EndpointFlux.config.endpoints_namespace
|
16
|
+
(::EndpointFlux.config.endpoints_namespace + '/' + namespace).camelize.constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
def request_object
|
20
|
+
::EndpointFlux::Request.new(
|
21
|
+
headers: headers.merge('Authorization' => request.headers['authorization']),
|
22
|
+
params: endpoint_params
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def endpoint_params
|
27
|
+
params.permit!.except(:controller, :action, :format).to_h.deep_symbolize_keys
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module EndpointFlux
|
2
|
+
class Request
|
3
|
+
def initialize(headers: {}, params: {}, namespace: nil)
|
4
|
+
@headers = headers
|
5
|
+
@params = params
|
6
|
+
@namespace = namespace
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :params
|
10
|
+
attr_accessor :headers
|
11
|
+
attr_accessor :namespace
|
12
|
+
attr_accessor :endpoint
|
13
|
+
attr_accessor :scope
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module EndpointFlux
|
2
|
+
class Response
|
3
|
+
def initialize(headers: {}, body: {})
|
4
|
+
@body = body
|
5
|
+
@headers = headers
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :body, :headers
|
9
|
+
|
10
|
+
def success?
|
11
|
+
body[:status] && body[:status].between?(200, 209)
|
12
|
+
end
|
13
|
+
|
14
|
+
def invalid?
|
15
|
+
body[:status] == 422
|
16
|
+
end
|
17
|
+
|
18
|
+
def forbidden?
|
19
|
+
body[:status] == 403
|
20
|
+
end
|
21
|
+
|
22
|
+
def unauthorized?
|
23
|
+
body[:status] == 401
|
24
|
+
end
|
25
|
+
|
26
|
+
def not_found?
|
27
|
+
body[:status] == 404
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::ClassLoader do
|
4
|
+
describe '#string_to_class_name' do
|
5
|
+
it 'converts string to class name' do
|
6
|
+
expect(subject.string_to_class_name('hey/bey/cey')).to eq('Hey::Bey::Cey')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#load_class!' do
|
11
|
+
context 'when wrong params given' do
|
12
|
+
it 'fails if the class is not existing' do
|
13
|
+
expect { subject.load_class!('hey/bey') }
|
14
|
+
.to raise_error('The [hey/bey] should be a string representing a class')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'fails if the class name is invalid' do
|
18
|
+
expect { subject.load_class!('111/bey') }
|
19
|
+
.to raise_error('The [111/bey] should be a string representing a class')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when valid params given' do
|
24
|
+
let(:sample_class) { stub_const 'SampleClass::SecondLevel', Class.new }
|
25
|
+
|
26
|
+
it 'returns the class back' do
|
27
|
+
expect(subject.load_class!(sample_class)).to be(sample_class)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Config do
|
4
|
+
describe '#default_middlewares' do
|
5
|
+
before do
|
6
|
+
stub_const('EndpointFlux::Middlewares::Authenticator::Sample', Class.new)
|
7
|
+
EndpointFlux::Middlewares::Authenticator::Sample.class_eval do
|
8
|
+
def self.perform(_, headers, response)
|
9
|
+
[{}, headers, response]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
subject.default_middlewares :authenticator, 'sample'
|
14
|
+
end
|
15
|
+
let(:middleware) { subject.default_middlewares[:authenticator].first }
|
16
|
+
|
17
|
+
it 'sets default middleware' do
|
18
|
+
expect(middleware.klass).to be(EndpointFlux::Middlewares::Authenticator::Sample)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Config do
|
4
|
+
describe '#endpoints_namespace' do
|
5
|
+
it 'sets default endpoints namespace' do
|
6
|
+
stub_const 'Some::Sample', Class.new
|
7
|
+
|
8
|
+
subject.endpoints_namespace 'some/sample'
|
9
|
+
|
10
|
+
expect(subject.endpoints_namespace).to be == 'some/sample'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Config::Interceptor do
|
4
|
+
describe '#add' do
|
5
|
+
context 'when wrong params given' do
|
6
|
+
it 'fails when no block given' do
|
7
|
+
expect { subject.add() }.to raise_error('Block not given')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'when valid params given' do
|
12
|
+
let(:block) { proc {} }
|
13
|
+
|
14
|
+
it 'adds the handler' do
|
15
|
+
subject.add(&block)
|
16
|
+
|
17
|
+
expect(subject.handlers).to include(block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#run' do
|
23
|
+
let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
|
24
|
+
let(:block) { proc { raise SampleException } }
|
25
|
+
|
26
|
+
context 'when valid params given' do
|
27
|
+
it 'runs the handler' do
|
28
|
+
subject.add(&block)
|
29
|
+
expect { subject.run('attrs') }
|
30
|
+
.to raise_error(sample_exception)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Config::Middleware do
|
4
|
+
let(:block) { proc { raise BlockException, 'bla bla' } }
|
5
|
+
let(:options) { { option: :option } }
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_const 'BlockException', Class.new(Exception)
|
9
|
+
stub_const 'PerformException', Class.new(Exception)
|
10
|
+
stub_const 'MiddlewareSample', Class.new
|
11
|
+
|
12
|
+
MiddlewareSample.class_eval do
|
13
|
+
def self.perform(*)
|
14
|
+
raise PerformException, 'bla bla'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when wrong params given' do
|
20
|
+
it 'fails when there is no params given' do
|
21
|
+
expect { described_class.new }.to raise_error('You must provide block or existing klass')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'fails when there is no perform method' do
|
25
|
+
stub_const 'NoPerformMiddlewareSample', Class.new
|
26
|
+
|
27
|
+
expect do
|
28
|
+
described_class.new(NoPerformMiddlewareSample)
|
29
|
+
end.to raise_error('The [NoPerformMiddlewareSample] class should define perform class method')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when valid params given' do
|
34
|
+
let(:subject) { described_class.new(MiddlewareSample, options, &block) }
|
35
|
+
|
36
|
+
it 'creates middleware instance with class' do
|
37
|
+
expect(subject.klass).to be(MiddlewareSample)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'creates middleware instance with handler' do
|
41
|
+
expect(subject.handler).to be(block)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'creates middleware instance with options' do
|
45
|
+
expect(subject.options).to be(options)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#run' do
|
50
|
+
it 'runs klass perform when it is given' do
|
51
|
+
middleware = described_class.new(MiddlewareSample)
|
52
|
+
|
53
|
+
expect { middleware.run({}) }.to raise_error(PerformException)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'runs klass handler when it is given' do
|
57
|
+
middleware = described_class.new(&block)
|
58
|
+
|
59
|
+
expect { middleware.run({}) }.to raise_error(BlockException)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Config::RescueFrom do
|
4
|
+
describe '#add' do
|
5
|
+
let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
|
6
|
+
|
7
|
+
context 'when wrong params given' do
|
8
|
+
it 'fails when no block given' do
|
9
|
+
expect { subject.add(sample_exception) }.to raise_error('Block not given')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when valid params given' do
|
14
|
+
let(:block) { proc {} }
|
15
|
+
|
16
|
+
it 'adds the exception handler' do
|
17
|
+
subject.add(sample_exception, &block)
|
18
|
+
|
19
|
+
expect(subject.exceptions).to include(sample_exception)
|
20
|
+
expect(subject.handlers.values).to include(block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#run' do
|
26
|
+
let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
|
27
|
+
let(:block_exception) { stub_const 'BlockException', Class.new(Exception) }
|
28
|
+
let(:block) { proc { raise BlockException } }
|
29
|
+
|
30
|
+
context 'when wrong params given' do
|
31
|
+
it 'fails when handler not given' do
|
32
|
+
expect { subject.run('name', 'attrs', sample_exception.new) }
|
33
|
+
.to raise_error('No handler given')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when valid params given' do
|
38
|
+
it 'runs the handler' do
|
39
|
+
subject.add(sample_exception, &block)
|
40
|
+
expect { subject.run('name', 'attrs', sample_exception.new) }
|
41
|
+
.to raise_error(block_exception)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe EndpointFlux::Endpoint do
|
4
|
+
let(:klass) { stub_const 'Sample', Class.new }
|
5
|
+
|
6
|
+
before do
|
7
|
+
klass.include EndpointFlux::Endpoint
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#flow' do
|
11
|
+
let(:params) { { some: :val } }
|
12
|
+
let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: params) }
|
13
|
+
let(:middleware_response) { EndpointFlux::Response.new }
|
14
|
+
|
15
|
+
before do
|
16
|
+
stub_const('EndpointFlux::Middlewares::Validator::Sample', Class.new)
|
17
|
+
EndpointFlux::Middlewares::Validator::Sample.class_eval do
|
18
|
+
def self.perform(request, response, _)
|
19
|
+
request.params = {}
|
20
|
+
[request, response]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
stub_const('EndpointFlux::Middlewares::Decorator::Sample', Class.new)
|
25
|
+
EndpointFlux::Middlewares::Decorator::Sample.class_eval do
|
26
|
+
def self.perform(request, _response, _)
|
27
|
+
[request, EndpointFlux::Response.new(headers: {}, body: {})]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
klass.flow %i[validator decorator]
|
32
|
+
|
33
|
+
EndpointFlux.config.default_middlewares :validator, :sample
|
34
|
+
EndpointFlux.config.default_middlewares :decorator, 'sample'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'uses default middleware if not defined' do
|
38
|
+
request, response = klass.perform(middleware_request)
|
39
|
+
expect(request.params).to eq({})
|
40
|
+
expect(response.body).to eq({})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|