virtuatable 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/lib/virtuatable/api/errors/bad_request.rb +15 -0
  3. data/lib/virtuatable/api/errors/base.rb +34 -0
  4. data/lib/virtuatable/api/errors/forbidden.rb +15 -0
  5. data/lib/virtuatable/api/errors/not_found.rb +15 -0
  6. data/lib/virtuatable/api/errors.rb +48 -0
  7. data/lib/virtuatable/api.rb +10 -0
  8. data/lib/virtuatable/application.rb +46 -0
  9. data/lib/virtuatable/builders/base.rb +95 -0
  10. data/lib/virtuatable/builders/errors/missing_env.rb +19 -0
  11. data/lib/virtuatable/builders/errors.rb +11 -0
  12. data/lib/virtuatable/builders/helpers/controllers.rb +24 -0
  13. data/lib/virtuatable/builders/helpers/environment.rb +21 -0
  14. data/lib/virtuatable/builders/helpers/folders.rb +22 -0
  15. data/lib/virtuatable/builders/helpers/loaders.rb +22 -0
  16. data/lib/virtuatable/builders/helpers/mongoid.rb +22 -0
  17. data/lib/virtuatable/builders/helpers/registration.rb +38 -0
  18. data/lib/virtuatable/builders/helpers/tests.rb +21 -0
  19. data/lib/virtuatable/builders/helpers.rb +17 -0
  20. data/lib/virtuatable/builders/tests.rb +17 -0
  21. data/lib/virtuatable/builders.rb +13 -0
  22. data/lib/virtuatable/controllers/base.rb +60 -0
  23. data/lib/virtuatable/controllers.rb +9 -0
  24. data/lib/virtuatable/helpers/accounts.rb +19 -0
  25. data/lib/virtuatable/helpers/applications.rb +22 -0
  26. data/lib/virtuatable/helpers/declarators.rb +87 -0
  27. data/lib/virtuatable/helpers/fields.rb +35 -0
  28. data/lib/virtuatable/helpers/gateways.rb +23 -0
  29. data/lib/virtuatable/helpers/routes.rb +11 -0
  30. data/lib/virtuatable/helpers/sessions.rb +29 -0
  31. data/lib/virtuatable/helpers.rb +16 -0
  32. data/lib/virtuatable/version.rb +5 -0
  33. data/lib/virtuatable.rb +12 -0
  34. metadata +411 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 664caa63ef674481d52d3e64d130b8d77d84b17d056bf67a83bdebaf8080b242
4
+ data.tar.gz: 561d5e41f63903e40b6aa6475f4ca02adcc21f72e83e5d05bced1455032798d2
5
+ SHA512:
6
+ metadata.gz: f3922bbe8ef2e8028bf038325230de839cfc72ed5ad55cb8a939ae8998cfbe76914efc15e824c7ae6088d07363502632562afc976b70417e0231e4620ecebc53
7
+ data.tar.gz: 17f71d7877daf35d1451dfa2057231686751a40f4843aa48b227175a75689a7c7c7342e521c034ed364814d5427fd6080d3f96aebfec21e069eb2bebbe6914d6
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module API
5
+ module Errors
6
+ # A bad request error is raised when the data given to a model makes this model invalid.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class BadRequest < Virtuatable::API::Errors::Base
9
+ def initialize(field:, error:)
10
+ super(field: field, error: error, status: 400)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module API
5
+ module Errors
6
+ # Standard class parent to all specialized http errors.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class Base < StandardError
9
+ # @!attribute [rw] field
10
+ # @return [String, Symbol] the name of the field in error in the model.
11
+ attr_accessor :field
12
+ # @!attribute [rw] action
13
+ # @return [String] the name of the action the user was trying to perform on the model (often crate or update).
14
+ attr_accessor :action
15
+ # @attribute [rw] error
16
+ # @return [String] the label of the error returned by the model.
17
+ attr_accessor :error
18
+ # @attribute [rw] status
19
+ # @return [Integer] the HTTP status code as a number (eg: 400, 422 or 500)
20
+ attr_accessor :status
21
+
22
+ def initialize(field:, error:, status:)
23
+ @field = field.to_s
24
+ @error = error
25
+ @status = status
26
+ end
27
+
28
+ def message
29
+ "#{field}.#{error}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module API
5
+ module Errors
6
+ # A forbidden error occurs when a user tries to perform an action he's not allowed to.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class Forbidden < Virtuatable::API::Errors::Base
9
+ def initialize(field:, error:)
10
+ super(field: field, error: error, status: 403)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module API
5
+ module Errors
6
+ # A not found error occurs when a user tries to reach a resource that does not exist.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class NotFound < Virtuatable::API::Errors::Base
9
+ def initialize(field:, error:)
10
+ super(field: field, error: error, status: 404)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module API
5
+ # This module defines method to raise HTTP errors in the routes easily.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Errors
8
+ autoload :Base, 'virtuatable/api/errors/base'
9
+ autoload :BadRequest, 'virtuatable/api/errors/bad_request'
10
+ autoload :Forbidden, 'virtuatable/api/errors/forbidden'
11
+ autoload :NotFound, 'virtuatable/api/errors/not_found'
12
+
13
+ # Stops the executing and raises an HTTP error in the route.
14
+ # The message MUST be of the for <field>.<error> to be correctly parsed.
15
+ # The action is automatically parsed from the route call and added.
16
+ #
17
+ # @param status [Integer] the HTTP status code the response will have
18
+ # @param message [String] the raw message to split and format as body.
19
+ def api_error(status, message)
20
+ field, error = message.split('.')
21
+ docs = settings.errors.try(field).try(error)
22
+ errors = { status: status, field: field, error: error, docs: docs }
23
+ halt status, errors.to_json
24
+ end
25
+
26
+ # Stops the execution to return a NOT FOUND response.
27
+ # @param field [String] the field in params concerned by the error.
28
+ # @param message [String] the message if different of "unknown".
29
+ def api_not_found(field, message: 'unknown')
30
+ api_error 404, "#{field}.#{message}"
31
+ end
32
+
33
+ # Stops the execution to return a BAD REQUEST response.
34
+ # @param field [String] the field in params concerned by the error.
35
+ # @param message [String] the message if different of "required".
36
+ def api_bad_request(field, message: 'required')
37
+ api_error 400, "#{field}.#{message}"
38
+ end
39
+
40
+ # Stops the execution to return a FORBIDDEN response.
41
+ # @param field [String] the field in params concerned by the error.
42
+ # @param message [String] the message if different of "forbidden".
43
+ def api_forbidden(field, message: 'forbidden')
44
+ api_error 403, "#{field}.#{message}"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # The API module gathers all classes called inside a route, for
5
+ # example the errors thrown from the routes as HTTP status.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module API
8
+ autoload :Errors, 'virtuatable/api/errors'
9
+ end
10
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # Wrapping class to easily create builders.
5
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
6
+ class Application
7
+ include Singleton
8
+
9
+ # @!attribute [rw] builder
10
+ # @return [Virtuatable::Builders::Base] the base builder for the application.
11
+ attr_accessor :builder
12
+
13
+ # Loads the application in normal mode, call this from a config.ru file to
14
+ # load the environment, configuration, and require the necessary files.
15
+ # @param name [String] the name of the service you're loading.
16
+ def self.load!(name, locations: caller_locations, path: '.')
17
+ builder = Virtuatable::Builders::Base.new(
18
+ locations: locations,
19
+ path: path,
20
+ name: name
21
+ )
22
+ self.instance.builder = builder
23
+ builder.load!
24
+ builder
25
+ end
26
+
27
+ # Loads the application from a spec/spec_helper to load the specs.
28
+ # @param name [String] the name of the service to load the specs of.
29
+ def self.load_tests!(name, locations: caller_locations, path: '..')
30
+ builder = Virtuatable::Builders::Tests.new(
31
+ locations: locations,
32
+ path: path,
33
+ name: name
34
+ )
35
+ self.instance.builder = builder
36
+ builder.load!
37
+ builder
38
+ end
39
+
40
+ # Wrapper to simplify the call to instance.:builder
41
+ # @return [Virtuatable::Builders::Base] the builder of the current application.
42
+ def self.builder
43
+ instance.builder
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # The builders classes declares the micro service at startup in one of the services
5
+ # It provides chainable methods to be able to configure and correctly launch the
6
+ # micro-service by requiring dependencies, files, and mounting controllers.
7
+ #
8
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
9
+ module Builders
10
+ # The base class provides methods to load all elements of the application.
11
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
12
+ class Base
13
+ extend Virtuatable::Builders::Helpers::Loaders
14
+ # We include this module only for test purposes to mock require_all
15
+ include RequireAll
16
+ # Include all the helpers now that loaders can be declared.
17
+ include Virtuatable::Builders::Helpers::Controllers
18
+ include Virtuatable::Builders::Helpers::Environment
19
+ include Virtuatable::Builders::Helpers::Folders
20
+ include Virtuatable::Builders::Helpers::Mongoid
21
+ include Virtuatable::Builders::Helpers::Registration
22
+
23
+ # @!attribute [r] directory
24
+ # @return [String] the directory from which the application is loaded.
25
+ # In most case, just pass __dir__ from the config.ru file.
26
+ attr_reader :directory
27
+ # @!attribute [r] mode
28
+ # @return [Symbol] :test or :development depending on what you're trying to
29
+ # load the service for.
30
+ attr_reader :mode
31
+ # @!attribute [rw] name
32
+ # @return [String] the name of the micro-service.
33
+ attr_accessor :name
34
+
35
+ # Constructor of the builder, initializing needed attributes.
36
+ # @param directory [String] the directory from which load the application.
37
+ def initialize(locations: caller_locations, path: '.', name:)
38
+ # The base folder of the file calling the builder
39
+ filedir = File.dirname(locations.first.absolute_path)
40
+ @directory = File.absolute_path(File.join(filedir, path))
41
+ @mode = :development
42
+ @name = name.to_s
43
+ end
44
+
45
+ def load!
46
+ all_loaders.each do |loader|
47
+ send(:"load_#{loader[:name]}!")
48
+ end
49
+ end
50
+
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
+ # Loads a list of folders given as method parameters
69
+ # @param *folders [Array<String>] the folders names passed as parameters.
70
+ def require_folders(*folders)
71
+ folders.each do |folder|
72
+ path = File.join(directory, folder)
73
+ require_all(path) if File.directory?(path)
74
+ end
75
+ end
76
+
77
+ def sanitized_ancestors
78
+ self.class.ancestors - self.class.included_modules
79
+ end
80
+
81
+ # Gets the loaders of the current class and all its ancestors that have loaders
82
+ # @return [Array<Symbol>] the name of the loaders declared.
83
+ def all_loaders
84
+ superclasses = sanitized_ancestors.select do |ancestor|
85
+ ancestor != self.class
86
+ end
87
+ ancestors_loaders = superclasses.map do |ancestor|
88
+ ancestor.respond_to?(:loaders) ? ancestor.loaders : []
89
+ end
90
+ flattened_loaders = (ancestors_loaders + self.class.loaders).flatten
91
+ flattened_loaders.sort_by { |loader| loader[:priority] }
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Errors
6
+ # This error is raised when a variable is missing.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class MissingEnv < StandardError
9
+ # @!attribute [r] variable
10
+ # @return [String] the nam:e of the missing variable.
11
+ attr_reader :variable
12
+
13
+ def initialize(variable:)
14
+ @variable = variable
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ # Module holding the errors raised at the loading of the service
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Errors
8
+ autoload :MissingEnv, 'virtuatable/builders/errors/missing_env'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # Loading helpers to require and map all controllers classes inside a service.
7
+ # A controller is defined as a class inside de "Controllers" root module.
8
+ # If the module "Controllers" has not been defined, the list of controllers is
9
+ # always empty, as no controller can be loaded.
10
+ #
11
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
12
+ module Controllers
13
+ # Loads all of the controllers, given that the /controllers folder
14
+ # has already been fully required, therefore all constants are declared.
15
+ def controllers
16
+ return [] if defined?(::Controllers).nil?
17
+
18
+ classes = Controllers.constants.map { |symbol| get_const(symbol) }
19
+ classes.select { |symbol| symbol.is_a? Class }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # Loads the environment variables from the .env file at the project's root.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ module Environment
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ declare_loader(:environment, priority: 0)
13
+ end
14
+
15
+ def load_environment!
16
+ Dotenv.load
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # This module loads the file for a standard application,
7
+ # not loading the files needed for specs or websockets.
8
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
9
+ module Folders
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ declare_loader(:folders, priority: 2)
14
+ end
15
+
16
+ def load_folders!
17
+ require_folders('controllers', 'services', 'decorators')
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # Add the methods to declare an array of loaders into a builder class.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ module Loaders
9
+ # @!attribute [rw] loaders
10
+ # @return [Array] an array of loading functions invoked at startup.
11
+ attr_accessor :loaders
12
+
13
+ # Declares a loader in the current builder class.
14
+ # @param loader [Symbol] the name of the loader, infered as the method name to call.
15
+ def declare_loader(loader, priority:)
16
+ loader_h = {name: loader.to_sym, priority: priority}
17
+ @loaders.nil? ? @loaders = [loader_h] : @loaders << loader_h
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # Loads the Mongoid Configuration given the folder from where the application
7
+ # is loaded, and the type of job requiring it (specs or a service basically)
8
+ module Mongoid
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ declare_loader(:mongoid, priority: 1)
13
+ end
14
+
15
+ def load_mongoid!
16
+ filepath = File.join(@directory, 'config', 'mongoid.yml')
17
+ ::Mongoid.load!(filepath, @mode)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # Registers the service in the database by declaring it as a
7
+ # Arkaan::Monitoring::Service object, and declaring the instance.
8
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
9
+ module Registration
10
+ extend ActiveSupport::Concern
11
+
12
+ # @!attribute [r] service
13
+ # @return [Arkaan::Monitoring::Service] the service linked to this application.
14
+ attr_reader :service
15
+ # @!attribute [r] instance
16
+ # @return [Arkaan::Monitoring::Instance] the instance of this application.
17
+ attr_reader :instance
18
+
19
+ included do
20
+ declare_loader(:registration, priority: 3)
21
+ end
22
+
23
+ # Registers the service in the micro-services registry (consisting in
24
+ # the arkaan_monitoring_services and arkaan_monitoring_instances collections)
25
+ def load_registration!
26
+ @service = Arkaan::Monitoring::Service.first_or_create!(
27
+ key: @name,
28
+ path: "/#{@name}"
29
+ )
30
+ @instance = service.instances.first_or_create!(
31
+ type: type,
32
+ url: ENV['SERVICE_URL']
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ module Helpers
6
+ # This helpers loads the folders specific in a specs loading scenario.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ module Tests
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ declare_loader(:tests, priority: 4)
13
+ end
14
+
15
+ def load_tests!
16
+ require_folders('spec/support', 'spec/shared')
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ # These helpers are used when loading the application.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Helpers
8
+ autoload :Controllers, 'virtuatable/builders/helpers/controllers'
9
+ autoload :Environment, 'virtuatable/builders/helpers/environment'
10
+ autoload :Folders, 'virtuatable/builders/helpers/folders'
11
+ autoload :Loaders, 'virtuatable/builders/helpers/loaders'
12
+ autoload :Mongoid, 'virtuatable/builders/helpers/mongoid'
13
+ autoload :Registration, 'virtuatable/builders/helpers/registration'
14
+ autoload :Tests, 'virtuatable/builders/helpers/tests'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Builders
5
+ # Builder used to declare an application from a spec/spec_helper file, loading everything
6
+ # a normal loader requires, then adding the files specialized in tests.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class Tests < Virtuatable::Builders::Base
9
+ include Virtuatable::Builders::Helpers::Tests
10
+
11
+ def initialize(path: '..', name:, locations: caller_locations)
12
+ super(locations: locations, path: path, name: name)
13
+ @mode = :test
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # Builders are used to load all the needed elements in the application,
5
+ # either from the config.ru as an app, or the spec_helper as tests.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Builders
8
+ autoload :Base, 'virtuatable/builders/base'
9
+ autoload :Errors, 'virtuatable/builders/errors'
10
+ autoload :Helpers, 'virtuatable/builders/helpers'
11
+ autoload :Tests, 'virtuatable/builders/tests'
12
+ end
13
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Controllers
5
+ # This class represents a base controller for the system, giving access
6
+ # to checking methods for sessions, gateways, applications, etc.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ class Base < Sinatra::Base
9
+ register Sinatra::ConfigFile
10
+ helpers Sinatra::CustomLogger
11
+ # Includes the custom errors throwers.
12
+ include Virtuatable::API::Errors
13
+ # Includes the checking methods for sessions.
14
+ include Virtuatable::Helpers::Sessions
15
+ # Include the checkers and getters for the API gateway.
16
+ include Virtuatable::Helpers::Gateways
17
+ # Include the checkers and getters for OAuth apps
18
+ include Virtuatable::Helpers::Applications
19
+ # Include checkers for field requirement and check
20
+ include Virtuatable::Helpers::Fields
21
+ # Include the getter for the currently requested route.
22
+ include Virtuatable::Helpers::Routes
23
+ # Include the getter and checkers for accounts.
24
+ include Virtuatable::Helpers::Accounts
25
+ # This module is extended, not included, because it provides routes
26
+ # declaration methods used in class declarations.
27
+ extend Virtuatable::Helpers::Declarators
28
+
29
+ configure do
30
+ set :logger, Logger.new(STDOUT)
31
+ logger.level = Logger::ERROR if ENV['RACK_ENV'] == 'test'
32
+ # This configuration options allow the error handler to work in tests.
33
+ set :show_exceptions, false
34
+ set :raise_errors, false
35
+ end
36
+
37
+ error Mongoid::Errors::Validations do |errors|
38
+ api_bad_request errors.document.errors.messages.keys.first
39
+ end
40
+
41
+ error Virtuatable::API::Errors::NotFound do |exception|
42
+ api_not_found exception.message
43
+ end
44
+
45
+ error Virtuatable::API::Errors::BadRequest do |exception|
46
+ api_bad_request exception.message
47
+ end
48
+
49
+ error Virtuatable::API::Errors::Forbidden do |exception|
50
+ api_forbidden exception.message
51
+ end
52
+
53
+ if ENV['RACK_ENV'] != 'test'
54
+ error StandardError do |error|
55
+ api_error 500, "unknown_field.#{error.class.name}"
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # Controllers are to be subclassed in each service.
5
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
6
+ module Controllers
7
+ autoload :Base, 'virtuatable/controllers/base'
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # These helpers provide methods used to get and check accounts.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Accounts
8
+ # Gets the account linked to the current session.
9
+ # @return [Arkaan::Account] the account linked to the current session.
10
+ def account
11
+ !respond_to?(:session) || session.nil? ? nil : session.account
12
+ end
13
+
14
+ def account!
15
+ api_bad_request 'session_id.required' if account.nil?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # Helpers to get and check OAuth applications connecting the the application.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Applications
8
+ def application
9
+ Arkaan::OAuth::Application.where(key: params['app_key']).first
10
+ end
11
+
12
+ # Looks for the application sending the API's request, and raises error if not found.
13
+ def application!(premium: false)
14
+ check_presence '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
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # This helpers module is a bit larger than the others as it provides methods
6
+ # to declare routes whithin a service, performing needed checks and filters.
7
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
8
+ module Declarators
9
+ # @!attribute [r] routes
10
+ # @return [Array<Arkaan::Monitoring::Route>] the currently declared routes.
11
+ attr_reader :api_routes
12
+
13
+ # Main method to declare new routes, persisting them in the database and
14
+ # declaring it in the Sinatra application with the needed before checks.
15
+ #
16
+ # @param verb [String] the HTTP method for the route.
17
+ # @param path [String] the whole URI with parameters for the route.
18
+ # @param options [Hash] the additional options for the route.
19
+ def api_route(verb, path, options: {}, &block)
20
+ options = default_options.merge(options)
21
+ route = add_route(verb: verb, path: path, options: options)
22
+
23
+ # TODO : do everything in the #send itself to avoid
24
+ # route reload issues when premium is changed. It will
25
+ # add some treatments but avoid many problems if route.premium
26
+ send(route.verb, route.path) do
27
+ application!(premium: current_route.premium) && gateway!
28
+ session! if current_route.authenticated
29
+ end
30
+ end
31
+
32
+ # Add a route to the database, then to the routes array.
33
+ # @param verb [String] the HTTP method used to request this route.
34
+ # @param path [String] the path used to request this route.
35
+ # @return [Arkaan::Monitoring::Route] the created route.
36
+ def add_route(verb:, path:, options:)
37
+ route = Arkaan::Monitoring::Route.find_or_create_by!(
38
+ path: complete_path(path),
39
+ verb: verb.downcase,
40
+ premium: options[:premium],
41
+ service: builder.service,
42
+ authenticated: options[:authenticated]
43
+ )
44
+ api_routes.nil? ? @api_routes = [route] : push_route(route)
45
+ add_permissions(route)
46
+ route
47
+ end
48
+
49
+ # Pushes the route in the api routes list, by creating it if needed
50
+ # @param route [Arkaan::Monitoring::Route] the route to push in the list of routes.
51
+ def push_route(route)
52
+ @api_routes << route if api_routes.none? do |tmp_route|
53
+ route.id == tmp_route.id
54
+ end
55
+ end
56
+
57
+ def add_permissions(route)
58
+ route.groups = Arkaan::Permissions::Group.where(is_superuser: true)
59
+ route.save!
60
+ route
61
+ end
62
+
63
+ def complete_path(path)
64
+ service_path = builder.service.path == '/' ? '' : builder.service.path
65
+ "#{service_path}#{path}"
66
+ end
67
+
68
+ # Returns the current builder loading the application.
69
+ # @return [Virtuatable::Builers::Base] the current builder of the application.
70
+ def builder
71
+ Virtuatable::Application.builder
72
+ end
73
+
74
+ # The default options for a route, being the most used value for each key.
75
+ # @return [Hash] the default options as a hash.
76
+ def default_options
77
+ {
78
+ # If TRUE the application MUST be premium to access the route.
79
+ # Mainly used to protect administration routes against illegal accesses.
80
+ premium: false,
81
+ # If TRUE the user MUST be authenticated to access the route.
82
+ authenticated: true
83
+ }
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # Helpers for the parameters of a request.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Fields
8
+ # Checks the presence of several fields given as parameters and halts the execution if it's not present.
9
+ # @param fields [Array<String>] an array of fields names to search in the parameters
10
+ def check_presence(*fields)
11
+ fields.each do |field|
12
+ api_bad_request "#{field}.required" unless field_defined?(field)
13
+ end
14
+ end
15
+
16
+ # Checks the presence of either fields given in parameters.
17
+ # It halts with an error only if ALL parameters are not given.
18
+ #
19
+ # @param fields [Array<String>] an array of fields names to search in the parameters
20
+ # @param key [String] the key to search in the errors configuration file.
21
+ def check_either_presence(*fields, key:)
22
+ api_bad_request "#{key}.required" if fields.none? do |field|
23
+ field_defined?(field)
24
+ end
25
+ end
26
+
27
+ # Checks if a given field is defined in the params
28
+ # @param field [String] the name of the field to check in the params
29
+ # @return [Boolean] TRUE if the field exists, FALSE otherwise.
30
+ def field_defined?(field)
31
+ !params.nil? && params.key?(field) && params[field] != ''
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # These helpers holds getters and checkers about API gateways.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Gateways
8
+ # Gets the gateway associated to the gatexway token in parameters.
9
+ # @return [Arkaan::Monitoring::Gateway] the gateway requesting the service
10
+ def gateway
11
+ Arkaan::Monitoring::Gateway.where(token: params['token']).first
12
+ end
13
+
14
+ # Checks the gateway requesting the service and raises an error if necessary.
15
+ def gateway!
16
+ check_presence 'token'
17
+ api_not_found 'token.unknown' if gateway.nil?
18
+
19
+ gateway
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module Virtuatable
2
+ module Helpers
3
+ module Routes
4
+ def current_route
5
+ splitted = request.env['sinatra.route'].split(' ')
6
+ verb = splitted.first.downcase
7
+ Arkaan::Monitoring::Route.find_by(verb: verb, path: splitted.last)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ module Helpers
5
+ # This helper gives access to methods about user's session on the API.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
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
+ # Checks the session of the user requesting the API and returns an error
15
+ # if it either not exists with the given token, or the token is not given.
16
+ #
17
+ # @raise [Virtuatable::API::Errors::NotFound] if the session is not found
18
+ # or the token not given in the parameters of the request.
19
+ # @raise [Virtuatable::API::Errors::BadRequest] if the session token is
20
+ # not correctly given in the parameters.
21
+ def session!
22
+ check_presence 'session_id'
23
+ api_not_found 'session_id.unknown' if session.nil?
24
+
25
+ session
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ # The helpers are used inside the controllers to dynamically
5
+ # add features and functions.
6
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
7
+ module Helpers
8
+ autoload :Accounts, 'virtuatable/helpers/accounts'
9
+ autoload :Applications, 'virtuatable/helpers/applications'
10
+ autoload :Declarators, 'virtuatable/helpers/declarators'
11
+ autoload :Fields, 'virtuatable/helpers/fields'
12
+ autoload :Gateways, 'virtuatable/helpers/gateways'
13
+ autoload :Routes, 'virtuatable/helpers/routes'
14
+ autoload :Sessions, 'virtuatable/helpers/sessions'
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Virtuatable
4
+ VERSION = '0.3.0'
5
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Main module of the application, containing each other one.
4
+ # @author Vincent Courtois <courtois.vincent@outlook.com>
5
+ module Virtuatable
6
+ autoload :API, 'virtuatable/api'
7
+ autoload :Application, 'virtuatable/application'
8
+ autoload :Builders, 'virtuatable/builders'
9
+ autoload :Controllers, 'virtuatable/controllers'
10
+ autoload :Helpers, 'virtuatable/helpers'
11
+ autoload :Loader, 'virtuatable/application'
12
+ end
metadata ADDED
@@ -0,0 +1,411 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: virtuatable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Courtois
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.6.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.6.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-json_expectations
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.7.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.7.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: factory_bot
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 5.1.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 5.1.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: database_cleaner
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.7.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.7.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.15.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.15.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: yard
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.9.20
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.9.20
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.11.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 0.11.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: rack
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 2.0.7
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 2.0.7
139
+ - !ruby/object:Gem::Dependency
140
+ name: require_all
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '='
144
+ - !ruby/object:Gem::Version
145
+ version: 3.0.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '='
151
+ - !ruby/object:Gem::Version
152
+ version: 3.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '='
158
+ - !ruby/object:Gem::Version
159
+ version: 0.76.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '='
165
+ - !ruby/object:Gem::Version
166
+ version: 0.76.0
167
+ - !ruby/object:Gem::Dependency
168
+ name: mongoid
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '='
172
+ - !ruby/object:Gem::Version
173
+ version: 7.0.1
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '='
179
+ - !ruby/object:Gem::Version
180
+ version: 7.0.1
181
+ - !ruby/object:Gem::Dependency
182
+ name: arkaan
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - '='
186
+ - !ruby/object:Gem::Version
187
+ version: 1.9.0
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '='
193
+ - !ruby/object:Gem::Version
194
+ version: 1.9.0
195
+ - !ruby/object:Gem::Dependency
196
+ name: activemodel
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - '='
200
+ - !ruby/object:Gem::Version
201
+ version: 5.2.3
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - '='
207
+ - !ruby/object:Gem::Version
208
+ version: 5.2.3
209
+ - !ruby/object:Gem::Dependency
210
+ name: activesupport
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - '='
214
+ - !ruby/object:Gem::Version
215
+ version: 5.2.3
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - '='
221
+ - !ruby/object:Gem::Version
222
+ version: 5.2.3
223
+ - !ruby/object:Gem::Dependency
224
+ name: bcrypt
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - '='
228
+ - !ruby/object:Gem::Version
229
+ version: 3.1.11
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - '='
235
+ - !ruby/object:Gem::Version
236
+ version: 3.1.11
237
+ - !ruby/object:Gem::Dependency
238
+ name: sinatra
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - '='
242
+ - !ruby/object:Gem::Version
243
+ version: 2.0.5
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - '='
249
+ - !ruby/object:Gem::Version
250
+ version: 2.0.5
251
+ - !ruby/object:Gem::Dependency
252
+ name: sinatra-contrib
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - '='
256
+ - !ruby/object:Gem::Version
257
+ version: 2.0.5
258
+ type: :runtime
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - '='
263
+ - !ruby/object:Gem::Version
264
+ version: 2.0.5
265
+ - !ruby/object:Gem::Dependency
266
+ name: platform-api
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - '='
270
+ - !ruby/object:Gem::Version
271
+ version: 2.1.0
272
+ type: :runtime
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - '='
277
+ - !ruby/object:Gem::Version
278
+ version: 2.1.0
279
+ - !ruby/object:Gem::Dependency
280
+ name: faraday
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - '='
284
+ - !ruby/object:Gem::Version
285
+ version: 0.15.2
286
+ type: :runtime
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - '='
291
+ - !ruby/object:Gem::Version
292
+ version: 0.15.2
293
+ - !ruby/object:Gem::Dependency
294
+ name: draper
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - '='
298
+ - !ruby/object:Gem::Version
299
+ version: 3.1.0
300
+ type: :runtime
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - '='
305
+ - !ruby/object:Gem::Version
306
+ version: 3.1.0
307
+ - !ruby/object:Gem::Dependency
308
+ name: actionview
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - '='
312
+ - !ruby/object:Gem::Version
313
+ version: 5.2.3
314
+ type: :runtime
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - '='
319
+ - !ruby/object:Gem::Version
320
+ version: 5.2.3
321
+ - !ruby/object:Gem::Dependency
322
+ name: dotenv
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - '='
326
+ - !ruby/object:Gem::Version
327
+ version: 2.7.2
328
+ type: :runtime
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - '='
333
+ - !ruby/object:Gem::Version
334
+ version: 2.7.2
335
+ - !ruby/object:Gem::Dependency
336
+ name: require_all
337
+ requirement: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - '='
340
+ - !ruby/object:Gem::Version
341
+ version: 3.0.0
342
+ type: :runtime
343
+ prerelease: false
344
+ version_requirements: !ruby/object:Gem::Requirement
345
+ requirements:
346
+ - - '='
347
+ - !ruby/object:Gem::Version
348
+ version: 3.0.0
349
+ description: This gem holds controllers, errors, service delcarations, etc. for the
350
+ Virtuatable services.
351
+ email: courtois.vincent@outlook.com
352
+ executables: []
353
+ extensions: []
354
+ extra_rdoc_files: []
355
+ files:
356
+ - lib/virtuatable.rb
357
+ - lib/virtuatable/api.rb
358
+ - lib/virtuatable/api/errors.rb
359
+ - lib/virtuatable/api/errors/bad_request.rb
360
+ - lib/virtuatable/api/errors/base.rb
361
+ - lib/virtuatable/api/errors/forbidden.rb
362
+ - lib/virtuatable/api/errors/not_found.rb
363
+ - lib/virtuatable/application.rb
364
+ - lib/virtuatable/builders.rb
365
+ - lib/virtuatable/builders/base.rb
366
+ - lib/virtuatable/builders/errors.rb
367
+ - lib/virtuatable/builders/errors/missing_env.rb
368
+ - lib/virtuatable/builders/helpers.rb
369
+ - lib/virtuatable/builders/helpers/controllers.rb
370
+ - lib/virtuatable/builders/helpers/environment.rb
371
+ - lib/virtuatable/builders/helpers/folders.rb
372
+ - lib/virtuatable/builders/helpers/loaders.rb
373
+ - lib/virtuatable/builders/helpers/mongoid.rb
374
+ - lib/virtuatable/builders/helpers/registration.rb
375
+ - lib/virtuatable/builders/helpers/tests.rb
376
+ - lib/virtuatable/builders/tests.rb
377
+ - lib/virtuatable/controllers.rb
378
+ - lib/virtuatable/controllers/base.rb
379
+ - lib/virtuatable/helpers.rb
380
+ - lib/virtuatable/helpers/accounts.rb
381
+ - lib/virtuatable/helpers/applications.rb
382
+ - lib/virtuatable/helpers/declarators.rb
383
+ - lib/virtuatable/helpers/fields.rb
384
+ - lib/virtuatable/helpers/gateways.rb
385
+ - lib/virtuatable/helpers/routes.rb
386
+ - lib/virtuatable/helpers/sessions.rb
387
+ - lib/virtuatable/version.rb
388
+ homepage: https://rubygems.org/gems/arkaan
389
+ licenses:
390
+ - MIT
391
+ metadata: {}
392
+ post_install_message:
393
+ rdoc_options: []
394
+ require_paths:
395
+ - lib
396
+ required_ruby_version: !ruby/object:Gem::Requirement
397
+ requirements:
398
+ - - ">="
399
+ - !ruby/object:Gem::Version
400
+ version: '0'
401
+ required_rubygems_version: !ruby/object:Gem::Requirement
402
+ requirements:
403
+ - - ">="
404
+ - !ruby/object:Gem::Version
405
+ version: '0'
406
+ requirements: []
407
+ rubygems_version: 3.0.3
408
+ signing_key:
409
+ specification_version: 4
410
+ summary: All the utility classes for the Virtuatable services
411
+ test_files: []