virtuatable 0.5.0 → 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/virtuatable/api/errors/base.rb +2 -0
  3. data/lib/virtuatable/api/responses.rb +20 -5
  4. data/lib/virtuatable/builders/base.rb +15 -20
  5. data/lib/virtuatable/builders/helpers/environment.rb +6 -2
  6. data/lib/virtuatable/builders/helpers/folders.rb +1 -0
  7. data/lib/virtuatable/builders/helpers/mongoid.rb +2 -0
  8. data/lib/virtuatable/builders/helpers/registration.rb +0 -7
  9. data/lib/virtuatable/builders/helpers/tests.rb +4 -1
  10. data/lib/virtuatable/builders/helpers.rb +1 -0
  11. data/lib/virtuatable/builders/tests.rb +5 -0
  12. data/lib/virtuatable/controllers/base.rb +22 -3
  13. data/lib/virtuatable/enhancers/base.rb +56 -0
  14. data/lib/virtuatable/enhancers/helpers/declarations.rb +34 -0
  15. data/lib/virtuatable/enhancers/helpers.rb +11 -0
  16. data/lib/virtuatable/enhancers.rb +13 -0
  17. data/lib/virtuatable/helpers/accounts.rb +8 -5
  18. data/lib/virtuatable/helpers/applications.rb +12 -8
  19. data/lib/virtuatable/helpers/declarators.rb +14 -11
  20. data/lib/virtuatable/helpers/parameters.rb +29 -0
  21. data/lib/virtuatable/helpers/routes.rb +3 -0
  22. data/lib/virtuatable/helpers/sessions.rb +20 -9
  23. data/lib/virtuatable/helpers.rb +1 -0
  24. data/lib/virtuatable/specs/factories/accounts.rb +54 -0
  25. data/lib/virtuatable/specs/factories/applications.rb +48 -0
  26. data/lib/virtuatable/specs/factories/groups.rb +50 -0
  27. data/lib/virtuatable/specs/factories/sessions.rb +38 -0
  28. data/lib/virtuatable/specs/factories.rb +15 -0
  29. data/lib/virtuatable/specs/shared/controllers.rb +195 -0
  30. data/lib/virtuatable/specs/shared.rb +11 -0
  31. data/lib/virtuatable/specs.rb +4 -85
  32. data/lib/virtuatable.rb +4 -0
  33. metadata +82 -114
  34. data/lib/virtuatable/helpers/gateways.rb +0 -23
  35. data/lib/virtuatable/version.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 514569bd58f7fea17204a3f89f5d0404286204311430bfe72c9d54e4c5c40886
4
- data.tar.gz: 53c6187ab3c547bf9ce3ab5213db35606626cbc374eddc7ac65b6eef6e9361db
3
+ metadata.gz: 6aef88eba041258b63ed6c79ce0e3046642e3a8555ffbbabb9e0dfee5f061c2e
4
+ data.tar.gz: 38abd6f714841c8e0e3984075ac7e2b699f688ccb3760652a0011a07f83b8106
5
5
  SHA512:
6
- metadata.gz: 2d4890c76a8ee25542c82a16c77bbb5b17e289f6c7ce2c4d2d5b1a3a3e91469f66f3db60f58dc35115dd76eba3713077f3b4e0a9b2758bc7a73aa3497c6a0a8c
7
- data.tar.gz: 160aadc26b64faf46c7c3cb62a127db92b31888a5acea04497eaae1911c684a4848405c233af1517d9a67e0a56e37df2035c6c8b383dc42b5866329adc49e850
6
+ metadata.gz: 27c96cc009bc195c21c6dd1f97d9779e7adfb956a76e3e36a497a32e709ebc19c429f23ac1ffa1b2447ac12d848c3eda22ebd70b75a6c1cd79e0ee35754a47bf
7
+ data.tar.gz: d15814d7745b08a1c2c4eb9b68fe2671c444fbc0f5d805665398953a40786612a09967e137948e828adb79d4d7a04c8e73befbca73830e7ebd881f8e45320ae1
@@ -25,6 +25,8 @@ module Virtuatable
25
25
  @status = status
26
26
  end
27
27
 
28
+ # Returns the formatted message for this exception.
29
+ # @return [String] a message indicating what field fails, and why.
28
30
  def message
29
31
  "#{field}.#{error}"
30
32
  end
@@ -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(&:to_h)
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.to_h.to_json
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.to_h.to_json
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({message: message})
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 directory [String] the directory from which load the application.
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 = :development
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 *folders [Array<String>] the folders names passed as parameters.
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('.env', "#{mode}.env")
17
- Virtuatable::Specs.include_shared_examples
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
@@ -13,6 +13,7 @@ module Virtuatable
13
13
  declare_loader(:folders, priority: 3)
14
14
  end
15
15
 
16
+ # Requires the main folders to run the application.
16
17
  def load_folders!
17
18
  require_folders('controllers', 'services', 'decorators')
18
19
  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: 4)
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
- api_bad_request errors.document.errors.messages.keys.first
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
- # Gets the account linked to the current session.
9
- # @return [Arkaan::Account] the account linked to the current session.
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
- !respond_to?(:session) || session.nil? ? nil : session.account
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 account!
15
- api_bad_request 'session_id.required' if account.nil?
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
- def application!(premium: false)
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
- api_not_found 'app_key.unknown' if application.nil?
16
- api_forbidden 'app_key.forbidden' if premium && !application.premium
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
- application
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 if route.premium
25
+ # add some treatments but avoid many problems if route.premium
26
26
  send(route.verb, route.path) do
27
- application!(premium: current_route.premium) && gateway!
28
- session! if current_route.authenticated
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: complete_path(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
- route.groups = Arkaan::Permissions::Group.where(is_superuser: true)
60
- route.save!
61
- route
62
- end
63
-
64
- def complete_path(path)
65
- "#{builder.service.path}#{path == '/' ? '' : path}"
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
- def session!
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
- api_not_found 'session_id.unknown' if session.nil?
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
- session
35
+ def session_model
36
+ Arkaan::Authentication::Session
26
37
  end
27
38
  end
28
39
  end
@@ -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