virtuaservices 0.1.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 +7 -0
- data/lib/virtuaservices.rb +11 -0
- data/lib/virtuaservices/account.rb +72 -0
- data/lib/virtuaservices/authentication.rb +7 -0
- data/lib/virtuaservices/authentication/session.rb +28 -0
- data/lib/virtuaservices/concerns.rb +13 -0
- data/lib/virtuaservices/concerns/activable.rb +18 -0
- data/lib/virtuaservices/concerns/diagnosticable.rb +22 -0
- data/lib/virtuaservices/concerns/enumerable.rb +44 -0
- data/lib/virtuaservices/concerns/mime_typable.rb +36 -0
- data/lib/virtuaservices/concerns/premiumable.rb +15 -0
- data/lib/virtuaservices/concerns/sluggable.rb +27 -0
- data/lib/virtuaservices/concerns/typable.rb +17 -0
- data/lib/virtuaservices/monitoring.rb +12 -0
- data/lib/virtuaservices/monitoring/action.rb +25 -0
- data/lib/virtuaservices/monitoring/gateway.rb +37 -0
- data/lib/virtuaservices/monitoring/instance.rb +36 -0
- data/lib/virtuaservices/monitoring/route.rb +36 -0
- data/lib/virtuaservices/monitoring/service.rb +37 -0
- data/lib/virtuaservices/monitoring/websocket.rb +25 -0
- data/lib/virtuaservices/oauth.rb +7 -0
- data/lib/virtuaservices/oauth/application.rb +33 -0
- data/lib/virtuaservices/permissions.rb +10 -0
- data/lib/virtuaservices/permissions/category.rb +15 -0
- data/lib/virtuaservices/permissions/group.rb +30 -0
- data/lib/virtuaservices/permissions/right.rb +19 -0
- data/lib/virtuaservices/specs.rb +89 -0
- data/lib/virtuaservices/utils.rb +10 -0
- data/lib/virtuaservices/utils/controllers.rb +8 -0
- data/lib/virtuaservices/utils/controllers/base.rb +193 -0
- data/lib/virtuaservices/utils/controllers/checked.rb +14 -0
- data/lib/virtuaservices/utils/errors.rb +12 -0
- data/lib/virtuaservices/utils/errors/bad_request.rb +14 -0
- data/lib/virtuaservices/utils/errors/forbidden.rb +14 -0
- data/lib/virtuaservices/utils/errors/http_error.rb +30 -0
- data/lib/virtuaservices/utils/errors/not_found.rb +14 -0
- data/lib/virtuaservices/utils/loaders.rb +7 -0
- data/lib/virtuaservices/utils/loaders/heroku.rb +20 -0
- data/lib/virtuaservices/utils/micro_service.rb +170 -0
- data/lib/virtuaservices/utils/seeder.rb +25 -0
- data/lib/virtuaservices/version.rb +3 -0
- metadata +321 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Monitoring
|
3
|
+
# A route is an endpoint accessible in a service. Each route has to have an associated endpoint in the deployed instances.
|
4
|
+
# @param Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Route
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include Virtuaservices::Concerns::Premiumable
|
9
|
+
include Virtuaservices::Concerns::Activable
|
10
|
+
|
11
|
+
# @!attribute [rw] path
|
12
|
+
# @return [String] the path (URI) of the route in the service?
|
13
|
+
field :path, type: String, default: '/'
|
14
|
+
# @!attribute [rw] verb
|
15
|
+
# @return [String] the verb (HTTP method) of this route in the service.
|
16
|
+
field :verb, type: String, default: 'get'
|
17
|
+
# @!attribute [rw] authenticated
|
18
|
+
# @return [Boolean] if true, the session_id is needed for this route, if false it is not.
|
19
|
+
field :authenticated, type: Boolean, default: true
|
20
|
+
|
21
|
+
# @!attribute [rw] service
|
22
|
+
# @return [Virtuaservices::Monitoring::Service] the service in which this route is declared.
|
23
|
+
belongs_to :service, class_name: 'Virtuaservices::Monitoring::Service', inverse_of: :routes
|
24
|
+
|
25
|
+
# @!attribute [rw] groups
|
26
|
+
# @return [Array<Virtuaservices::Permissions::Group>] the groups having permission to access this route.
|
27
|
+
has_and_belongs_to_many :groups, class_name: 'Virtuaservices::Permissions::Group', inverse_of: :groups
|
28
|
+
|
29
|
+
validates :path,
|
30
|
+
format: {with: /\A(\/|((\/:?[a-zA-Z0-9_]+)+))\z/, message: 'pattern', if: :path?}
|
31
|
+
|
32
|
+
validates :verb,
|
33
|
+
inclusion: {message: 'unknown', in: ['get', 'post', 'put', 'delete', 'patch', 'option']}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Monitoring
|
3
|
+
# A service is the representation of one of the applications composing the API.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Service
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include Virtuaservices::Concerns::Activable
|
9
|
+
include Virtuaservices::Concerns::Diagnosticable
|
10
|
+
include Virtuaservices::Concerns::Premiumable
|
11
|
+
|
12
|
+
# @!attribute [rw] key
|
13
|
+
# @return [String] the name, or title of the service, optionally given to identify it more easily.
|
14
|
+
field :key, type: String
|
15
|
+
# @!attribute [rw] path
|
16
|
+
# @return [String] the path the service will be mapped on in the API.
|
17
|
+
field :path, type: String, default: '/'
|
18
|
+
# @!attribute [rw] test_mode
|
19
|
+
# @return [Boolean] TRUE if the service is currently in test mode and thus the gateway shall only qurty local instances.
|
20
|
+
field :test_mode, type: Boolean, default: false
|
21
|
+
|
22
|
+
# @!attribute [rw] creator
|
23
|
+
# @return [Virtuaservices::Account] the creator of this service.
|
24
|
+
belongs_to :creator, class_name: 'Virtuaservices::Account', optional: true, inverse_of: :services
|
25
|
+
# @!attribute [rw] instances
|
26
|
+
# @return [Array<Virtuaservices::Monitoring::Instance>] the instances of this service currently deployed.
|
27
|
+
embeds_many :instances, class_name: 'Virtuaservices::Monitoring::Instance', inverse_of: :service
|
28
|
+
# @!attribute [rw] routes
|
29
|
+
# @return [Array<Virtuaservices::Monitoring::Route>] the routes associated to this service, accessible from the gateway.
|
30
|
+
has_many :routes, class_name: 'Virtuaservices::Monitoring::Route', inverse_of: :service
|
31
|
+
|
32
|
+
validates :key, uniqueness: {message: 'uniq'}
|
33
|
+
|
34
|
+
validates :path, format: {with: /\A(\/:?[a-z]+)+\z/, message: 'pattern'}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Monitoring
|
3
|
+
# The websocket is a particular kind of service, just like the gateway. It always has the same signature.
|
4
|
+
# A websocket document is a particular instance of websocket, located on a server and answering to a URL.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Websocket
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
include Virtuaservices::Concerns::Activable
|
10
|
+
include Virtuaservices::Concerns::Diagnosticable
|
11
|
+
|
12
|
+
# @!attribute [rw] url
|
13
|
+
# @return [String] the URL of the websocket to be contacted on.
|
14
|
+
field :url, type: String
|
15
|
+
|
16
|
+
# @!attribute [rw] creator
|
17
|
+
# @return [Virtuaservices::Account] the account that created this web socket instance in the database.
|
18
|
+
belongs_to :creator, class_name: 'Virtuaservices::Account', inverse_of: :web_sockets, optional: true
|
19
|
+
|
20
|
+
validates :url,
|
21
|
+
presence: {message: 'required'},
|
22
|
+
format: {with: /\A(ws:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?\z/, message: 'pattern', if: :url?}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module OAuth
|
3
|
+
# An application is what is referred to in the OAuth2.0 RFC as a client, wanting to access private informations about the user.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Application
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
|
9
|
+
# @!attribute [rw] name
|
10
|
+
# @return [String] the unique name of the application, mainly used to identify and display it.
|
11
|
+
field :name, type: String
|
12
|
+
# @!attribute [rw] key
|
13
|
+
# @return [String] the unique key for the application, identifying it when requesting a token for the API.
|
14
|
+
field :key, type: String, default: ->{ SecureRandom.hex }
|
15
|
+
# @!attribute [rw] premium
|
16
|
+
# @return [Boolean] a value indicating whether the application should automatically receive a token when an account is created, or not.
|
17
|
+
field :premium, type: Boolean, default: false
|
18
|
+
|
19
|
+
# @!attribute [rw] creator
|
20
|
+
# @return [Virtuaservices::Account] the account that has created this application, considered its owner.
|
21
|
+
belongs_to :creator, class_name: 'Virtuaservices::Account', inverse_of: :applications
|
22
|
+
|
23
|
+
validates :name,
|
24
|
+
presence: {message: 'required'},
|
25
|
+
length: {minimum: 6, message: 'minlength'},
|
26
|
+
uniqueness: {message: 'uniq'}
|
27
|
+
|
28
|
+
validates :key,
|
29
|
+
presence: {message: 'required'},
|
30
|
+
uniqueness: {message: 'uniq'}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
# This module holds the logic for all the classes concerning the permissions abd rights for the user.
|
3
|
+
# A permission is restricting the access to one or several features to the users having it.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Permissions
|
6
|
+
autoload :Right , 'virtuaservices/permissions/right'
|
7
|
+
autoload :Group , 'virtuaservices/permissions/group'
|
8
|
+
autoload :Category, 'virtuaservices/permissions/category'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Permissions
|
3
|
+
# A category of rights regroups one or several rights for convenience purposes.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Category
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include Virtuaservices::Concerns::Sluggable
|
9
|
+
|
10
|
+
has_many :rights, class_name: 'Virtuaservices::Permissions::Right', inverse_of: :category
|
11
|
+
|
12
|
+
make_sluggable 'category'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Permissions
|
3
|
+
# A group gathers one or several users to give them the same rights for conviniency purposes.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Group
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include Virtuaservices::Concerns::Sluggable
|
9
|
+
|
10
|
+
# @!attribute [rw] is_default
|
11
|
+
# @return [Boolean] a boolean indicating whether this group is given when a new user registered or not.
|
12
|
+
field :is_default, type: Boolean, default: false
|
13
|
+
# @!attribute [rw] is_superuser
|
14
|
+
# @return [Boolean] a boolean indicating whether this group should have access to all groups and rights or not.
|
15
|
+
field :is_superuser, type: Boolean, default: false
|
16
|
+
|
17
|
+
# @!attribute [rw] accounts
|
18
|
+
# @return [Array<Virtuaservices::Account>] the accounts having the rights granted by this group.
|
19
|
+
has_and_belongs_to_many :accounts, class_name: 'Virtuaservices::Account', inverse_of: :groups
|
20
|
+
# @!attribute [rw] rights
|
21
|
+
# @return [Array<Virtuaservices::Permissions::Right>] the rights granted by belonging to this group.
|
22
|
+
has_and_belongs_to_many :rights, class_name: 'Virtuaservices::Permissions::Right', inverse_of: :groups
|
23
|
+
# @!attribute [rw] routes
|
24
|
+
# @return [Array<Virtuaservices::Monitoring::Route>] the routes this group can access in the API.
|
25
|
+
has_and_belongs_to_many :routes, class_name: 'Virtuaservices::Monitoring::Route', inverse_of: :groups
|
26
|
+
|
27
|
+
make_sluggable 'group'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
module Permissions
|
3
|
+
# A right is the access to one or several features in the application. It's applied to a group, and transitively to an account.
|
4
|
+
# @author Vincent Courtois <courtois;vincent@outlook.com>
|
5
|
+
class Right
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include Virtuaservices::Concerns::Sluggable
|
9
|
+
|
10
|
+
# @!attribute [rw] groups
|
11
|
+
# @return [Array<Virtuaservices::Permissions::Group>] the groups granted with the permission to access features opened by this right.
|
12
|
+
has_and_belongs_to_many :groups, class_name: 'Virtuaservices::Permissions::Group', inverse_of: :rights
|
13
|
+
|
14
|
+
belongs_to :category, class_name: 'Virtuaservices::Permissions::Category', inverse_of: :rights
|
15
|
+
|
16
|
+
make_sluggable 'right'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
# This module holds all the logic for the specs tools for all micro services (shared examples and other things).
|
3
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
4
|
+
module Specs
|
5
|
+
|
6
|
+
# Includes all the shared examples you could need, describing the basic behaviour of a route.
|
7
|
+
def self.include_shared_examples
|
8
|
+
RSpec.shared_examples 'a route' do |_verb, _path|
|
9
|
+
let(:verb) { _verb }
|
10
|
+
let(:path) { _path }
|
11
|
+
|
12
|
+
def do_request(parameters)
|
13
|
+
public_send verb.to_sym, path, ['get', 'delete'].include?(verb) ? parameters : parameters.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'common errors' do
|
17
|
+
describe 'bad request errors' do
|
18
|
+
describe 'no token error' do
|
19
|
+
before do
|
20
|
+
do_request({app_key: 'test_key'})
|
21
|
+
end
|
22
|
+
it 'Raises a bad request (400) error when the parameters don\'t contain the token of the gateway' do
|
23
|
+
expect(last_response.status).to be 400
|
24
|
+
end
|
25
|
+
it 'returns the correct response if the parameters do not contain a gateway token' do
|
26
|
+
expect(JSON.parse(last_response.body)).to eq({
|
27
|
+
'status' => 400,
|
28
|
+
'field' => 'token',
|
29
|
+
'error' => 'required',
|
30
|
+
'docs' => 'https://github.com/jdr-tools/wiki/wiki/Common-errors#gateway-token-not-given'
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
describe 'no application key error' do
|
35
|
+
before do
|
36
|
+
do_request({token: 'test_token'})
|
37
|
+
end
|
38
|
+
it 'Raises a bad request (400) error when the parameters don\'t contain the application key' do
|
39
|
+
expect(last_response.status).to be 400
|
40
|
+
end
|
41
|
+
it 'returns the correct response if the parameters do not contain a application key' do
|
42
|
+
expect(JSON.parse(last_response.body)).to eq({
|
43
|
+
'status' => 400,
|
44
|
+
'field' => 'app_key',
|
45
|
+
'error' => 'required',
|
46
|
+
'docs' => 'https://github.com/jdr-tools/wiki/wiki/Common-errors#application-key-not-given'
|
47
|
+
})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
describe 'not_found errors' do
|
52
|
+
describe 'application not found' do
|
53
|
+
before do
|
54
|
+
do_request({token: 'test_token', app_key: 'another_key'})
|
55
|
+
end
|
56
|
+
it 'Raises a not found (404) error when the key doesn\'t belong to any application' do
|
57
|
+
expect(last_response.status).to be 404
|
58
|
+
end
|
59
|
+
it 'returns the correct body when the application doesn\'t exist' do
|
60
|
+
expect(JSON.parse(last_response.body)).to eq({
|
61
|
+
'status' => 404,
|
62
|
+
'field' => 'app_key',
|
63
|
+
'error' => 'unknown',
|
64
|
+
'docs' => 'https://github.com/jdr-tools/wiki/wiki/Common-errors#application-key-not-found'
|
65
|
+
})
|
66
|
+
end
|
67
|
+
end
|
68
|
+
describe 'gateway not found' do
|
69
|
+
before do
|
70
|
+
do_request({token: 'other_token', app_key: 'test_key'})
|
71
|
+
end
|
72
|
+
it 'Raises a not found (404) error when the gateway does\'nt exist' do
|
73
|
+
expect(last_response.status).to be 404
|
74
|
+
end
|
75
|
+
it 'returns the correct body when the gateway doesn\'t exist' do
|
76
|
+
expect(JSON.parse(last_response.body)).to eq({
|
77
|
+
'status' => 404,
|
78
|
+
'field' => 'token',
|
79
|
+
'error' => 'unknown',
|
80
|
+
'docs' => 'https://github.com/jdr-tools/wiki/wiki/Common-errors#gateway-token-not-found'
|
81
|
+
})
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Virtuaservices
|
2
|
+
# Utility classes for the different micro-services of the suite.
|
3
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
4
|
+
module Utils
|
5
|
+
autoload :Controllers , 'virtuaservices/utils/controllers'
|
6
|
+
autoload :Errors , 'virtuaservices/utils/errors'
|
7
|
+
autoload :Loaders , 'virtuaservices/utils/loaders'
|
8
|
+
autoload :MicroService, 'virtuaservices/utils/micro_service'
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
module Arkaan
|
2
|
+
module Utils
|
3
|
+
module Controllers
|
4
|
+
# Base controller to handle the standard error when accessing the API.
|
5
|
+
# @author Vincent Courtois <courtois.vincenet@outlook.com>
|
6
|
+
class Base < Sinatra::Base
|
7
|
+
register Sinatra::ConfigFile
|
8
|
+
helpers Sinatra::CustomLogger
|
9
|
+
|
10
|
+
configure do
|
11
|
+
set :logger, Logger.new(STDOUT)
|
12
|
+
logger.level = Logger::ERROR if ENV['RACK_ENV'] == 'test'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Creates a premium route whithin the Sinatra application, and registers it in the database if it does not already exists.
|
16
|
+
# @param verb [String] the HTTP method used to create this route.
|
17
|
+
# @param path [String] the path, beginning with a /, of the route to create.
|
18
|
+
def self.declare_route(verb, path, options: {}, &block)
|
19
|
+
self.declare_route_with(verb, path, false, options, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Creates a non premium route whithin the Sinatra application, and registers it in the database if it does not already exists.
|
23
|
+
# @param verb [String] the HTTP method used to create this route.
|
24
|
+
# @param path [String] the path, beginning with a /, of the route to create.
|
25
|
+
def self.declare_premium_route(verb, path, options: {}, &block)
|
26
|
+
self.declare_route_with(verb, path, true, options, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates a route whithin the Sinatra application, and registers it in the database if it does not already exists.
|
30
|
+
# @param verb [String] the HTTP method used to create this route.
|
31
|
+
# @param path [String] the path, beginning with a /, of the route to create.
|
32
|
+
# @param premium [Boolean] TRUE to make the route premium, FALSE otherwise.
|
33
|
+
def self.declare_route_with(verb, path, premium, options, &block)
|
34
|
+
service = Arkaan::Utils::MicroService.instance.service
|
35
|
+
complete_path = "#{Arkaan::Utils::MicroService.instance.path}#{path == '/' ? '' : path}"
|
36
|
+
|
37
|
+
unless service.nil? || !service.routes.where(path: path, verb: verb).first.nil?
|
38
|
+
route = Arkaan::Monitoring::Route.create(path: path, verb: verb, premium: premium, service: service)
|
39
|
+
if !options.nil? && !options[:authenticated].nil?
|
40
|
+
route.update_attribute(:authenticated, false)
|
41
|
+
end
|
42
|
+
Arkaan::Permissions::Group.where(is_superuser: true).each do |group|
|
43
|
+
group.routes << route
|
44
|
+
group.save!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
if premium
|
48
|
+
self.public_send(verb, complete_path) do
|
49
|
+
@sinatra_route = parse_current_route
|
50
|
+
if !@application.premium?
|
51
|
+
custom_error(403, 'common.app_key.forbidden')
|
52
|
+
end
|
53
|
+
instance_eval(&block)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
logger.info "#{verb} #{complete_path}"
|
57
|
+
self.public_send(verb, complete_path, &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Loads the errors configuration file from the config folder.
|
62
|
+
# @param file [String] send __FILE__
|
63
|
+
def self.load_errors_from(file)
|
64
|
+
config_file File.join(File.dirname(file), '..', 'config', 'errors.yml')
|
65
|
+
end
|
66
|
+
|
67
|
+
def before_checks
|
68
|
+
add_body_to_params
|
69
|
+
|
70
|
+
check_presence('token', 'app_key', route: 'common')
|
71
|
+
|
72
|
+
gateway = Arkaan::Monitoring::Gateway.where(token: params['token']).first
|
73
|
+
@application = Arkaan::OAuth::Application.where(key: params['app_key']).first
|
74
|
+
|
75
|
+
if gateway.nil?
|
76
|
+
custom_error(404, 'common.token.unknown')
|
77
|
+
elsif @application.nil?
|
78
|
+
custom_error(404, 'common.app_key.unknown')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Checks the presence of several fields given as parameters and halts the execution if it's not present.
|
83
|
+
# @param fields [Array<String>] an array of fields names to search in the parameters
|
84
|
+
# @param route [String] the name of the route you're requiring to put in the error message.
|
85
|
+
def check_presence(*fields, route:)
|
86
|
+
fields.each do |field|
|
87
|
+
custom_error(400, "#{route}.#{field}.required") if params[field].nil? || params[field] == ''
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Checks the presence of either fields given in parameters. It halts with an error only if ALL parameters are not given.
|
92
|
+
# @param fields [Array<String>] an array of fields names to search in the parameters
|
93
|
+
# @param route [String] the name of the route you're requiring to put in the error message.
|
94
|
+
# @param key [String] the key to search in the errors configuration file.
|
95
|
+
def check_either_presence(*fields, route:, key:)
|
96
|
+
fields.each do |field|
|
97
|
+
return true if !params[field].nil? && params[field] != ''
|
98
|
+
end
|
99
|
+
custom_error 400, "#{route}.#{key}.required"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Checks if the session ID is given in the parameters and if the session exists.
|
103
|
+
# @param action [String] the action used to get the errors from the errors file.
|
104
|
+
# @return [Arkaan::Authentication::Session] the session when it exists.
|
105
|
+
def check_session(action)
|
106
|
+
check_presence('session_id', route: action)
|
107
|
+
session = Arkaan::Authentication::Session.where(token: params['session_id']).first
|
108
|
+
if session.nil?
|
109
|
+
custom_error(404, "#{action}.session_id.unknown")
|
110
|
+
end
|
111
|
+
return session
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_application(action)
|
115
|
+
check_presence('app_key', route: action)
|
116
|
+
application = Arkaan::OAuth::Application.where(key: params['app_key']).first
|
117
|
+
custom_error(404, "#{action}.app_key.unknown") if application.nil?
|
118
|
+
return application
|
119
|
+
end
|
120
|
+
|
121
|
+
# Adds the parsed body to the parameters, overwriting the parameters of the querystring with the values
|
122
|
+
# of the SON body if they have similar keys.
|
123
|
+
def add_body_to_params
|
124
|
+
if request.body.respond_to?(:rewind) && request.body.respond_to?(:read)
|
125
|
+
request.body.rewind
|
126
|
+
parsed_body = JSON.parse(request.body.read.to_s) rescue {}
|
127
|
+
parsed_body.keys.each do |key|
|
128
|
+
params[key] = parsed_body[key]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Gets the current route in the database from the sinatra route.
|
134
|
+
# @return [Arkaan::Monitoring::Route] the route declared in the services registry.
|
135
|
+
def parse_current_route
|
136
|
+
splitted = request.env['sinatra.route'].split(' ')
|
137
|
+
return Arkaan::Monitoring::Route.where(verb: splitted.first.downcase, path: splitted.last).first
|
138
|
+
end
|
139
|
+
|
140
|
+
# Halts the application and creates the returned body from the parameters and the errors config file.
|
141
|
+
# @param status [Integer] the HTTP status to halt the application with.
|
142
|
+
# @param path [String] the path in the configuration file to access the URL.
|
143
|
+
def custom_error(status, path)
|
144
|
+
route, field, error = path.split('.')
|
145
|
+
docs = settings.errors[route][field][error] rescue ''
|
146
|
+
halt status, {status: status, field: field, error: error, docs: docs}.to_json
|
147
|
+
end
|
148
|
+
|
149
|
+
# Halts the application with a Bad Request error affecting a field of a model.
|
150
|
+
# @param instance [Mongoid::Document] the document having a field in error.
|
151
|
+
# @param route [String] the type of action you're currently doing (e.g: 'creation')
|
152
|
+
def model_error(instance, route)
|
153
|
+
messages = instance.errors.messages
|
154
|
+
field = messages.keys.first
|
155
|
+
custom_error(400, "#{route}.#{field}.#{messages[field].first}")
|
156
|
+
end
|
157
|
+
|
158
|
+
# Select parameters in the params hash, by its keys.
|
159
|
+
# @param fields [Array<String>] the keys to select in the params hash.
|
160
|
+
# @return [Hash] the selected chunk of the params hash.
|
161
|
+
def select_params(*fields)
|
162
|
+
return params.select { |key, value| fields.include?(key) }
|
163
|
+
end
|
164
|
+
|
165
|
+
# Creates a custom error from an existing Arkaan exception class.
|
166
|
+
# @param exception {StandardError} the exception to transform in a usable error.
|
167
|
+
def handle_arkaan_exception(exception)
|
168
|
+
custom_error(exception.status, "#{exception.action}.#{exception.field}.#{exception.error}")
|
169
|
+
end
|
170
|
+
|
171
|
+
error Arkaan::Utils::Errors::BadRequest do |exception|
|
172
|
+
handle_arkaan_exception(exception)
|
173
|
+
end
|
174
|
+
|
175
|
+
error Arkaan::Utils::Errors::Forbidden do |exception|
|
176
|
+
handle_arkaan_exception(exception)
|
177
|
+
end
|
178
|
+
|
179
|
+
error Arkaan::Utils::Errors::NotFound do |exception|
|
180
|
+
handle_arkaan_exception(exception)
|
181
|
+
end
|
182
|
+
|
183
|
+
error Arkaan::Factories::Errors::GatewayNotFound do |exception|
|
184
|
+
handle_arkaan_exception(exception)
|
185
|
+
end
|
186
|
+
|
187
|
+
error StandardError do |exception|
|
188
|
+
custom_error(500, 'system_error.unknown_field.unknown_error')
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|