endpoint-flux 1.1.4

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/CONTRIBUTING.md +18 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +37 -0
  6. data/README.md +607 -0
  7. data/circle.yml +14 -0
  8. data/endpoint_flux.gemspec +18 -0
  9. data/lib/endpoint_flux.rb +20 -0
  10. data/lib/endpoint_flux/class_loader.rb +58 -0
  11. data/lib/endpoint_flux/config.rb +85 -0
  12. data/lib/endpoint_flux/config/interceptor.rb +23 -0
  13. data/lib/endpoint_flux/config/middleware.rb +38 -0
  14. data/lib/endpoint_flux/config/rescue_from.rb +28 -0
  15. data/lib/endpoint_flux/endpoint.rb +81 -0
  16. data/lib/endpoint_flux/exceptions.rb +10 -0
  17. data/lib/endpoint_flux/exceptions/base.rb +21 -0
  18. data/lib/endpoint_flux/exceptions/forbidden.rb +12 -0
  19. data/lib/endpoint_flux/exceptions/not_found.rb +12 -0
  20. data/lib/endpoint_flux/exceptions/service_unavailable.rb +12 -0
  21. data/lib/endpoint_flux/exceptions/unauthorized.rb +12 -0
  22. data/lib/endpoint_flux/exceptions/validation.rb +13 -0
  23. data/lib/endpoint_flux/middlewares.rb +8 -0
  24. data/lib/endpoint_flux/middlewares/authenticator/skip.rb +11 -0
  25. data/lib/endpoint_flux/middlewares/authorizator/skip.rb +11 -0
  26. data/lib/endpoint_flux/middlewares/decorator/add_status.rb +12 -0
  27. data/lib/endpoint_flux/middlewares/decorator/skip.rb +11 -0
  28. data/lib/endpoint_flux/middlewares/policy/skip.rb +11 -0
  29. data/lib/endpoint_flux/middlewares/validator/empty.rb +12 -0
  30. data/lib/endpoint_flux/rails/concerns/endpoint_controller.rb +43 -0
  31. data/lib/endpoint_flux/request.rb +17 -0
  32. data/lib/endpoint_flux/response.rb +30 -0
  33. data/lib/endpoint_flux/version.rb +3 -0
  34. data/spec/lib/class_loader_spec.rb +31 -0
  35. data/spec/lib/config/default_middlewares_spec.rb +21 -0
  36. data/spec/lib/config/endpoints_namespace_spec.rb +13 -0
  37. data/spec/lib/config/flow_spec.rb +8 -0
  38. data/spec/lib/config/interceptor_spec.rb +34 -0
  39. data/spec/lib/config/middleware_spec.rb +62 -0
  40. data/spec/lib/config/rescue_from_spec.rb +45 -0
  41. data/spec/lib/endpoint/flow_spec.rb +43 -0
  42. data/spec/lib/endpoint/middlewares_spec.rb +110 -0
  43. data/spec/lib/endpoint/perform_spec.rb +61 -0
  44. data/spec/lib/endpoint/rescue_from_spec.rb +61 -0
  45. data/spec/lib/endpoint_flux/rails/concerns/endpoint_controller_spec.rb +75 -0
  46. data/spec/lib/endpoint_flux/request_spec.rb +44 -0
  47. data/spec/lib/exceptions/forbidden_spec.rb +12 -0
  48. data/spec/lib/exceptions/not_found_spec.rb +12 -0
  49. data/spec/lib/exceptions/service_unavailable_spec.rb +12 -0
  50. data/spec/lib/exceptions/unauthorized_spec.rb +12 -0
  51. data/spec/lib/exceptions/validation_spec.rb +14 -0
  52. data/spec/lib/middlewares/authenticator/skip_spec.rb +5 -0
  53. data/spec/lib/middlewares/authorizator/skip_spec.rb +5 -0
  54. data/spec/lib/middlewares/decorator/add_status_spec.rb +17 -0
  55. data/spec/lib/middlewares/decorator/skip_spec.rb +5 -0
  56. data/spec/lib/middlewares/policy/skip_spec.rb +5 -0
  57. data/spec/lib/middlewares/shared_examples.rb +19 -0
  58. data/spec/lib/middlewares/validator/empty_spec.rb +15 -0
  59. data/spec/lib/response_spec.rb +131 -0
  60. data/spec/spec_helper.rb +52 -0
  61. metadata +157 -0
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { class_double('Sample') }
5
+
6
+ before do
7
+ EndpointFlux.config EndpointFlux::Config.new
8
+
9
+ klass.include EndpointFlux::Endpoint
10
+ end
11
+
12
+ context 'with exceptions' do
13
+ it 'fails with wrong string' do
14
+ klass.flow [:validator]
15
+
16
+ expect do
17
+ klass.validator 'some_not_existing_class'
18
+ end.to raise_error('You must provide block or existing klass')
19
+ end
20
+
21
+ it 'fails whit wrong class passed' do
22
+ stub_const 'EndpointFlux::Middlewares::Validator::SampleMiddleware', Class.new
23
+
24
+ klass.flow [:validator]
25
+
26
+ expect { klass.validator 'sample_middleware' }.to raise_error(
27
+ 'The [EndpointFlux::Middlewares::Validator::SampleMiddleware] '\
28
+ 'class should define perform class method'
29
+ )
30
+ end
31
+
32
+ context 'when wrong param passed' do
33
+ it do
34
+ klass.flow [:validator]
35
+
36
+ expect { klass.validator 1334 }.to raise_error(
37
+ 'You must provide block or existing klass'
38
+ )
39
+ end
40
+
41
+ it do
42
+ stub_const 'SampleMiddleware', Class.new
43
+
44
+ klass.flow [:validator]
45
+
46
+ expect { klass.validator SampleMiddleware }.to raise_error(
47
+ 'You must provide block or existing klass'
48
+ )
49
+ end
50
+ end
51
+ end
52
+
53
+ describe 'middlewares' do
54
+ before do
55
+ stub_const 'SomeNamespace::MiddlewareName::SampleMiddleware', Class.new
56
+ SomeNamespace::MiddlewareName::SampleMiddleware.class_eval do
57
+ def self.perform(*args)
58
+ args
59
+ end
60
+ end
61
+
62
+ EndpointFlux.config.middlewares_namespaces << 'some_namespace'
63
+ end
64
+
65
+ before do
66
+ klass.flow [:middleware_name]
67
+ end
68
+
69
+ let(:middleware) { klass.middleware_name.first }
70
+
71
+ it 'sets middleware with options' do
72
+ klass.middleware_name 'sample_middleware', some: :option
73
+
74
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
75
+ expect(middleware.options).to eq(some: :option)
76
+ end
77
+
78
+ it 'sets middleware' do
79
+ klass.middleware_name 'sample_middleware'
80
+
81
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
82
+ end
83
+
84
+ it 'does not add twice' do
85
+ klass.middleware_name 'sample_middleware'
86
+ klass.middleware_name 'sample_middleware'
87
+
88
+ middleware = klass.middleware_name.first
89
+
90
+ expect(middleware.klass).to be(SomeNamespace::MiddlewareName::SampleMiddleware)
91
+ end
92
+
93
+ context 'block' do
94
+ let(:block) { proc {} }
95
+
96
+ it 'sets middleware' do
97
+ klass.middleware_name(&block)
98
+
99
+ expect(middleware.handler).to be == block
100
+ end
101
+
102
+ it 'does not adds twice' do
103
+ klass.middleware_name(&block)
104
+ klass.middleware_name(&block)
105
+
106
+ expect(middleware.handler).to be == block
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { stub_const 'Sample', Class.new }
5
+ let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: params) }
6
+ let(:middleware_response) { EndpointFlux::Response.new }
7
+
8
+ before do
9
+ EndpointFlux.config EndpointFlux::Config.new
10
+
11
+ klass.include EndpointFlux::Endpoint
12
+ end
13
+
14
+ describe '#perform' do
15
+ before do
16
+ stub_const 'EndpointFlux::Middlewares::Validator::SampleValidator', Class.new
17
+ EndpointFlux::Middlewares::Validator::SampleValidator.class_eval do
18
+ def self.perform(request, response, _)
19
+ request.params = {}
20
+ [request, response, {}]
21
+ end
22
+ end
23
+ end
24
+
25
+ let(:params) { { some: :val } }
26
+
27
+ it 'checks if middleware exists' do
28
+ klass.flow [:validator]
29
+
30
+ expect { klass.perform(middleware_request) }
31
+ .to raise_error('No middleware registred for [:validator]')
32
+ end
33
+
34
+ context 'middleware passed as string' do
35
+ it 'runs middleware passed as string' do
36
+ klass.flow [:validator]
37
+ klass.validator 'sample_validator'
38
+
39
+ request, response = klass.perform(middleware_request)
40
+
41
+ expect(request.params).to eq({})
42
+ expect(response.body).to eq({})
43
+ end
44
+ end
45
+
46
+ context 'default middleware' do
47
+ before do
48
+ klass.flow [:validator]
49
+
50
+ EndpointFlux.config.default_middlewares :validator, 'sample_validator'
51
+ end
52
+
53
+ it 'uses default if not defined' do
54
+ request, response = klass.perform(middleware_request)
55
+
56
+ expect(request.params).to eq({})
57
+ expect(response.body).to eq({})
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Endpoint do
4
+ let(:klass) { stub_const 'Sample', Class.new }
5
+ let(:middleware_request) { EndpointFlux::Request.new(headers: {}, params: {}) }
6
+ let(:middleware_response) { EndpointFlux::Response.new }
7
+
8
+ before do
9
+ EndpointFlux.config EndpointFlux::Config.new
10
+
11
+ klass.include EndpointFlux::Endpoint
12
+ end
13
+
14
+ describe '#rescue_from' do
15
+ let(:sample_exception) { stub_const 'SampleException', Class.new(Exception) }
16
+ let!(:sample_validator) do
17
+ stub_const 'EndpointFlux::Middlewares::Validator::Sample', Class.new
18
+ EndpointFlux::Middlewares::Validator::Sample.class_eval do
19
+ def self.perform(*)
20
+ raise SampleException, 'bla bla'
21
+ end
22
+ end
23
+ EndpointFlux::Middlewares::Validator::Sample
24
+ end
25
+ let!(:sample_decorator) do
26
+ stub_const 'EndpointFlux::Middlewares::Decorator::Sample', Class.new
27
+ EndpointFlux::Middlewares::Decorator::Sample.class_eval do
28
+ def self.perform(request, response, options)
29
+ response.body[:decorator] = true
30
+ [request, response, options]
31
+ end
32
+ end
33
+ EndpointFlux::Middlewares::Decorator::Sample
34
+ end
35
+
36
+ it 'fails if exception not found' do
37
+ expect do
38
+ EndpointFlux.config.rescue_from 'NonExsistingClasss' do |_, attrs|
39
+ # code
40
+ end
41
+ end.to raise_error('The [NonExsistingClasss] should be a string representing a class')
42
+ end
43
+
44
+ context 'default middleware' do
45
+ before do
46
+ klass.flow %i[validator decorator]
47
+ klass.validator 'sample'
48
+ klass.decorator 'sample'
49
+
50
+ EndpointFlux.config.rescue_from sample_exception do |_, attrs|
51
+ [attrs[0], attrs[1], { status: false }]
52
+ end
53
+ end
54
+
55
+ it 'uses default if not defined' do
56
+ _, response = klass.perform(middleware_request)
57
+ expect(response.body[:status]).to be_falsey
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,75 @@
1
+ module ActiveSupport
2
+ module Concern ; end
3
+ end
4
+
5
+ require 'spec_helper'
6
+ require 'endpoint_flux/rails/concerns/endpoint_controller'
7
+ require 'ostruct'
8
+
9
+ class RemoteIpDummyClass
10
+ include EndpointFlux::Rails::Concerns::EndpointController
11
+
12
+ def headers
13
+ {}
14
+ end
15
+
16
+ def request
17
+ OpenStruct.new(
18
+ headers: { 'authorization' => 'authorization header' },
19
+ remote_ip: '172.18.0.1',
20
+ env: { 'HTTP_X_FORWARDED_FOR' => '172.18.0.2' }
21
+ )
22
+ end
23
+ end
24
+
25
+ class LocalIpDummyClass
26
+ include EndpointFlux::Rails::Concerns::EndpointController
27
+
28
+ def headers
29
+ {}
30
+ end
31
+
32
+ def request
33
+ OpenStruct.new(
34
+ headers: { 'authorization' => 'authorization header' },
35
+ remote_ip: '127.0.0.1',
36
+ env: { 'HTTP_X_FORWARDED_FOR' => '172.18.0.2' }
37
+ )
38
+ end
39
+ end
40
+
41
+ RSpec.describe EndpointFlux::Rails::Concerns::EndpointController do
42
+ describe '#request_object' do
43
+ before do
44
+ allow(subject).to receive(:endpoint_params).and_return({})
45
+ end
46
+
47
+ context 'remote ip' do
48
+ subject { RemoteIpDummyClass.new }
49
+
50
+ it 'sets property as remote_ip' do
51
+ expect(
52
+ ::EndpointFlux::Request
53
+ ).to receive(:new).with(headers: { 'Authorization' => 'authorization header' },
54
+ params: subject.endpoint_params,
55
+ remote_ip: subject.request.remote_ip)
56
+
57
+ subject.request_object
58
+ end
59
+ end
60
+
61
+ context 'local ip' do
62
+ subject { LocalIpDummyClass.new }
63
+
64
+ it 'sets property as HTTP_X_FORWARDED_FOR' do
65
+ expect(
66
+ ::EndpointFlux::Request
67
+ ).to receive(:new).with(headers: { 'Authorization' => 'authorization header' },
68
+ params: subject.endpoint_params,
69
+ remote_ip: subject.request.env['HTTP_X_FORWARDED_FOR'])
70
+
71
+ subject.request_object
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Request do
4
+ it { should respond_to :headers }
5
+ it { should respond_to :remote_ip }
6
+ it { should respond_to :params }
7
+ it { should respond_to :namespace }
8
+ it { should respond_to :endpoint }
9
+ it { should respond_to :scope }
10
+
11
+ describe '#initialize' do
12
+ context 'when all params specified' do
13
+ let(:params) { { param: :val } }
14
+ let(:headers) { { header: :val } }
15
+ let(:remote_ip) { '127.0.0.1' }
16
+ let(:namespace) { 'namespace' }
17
+
18
+ it 'should set args' do
19
+ request = EndpointFlux::Request.new(
20
+ params: params,
21
+ headers: headers,
22
+ remote_ip: remote_ip,
23
+ namespace: namespace
24
+ )
25
+
26
+ expect(request.params).to eq params
27
+ expect(request.headers).to eq headers
28
+ expect(request.remote_ip).to eq remote_ip
29
+ expect(request.namespace).to eq namespace
30
+ end
31
+
32
+ context 'when params missed' do
33
+ it 'should set default values' do
34
+ request = EndpointFlux::Request.new
35
+
36
+ expect(request.params).to be_empty
37
+ expect(request.headers).to be_empty
38
+ expect(request.remote_ip).to eq ''
39
+ expect(request.namespace).to be_nil
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Forbidden do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 403,
8
+ message: 'Forbidden'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::NotFound do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 404,
8
+ message: 'not found'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::ServiceUnavailable do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 503,
8
+ message: 'service unavailable'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Unauthorized do
4
+ describe '#to_hash' do
5
+ it 'returns correct hash' do
6
+ expect(subject.to_hash).to eq(
7
+ status: 401,
8
+ message: 'Unauthorized'
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe EndpointFlux::Exceptions::Validation do
4
+ describe '#to_hash' do
5
+ let(:messages) { {name: 'not valid'} }
6
+ it 'returns correct hash' do
7
+ expect(EndpointFlux::Exceptions::Validation.new(messages).to_hash).to eq(
8
+ status: 422,
9
+ message: 'validation errors',
10
+ errors: messages
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Authenticator::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,5 @@
1
+ require_relative '../../middlewares/shared_examples'
2
+
3
+ RSpec.describe EndpointFlux::Middlewares::Authorizator::Skip do
4
+ include_examples 'perform does not change the params'
5
+ end
@@ -0,0 +1,17 @@
1
+ RSpec.describe EndpointFlux::Middlewares::Decorator::AddStatus do
2
+ describe '#perform' do
3
+ let(:params) { { some: 'value' } }
4
+ let(:body) { { status: 200 } }
5
+ let(:request) { EndpointFlux::Request.new(headers: {}, params: params) }
6
+ let(:response) { EndpointFlux::Response.new(headers: {}, body: body) }
7
+
8
+ it 'returns response with status in body' do
9
+ middleware_request, middleware_response = subject.perform(request, response, {})
10
+
11
+ expect(middleware_request.headers).to eq({})
12
+ expect(middleware_request.params).to eq(params)
13
+ expect(middleware_response.headers).to eq({})
14
+ expect(middleware_response.body).to eq(body)
15
+ end
16
+ end
17
+ end