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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eaef58986378462da6ff78e3aeac595cbed418f3351254e3e99b303059fe21d1
|
4
|
+
data.tar.gz: 1ed97f4ff856ecfbe5ccf969547ee0141f03f1e9c59304661880f6d4e87bfaf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffc760f437db7e376de09c5e88fa794e440729600819f8cce7474d4db6a122185fc20472020e131ae889d6371f1cf95f0fb7389506ac4ec1f5a9840a3ed2dc98
|
7
|
+
data.tar.gz: '08addb4e9612082536359a2a624f5eded215ba382a8f9b16aebf016cfc35b9c9dbc12a503a3160780dc81896bdabf0434f1966062d5eb339e999eadef92cbec1'
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# A user account with all related attributes. It holds credentials and informations about a designated user.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Account
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
include ActiveModel::SecurePassword
|
9
|
+
include Core::Models::Concerns::Enumerable
|
10
|
+
|
11
|
+
# @!attribute [rw] username
|
12
|
+
# @return [String] the nickname the user chose at subscription, must be given, unique, and 6 or more characters long.
|
13
|
+
field :username, type: String
|
14
|
+
# @!attribute [r] password_digest
|
15
|
+
# @return [String] the password of the user, encrypted with the Blowfish algorithm.
|
16
|
+
field :password_digest, type: String
|
17
|
+
# @!attribute [rw] lastname
|
18
|
+
# @return [String] the last name (family name) of the user.
|
19
|
+
field :lastname, type: String, default: ''
|
20
|
+
# @!attribute [rw] firstname
|
21
|
+
# @return [String] the first name of the user.
|
22
|
+
field :firstname, type: String, default: ''
|
23
|
+
# @!attribute [rw] email
|
24
|
+
# @return [String] the email address of the user, useful to contact them ; it must be given, unique, and have an email format.
|
25
|
+
field :email, type: String
|
26
|
+
# @!attribute [rw] language
|
27
|
+
# @return [Symbol] the language preferred by this user.
|
28
|
+
enum_field :language, [:en_GB, :fr_FR], default: :fr_FR
|
29
|
+
# @!attribute [rw] gender
|
30
|
+
# @return [Symbol] the way you prefer the application to gender you.
|
31
|
+
enum_field :gender, [:female, :male, :neutral], default: :neutral
|
32
|
+
|
33
|
+
# @!attribute [w] password
|
34
|
+
# @return [String] password, in clear, of the user ; do not attempt to get the value, just set it when changing the password.
|
35
|
+
# @!attribute [w] password_confirmation
|
36
|
+
# @return [String] the confirmation of the password, do not get, just set it ; it must be the same as the password.
|
37
|
+
has_secure_password validations: false
|
38
|
+
|
39
|
+
# @!attribute [rw] groups
|
40
|
+
# @return [Array<Core::Models::Permissions::Group>] the groups giving their corresponding rights to the current account.
|
41
|
+
has_and_belongs_to_many :groups, class_name: 'Core::Models::Permissions::Group', inverse_of: :accounts
|
42
|
+
|
43
|
+
# @!attribute [rw] applications
|
44
|
+
# @return [Array<Core::Models::OAuth::Application] the applications this user has created and owns.
|
45
|
+
has_many :applications, class_name: 'Core::Models::OAuth::Application', inverse_of: :creator
|
46
|
+
# @!attribute [rw] authorizations
|
47
|
+
# @return [Array<Core::Models::OAuth::Authorization>] the authorization issued by this account to third-party applications to access its data.
|
48
|
+
has_many :authorizations, class_name: 'Core::Models::OAuth::Authorization', inverse_of: :account
|
49
|
+
# @!attribute [rw] services
|
50
|
+
# @return [Array<Core::Models::Monitoring::Service>] the services created by this user.
|
51
|
+
has_many :services, class_name: 'Core::Models::Monitoring::Service', inverse_of: :creator
|
52
|
+
# @!attribute [rw] sessions
|
53
|
+
# @return [Array<Core::Models::Authentication::Session>] the sessions on which this account is, or has been logged in.
|
54
|
+
has_many :sessions, class_name: 'Core::Models::Authentication::Session', inverse_of: :account
|
55
|
+
# @!attribute [rw] invitations
|
56
|
+
# @return [Array<Core::Models::Campaigns::Invitation>] the invitations in campaigns you have been issued.
|
57
|
+
has_many :invitations, class_name: 'Core::Models::Campaigns::Invitation', inverse_of: :account
|
58
|
+
# @!attribute [rw] invitations
|
59
|
+
# @return [Array<Core::Models::Campaigns::Invitation>] the invitations you've issued yourself to other players.
|
60
|
+
has_many :created_invitations, class_name: 'Core::Models::Campaigns::Invitation', inverse_of: :creator
|
61
|
+
# @!attribute [rw] permissions
|
62
|
+
# @return [Array<Core::Models::Files::Permission>] the file access permissions granted to this account.
|
63
|
+
has_many :permissions, class_name: 'Core::Models::Files::Permission', inverse_of: :account
|
64
|
+
# @!attribute [rw] messages
|
65
|
+
# @return [Array<Core::Models::Chatrooms::Messages>] all the messages ever sent by the user.
|
66
|
+
has_many :messages, class_name: 'Core::Models::Chatrooms::Message', inverse_of: :account
|
67
|
+
|
68
|
+
has_many :memberships, class_name: 'Core::Models::Chatrooms::Membership', inverse_of: :account
|
69
|
+
|
70
|
+
# @!attribute [rw] notifications
|
71
|
+
# @return [Array<Core::Models::Notification>] the notifications linked to this user.
|
72
|
+
embeds_many :notifications, class_name: 'Core::Models::Notification', inverse_of: :account
|
73
|
+
|
74
|
+
# @return [Array<Core::Models::Notification>] the unread notifications that should be displayed first for the user.
|
75
|
+
def unread_notifications
|
76
|
+
notifications.where(read: false)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @return [Array<Core::Models::Notification>] the notifications already read, less important to display than the unread ones.
|
80
|
+
def read_notifications
|
81
|
+
notifications.where(read: true)
|
82
|
+
end
|
83
|
+
|
84
|
+
validates :username,
|
85
|
+
presence: {message: 'required'},
|
86
|
+
length: {minimum: 6, message: 'minlength', if: :username?},
|
87
|
+
uniqueness: {message: 'uniq', if: :username?}
|
88
|
+
|
89
|
+
validates :email,
|
90
|
+
presence: {message: 'required'},
|
91
|
+
format: {with: /\A[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\z/, message: 'pattern', if: :email?},
|
92
|
+
uniqueness: {message: 'uniq', if: :email?}
|
93
|
+
|
94
|
+
validates :password,
|
95
|
+
presence: {message: 'required', if: ->{ !persisted? || password_digest_changed? }},
|
96
|
+
confirmation: {message: 'confirmation', if: :password_digest_changed?}
|
97
|
+
|
98
|
+
validates :password_confirmation,
|
99
|
+
presence: {message: 'required', if: :password_digest_changed?}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Authentication
|
4
|
+
# A session represents the connection of the user on our frontend application. Nobody else than our frontend should
|
5
|
+
# have access to the session or it's content (in particular to the token), instead they shall use the OAuth2.0 protocol.
|
6
|
+
# A session shall ONLY be created by a premium application (only our frontend applications are premium).
|
7
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
8
|
+
class Session
|
9
|
+
include Mongoid::Document
|
10
|
+
include Mongoid::Timestamps
|
11
|
+
|
12
|
+
# @!attribute [rw] token
|
13
|
+
# @return [String] the unique token for this session, used to identify it and be sure the user is connected on this application.
|
14
|
+
field :token, type: String
|
15
|
+
# @!attribute [rw] websocket_id
|
16
|
+
# @return [String] the ID of the websocket on which the session is connected. It's not an association because instances are embedded.
|
17
|
+
field :websocket_id, type: String, default: ''
|
18
|
+
|
19
|
+
# @!attribute [rw] account
|
20
|
+
# @return [Core::Models::Account] the account connected to the application.
|
21
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :sessions
|
22
|
+
|
23
|
+
validates :token,
|
24
|
+
presence: {message: 'required'},
|
25
|
+
uniqueness: {message: 'uniq', if: :token?},
|
26
|
+
length: {minimum: 10, message: 'minlength', if: :token?}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# A campaign is a gathering of accounts playing on the same interface, and interacting in a common game.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
class Campaign
|
6
|
+
include Mongoid::Document
|
7
|
+
include Mongoid::Timestamps
|
8
|
+
|
9
|
+
# @!attribute [rw] title
|
10
|
+
# @return [String] the title, or name, of the campaign, used to identify it in the list.
|
11
|
+
field :title, type: String
|
12
|
+
# @!attribute [rw] description
|
13
|
+
# @return [String] a more detailed description, used to give further information about the campaign in general.
|
14
|
+
field :description, type: String
|
15
|
+
# @!attribute [rw] is_private
|
16
|
+
# @return [Boolean] TRUE if the campaign can be joined only by being invited by the creator, FALSE if it's publicly displayed and accessible.
|
17
|
+
field :is_private, type: Boolean, default: true
|
18
|
+
# @!attribute [rw] tags
|
19
|
+
# @return [Array<String>] an array of tags describing characteristics of this campaign.
|
20
|
+
field :tags, type: Array, default: []
|
21
|
+
# @!attributes [rw] max_players
|
22
|
+
# @return [Integer] the maximum number of players allowed in this campaign.
|
23
|
+
field :max_players, type: Integer, default: 5
|
24
|
+
|
25
|
+
# @!attribute [rw] invitations
|
26
|
+
# @return [Array<Core::Models::Campaigns::Invitation>] the invitations to players that have been made for this campaign.
|
27
|
+
has_many :invitations, class_name: 'Core::Models::Campaigns::Invitation', inverse_of: :campaign
|
28
|
+
# @!attribute [rw] files
|
29
|
+
# @return [Array<Core::Models::Files::Document>] the files uploaded in this campaign.
|
30
|
+
has_many :files, class_name: 'Core::Models::Files::Document'
|
31
|
+
|
32
|
+
# @!attribute [rw] chatroom
|
33
|
+
# @return [Core::Models::Chatrooms::Campaign] the chatroom linked to this campaign.
|
34
|
+
embeds_one :chatroom, class_name: 'Core::Models::Chatrooms::Campaign', inverse_of: :campaign
|
35
|
+
|
36
|
+
# @!attribute [rw] ruleset
|
37
|
+
# @return [Core::Models::Ruleset] the set of rules this campaign is based upon.
|
38
|
+
belongs_to :ruleset, class_name: 'Core::Models::Ruleset', inverse_of: :campaigns, optional: true
|
39
|
+
|
40
|
+
validates :title,
|
41
|
+
presence: {message: 'required'},
|
42
|
+
length: {minimum: 4, message: 'minlength', if: :title?}
|
43
|
+
|
44
|
+
validates :max_players,
|
45
|
+
numericality: {less_than: 21, message: 'maximum'}
|
46
|
+
|
47
|
+
validate :title_unicity
|
48
|
+
|
49
|
+
validate :max_players_minimum
|
50
|
+
|
51
|
+
# Sets the creator of the campaign. This method is mainly used for backward-compatibility needs.
|
52
|
+
# @param account [Core::Models::Account] the account of the creator for this campaign.
|
53
|
+
def creator=(account)
|
54
|
+
if !invitations.where(account: account).exists?
|
55
|
+
invitation = Core::Models::Campaigns::Invitation.create(
|
56
|
+
campaign: self,
|
57
|
+
account: account,
|
58
|
+
status: :creator
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Getter for the creator account of this campaign.
|
64
|
+
# @return [Core::Models::Account] the account of the player creating this campaign.
|
65
|
+
def creator
|
66
|
+
invitations.to_a.find(&:status_creator?).account
|
67
|
+
end
|
68
|
+
|
69
|
+
# Adds an error message if the account creating this campaign already has a campaign with the very same name.
|
70
|
+
def title_unicity
|
71
|
+
# First we take all the other campaign ids of the user.
|
72
|
+
campaign_ids = creator.invitations.where(:campaign_id.ne => _id).pluck(:campaign_id)
|
73
|
+
# With this list of campaign IDs, we look for a campaign with the same title.
|
74
|
+
same_title_campaign = Core::Models::Campaign.where(:_id.in => campaign_ids, title: title)
|
75
|
+
if !creator.nil? && title? && same_title_campaign.exists?
|
76
|
+
errors.add(:title, 'uniq')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Validation for the max number of players for a campaign.
|
81
|
+
# If there is a max number of players, and the current number of
|
82
|
+
# players is above it, or the max number of players is 0, raises an error.
|
83
|
+
def max_players_minimum
|
84
|
+
if max_players? && (max_players < players_count || max_players < 1)
|
85
|
+
errors.add(:max_players, 'minimum')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Array<Core::Models::Campaigns::Invitation>] the players in this campaign.
|
90
|
+
def players
|
91
|
+
invitations.to_a.select do |invitation|
|
92
|
+
[:creator, :accepted].include? invitation.enum_status
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [Integer] the number of players in this campaign.
|
97
|
+
def players_count
|
98
|
+
players.count
|
99
|
+
end
|
100
|
+
|
101
|
+
def messages
|
102
|
+
chatroom.messages
|
103
|
+
end
|
104
|
+
|
105
|
+
after_initialize do
|
106
|
+
self.chatroom = Core::Models::Chatrooms::Campaign.new(campaign: self)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Core
|
4
|
+
module Models
|
5
|
+
module Campaigns
|
6
|
+
# An invitation is the linked between a player and a campaign.
|
7
|
+
# It keeps the history of the interaction between the player and the campaign.
|
8
|
+
#
|
9
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
10
|
+
class Invitation
|
11
|
+
include Mongoid::Document
|
12
|
+
include Mongoid::Timestamps
|
13
|
+
include Core::Models::Concerns::Enumerable
|
14
|
+
include Core::Models::Concerns::Historizable
|
15
|
+
|
16
|
+
# @!attribute [rw] account
|
17
|
+
# @return [Core::Models::Account] the account the invitation has been issued to.
|
18
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :invitations
|
19
|
+
# @!attribute [rw] campaign
|
20
|
+
# @return [Core::Models::Campaign] the campaign the invitation has been made in.
|
21
|
+
belongs_to :campaign, class_name: 'Core::Models::Campaign', inverse_of: :invitations
|
22
|
+
|
23
|
+
# @!attribute [rw] status
|
24
|
+
# @return [Symbol] the current status of the invitation.
|
25
|
+
historize enum_field :status,
|
26
|
+
[:pending, :request, :accepted, :refused, :expelled, :left, :master, :creator],
|
27
|
+
default: :pending
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Core
|
4
|
+
module Models
|
5
|
+
module Campaigns
|
6
|
+
# A campaign tag is a string describing a characteristic of the campaign it's in.
|
7
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
8
|
+
class Tag
|
9
|
+
include Mongoid::Document
|
10
|
+
include Mongoid::Timestamps
|
11
|
+
|
12
|
+
# @!attribute [rw] content
|
13
|
+
# @return [String] the string content of the tag, describing a characteristic.
|
14
|
+
field :content, type: String
|
15
|
+
# @!attribute [rw] count
|
16
|
+
# @return [Integer] the number of campaigns this tag is in, avoiding a join.
|
17
|
+
field :count, type: Integer, default: 1
|
18
|
+
|
19
|
+
validates :content, presence: { message: 'required' }, uniqueness: { message: 'uniq' }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# The campaigns module is holding the logic for some objects related to campaigns.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Campaigns
|
6
|
+
autoload :Invitation, 'core/models/campaigns/invitation'
|
7
|
+
autoload :Tag , 'core/models/campaigns/tag'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Chatrooms
|
4
|
+
# The base chatroom class, made to be subclassed in campaign and personal chatrooms.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Base
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Timestamps
|
9
|
+
|
10
|
+
# @!attribute [rw] messages
|
11
|
+
# @return [Array<Core::Models::Chatrooms::Message>] the messages sent in this chatroom.
|
12
|
+
has_many :messages, class_name: 'Core::Models::Chatrooms::Message', inverse_of: :chatroom
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Chatrooms
|
4
|
+
# Represents the chatroom embedded in a campaign.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Campaign < Core::Models::Chatrooms::Base
|
7
|
+
# @!attribute [rw] campaign
|
8
|
+
# @return [Core::Models::Campaign] the campaign the chatroom is linked to.
|
9
|
+
embedded_in :campaign, class_name: 'Core::Models::Campaign', inverse_of: :chatroom
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Chatrooms
|
4
|
+
class Membership
|
5
|
+
include Mongoid::Document
|
6
|
+
include Mongoid::Timestamps
|
7
|
+
include Core::Models::Concerns::Enumerable
|
8
|
+
|
9
|
+
enum_field :status, [:shown, :hidden], default: :shown
|
10
|
+
|
11
|
+
belongs_to :chatroom, class_name: 'Core::Models::Chatrooms::Private', inverse_of: :memberships
|
12
|
+
|
13
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :memberships
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Chatrooms
|
4
|
+
# This model represents an in-game tchat message sent in the tchat of a campaign.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
class Message
|
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 message (plain text or command) contained in the data, used to parse and display it.
|
13
|
+
enum_field :type, [:text, :command], default: :text
|
14
|
+
# @!attribute [rw] data
|
15
|
+
# @return [Hash] the additional data passed to the message (arguments of the command, or content of the text)
|
16
|
+
field :data, type: Hash, default: {}
|
17
|
+
# @!attribute {rw} raw
|
18
|
+
# @return [String] the content as typed by the user, without any parsing or transformation.
|
19
|
+
field :raw, type: String, default: ''
|
20
|
+
# @!attribute [rw] deleted
|
21
|
+
# @return [Boolean] TRUE if the message has been marked as deleted by its user, FALSE otherwise.
|
22
|
+
field :deleted, type: Boolean, default: false
|
23
|
+
|
24
|
+
# @!attribute [rw] campaign
|
25
|
+
# @return [Core::Models::Chatrooms::Campaign] the chatroom in which the message has been emitted.
|
26
|
+
belongs_to :chatroom, class_name: 'Core::Models::Chatrooms::Campaign', inverse_of: :messages
|
27
|
+
# @!attribute [rw] player
|
28
|
+
# @return [Core::Models::Account] the account that has emitted the message in the campaign.
|
29
|
+
belongs_to :account, class_name: 'Core::Models::Account', inverse_of: :messages
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
# The chatrooms modules regroup all classes concerning messages between players.
|
4
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
5
|
+
module Chatrooms
|
6
|
+
autoload :Base , 'core/models/chatrooms/base'
|
7
|
+
autoload :Campaign , 'core/models/chatrooms/campaign'
|
8
|
+
autoload :Conversation, 'core/models/chatrooms/conversation'
|
9
|
+
autoload :Message , 'core/models/chatrooms/message'
|
10
|
+
autoload :Membership , 'core/models/chatrooms/membership'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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 Activable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# @!attribute [rw] active
|
11
|
+
# @return [Boolean] the active status of the instance, indicating if someone has deactivated it or not.
|
12
|
+
field :active, type: Boolean, default: true
|
13
|
+
|
14
|
+
scope :active , ->{ where(active: true) }
|
15
|
+
scope :inactive, ->{ where(active: false) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Includes the diagnostic URL field, and the related validations.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Diagnosticable
|
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
|
+
included do
|
12
|
+
# @!attribute [rw] diagnostic
|
13
|
+
# @return [String] the diagnostic URL to know the status of an entity (usually a gateway, or an instance of a service).
|
14
|
+
field :diagnostic, type: String, default: '/status'
|
15
|
+
|
16
|
+
validates :diagnostic,
|
17
|
+
presence: {message: "required"},
|
18
|
+
length: {minimum: 4, message: "minlength"},
|
19
|
+
format: {with: /\A(\/[a-z]+)+\z/, message: "pattern"}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Defines enumerations for the Mongoid models. An enumeration is a field that can only use a given set of values.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Enumerable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
# Submodule holding all the static methods add to the current subclass.
|
10
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
# Creates the field with the given name, set of possible values, and options.
|
14
|
+
# @param field_name [String] the name of the enumerated field.
|
15
|
+
# @param values [Array<Symbol>] the possible values of the enumerated field.
|
16
|
+
# @param options [Hash<Symbol, Any>] the possible options for the field.
|
17
|
+
def enum_field(field_name, values, options = {})
|
18
|
+
returned = field :"enum_#{field_name}", type: Symbol, default: options[:default]
|
19
|
+
|
20
|
+
validates :"enum_#{field_name}", inclusion: {in: values.map(&:to_sym), message: 'inclusion'}
|
21
|
+
|
22
|
+
define_method field_name do
|
23
|
+
return self["enum_#{field_name}"]
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method "#{field_name}=" do |value|
|
27
|
+
if values.include? value.to_sym
|
28
|
+
self["enum_#{field_name}"] = value.to_sym
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
values.map(&:to_sym).each do |value|
|
33
|
+
define_method "#{field_name}_#{value}!" do
|
34
|
+
self["enum_#{field_name}"] = value
|
35
|
+
end
|
36
|
+
|
37
|
+
define_method "#{field_name}_#{value}?" do
|
38
|
+
self["enum_#{field_name}"] == value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# This is to make enumerations historizable by
|
43
|
+
# returning the field object created by Mongoid.
|
44
|
+
returned
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Core
|
4
|
+
module Models
|
5
|
+
module Concerns
|
6
|
+
# This module is what I call "a beautiful piece of Ruby engineering"
|
7
|
+
# It takes any mongoid field that you may have declared, and historizes
|
8
|
+
# it in a dedicated relation if this relation does not already exists.
|
9
|
+
#
|
10
|
+
# What it does exactly :
|
11
|
+
# - Creates the :history relation if it does not already exists.
|
12
|
+
# - Creates a method to check for changes of a specific attribute.
|
13
|
+
# - Check for changes at initialization to insert the first value.
|
14
|
+
# - Check for changes at update/save to store the history.
|
15
|
+
#
|
16
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
17
|
+
module Historizable
|
18
|
+
extend ActiveSupport::Concern
|
19
|
+
|
20
|
+
# Adds an entry in the history table for the given field.
|
21
|
+
# It checks several things to make the history entry valid :
|
22
|
+
# - the new value is different from the old value
|
23
|
+
# - the old value is identical to the last recorded new value.
|
24
|
+
#
|
25
|
+
# @param field [String] the name of the field to historize
|
26
|
+
# @param from [Any] the old value before update
|
27
|
+
# @param to [Any] the new value after update.
|
28
|
+
def add_history(field:, from:, to:)
|
29
|
+
return if from == to
|
30
|
+
return if !history.empty? && history.order_by(:created_at.desc).first.to != from
|
31
|
+
|
32
|
+
event = Core::Models::Event.create(field: field, from: from, to: to, document: self)
|
33
|
+
event.save
|
34
|
+
end
|
35
|
+
|
36
|
+
# Submodule holding all the static methods add to the current subclass.
|
37
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
38
|
+
module ClassMethods
|
39
|
+
|
40
|
+
# Takes the Mongoid declared field and creates the callbacks
|
41
|
+
# to intercept any value change and add it to the history.
|
42
|
+
# @field field [Mongoid::Fields::Standard] the Mongoid field to historize.
|
43
|
+
def historize(field)
|
44
|
+
|
45
|
+
unless relations.key?('history')
|
46
|
+
embeds_many :history, class_name: 'Core::Models::Event'
|
47
|
+
end
|
48
|
+
|
49
|
+
after_initialize do |doc|
|
50
|
+
add_history(field: field.name, from: nil, to: doc[field.name])
|
51
|
+
end
|
52
|
+
|
53
|
+
after_save do |doc|
|
54
|
+
if doc.changed_attributes.key?(field.name)
|
55
|
+
from = doc.changed_attributes[field.name]
|
56
|
+
add_history(field: field.name, from: from, to: doc[field.name])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Includes the MIME type field to files to ensure only supported types are included.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module MimeTypable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
# Submodule holding all the static methods add to the current subclass.
|
10
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
11
|
+
module ClassMethods
|
12
|
+
# Defines the MIME type attribute with the given possible MIME types.
|
13
|
+
# @param values [Array<String>] the possible MIME types, * can be used as wild cards.
|
14
|
+
def mime_type(values)
|
15
|
+
|
16
|
+
# @!attribute [rw] mime_type
|
17
|
+
# @return [String] the MIME type of the file, obtained from the uploaded file.
|
18
|
+
field :mime_type, type: String
|
19
|
+
|
20
|
+
validates :mime_type, presence: {message: 'required'}
|
21
|
+
|
22
|
+
validate :mime_type_validity, if: :mime_type?
|
23
|
+
|
24
|
+
# Validates the validity of the MIME type by checking if it respects any of the given mime types.
|
25
|
+
# If it does not respect any MIME types possible, it adds an error to the mime_type field and invalidates.
|
26
|
+
define_method :mime_type_validity do
|
27
|
+
checked_types = if values.is_a? Symbol
|
28
|
+
self.send(values) rescue []
|
29
|
+
else
|
30
|
+
values
|
31
|
+
end
|
32
|
+
return true if checked_types.empty?
|
33
|
+
checked_types.each do |type|
|
34
|
+
type_regex = ::Regexp.new("^#{type.sub(/\*/, '(.+)')}$")
|
35
|
+
return true if !type_regex.match(mime_type).nil?
|
36
|
+
end
|
37
|
+
errors.add(:mime_type, 'pattern')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Core
|
2
|
+
module Models
|
3
|
+
module Concerns
|
4
|
+
# Includes the premium field to make the entity including it accessible only to premium applications or not.
|
5
|
+
# @author Vincent Courtois <courtois.vincent@outlook.com>
|
6
|
+
module Premiumable
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# @!attribute [rw] premium
|
11
|
+
# @return [Boolean] TRUE if the entity is made to be accessible only to premiuma pplications, FALSE otherwise.
|
12
|
+
field :premium, type: Boolean, default: false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|