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
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
|