summaryrefslogtreecommitdiffstats
path: root/src/RankManager.h
blob: 3ccbd2fd4968215291783320757a43a11af1d936 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

// RankManager.h

// Declares the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players




#pragma once

#include "SQLiteCpp/Database.h"
#include "SQLiteCpp/Transaction.h"





class cMojangAPI;





class cRankManager
{
public:
	/** Acquire this lock to perform mass changes.
	Improves performance by wrapping everything into a transaction.
	Makes sure that no other thread is accessing the DB. */
	class cMassChangeLock
	{
	public:
		cMassChangeLock(cRankManager & a_RankManager) :
			m_Lock(a_RankManager.m_CS),
			m_Transaction(a_RankManager.m_DB)
		{
		}
		
		~cMassChangeLock()
		{
			m_Transaction.commit();
		}
		
	protected:
		cCSLock m_Lock;
		SQLite::Transaction m_Transaction;
	};
	
	
	/** Creates the rank manager. Needs to be initialized before other use. */
	cRankManager(void);
	
	/** Initializes the rank manager. Performs migration and default-setting if no data is found in the DB.
	The a_MojangAPI param is used when migrating from old ini files, to look up player UUIDs. */
	void Initialize(cMojangAPI & a_MojangAPI);
	
	/** Returns the name of the rank that the specified player has assigned to them. */
	AString GetPlayerRankName(const AString & a_PlayerUUID);
	
	/** Returns the names of Groups that the specified player has assigned to them. */
	AStringVector GetPlayerGroups(const AString & a_PlayerUUID);
	
	/** Returns the permissions that the specified player has assigned to them. */
	AStringVector GetPlayerPermissions(const AString & a_PlayerUUID);
	
	/** Returns the names of groups that the specified rank has assigned to it.
	Returns an empty vector if the rank doesn't exist. */
	AStringVector GetRankGroups(const AString & a_RankName);
	
	/** Returns the permissions that the specified group has assigned to it.
	Returns an empty vector if the group doesn't exist. */
	AStringVector GetGroupPermissions(const AString & a_GroupName);
	
	/** Returns all permissions that the specified rank has assigned to it, through all its groups.
	Returns an empty vector if the rank doesn't exist. Any non-existent groups are ignored. */
	AStringVector GetRankPermissions(const AString & a_RankName);
	
	/** Returns the names of all defined ranks. */
	AStringVector GetAllRanks(void);
	
	/** Returns the names of all permission groups. */
	AStringVector GetAllGroups(void);
	
	/** Returns all the distinct permissions that are stored in the DB. */
	AStringVector GetAllPermissions(void);
	
	/** Returns the message visuals (prefix, postfix, color) for the specified player.
	Returns true if the visuals were read from the DB, false if not (player not found etc). */
	bool GetPlayerMsgVisuals(
		const AString & a_PlayerUUID,
		AString & a_MsgPrefix,
		AString & a_MsgSuffix,
		AString & a_MsgNameColorCode
	);
	
	/** Adds a new rank. No action if the rank already exists. */
	void AddRank(
		const AString & a_RankName,
		const AString & a_MsgPrefix,
		const AString & a_MsgSuffix,
		const AString & a_MsgNameColorCode
	);
	
	/** Adds a new permission group. No action if such a group already exists. */
	void AddGroup(const AString & a_GroupName);
	
	/** Bulk-adds groups. Group names that already exist are silently skipped. */
	void AddGroups(const AStringVector & a_GroupNames);
	
	/** Adds the specified permission group to the specified rank.
	Fails if the rank or group names are not found.
	Returns true if successful, false on error. */
	bool AddGroupToRank(const AString & a_GroupName, const AString & a_RankName);
	
	/** Adds the specified permission to the specified permission group.
	Fails if the permission group name is not found.
	Returns true if successful, false on error. */
	bool AddPermissionToGroup(const AString & a_Permission, const AString & a_GroupName);
	
	/** Adds the specified permissions to the specified permission group.
	Fails if the permission group name is not found.
	Returns true if successful, false on error. */
	bool AddPermissionsToGroup(const AStringVector & a_Permissions, const AString & a_GroupName);
	
	/** Removes the specified rank.
	All players assigned to that rank will be re-assigned to a_ReplacementRankName.
	If a_ReplacementRankName is empty or not a valid rank, the player will be removed from the DB,
	which means they will receive the default rank the next time they are queried. */
	void RemoveRank(const AString & a_RankName, const AString & a_ReplacementRankName);
	
	/** Removes the specified group completely.
	The group will first be removed from all ranks using it, and then removed itself. */
	void RemoveGroup(const AString & a_GroupName);
	
	/** Removes the specified group from the specified rank.
	The group will stay defined, even if no rank is using it. */
	void RemoveGroupFromRank(const AString & a_GroupName, const AString & a_RankName);
	
	/** Removes the specified permission from the specified group. */
	void RemovePermissionFromGroup(const AString & a_Permission, const AString & a_GroupName);
	
	/** Renames the specified rank. No action if the rank name is not found.
	Fails if the new name is already used.
	Returns true on success, false on failure. */
	bool RenameRank(const AString & a_OldName, const AString & a_NewName);
	
	/** Renames the specified group. No action if the rank name is not found.
	Fails if the new name is already used.
	Returns true on success, false on failure. */
	bool RenameGroup(const AString & a_OldName, const AString & a_NewName);
	
	/** Sets the specified player's rank.
	If the player already had rank assigned to them, it is overwritten with the new rank and name.
	Note that this doesn't change the cPlayer if the player is already connected, you need to update all the
	cPlayer instances manually.
	The PlayerName is provided for reference, so that GetRankPlayerNames() can work. */
	void SetPlayerRank(const AString & a_PlayerUUID, const AString & a_PlayerName, const AString & a_RankName);
	
	/** Sets the message visuals of an existing rank. No action if the rank name is not found. */
	void SetRankVisuals(
		const AString & a_RankName,
		const AString & a_MsgPrefix,
		const AString & a_MsgSuffix,
		const AString & a_MsgNameColorCode
	);
	
	/** Returns the message visuals of an existing rank.
	Returns true if successful, false on error (rank doesn't exist). */
	bool GetRankVisuals(
		const AString & a_RankName,
		AString & a_MsgPrefix,
		AString & a_MsgSuffix,
		AString & a_MsgNameColorCode
	);
	
	/** Returns true iff the specified rank exists in the DB. */
	bool RankExists(const AString & a_RankName);
	
	/** Returns true iff the specified group exists in the DB. */
	bool GroupExists(const AString & a_GroupName);
	
	/** Returns true iff the specified player has a rank assigned to them in the DB. */
	bool IsPlayerRankSet(const AString & a_PlayerUUID);
	
	/** Returns true iff the specified rank contains the specified group. */
	bool IsGroupInRank(const AString & a_GroupName, const AString & a_RankName);
	
	/** Returns true iff the specified group contains the specified permission. */
	bool IsPermissionInGroup(const AString & a_Permission, const AString & a_GroupName);
	
protected:

	/** The database storage for all the data. Protected by m_CS. */
	SQLite::Database m_DB;
	
	/** The mutex protecting m_DB against multi-threaded access. */
	cCriticalSection m_CS;
	
	/** Set to true once the manager is initialized. */
	bool m_IsInitialized;
	
	
	/** Returns true if all the DB tables are empty, indicating a fresh new install. */
	bool AreDBTablesEmpty(void);
	
	/** Returns true iff the specified DB table is empty.
	If there's an error while querying, returns false. */
	bool IsDBTableEmpty(const AString & a_TableName);
} ;