apress-api 1.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.drone.yml +30 -0
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/Appraisals +31 -0
- data/CHANGELOG.md +227 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/app/controllers/apress/api/deprecated_versions_controller.rb +15 -0
- data/app/controllers/apress/api/v1/callbacks_controller.rb +30 -0
- data/app/controllers/apress/api/v1/tokens_controller.rb +24 -0
- data/app/docs/schema/api/v1/types/apress/api/link.rb +29 -0
- data/app/docs/schema/api/v1/types/apress/api/links.rb +24 -0
- data/app/docs/swagger/v1/controllers/apress/api/tokens_controller.rb +64 -0
- data/app/docs/swagger/v1/default_responses/bad_request.rb +16 -0
- data/app/docs/swagger/v1/default_responses/not_found.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unauthenticated.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unauthorized.rb +16 -0
- data/app/docs/swagger/v1/default_responses/unprocessable.rb +16 -0
- data/app/docs/swagger/v1/default_responses/updates_locked.rb +13 -0
- data/app/docs/swagger/v1/models/apress/api/client.rb +53 -0
- data/app/docs/swagger/v1/models/apress/api/simple_error.rb +27 -0
- data/app/docs/swagger/v1/models/apress/api/unproccesable_error.rb +16 -0
- data/app/docs/swagger/v1/models/apress/api/unprocessable_error.rb +37 -0
- data/app/docs/swagger/v1/root.rb +28 -0
- data/app/interactors/apress/api/callbacks/base_callback.rb +42 -0
- data/app/interactors/apress/api/delayed_fire_callback.rb +25 -0
- data/app/jobs/apress/api/event_handler_enqueueing_job.rb +19 -0
- data/app/jobs/apress/api/fire_callback_job.rb +25 -0
- data/app/models/apress/api/client.rb +60 -0
- data/app/policies/apress/api/callback_policy.rb +15 -0
- data/app/services/apress/api/auth_service.rb +37 -0
- data/app/views/apress/api/shared/_exception.json.jbuilder +4 -0
- data/app/views/apress/api/shared/error.json.jbuilder +5 -0
- data/app/views/apress/api/shared/parameter_missing_errors.json.jbuilder +9 -0
- data/app/views/apress/api/shared/unprocessable_errors.json.jbuilder +9 -0
- data/app/views/apress/api/v1/clients/_client.json.jbuilder +2 -0
- data/app/views/apress/api/v1/tokens/create.json.jbuilder +4 -0
- data/apress-api.gemspec +46 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20150716000000_create_api_clients.rb +38 -0
- data/dip.yml +48 -0
- data/docker-compose.development.yml +18 -0
- data/docker-compose.drone.yml +7 -0
- data/docker-compose.yml +20 -0
- data/lib/apress-api.rb +1 -0
- data/lib/apress/api.rb +25 -0
- data/lib/apress/api/api_controller/authentification.rb +33 -0
- data/lib/apress/api/api_controller/base.rb +63 -0
- data/lib/apress/api/api_controller/compatibility.rb +26 -0
- data/lib/apress/api/api_controller/pagination.rb +60 -0
- data/lib/apress/api/api_controller/pagination_helper.rb +55 -0
- data/lib/apress/api/api_controller/rescue.rb +89 -0
- data/lib/apress/api/api_controller/responds.rb +25 -0
- data/lib/apress/api/callbacks/config.rb +56 -0
- data/lib/apress/api/callbacks/fire_callback_error.rb +12 -0
- data/lib/apress/api/callbacks/integration.rb +28 -0
- data/lib/apress/api/callbacks/repeat_callback_error.rb +12 -0
- data/lib/apress/api/engine.rb +33 -0
- data/lib/apress/api/extensions/jbuilder/jbuilder_template.rb +41 -0
- data/lib/apress/api/rspec.rb +48 -0
- data/lib/apress/api/rspec/utils.rb +17 -0
- data/lib/apress/api/testing/json_matcher.rb +9 -0
- data/lib/apress/api/version.rb +5 -0
- data/lib/tasks/docs.rake +12 -0
- data/spec/controllers/api_controller/authentification_spec.rb +79 -0
- data/spec/controllers/api_controller/pagination_spec.rb +199 -0
- data/spec/controllers/api_controller/rescue_spec.rb +167 -0
- data/spec/controllers/deprecated_versions_controller_spec.rb +10 -0
- data/spec/controllers/v1/callbacks_controller_spec.rb +50 -0
- data/spec/controllers/v1/tokens_controller_spec.rb +53 -0
- data/spec/factories/client_factory.rb +4 -0
- data/spec/helpers/paginating_cache_spec.rb +72 -0
- data/spec/interactors/apress/api/delayed_fire_callback_spec.rb +43 -0
- data/spec/internal/app/integrations/error_client/fire_callback.rb +14 -0
- data/spec/internal/app/integrations/service_client/fire_callback.rb +7 -0
- data/spec/internal/app/jobs/handler_job.rb +5 -0
- data/spec/internal/app/jobs/second_handler_job.rb +5 -0
- data/spec/internal/app/models/dummy_model.rb +15 -0
- data/spec/internal/config/database.yml +5 -0
- data/spec/internal/config/environments/test.rb +5 -0
- data/spec/internal/config/initializers/api.rb +10 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +5 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/jobs/apress/api/event_handler_equeueing_job_spec.rb +31 -0
- data/spec/jobs/apress/api/fire_callback_job_spec.rb +34 -0
- data/spec/lib/apress/api/callbacks/integration_spec.rb +24 -0
- data/spec/models/client_spec.rb +25 -0
- data/spec/services/auth_service_spec.rb +64 -0
- data/spec/spec_helper.rb +34 -0
- metadata +518 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Schema
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Types
|
5
|
+
module Apress
|
6
|
+
module Api
|
7
|
+
class Link < ::Apress::Api::Swagger::Schema
|
8
|
+
swagger_schema name.to_sym do
|
9
|
+
key :required, [:href]
|
10
|
+
key :description, 'A representation of a link object'
|
11
|
+
|
12
|
+
property :href do
|
13
|
+
key :type, :string
|
14
|
+
key :description, 'A string containing the link’s URL'
|
15
|
+
key :example, 'https://www.example.com/api/v1/review_comments'
|
16
|
+
end
|
17
|
+
|
18
|
+
property :meta do
|
19
|
+
key :type, :object
|
20
|
+
key :description, 'A meta object containing non-standard meta-information about the link'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Schema
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Types
|
5
|
+
module Apress
|
6
|
+
module Api
|
7
|
+
class Links < ::Apress::Api::Swagger::Schema
|
8
|
+
swagger_schema name.to_sym do
|
9
|
+
key :description, 'A representation of a links object (http://jsonapi.org/format/#document-links)'
|
10
|
+
key :type, :object
|
11
|
+
key :additionalProperties, {
|
12
|
+
oneOf: [
|
13
|
+
{'type': 'string'},
|
14
|
+
{'$ref' => '#/definitions/Schema::Api::V1::Types::Apress::Api::Link'}
|
15
|
+
]
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module Controllers
|
4
|
+
module Apress
|
5
|
+
module Api
|
6
|
+
class TokensController < ::Apress::Api::Swagger::Schema
|
7
|
+
swagger_path '/clients/{access_id}/tokens' do
|
8
|
+
operation :post do
|
9
|
+
key :produces, ['application/json']
|
10
|
+
|
11
|
+
key :description, 'Refreshes token for client with given access_id'
|
12
|
+
key :operationId, 'refreshToken'
|
13
|
+
key :tags, ['clients']
|
14
|
+
|
15
|
+
parameter do
|
16
|
+
key :name, :access_id
|
17
|
+
key :in, :path
|
18
|
+
key :description, "client's access_id"
|
19
|
+
key :required, true
|
20
|
+
key :type, :string
|
21
|
+
end
|
22
|
+
|
23
|
+
parameter do
|
24
|
+
key :name, 'refresh_token'
|
25
|
+
key :in, :body
|
26
|
+
key :description, "Client's refresh token"
|
27
|
+
key :required, true
|
28
|
+
schema type: :object do
|
29
|
+
property :refresh_token do
|
30
|
+
key :type, :string
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
response 200 do
|
36
|
+
key :description, 'Success response'
|
37
|
+
schema type: 'object' do
|
38
|
+
property :client do
|
39
|
+
key :'$ref', :'Swagger::V1::Models::Apress::Api::Client'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
response 400 do
|
45
|
+
key :description, 'refresh token not valid for current access_id'
|
46
|
+
schema do
|
47
|
+
key :'$ref', :'Swagger::V1::Models::Apress::Api::SimpleError'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
response 403 do
|
52
|
+
key :description, 'refresh token is expired'
|
53
|
+
schema do
|
54
|
+
key :'$ref', :'Swagger::V1::Models::Apress::Api::SimpleError'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module DefaultResponses
|
4
|
+
module BadRequest
|
5
|
+
def self.extended(base)
|
6
|
+
base.response 400 do
|
7
|
+
key :description, "Переданные параметры не могут быть обработаны"
|
8
|
+
schema do
|
9
|
+
key :'$ref', :'Swagger::V1::::Models::Apress::Api::UnprocessableError'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module DefaultResponses
|
4
|
+
module NotFound
|
5
|
+
def self.extended(base)
|
6
|
+
base.response 404 do
|
7
|
+
key :description, "Запрашиваемый ресурс не найден"
|
8
|
+
schema do
|
9
|
+
key :'$ref', :'Swagger::V1::::Models::Apress::Api::SimpleError'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module DefaultResponses
|
4
|
+
module Unauthenticated
|
5
|
+
def self.extended(base)
|
6
|
+
base.response 401 do
|
7
|
+
key :description, "Запрос не прошел аутентификацию (проблема с подписью запроса)"
|
8
|
+
schema do
|
9
|
+
key :'$ref', :'Swagger::V1::::Models::Apress::Api::SimpleError'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module DefaultResponses
|
4
|
+
module Unauthorized
|
5
|
+
def self.extended(base)
|
6
|
+
base.response 403 do
|
7
|
+
key :description, "Нет доступа к ресурсу"
|
8
|
+
schema do
|
9
|
+
key :'$ref', :'Swagger::V1::::Models::Apress::Api::SimpleError'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module DefaultResponses
|
4
|
+
module Unprocessable
|
5
|
+
def self.extended(base)
|
6
|
+
base.response 422 do
|
7
|
+
key :description, "Переданные параметры не валидны"
|
8
|
+
schema do
|
9
|
+
key :'$ref', :'Swagger::V1::::Models::Apress::Api::UnprocessableError'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Apress
|
5
|
+
module Api
|
6
|
+
class Client < ::Apress::Documentation::Swagger::Schema
|
7
|
+
swagger_schema name.to_sym do
|
8
|
+
key :required, [
|
9
|
+
:id,
|
10
|
+
:access_id,
|
11
|
+
:secret_token_expire_at,
|
12
|
+
:secret_token,
|
13
|
+
:refresh_token_expire_at,
|
14
|
+
:refresh_token,
|
15
|
+
:user_agent,
|
16
|
+
:updated_at,
|
17
|
+
:created_at
|
18
|
+
]
|
19
|
+
|
20
|
+
property :id do
|
21
|
+
key :type, :integer
|
22
|
+
key :format, :int64
|
23
|
+
end
|
24
|
+
|
25
|
+
{
|
26
|
+
access_id: '6760dc04-db3e-4c18-b7a3-5cd68718e869',
|
27
|
+
secret_token: 'fflnVd5JyQAlH4EICLEV/c49RQRj0MaINNKFAVsuxngfcQHzLw7L9uF7fnOm/mbn4SBs3ssCUjvjcTjb4nQ==',
|
28
|
+
refresh_token: 'kmwCUAQxg2YOCZg2ENLQ4t4hfH8DYKPb6e+6ZkSl1K/zOyAXflUeL9Ef/jL7rEMTfuu0QqbrMm8SNsEnww==',
|
29
|
+
secret_token_expire_at: Time.current,
|
30
|
+
refresh_token_expire_at: Time.current,
|
31
|
+
user_agent: nil
|
32
|
+
}.each do |k, v|
|
33
|
+
property k do
|
34
|
+
key :type, :string
|
35
|
+
key :example, v if v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
[:created_at, :updated_at].each do |k|
|
40
|
+
property k do
|
41
|
+
key :type, :string
|
42
|
+
key :format, :date
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
ActiveSupport.run_load_hooks(:'swagger/models/v1/apress/api/client', self)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Apress
|
5
|
+
module Api
|
6
|
+
class SimpleError < ::Apress::Documentation::Swagger::Schema
|
7
|
+
swagger_schema name.to_sym do
|
8
|
+
keys = [
|
9
|
+
:status,
|
10
|
+
:message,
|
11
|
+
:backtrace
|
12
|
+
]
|
13
|
+
|
14
|
+
key :required, keys
|
15
|
+
|
16
|
+
keys.each do |k|
|
17
|
+
property k do
|
18
|
+
key :type, :string
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'unprocessable_error'
|
2
|
+
|
3
|
+
module Swagger
|
4
|
+
module V1
|
5
|
+
module Models
|
6
|
+
module Apress
|
7
|
+
module Api
|
8
|
+
# Deprecated: Please use `UnprocessableError` instead
|
9
|
+
class UnproccesableError < ::Apress::Documentation::Swagger::Schema
|
10
|
+
include UnprocessableError::Schema
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
module Models
|
4
|
+
module Apress
|
5
|
+
module Api
|
6
|
+
class UnprocessableError < ::Apress::Documentation::Swagger::Schema
|
7
|
+
module Schema
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
swagger_schema name.to_sym do
|
12
|
+
key :required, [:errors, :status]
|
13
|
+
|
14
|
+
property :status do
|
15
|
+
key :type, :string
|
16
|
+
end
|
17
|
+
|
18
|
+
property :errors do
|
19
|
+
key :type, :array
|
20
|
+
items do
|
21
|
+
key :type, :object
|
22
|
+
property :error do
|
23
|
+
key :type, :object
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
include Schema
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Swagger
|
2
|
+
module V1
|
3
|
+
class Root < ::Apress::Documentation::Swagger::Schema
|
4
|
+
swagger_root do
|
5
|
+
key :swagger, '2.0'
|
6
|
+
info do
|
7
|
+
key :version, '1.0.0'
|
8
|
+
key :title, 'Apress API'
|
9
|
+
key :description, 'Apress API'
|
10
|
+
key :termsOfService, 'None'
|
11
|
+
contact do
|
12
|
+
key :name, 'Abak-Press Team'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
key :basePath, '/api/v1'
|
17
|
+
key :produces, ['application/json']
|
18
|
+
|
19
|
+
security_definition :APIAuth do
|
20
|
+
key :type, :apiKey
|
21
|
+
key :in, :header
|
22
|
+
key :name, 'Authorization'
|
23
|
+
key :description, 'Authentication by access_id token based on HMAC'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Apress
|
2
|
+
module Api
|
3
|
+
module Callbacks
|
4
|
+
class BaseCallback
|
5
|
+
include Interactor
|
6
|
+
|
7
|
+
def self.retry_exceptions
|
8
|
+
@retry_exceptions ||= Set.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.repeat_exceptions
|
12
|
+
@repeat_exceptions ||= Set.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.add_retry_exceptions(*errors)
|
16
|
+
retry_exceptions.merge(errors)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.add_repeat_exceptions(*errors)
|
20
|
+
repeat_exceptions.merge(errors)
|
21
|
+
retry_exceptions.merge(errors)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.inherited(other)
|
25
|
+
other.around do |interactor|
|
26
|
+
begin
|
27
|
+
interactor.call
|
28
|
+
rescue Exception => error
|
29
|
+
if self.class.repeat_exceptions.any? { |ex| ex === error }
|
30
|
+
raise Apress::Api::Callbacks::RepeatCallbackError.new(error.message, error.backtrace)
|
31
|
+
elsif self.class.retry_exceptions.any? { |ex| error.is_a?(Class) && ex >= error || ex === error }
|
32
|
+
raise Apress::Api::Callbacks::FireCallbackError.new(error.message, error.backtrace)
|
33
|
+
else
|
34
|
+
raise error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Apress
|
2
|
+
module Api
|
3
|
+
class DelayedFireCallback
|
4
|
+
include Interactor
|
5
|
+
|
6
|
+
delegate :event, :params, to: :context
|
7
|
+
def call
|
8
|
+
services = Apress::Api::Callbacks::Config.services(event)
|
9
|
+
|
10
|
+
return if services.blank?
|
11
|
+
|
12
|
+
::Resque.redis.multi do
|
13
|
+
services.each do |service|
|
14
|
+
::Resque.enqueue(
|
15
|
+
::Apress::Api::FireCallbackJob,
|
16
|
+
service,
|
17
|
+
event,
|
18
|
+
params
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|