virtuatable 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []