virtuatable 0.5.0 → 3.2.3
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 +4 -4
- data/lib/virtuatable/api/errors/base.rb +2 -0
- data/lib/virtuatable/api/responses.rb +20 -5
- data/lib/virtuatable/builders/base.rb +15 -20
- data/lib/virtuatable/builders/helpers/environment.rb +6 -2
- data/lib/virtuatable/builders/helpers/folders.rb +1 -0
- data/lib/virtuatable/builders/helpers/mongoid.rb +2 -0
- data/lib/virtuatable/builders/helpers/registration.rb +0 -7
- data/lib/virtuatable/builders/helpers/tests.rb +4 -1
- data/lib/virtuatable/builders/helpers.rb +1 -0
- data/lib/virtuatable/builders/tests.rb +5 -0
- data/lib/virtuatable/controllers/base.rb +22 -3
- data/lib/virtuatable/enhancers/base.rb +56 -0
- data/lib/virtuatable/enhancers/helpers/declarations.rb +34 -0
- data/lib/virtuatable/enhancers/helpers.rb +11 -0
- data/lib/virtuatable/enhancers.rb +13 -0
- data/lib/virtuatable/helpers/accounts.rb +8 -5
- data/lib/virtuatable/helpers/applications.rb +12 -8
- data/lib/virtuatable/helpers/declarators.rb +14 -11
- data/lib/virtuatable/helpers/parameters.rb +29 -0
- data/lib/virtuatable/helpers/routes.rb +3 -0
- data/lib/virtuatable/helpers/sessions.rb +20 -9
- data/lib/virtuatable/helpers.rb +1 -0
- data/lib/virtuatable/specs/factories/accounts.rb +54 -0
- data/lib/virtuatable/specs/factories/applications.rb +48 -0
- data/lib/virtuatable/specs/factories/groups.rb +50 -0
- data/lib/virtuatable/specs/factories/sessions.rb +38 -0
- data/lib/virtuatable/specs/factories.rb +15 -0
- data/lib/virtuatable/specs/shared/controllers.rb +195 -0
- data/lib/virtuatable/specs/shared.rb +11 -0
- data/lib/virtuatable/specs.rb +4 -85
- data/lib/virtuatable.rb +4 -0
- metadata +82 -114
- data/lib/virtuatable/helpers/gateways.rb +0 -23
- data/lib/virtuatable/version.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6aef88eba041258b63ed6c79ce0e3046642e3a8555ffbbabb9e0dfee5f061c2e
|
4
|
+
data.tar.gz: 38abd6f714841c8e0e3984075ac7e2b699f688ccb3760652a0011a07f83b8106
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27c96cc009bc195c21c6dd1f97d9779e7adfb956a76e3e36a497a32e709ebc19c429f23ac1ffa1b2447ac12d848c3eda22ebd70b75a6c1cd79e0ee35754a47bf
|
7
|
+
data.tar.gz: d15814d7745b08a1c2c4eb9b68fe2671c444fbc0f5d805665398953a40786612a09967e137948e828adb79d4d7a04c8e73befbca73830e7ebd881f8e45320ae1
|
@@ -10,10 +10,10 @@ module Virtuatable
|
|
10
10
|
# - :count will hold the number of items displayed in the list
|
11
11
|
# - :items will hold the list of items.
|
12
12
|
# @param items [Array] the items to format as a standard API response.
|
13
|
-
def api_list(items)
|
13
|
+
def api_list(items, mapper = :to_h)
|
14
14
|
halt 200, {
|
15
15
|
count: items.count,
|
16
|
-
items: items.map(
|
16
|
+
items: items.map { |item| enhanced_h(item, mapper.to_sym) }
|
17
17
|
}.to_json
|
18
18
|
end
|
19
19
|
|
@@ -21,19 +21,34 @@ module Virtuatable
|
|
21
21
|
# returning the informations about the created item.
|
22
22
|
# @param item [Object] any object that responds to #to_h to display to the user.
|
23
23
|
def api_created(item)
|
24
|
-
halt 201, item
|
24
|
+
halt 201, enhanced_json(item)
|
25
25
|
end
|
26
26
|
|
27
27
|
# Displays an item with the standards of the API.
|
28
28
|
# @param item [Object] the item to display as a JSON formatted hash.
|
29
29
|
def api_item(item)
|
30
|
-
halt 200, item
|
30
|
+
halt 200, enhanced_json(item)
|
31
31
|
end
|
32
32
|
|
33
33
|
# Displays a message with a 200 status code
|
34
34
|
# @param message [String] the message to display with the API standards.
|
35
35
|
def api_ok(message)
|
36
|
-
api_item
|
36
|
+
api_item message: message
|
37
|
+
end
|
38
|
+
|
39
|
+
# Displays an empty body with a 204 status code
|
40
|
+
def api_empty
|
41
|
+
halt 204, ''
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def enhanced_h(item, mapper = :to_h)
|
47
|
+
(item.respond_to?(:enhance) ? item.enhance : item).send(mapper)
|
48
|
+
end
|
49
|
+
|
50
|
+
def enhanced_json(item)
|
51
|
+
enhanced_h(item).to_json
|
37
52
|
end
|
38
53
|
end
|
39
54
|
end
|
@@ -33,47 +33,42 @@ module Virtuatable
|
|
33
33
|
attr_accessor :name
|
34
34
|
|
35
35
|
# Constructor of the builder, initializing needed attributes.
|
36
|
-
# @param
|
36
|
+
# @param locations [Array<String>] you should not modify this parameter, it
|
37
|
+
# determines from which folder the application is supposed to be loaded.
|
38
|
+
# @param path [String] the path from the loaded directory that leads to
|
39
|
+
# the root of the application (to find all other files and folders)
|
40
|
+
# @param name [String] the name of the loaded service, determining its url.
|
37
41
|
def initialize(locations: caller_locations, path: '.', name:)
|
38
42
|
# The base folder of the file calling the builder
|
39
43
|
filedir = File.dirname(locations.first.absolute_path)
|
40
44
|
@directory = File.absolute_path(File.join(filedir, path))
|
41
|
-
@mode =
|
45
|
+
@mode = (ENV['RACK_ENV'] || 'development').to_sym
|
42
46
|
@name = name.to_s
|
43
47
|
end
|
44
48
|
|
49
|
+
# Main method to load the application. This method is called after creating
|
50
|
+
# a builder in the Virtuatable::Application class.
|
45
51
|
def load!
|
46
52
|
all_loaders.each do |loader|
|
47
53
|
send(:"load_#{loader[:name]}!")
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
51
|
-
# Checks the presence of all the needed environment variables.
|
52
|
-
# @raise [Virtuatable::Builders::Errors::MissingEnv] if a variable is not present,
|
53
|
-
# for a variable to be present she has to be a key of the ENV constant.
|
54
|
-
def check_variables!
|
55
|
-
names = ['INSTANCE_TYPE']
|
56
|
-
names.each do |varname|
|
57
|
-
exception_klass = Virtuatable::Builders::Errors::MissingEnv
|
58
|
-
raise exception_klass.new(variable: varname) unless ENV.key?(varname)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Returns the type of the instance, default being a UNIX server
|
63
|
-
# @return [Symbol] the type of instance currently loading.
|
64
|
-
def type
|
65
|
-
ENV['INSTANCE_TYPE'].nil? ? :unix : ENV['INSTANCE_TYPE'].to_sym
|
66
|
-
end
|
67
|
-
|
68
57
|
# Loads a list of folders given as method parameters
|
69
|
-
# @param
|
58
|
+
# @param folders [Array<String>] the folders names passed as parameters.
|
70
59
|
def require_folders(*folders)
|
71
60
|
folders.each do |folder|
|
61
|
+
base_path = File.join('.', folder, 'base.rb')
|
62
|
+
require base_path if File.exist?(base_path)
|
72
63
|
path = File.join(directory, folder)
|
73
64
|
require_all(path) if File.directory?(path)
|
74
65
|
end
|
75
66
|
end
|
76
67
|
|
68
|
+
# Returns the ancestors of this class without the included modules.
|
69
|
+
# Ruby puts the included modules in the ancestors and we don't want to
|
70
|
+
# search for the loaders in it as we know it won't be there.
|
71
|
+
# @return [Array<Class>] the ancestors of the class without included modules.
|
77
72
|
def sanitized_ancestors
|
78
73
|
self.class.ancestors - self.class.included_modules
|
79
74
|
end
|
@@ -12,9 +12,13 @@ module Virtuatable
|
|
12
12
|
declare_loader(:environment, priority: 0)
|
13
13
|
end
|
14
14
|
|
15
|
+
# Loads the environment variables used in the application.
|
15
16
|
def load_environment!
|
16
|
-
Dotenv.load(
|
17
|
-
|
17
|
+
Dotenv.load(env_file, env_file(mode))
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_file(name = '')
|
21
|
+
File.join(directory, "#{name}.env")
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
@@ -12,8 +12,10 @@ module Virtuatable
|
|
12
12
|
declare_loader(:mongoid, priority: 1)
|
13
13
|
end
|
14
14
|
|
15
|
+
# Loads Mongoid configuration file from the standard path.
|
15
16
|
def load_mongoid!
|
16
17
|
filepath = File.join(@directory, 'config', 'mongoid.yml')
|
18
|
+
filepath = File.readlink(filepath) while File.symlink?(filepath)
|
17
19
|
::Mongoid.load!(filepath, @mode)
|
18
20
|
end
|
19
21
|
end
|
@@ -12,9 +12,6 @@ module Virtuatable
|
|
12
12
|
# @!attribute [r] service
|
13
13
|
# @return [Arkaan::Monitoring::Service] the service linked to this application.
|
14
14
|
attr_reader :service
|
15
|
-
# @!attribute [r] instance
|
16
|
-
# @return [Arkaan::Monitoring::Instance] the instance of this application.
|
17
|
-
attr_reader :instance
|
18
15
|
|
19
16
|
included do
|
20
17
|
declare_loader(:registration, priority: 2)
|
@@ -27,10 +24,6 @@ module Virtuatable
|
|
27
24
|
key: @name,
|
28
25
|
path: "/#{@name}"
|
29
26
|
)
|
30
|
-
@instance = service.instances.first_or_create!(
|
31
|
-
type: type,
|
32
|
-
url: ENV['SERVICE_URL']
|
33
|
-
)
|
34
27
|
end
|
35
28
|
end
|
36
29
|
end
|
@@ -9,9 +9,12 @@ module Virtuatable
|
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
11
11
|
included do
|
12
|
-
declare_loader(:tests, priority:
|
12
|
+
declare_loader(:tests, priority: 5)
|
13
13
|
end
|
14
14
|
|
15
|
+
# Loads the folders containing files related to the tests.
|
16
|
+
# - spec/support contains files used to confiture each test module
|
17
|
+
# - spec/shared contain all rspec shared examples and contexts
|
15
18
|
def load_tests!
|
16
19
|
require_folders('spec/support', 'spec/shared')
|
17
20
|
end
|
@@ -11,6 +11,7 @@ module Virtuatable
|
|
11
11
|
autoload :Loaders, 'virtuatable/builders/helpers/loaders'
|
12
12
|
autoload :Mongoid, 'virtuatable/builders/helpers/mongoid'
|
13
13
|
autoload :Registration, 'virtuatable/builders/helpers/registration'
|
14
|
+
autoload :Specs, 'virtuatable/builders/helpers/specs'
|
14
15
|
autoload :Tests, 'virtuatable/builders/helpers/tests'
|
15
16
|
end
|
16
17
|
end
|
@@ -7,6 +7,11 @@ module Virtuatable
|
|
7
7
|
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
8
8
|
class Tests < Virtuatable::Builders::Base
|
9
9
|
include Virtuatable::Builders::Helpers::Tests
|
10
|
+
include Virtuatable::Specs::Factories::Accounts
|
11
|
+
include Virtuatable::Specs::Factories::Applications
|
12
|
+
include Virtuatable::Specs::Factories::Groups
|
13
|
+
include Virtuatable::Specs::Factories::Sessions
|
14
|
+
include Virtuatable::Specs::Shared::Controllers
|
10
15
|
|
11
16
|
def initialize(path: '..', name:, locations: caller_locations)
|
12
17
|
super(locations: locations, path: path, name: name)
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'sinatra/config_file'
|
4
|
+
require 'sinatra/custom_logger'
|
5
|
+
|
3
6
|
module Virtuatable
|
4
7
|
module Controllers
|
5
8
|
# This class represents a base controller for the system, giving access
|
@@ -13,8 +16,6 @@ module Virtuatable
|
|
13
16
|
include Virtuatable::API::Responses
|
14
17
|
# Includes the checking methods for sessions.
|
15
18
|
include Virtuatable::Helpers::Sessions
|
16
|
-
# Include the checkers and getters for the API gateway.
|
17
|
-
include Virtuatable::Helpers::Gateways
|
18
19
|
# Include the checkers and getters for OAuth apps
|
19
20
|
include Virtuatable::Helpers::Applications
|
20
21
|
# Include checkers for field requirement and check
|
@@ -23,10 +24,16 @@ module Virtuatable
|
|
23
24
|
include Virtuatable::Helpers::Routes
|
24
25
|
# Include the getter and checkers for accounts.
|
25
26
|
include Virtuatable::Helpers::Accounts
|
27
|
+
# Include the loading of the parameters from the JSON body
|
28
|
+
include Virtuatable::Helpers::Parameters
|
26
29
|
# This module is extended, not included, because it provides routes
|
27
30
|
# declaration methods used in class declarations.
|
28
31
|
extend Virtuatable::Helpers::Declarators
|
29
32
|
|
33
|
+
def service
|
34
|
+
Virtuatable::Application.instance.builder.service
|
35
|
+
end
|
36
|
+
|
30
37
|
configure do
|
31
38
|
set :logger, Logger.new(STDOUT)
|
32
39
|
logger.level = Logger::ERROR if ENV['RACK_ENV'] == 'test'
|
@@ -36,7 +43,19 @@ module Virtuatable
|
|
36
43
|
end
|
37
44
|
|
38
45
|
error Mongoid::Errors::Validations do |errors|
|
39
|
-
|
46
|
+
key = errors.document.errors.messages.keys.first
|
47
|
+
message = errors.document.errors.messages[key][0]
|
48
|
+
api_bad_request key, message: message
|
49
|
+
end
|
50
|
+
|
51
|
+
error Mongoid::Errors::DocumentNotFound do |exception|
|
52
|
+
# If it's an array, it's IDs that have not been found, else it's
|
53
|
+
# another attribute given as key of the hash.
|
54
|
+
if exception.params.is_a? Array
|
55
|
+
api_not_found 'id.unknown'
|
56
|
+
else
|
57
|
+
api_not_found "#{exception.params.keys.first}.unknown"
|
58
|
+
end
|
40
59
|
end
|
41
60
|
|
42
61
|
error Virtuatable::API::Errors::NotFound do |exception|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
module Enhancers
|
5
|
+
# Base class to be extended by all enhancers. It provides a way to declare
|
6
|
+
# this class as the enhancer of another class, to access the properties
|
7
|
+
# of the enhanced class as instance attributes.
|
8
|
+
#
|
9
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
10
|
+
class Base
|
11
|
+
extend Virtuatable::Enhancers::Helpers::Declarations
|
12
|
+
|
13
|
+
# @!attribute [r] object
|
14
|
+
# @return [Object] the enhanced object.
|
15
|
+
attr_reader :object
|
16
|
+
|
17
|
+
def initialize(object)
|
18
|
+
@object = object
|
19
|
+
end
|
20
|
+
|
21
|
+
# That's the heart of the enhancers mecanism. This method sends the call
|
22
|
+
# to the decorated object if this one can answer it, or raises an error.
|
23
|
+
# @param name [String, Symbol] the name of the method to call on the decorated object.
|
24
|
+
# @param args [Array] the arguments passed during the call to the function.
|
25
|
+
# @param block [Block] the optional blockcode passed to the function.
|
26
|
+
def method_missing(name, *args, &block)
|
27
|
+
return enhance_association(name) if object.respond_to?(:associations) && object.associations.key?(name)
|
28
|
+
|
29
|
+
object.respond_to?(name) ? object.send(name, *args, &block) : super
|
30
|
+
end
|
31
|
+
|
32
|
+
# Determines if this object can transfer any of its calls to the decorated object.
|
33
|
+
# @param name [String] the name of the called function.
|
34
|
+
# @return [Boolean] TRUE if the decorated object can answer the call, FALSE otherwise.
|
35
|
+
def respond_to_missing?(name, _include_private = false)
|
36
|
+
object.respond_to? name
|
37
|
+
end
|
38
|
+
|
39
|
+
def enhance_association(name)
|
40
|
+
elements = object.send(name.to_sym)
|
41
|
+
return nil if elements.nil?
|
42
|
+
return enhance_collection(name, elements) if elements.is_a?(Enumerable)
|
43
|
+
return elements.enhance if elements.respond_to?(:enhance)
|
44
|
+
|
45
|
+
Virtuatable::Enhancers::Base.new(elements)
|
46
|
+
end
|
47
|
+
|
48
|
+
def enhance_collection(name, collection)
|
49
|
+
enhancable = object.associations[name].klass.respond_to?(:enhancer)
|
50
|
+
return collection.map(&:enhance) if enhancable
|
51
|
+
|
52
|
+
collection.map { |item| Virtuatable::Enhancers::Base.new(item) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
module Enhancers
|
5
|
+
module Helpers
|
6
|
+
# This module holds the static methods to declare an enhancer
|
7
|
+
# in another class, linking both and allowing to automatically
|
8
|
+
# create enhanced instances by calling the same methods in the
|
9
|
+
# enhancer that one would call on the enhanced class.
|
10
|
+
#
|
11
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
12
|
+
module Declarations
|
13
|
+
# @!attribute [r] enhanced
|
14
|
+
# @return [Class] the class object of the enhanced object type.
|
15
|
+
attr_reader :enhanced
|
16
|
+
|
17
|
+
# Enhances the given class by declaring itself as its enhancer.
|
18
|
+
# @param class_object [Class] the class to enhance.
|
19
|
+
def enhances(class_object)
|
20
|
+
@enhanced = class_object
|
21
|
+
self_class = self
|
22
|
+
class_object.singleton_class.class_eval do
|
23
|
+
define_method :enhancer do
|
24
|
+
self_class
|
25
|
+
end
|
26
|
+
end
|
27
|
+
class_object.define_method :enhance do
|
28
|
+
self_class.new(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
module Enhancers
|
5
|
+
# Helpers hold the secondary modules extended or included in the base enhancer.
|
6
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
|
+
module Helpers
|
8
|
+
autoload :Declarations, 'virtuatable/enhancers/helpers/declarations'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
# The enhancers are the equivalent of a decorator.
|
5
|
+
# It provides a simple system to add features to a class
|
6
|
+
# without reopening or altering the said class.
|
7
|
+
#
|
8
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
9
|
+
module Enhancers
|
10
|
+
autoload :Base, 'virtuatable/enhancers/base'
|
11
|
+
autoload :Helpers, 'virtuatable/enhancers/helpers'
|
12
|
+
end
|
13
|
+
end
|
@@ -5,14 +5,17 @@ module Virtuatable
|
|
5
5
|
# These helpers provide methods used to get and check accounts.
|
6
6
|
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
7
|
module Accounts
|
8
|
-
#
|
9
|
-
# @
|
8
|
+
# Raises a bad request error if the account if not found.
|
9
|
+
# @raise [Virtuatable::API::Errors::BadRequest] the error raised when the account is not found.
|
10
10
|
def account
|
11
|
-
|
11
|
+
return @account unless @account.nil?
|
12
|
+
|
13
|
+
session_id_required if !respond_to?(:session) || session.nil?
|
14
|
+
@account = session.account
|
12
15
|
end
|
13
16
|
|
14
|
-
def
|
15
|
-
api_bad_request
|
17
|
+
def account_id_not_found
|
18
|
+
api_bad_request('session_id.required')
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -5,17 +5,21 @@ module Virtuatable
|
|
5
5
|
# Helpers to get and check OAuth applications connecting the the application.
|
6
6
|
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
7
|
module Applications
|
8
|
-
def application
|
9
|
-
Arkaan::OAuth::Application.where(key: params['app_key']).first
|
10
|
-
end
|
11
|
-
|
12
8
|
# Looks for the application sending the API's request, and raises error if not found.
|
13
|
-
|
9
|
+
# @param [Arkaan::OAuth::Application] the application requesting the service.
|
10
|
+
def application(premium: false)
|
11
|
+
return @application unless @application.nil?
|
12
|
+
|
14
13
|
check_presence 'app_key'
|
15
|
-
|
16
|
-
|
14
|
+
@application = application_model.find_by(app_key: params['app_key'])
|
15
|
+
api_not_found 'app_key.unknown' if @application.nil?
|
16
|
+
api_forbidden 'app_key.forbidden' if premium && !@application.premium
|
17
|
+
|
18
|
+
@application
|
19
|
+
end
|
17
20
|
|
18
|
-
|
21
|
+
def application_model
|
22
|
+
Arkaan::OAuth::Application
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -22,10 +22,10 @@ module Virtuatable
|
|
22
22
|
|
23
23
|
# TODO : do everything in the #send itself to avoid
|
24
24
|
# route reload issues when premium is changed. It will
|
25
|
-
# add some treatments but avoid many problems
|
25
|
+
# add some treatments but avoid many problems if route.premium
|
26
26
|
send(route.verb, route.path) do
|
27
|
-
application
|
28
|
-
session
|
27
|
+
application(premium: current_route.premium)
|
28
|
+
session if current_route.authenticated
|
29
29
|
instance_eval(&block)
|
30
30
|
end
|
31
31
|
end
|
@@ -36,7 +36,7 @@ module Virtuatable
|
|
36
36
|
# @return [Arkaan::Monitoring::Route] the created route.
|
37
37
|
def add_route(verb:, path:, options:)
|
38
38
|
route = Arkaan::Monitoring::Route.find_or_create_by!(
|
39
|
-
path:
|
39
|
+
path: path,
|
40
40
|
verb: verb.downcase,
|
41
41
|
premium: options[:premium],
|
42
42
|
service: builder.service,
|
@@ -55,14 +55,17 @@ module Virtuatable
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
+
# Add the default access permissions to a route. Any group tagged superuser
|
59
|
+
# can automatically access any newly declared_route.
|
60
|
+
# params route [Arkaan::Monitoring::Route] the route to add the permissions to.
|
58
61
|
def add_permissions(route)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
groups = Arkaan::Permissions::Group.where(is_superuser: true)
|
63
|
+
groups.each do |group|
|
64
|
+
unless route.groups.where(id: group.id).exists?
|
65
|
+
route.groups << group
|
66
|
+
route.save!
|
67
|
+
end
|
68
|
+
end
|
66
69
|
end
|
67
70
|
|
68
71
|
# Returns the current builder loading the application.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
module Helpers
|
5
|
+
# Helpers to correctly build the parameters hash, even from the JSON body.
|
6
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
|
+
module Parameters
|
8
|
+
# Returns the parameters depending on whether the request has a body
|
9
|
+
# or not. If it has a body, it parses it, otherwise it just returns the params.
|
10
|
+
# @return [Hash] the parameters sent with the request.
|
11
|
+
def params(*subset)
|
12
|
+
all_params = super.merge(body_params)
|
13
|
+
# If we don't want a subset of the parameters, return it all.
|
14
|
+
return all_params if subset.empty?
|
15
|
+
|
16
|
+
all_params.select { |key, _| subset.map(&:to_s).include? key }
|
17
|
+
end
|
18
|
+
|
19
|
+
# The parameters from the JSON body if it is sent.
|
20
|
+
# @return [Hash] the JSON body parsed as a dictionary.
|
21
|
+
def body_params
|
22
|
+
request.body.rewind
|
23
|
+
JSON.parse(request.body.read.to_s)
|
24
|
+
rescue JSON::ParserError
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -6,6 +6,9 @@ module Virtuatable
|
|
6
6
|
# Arkaan::Monitoring::Route object from whithin sinatra routes.
|
7
7
|
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
8
8
|
module Routes
|
9
|
+
# The currently requested API route, used to see inside the block
|
10
|
+
# if the route is premium or not, authenticated or not.
|
11
|
+
# @return [Arkaan::Monitoring::Route] the currently requested route.
|
9
12
|
def current_route
|
10
13
|
splitted = request.env['sinatra.route'].split(' ')
|
11
14
|
verb = splitted.first.downcase
|
@@ -5,12 +5,6 @@ module Virtuatable
|
|
5
5
|
# This helper gives access to methods about user's session on the API.
|
6
6
|
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
7
|
module Sessions
|
8
|
-
# Returns the session of the user requesting the API.
|
9
|
-
# @return [Arkaan::Authentication::Session] the session of the requester.
|
10
|
-
def session
|
11
|
-
Arkaan::Authentication::Session.where(token: params['session_id']).first
|
12
|
-
end
|
13
|
-
|
14
8
|
# Checks the session of the user requesting the API and returns an error
|
15
9
|
# if it either not exists with the given token, or the token is not given.
|
16
10
|
#
|
@@ -18,11 +12,28 @@ module Virtuatable
|
|
18
12
|
# or the token not given in the parameters of the request.
|
19
13
|
# @raise [Virtuatable::API::Errors::BadRequest] if the session token is
|
20
14
|
# not correctly given in the parameters.
|
21
|
-
|
15
|
+
#
|
16
|
+
# @return [Arkaan::Authentication::Session] the current session of the user.
|
17
|
+
def session
|
18
|
+
return @session unless @session.nil?
|
19
|
+
|
22
20
|
check_presence 'session_id'
|
23
|
-
|
21
|
+
@session = session_model.find_by(session_id: params['session_id'])
|
22
|
+
return api_not_found('session_id.unknown') if @session.nil?
|
23
|
+
|
24
|
+
check_current_route_access @session
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_current_route_access(tmp_session)
|
28
|
+
tmp_session.account.groups.each do |group|
|
29
|
+
routes_ids = group.routes.map(&:_id)
|
30
|
+
return tmp_session if routes_ids.include?(current_route.id)
|
31
|
+
end
|
32
|
+
api_forbidden('session_id.forbidden')
|
33
|
+
end
|
24
34
|
|
25
|
-
|
35
|
+
def session_model
|
36
|
+
Arkaan::Authentication::Session
|
26
37
|
end
|
27
38
|
end
|
28
39
|
end
|
data/lib/virtuatable/helpers.rb
CHANGED
@@ -10,6 +10,7 @@ module Virtuatable
|
|
10
10
|
autoload :Declarators, 'virtuatable/helpers/declarators'
|
11
11
|
autoload :Fields, 'virtuatable/helpers/fields'
|
12
12
|
autoload :Gateways, 'virtuatable/helpers/gateways'
|
13
|
+
autoload :Parameters, 'virtuatable/helpers/parameters'
|
13
14
|
autoload :Routes, 'virtuatable/helpers/routes'
|
14
15
|
autoload :Sessions, 'virtuatable/helpers/sessions'
|
15
16
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Virtuatable
|
4
|
+
module Specs
|
5
|
+
module Factories
|
6
|
+
# This module creates the factories concerning accounts, with or
|
7
|
+
# without rights, and with random values for each field.
|
8
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
9
|
+
module Accounts
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
declare_loader :accounts_factory, priority: 5
|
14
|
+
end
|
15
|
+
|
16
|
+
# rubocop:disable Metrics/MethodLength
|
17
|
+
def load_accounts_factory!
|
18
|
+
# This avoids multiple re-declarations by setting a flag.
|
19
|
+
return if self.class.class_variable_defined?(:@@accounts_declared)
|
20
|
+
|
21
|
+
FactoryBot.define do
|
22
|
+
factory :vt_empty_account, class: Arkaan::Account do
|
23
|
+
# Creates a random account with no particular right. This
|
24
|
+
# is useful to see when a user is NOT authorized to access
|
25
|
+
# a resource. Add groups to access resources.
|
26
|
+
factory :random_account do
|
27
|
+
username do
|
28
|
+
Faker::Alphanumeric.unique.alphanumeric(
|
29
|
+
number: 16,
|
30
|
+
min_alpha: 16
|
31
|
+
)
|
32
|
+
end
|
33
|
+
password { 'super_secure_pwd' }
|
34
|
+
password_confirmation { 'super_secure_pwd' }
|
35
|
+
email { Faker::Internet.unique.safe_email }
|
36
|
+
|
37
|
+
# This creates an administrator as "a user with access to
|
38
|
+
# all the routes in a group". This is NOT a superuser.
|
39
|
+
factory :random_administrator do
|
40
|
+
groups { [association(:random_admin_group)] }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# rubocop:disable Style/ClassVars
|
47
|
+
@@accounts_declared = true
|
48
|
+
# rubocop:enable Style/ClassVars
|
49
|
+
end
|
50
|
+
# rubocop:enable Metrics/MethodLength
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|