virtuatable-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/core/models/account.rb +102 -0
- data/lib/core/models/authentication/session.rb +30 -0
- data/lib/core/models/authentication.rb +9 -0
- data/lib/core/models/campaign.rb +110 -0
- data/lib/core/models/campaigns/invitation.rb +31 -0
- data/lib/core/models/campaigns/tag.rb +23 -0
- data/lib/core/models/campaigns.rb +10 -0
- data/lib/core/models/chatrooms/base.rb +16 -0
- data/lib/core/models/chatrooms/campaign.rb +13 -0
- data/lib/core/models/chatrooms/conversation.rb +9 -0
- data/lib/core/models/chatrooms/membership.rb +17 -0
- data/lib/core/models/chatrooms/message.rb +33 -0
- data/lib/core/models/chatrooms.rb +13 -0
- data/lib/core/models/concerns/activable.rb +20 -0
- data/lib/core/models/concerns/diagnosticable.rb +24 -0
- data/lib/core/models/concerns/enumerable.rb +50 -0
- data/lib/core/models/concerns/historizable.rb +64 -0
- data/lib/core/models/concerns/mime_typable.rb +44 -0
- data/lib/core/models/concerns/premiumable.rb +17 -0
- data/lib/core/models/concerns/sluggable.rb +29 -0
- data/lib/core/models/concerns/typable.rb +19 -0
- data/lib/core/models/concerns.rb +16 -0
- data/lib/core/models/decorators/errors/env_variable_missing.rb +16 -0
- data/lib/core/models/decorators/errors.rb +11 -0
- data/lib/core/models/decorators/gateway.rb +111 -0
- data/lib/core/models/event.rb +31 -0
- data/lib/core/models/factories/errors/gateway_not_found.rb +16 -0
- data/lib/core/models/factories/errors.rb +11 -0
- data/lib/core/models/factories.rb +10 -0
- data/lib/core/models/files/document.rb +52 -0
- data/lib/core/models/files/permission.rb +24 -0
- data/lib/core/models/files.rb +8 -0
- data/lib/core/models/monitoring/route.rb +44 -0
- data/lib/core/models/monitoring/service.rb +33 -0
- data/lib/core/models/monitoring.rb +10 -0
- data/lib/core/models/notification.rb +24 -0
- data/lib/core/models/oauth/access_token.rb +34 -0
- data/lib/core/models/oauth/application.rb +58 -0
- data/lib/core/models/oauth/authorization.rb +33 -0
- data/lib/core/models/oauth/refresh_token.rb +20 -0
- data/lib/core/models/oauth.rb +12 -0
- data/lib/core/models/permissions/category.rb +17 -0
- data/lib/core/models/permissions/group.rb +32 -0
- data/lib/core/models/permissions/right.rb +21 -0
- data/lib/core/models/permissions.rb +12 -0
- data/lib/core/models/ruleset.rb +32 -0
- data/lib/core/models.rb +27 -0
- data/lib/core/version.rb +3 -0
- data/lib/core.rb +10 -0
- metadata +329 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Includes the slug field, always the same in all models.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Sluggable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
# Module holding the class methods for the classes including this concern.
|
10
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
11
|
+
module ClassMethods
|
12
|
+
# Add the field and its validations in the model including it.
|
13
|
+
# @param entity_type [String,Symbol] the name of the model including it, to be included in the error messages.
|
14
|
+
def make_sluggable(entity_type)
|
15
|
+
# @!attribute [rw] slug
|
16
|
+
# @return [String] the slug of the current entity ; it must be snake-cased, longer than four characters, unique for the entity and given.
|
17
|
+
field :slug, type: String
|
18
|
+
|
19
|
+
validates :slug,
|
20
|
+
length: {minimum: 4, message: 'minlength', if: :slug?},
|
21
|
+
format: {with: /\A[a-z]+(_[a-z]+)*\z/, message: 'pattern', if: :slug?},
|
22
|
+
uniqueness: {message: 'uniq', if: :slug?},
|
23
|
+
presence: {message: 'required'}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Concerns for the objects that can be activated or deactivated, included the corresponding scopes.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Typable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
include Core::Models::Concerns::Enumerable
|
11
|
+
|
12
|
+
# @!attribute [rw] type
|
13
|
+
# @return [Symbol] the type of the instance, determining its way of being deployed, restarted, etc.
|
14
|
+
enum_field :type, [:heroku, :local, :unix], default: :heroku
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# This module holds the shared concerns to include in the desired models.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Concerns
|
6
|
+
autoload :Activable , 'core/models/concerns/activable'
|
7
|
+
autoload :Diagnosticable, 'core/models/concerns/diagnosticable'
|
8
|
+
autoload :Enumerable , 'core/models/concerns/enumerable'
|
9
|
+
autoload :Historizable , 'core/models/concerns/historizable'
|
10
|
+
autoload :MimeTypable , 'core/models/concerns/mime_typable'
|
11
|
+
autoload :Premiumable , 'core/models/concerns/premiumable'
|
12
|
+
autoload :Sluggable , 'core/models/concerns/sluggable'
|
13
|
+
autoload :Typable , 'core/models/concerns/typable'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Decorators
|
4
|
+
module Errors
|
5
|
+
# Error raised if the application key variable is missing.
|
6
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
|
+
class EnvVariableMissing < Core::Models::Utils::Errors::HTTPError
|
8
|
+
|
9
|
+
def initialize(action:)
|
10
|
+
super(action, 'app_key', 'not_found', 404)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Decorators
|
4
|
+
# Module holding all the errors concerning the code of the decorators.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Errors
|
7
|
+
autoload :EnvVariableMissing, 'core/models/decorators/errors/env_variable_missing'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Decorators
|
4
|
+
# Decorator for a service, providing methods to make requests on it.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Gateway < Draper::Decorator
|
7
|
+
delegate_all
|
8
|
+
|
9
|
+
# @!attribute [rw] action
|
10
|
+
# @return [String] the action of the route using this API.
|
11
|
+
attr_accessor :action
|
12
|
+
|
13
|
+
attr_accessor :logger
|
14
|
+
|
15
|
+
def initialize(action, _object)
|
16
|
+
super(_object)
|
17
|
+
@logger = Logger.new(STDOUT)
|
18
|
+
@action = action
|
19
|
+
end
|
20
|
+
|
21
|
+
# Shortcut to make a DELETE request on the API.
|
22
|
+
# @param session [Core::Models::Authentication::Session] the session of the user requesting the API.
|
23
|
+
# @param url [String] the URL you want to reach on the service.
|
24
|
+
# @param params [Hash] the additional parameters to pass in the JSON body.
|
25
|
+
def delete(session:, url:, params:)
|
26
|
+
return make_request_without_body(verb: 'delete', session: session, url: url, params: params)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Shortcut to make a GET request on the API.
|
30
|
+
# @param session [Core::Models::Authentication::Session] the session of the user requesting the API.
|
31
|
+
# @param url [String] the URL you want to reach on the service.
|
32
|
+
# @param params [Hash] the additional parameters to pass in the JSON body.
|
33
|
+
def get(session:, url:, params:)
|
34
|
+
return make_request_without_body(verb: 'get', session: session, url: url, params: params)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shortcut to make a POST request on the API.
|
38
|
+
# @param session [Core::Models::Authentication::Session] the session of the user requesting the API.
|
39
|
+
# @param url [String] the URL you want to reach on the service.
|
40
|
+
# @param params [Hash] the additional parameters to pass in the JSON body.
|
41
|
+
def post(session:, url:, params:)
|
42
|
+
return make_request(verb: 'post', session: session, url: url, params: params)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Shortcut to make a PUT request on the API.
|
46
|
+
# @param session [Core::Models::Authentication::Session] the session of the user requesting the API.
|
47
|
+
# @param url [String] the URL you want to reach on the service.
|
48
|
+
# @param params [Hash] the additional parameters to pass in the JSON body.
|
49
|
+
def put(session:, url:, params:)
|
50
|
+
return make_request(verb: 'put', session: session, url: url, params: params)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Makes a POST request to the given service with the following steps :
|
56
|
+
# 1. Gets an active and running instance of the service to make the request.
|
57
|
+
# 2. Creates a Faraday connection to use it as a pipeline for the request.
|
58
|
+
# 3. Makes the actual request and returns an object with the status and body of the response.
|
59
|
+
#
|
60
|
+
# @param verb [String] the HTTP verb to use for this request.
|
61
|
+
# @param session [Core::Models::Authentication::Session] the session of the user requesting the API.
|
62
|
+
# @param url [String] the URL you want to reach on the service.
|
63
|
+
# @param params [Hash] the additional parameters to pass in the JSON body.
|
64
|
+
#
|
65
|
+
# @return [Hash, Boolean] FALSE if no instance are found, or an object with :status and :body keys correspding
|
66
|
+
# to the status and body of the response to the request
|
67
|
+
def make_request(verb:, session:, url:, params:)
|
68
|
+
params = before_requests(session, params)
|
69
|
+
connection = get_connection
|
70
|
+
|
71
|
+
response = connection.send(verb) do |req|
|
72
|
+
req.url url
|
73
|
+
req.headers['Content-Type'] = 'application/json'
|
74
|
+
req.body = params.to_json
|
75
|
+
end
|
76
|
+
|
77
|
+
return {
|
78
|
+
status: response.status,
|
79
|
+
body: JSON.parse(response.body)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def make_request_without_body(verb:, session:, url:, params:)
|
84
|
+
params = before_requests(session, params)
|
85
|
+
connection = get_connection
|
86
|
+
response = connection.send(verb) do |req|
|
87
|
+
req.url url, params
|
88
|
+
req.headers['Content-Type'] = 'application/json'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def before_requests(session, params)
|
93
|
+
if ENV['APP_KEY'].nil?
|
94
|
+
raise Core::Models::Decorators::Errors::EnvVariableMissing.new(action: action)
|
95
|
+
end
|
96
|
+
params[:app_key] = ENV['APP_KEY']
|
97
|
+
params[:session_id] = session.token
|
98
|
+
return params
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_connection
|
102
|
+
Faraday.new(object.url) do |faraday|
|
103
|
+
faraday.request :url_encoded
|
104
|
+
faraday.response :logger
|
105
|
+
faraday.adapter Faraday.default_adapter
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Core
|
4
|
+
module Models
|
5
|
+
# An event is symbolizing a timestamped change in a model.
|
6
|
+
# It is recommended NOT to use this class directly but to use
|
7
|
+
# the Core::Models::Concerns::Historizable concern in a model.
|
8
|
+
#
|
9
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
10
|
+
class Event
|
11
|
+
include Mongoid::Document
|
12
|
+
include Mongoid::Timestamps
|
13
|
+
|
14
|
+
# @!attribute [rw] field
|
15
|
+
# @return [String] the name of the field being historized
|
16
|
+
field :field, type: String
|
17
|
+
# @!attribute [rw] from
|
18
|
+
# @return [Any] the value of the field before update
|
19
|
+
field :from
|
20
|
+
# @!attribute [rw] to
|
21
|
+
# @return [Any] the value of the field after update
|
22
|
+
field :to
|
23
|
+
|
24
|
+
# @!attribute [rw] document
|
25
|
+
# @return [Any] the model in which the history is embedded
|
26
|
+
embedded_in :document, polymorphic: true, inverse_of: :history
|
27
|
+
|
28
|
+
validates :field, presence: { message: 'required' }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Factories
|
4
|
+
module Errors
|
5
|
+
# Error raised when not gateway active and running is found in the factory.
|
6
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
|
+
class GatewayNotFound < Core::Models::Utils::Errors::HTTPError
|
8
|
+
|
9
|
+
def initialize(action:)
|
10
|
+
super(action, 'gateway_id', 'not_found', 404)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Factories
|
4
|
+
# Module holding all the errors concerning the code of the factories.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Errors
|
7
|
+
autoload :GatewayNotFound, 'core/models/factories/errors/gateway_not_found'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# Static factories are used to create decorated objects easily.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Factories
|
6
|
+
autoload :Gateways, 'core/models/factories/gateways'
|
7
|
+
autoload :Errors , 'core/models/factories/errors'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Files
|
4
|
+
# a document is an uploaded file in the S3 clone application.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Document
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
|
10
|
+
# @!attribute [rw] name
|
11
|
+
# @return [String] the filename the user entered when uploading the file.
|
12
|
+
field :name, type: String
|
13
|
+
|
14
|
+
field :extension, type: String
|
15
|
+
# @!attribute [rw] size
|
16
|
+
# @return [String] the size, in bytes, of the uploaded file.
|
17
|
+
field :size, type: Integer, default: 0
|
18
|
+
# @!attribute [rw] folder
|
19
|
+
# @return [String] the folder in which the file is stored in the S3 clone.
|
20
|
+
field :folder, type: String, default: '/'
|
21
|
+
# @!attribute [rw] mime_type
|
22
|
+
# @return [String] the MIME type of the file. this MAY not correspond to the real
|
23
|
+
# MIME type of the uploaded file, this is just an indication.
|
24
|
+
field :mime_type, type: String
|
25
|
+
|
26
|
+
# @!attribute [rw] creator
|
27
|
+
# @return [Core::Models::Account] the account of the person that uploaded the file.
|
28
|
+
belongs_to :creator, class_name: 'Core::Models::Account', inverse_of: :files
|
29
|
+
|
30
|
+
# @!attribute [rw] permissions
|
31
|
+
# @return [Array<Core::Models::Files::Permission>] the permissions granted to access this file.
|
32
|
+
has_many :permissions, class_name: 'Core::Models::Files::Permission', inverse_of: :file
|
33
|
+
|
34
|
+
validates :name, :extension, :folder, :mime_type, presence: {message: 'required'}
|
35
|
+
|
36
|
+
validates :folder, format: {without: /\/\//, message: 'format'}
|
37
|
+
|
38
|
+
validate :filename_unicity
|
39
|
+
|
40
|
+
def filename_unicity
|
41
|
+
existing = Core::Models::Files::Document.where(
|
42
|
+
name: name,
|
43
|
+
folder: folder,
|
44
|
+
extension: extension,
|
45
|
+
:id.ne => id
|
46
|
+
)
|
47
|
+
errors.add(:name, 'uniq') unless existing.first.nil?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Files
|
4
|
+
# The permission granted to a user to access and/or delete a file.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Permission
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
include Core::Models::Concerns::Enumerable
|
10
|
+
|
11
|
+
# @!attribute [rw] type
|
12
|
+
# @return [Symbol] the type of permission granted (is the user able to delete the file ?)
|
13
|
+
enum_field :type, [:read, :read_write]
|
14
|
+
|
15
|
+
# @!attribute [rw] file
|
16
|
+
# @return [Core::Models::Files::Document] the document the permission is linked to.
|
17
|
+
belongs_to :file, class_name: 'Core::Models::Files::Document', inverse_of: :permissions
|
18
|
+
# @!attribute [rw] account
|
19
|
+
# @return [Core::Models::Account] the user being granted the access to the file.
|
20
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :permissions
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Monitoring
|
4
|
+
# A route is an endpoint accessible in a service. Each route has to have an associated endpoint in the deployed instances.
|
5
|
+
# @param Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Route
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
include Core::Models::Concerns::Premiumable
|
10
|
+
include Core::Models::Concerns::Activable
|
11
|
+
|
12
|
+
# @!attribute [rw] path
|
13
|
+
# @return [String] the path (URI) of the route in the service?
|
14
|
+
field :path, type: String, default: '/'
|
15
|
+
# @!attribute [rw] verb
|
16
|
+
# @return [String] the verb (HTTP method) of this route in the service.
|
17
|
+
field :verb, type: String, default: 'get'
|
18
|
+
# @!attribute [rw] authenticated
|
19
|
+
# @return [Boolean] if true, the session_id is needed for this route, if false it is not.
|
20
|
+
field :authenticated, type: Boolean, default: true
|
21
|
+
|
22
|
+
# @!attribute [rw] service
|
23
|
+
# @return [Core::Models::Monitoring::Service] the service in which this route is declared.
|
24
|
+
belongs_to :service, class_name: 'Core::Models::Monitoring::Service', inverse_of: :routes
|
25
|
+
|
26
|
+
# @!attribute [rw] groups
|
27
|
+
# @return [Array<Core::Models::Permissions::Group>] the groups having permission to access this route.
|
28
|
+
has_and_belongs_to_many :groups, class_name: 'Core::Models::Permissions::Group', inverse_of: :groups
|
29
|
+
|
30
|
+
validates :path,
|
31
|
+
format: {with: /\A(\/|((\/:?[a-zA-Z0-9_]+)+))\z/, message: 'pattern', if: :path?}
|
32
|
+
|
33
|
+
validates :verb,
|
34
|
+
inclusion: {message: 'unknown', in: ['get', 'post', 'put', 'delete', 'patch', 'option']}
|
35
|
+
|
36
|
+
# Returns the complete path, enriched with the path of the service.
|
37
|
+
# @return [String] the complete path to access this route from the outside.
|
38
|
+
def complete_path
|
39
|
+
path == '/' ? service.path : "#{service.path}#{path}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Monitoring
|
4
|
+
# A service is the representation of one of the applications composing the API.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Service
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
include Core::Models::Concerns::Activable
|
10
|
+
include Core::Models::Concerns::Diagnosticable
|
11
|
+
include Core::Models::Concerns::Premiumable
|
12
|
+
|
13
|
+
# @!attribute [rw] key
|
14
|
+
# @return [String] the name of the service, used as a namespace on the Kubernetes side.
|
15
|
+
field :key, type: String
|
16
|
+
# @!attribute [rw] path
|
17
|
+
# @return [String] the path the service will be mapped on in the API. This will be used in the Ingress.
|
18
|
+
field :path, type: String, default: '/'
|
19
|
+
|
20
|
+
# @!attribute [rw] creator
|
21
|
+
# @return [Core::Models::Account] the creator of this service.
|
22
|
+
belongs_to :creator, class_name: 'Core::Models::Account', optional: true, inverse_of: :services
|
23
|
+
# @!attribute [rw] routes
|
24
|
+
# @return [Array<Core::Models::Monitoring::Route>] the routes associated to this service, accessible from the gateway.
|
25
|
+
has_many :routes, class_name: 'Core::Models::Monitoring::Route', inverse_of: :service
|
26
|
+
|
27
|
+
validates :key, uniqueness: {message: 'uniq'}
|
28
|
+
|
29
|
+
validates :path, format: {with: /\A(\/:?[a-z]+)+\z/, message: 'pattern'}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# The monitoring module holds all the logic about the services so they can be activated or deactivated.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Monitoring
|
6
|
+
autoload :Route , 'core/models/monitoring/route'
|
7
|
+
autoload :Service, 'core/models/monitoring/service'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# A notification is a little something to warn a user that an action concerning him or her occurred.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Notification
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
|
9
|
+
# @!attribute [rw] type
|
10
|
+
# @return [String] the type of notification this is supposed to be. All types are custom and facultative.
|
11
|
+
field :type, type: String, default: 'NOTIFICATIONS.DEFAULT'
|
12
|
+
# @!attribute [rw] read
|
13
|
+
# @return [Boolean] TRUE if the notification has been read (seen by the user), FALSE otherwise.
|
14
|
+
field :read, type: Boolean, default: false
|
15
|
+
# @!attribute [rw] data
|
16
|
+
# @return [Hash] the custom data that can be attached to this notification, for example for an invitation it can be the invited username.
|
17
|
+
field :data, type: Hash, default: {}
|
18
|
+
|
19
|
+
# @!attribute [rw] account
|
20
|
+
# @return [Core::Models::Account] the account concerned by this notification.
|
21
|
+
embedded_in :account, class_name: 'Core::Models::Account', inverse_of: :notifications
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module OAuth
|
4
|
+
# An access token is the value assigned to the application
|
5
|
+
# to access the data the user is allowed to access.
|
6
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
7
|
+
class AccessToken
|
8
|
+
include Mongoid::Document
|
9
|
+
include Mongoid::Timestamps
|
10
|
+
|
11
|
+
# @!attribute [rw] value
|
12
|
+
# @return [String] the value of the token, returned to the application when built.
|
13
|
+
field :value, type: String, default: ->{ SecureRandom.hex }
|
14
|
+
# @!attribute [rw] expiration
|
15
|
+
# @return [Integer] the time, in seconds, after which the token is declared expired, and thus can't be used anymore.
|
16
|
+
field :expiration, type: Integer, default: 86400
|
17
|
+
|
18
|
+
# @!attribute [rw] authorization
|
19
|
+
# @return [Core::Models::OAuth::Authorization] the authorization code that issued this token to the application for this user.
|
20
|
+
belongs_to :authorization, class_name: 'Core::Models::OAuth::Authorization', inverse_of: :tokens
|
21
|
+
|
22
|
+
validates :value,
|
23
|
+
presence: {message: 'required'},
|
24
|
+
uniqueness: {message: 'uniq'}
|
25
|
+
|
26
|
+
# Checks if the current date is inferior to the creation date + expiration period
|
27
|
+
# @return [Boolean] TRUE if the token is expired, FALSE otherwise.
|
28
|
+
def expired?
|
29
|
+
created_at.to_time.to_i + expiration < Time.now.to_i
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module OAuth
|
4
|
+
# An application is what is referred to in the OAuth2.0 RFC as a client, wanting to access private informations about the user.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Application
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
|
10
|
+
# @!attribute [rw] name
|
11
|
+
# @return [String] the unique name of the application, mainly used to identify and display it.
|
12
|
+
field :name, type: String
|
13
|
+
# @!attribute [rw] key
|
14
|
+
# @return [String] the unique key for the application, identifying it when requesting a token for the API.
|
15
|
+
field :key, type: String, default: ->{ SecureRandom.hex }
|
16
|
+
# @!attribute [rw] premium
|
17
|
+
# @return [Boolean] a value indicating whether the application should automatically receive a token when an account is created, or not.
|
18
|
+
field :premium, type: Boolean, default: false
|
19
|
+
# @!attirbute [rw] redirect_uris
|
20
|
+
# @return [Array<String>] the redirection URIs used for this application.
|
21
|
+
field :redirect_uris, type: Array, default: []
|
22
|
+
|
23
|
+
# @!attribute [rw] creator
|
24
|
+
# @return [Core::Models::Account] the account that has created this application, considered its owner.
|
25
|
+
belongs_to :creator, class_name: 'Core::Models::Account', inverse_of: :applications
|
26
|
+
# @!attribute [rw] authorizations
|
27
|
+
# @return [Array<Core::Models::OAuth::Authorization>] the authorizations linked to the accounts this application can get the data from.
|
28
|
+
has_many :authorizations, class_name: 'Core::Models::OAuth::Authorization', inverse_of: :application
|
29
|
+
|
30
|
+
validates :name,
|
31
|
+
presence: {message: 'required'},
|
32
|
+
length: {minimum: 6, message: 'minlength'},
|
33
|
+
uniqueness: {message: 'uniq'}
|
34
|
+
|
35
|
+
validates :key,
|
36
|
+
presence: {message: 'required'},
|
37
|
+
uniqueness: {message: 'uniq'}
|
38
|
+
|
39
|
+
validate :redirect_uris_values
|
40
|
+
|
41
|
+
# Checks the URIs to get sure they are correct, a URI is correct if :
|
42
|
+
# - it is a string
|
43
|
+
# - it has a correct URL format.
|
44
|
+
def redirect_uris_values
|
45
|
+
redirect_uris.each do |uri|
|
46
|
+
if !uri.is_a? String
|
47
|
+
errors.add(:redirect_uris, 'type')
|
48
|
+
break
|
49
|
+
elsif uri.match(/\A(https?:\/\/)((([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*)|(localhost:[0-9]{2,4})\/?)\z/).nil?
|
50
|
+
errors.add(:redirect_uris, 'format')
|
51
|
+
break
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module OAuth
|
4
|
+
# An OAuth authorization is granted by a user to an application to access its personal data.
|
5
|
+
# The application then transforms it into an access token to be able to send it with
|
6
|
+
# further requests, so that we know the user has authorized the application to access its data.
|
7
|
+
#
|
8
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
9
|
+
class Authorization
|
10
|
+
include Mongoid::Document
|
11
|
+
include Mongoid::Timestamps
|
12
|
+
|
13
|
+
# @!attribute [rw] code
|
14
|
+
# @return [String] the value corresponding to the authentication code in the RFC of OAuth2.0, kep for historic purpose.
|
15
|
+
field :code, type: String, default: ->{ SecureRandom.hex }
|
16
|
+
|
17
|
+
# @!attribute [rw] account
|
18
|
+
# @return [Arkaaan::Account] the account granting the authorization to access its data to the application.
|
19
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :authorizations
|
20
|
+
# @!attribute [rw] application
|
21
|
+
# @return [Core::Models::OAuth::Application] the application asking to access account's data.
|
22
|
+
belongs_to :application, class_name: 'Core::Models::OAuth::Application', inverse_of: :authorizations
|
23
|
+
# @!attribute [rw] token
|
24
|
+
# @return [Core::Models::OAuth::AccessToken] the access token used further in the application process to access private data of the account.
|
25
|
+
has_many :tokens, class_name: 'Core::Models::OAuth::AccessToken', inverse_of: :authorization
|
26
|
+
|
27
|
+
validates :code,
|
28
|
+
presence: {message: 'required'},
|
29
|
+
uniqueness: {message: 'uniq'}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module OAuth
|
4
|
+
# A refresh token is used when an access token is expired, to get a new one. It is then recreated for the next expiration.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class RefreshToken
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
|
10
|
+
# @!attribute [rw] value
|
11
|
+
# @return [String] the value of the token, returned to the application when built.
|
12
|
+
field :value, type: String, default: ->{ SecureRandom.hex }
|
13
|
+
|
14
|
+
# @!attribute [rw] authorization
|
15
|
+
# @return [Core::Models::OAuth::Authorization] the authorization code that issued this token to the application for this user.
|
16
|
+
belongs_to :authorization, class_name: 'Core::Models::OAuth::Authorization', inverse_of: :refresh_token
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# This module holds the logic for the connection of an application to our API.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module OAuth
|
6
|
+
autoload :Application , 'core/models/oauth/application'
|
7
|
+
autoload :Authorization, 'core/models/oauth/authorization'
|
8
|
+
autoload :AccessToken , 'core/models/oauth/access_token'
|
9
|
+
autoload :RefreshToken , 'core/models/oauth/refresh_token'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|