virtuatable-core 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|