2014-08-05 16:37:00 +00:00
// RankManager.cpp
// Implements the cRankManager class that represents the rank manager responsible for assigning permissions and message visuals to players
# include "Globals.h"
# include "RankManager.h"
2014-08-08 08:02:25 +00:00
# include "SQLiteCpp/Transaction.h"
2014-08-13 07:53:33 +00:00
# include "inifile/iniFile.h"
# include "Protocol/MojangAPI.h"
2014-08-05 16:37:00 +00:00
2014-08-08 19:30:47 +00:00
/*
2014-08-05 16:37:00 +00:00
// This code is for internal testing while developing the cRankManager class
static class cRankMgrTest
{
public :
cRankMgrTest ( void ) :
m_Mgr ( )
{
2014-08-08 08:02:25 +00:00
// Initialize logging:
new cMCLogger ( ) ;
AString UUID = " b1caf24202a841a78055a079c460eee7 " ; // UUID for "xoft"
LOG ( " Testing UUID %s " , UUID . c_str ( ) ) ;
2014-08-05 16:37:00 +00:00
2014-08-08 08:02:25 +00:00
// Test the initial state of the ranks:
LOG ( " Initial test: " ) ;
ReportPlayer ( UUID ) ;
// Add a rank, a few groups and permissions and set the player to use them:
LOG ( " Adding data... " ) ;
2014-08-08 19:30:47 +00:00
m_Mgr . AddRank ( " TestRank1 " , " [test] " , " [/test] " , " 7 " ) ;
m_Mgr . AddRank ( " TestRank2 " , " [t2] " , " [/t2] " , " 8 " ) ;
2014-08-08 08:02:25 +00:00
m_Mgr . AddGroup ( " TestGroup1 " ) ;
m_Mgr . AddGroup ( " TestGroup2 " ) ;
2014-08-08 19:30:47 +00:00
m_Mgr . AddGroupToRank ( " TestGroup1 " , " TestRank1 " ) ;
m_Mgr . AddGroupToRank ( " TestGroup2 " , " TestRank1 " ) ;
m_Mgr . AddGroupToRank ( " TestGroup2 " , " TestRank2 " ) ;
2014-08-08 08:02:25 +00:00
m_Mgr . AddPermissionToGroup ( " testpermission1.1 " , " TestGroup1 " ) ;
m_Mgr . AddPermissionToGroup ( " testpermission1.2 " , " TestGroup1 " ) ;
2014-08-08 19:30:47 +00:00
m_Mgr . AddPermissionToGroup ( " testpermission1.3 " , " TestGroup1 " ) ;
m_Mgr . AddPermissionToGroup ( " common " , " TestGroup1 " ) ;
2014-08-08 08:02:25 +00:00
m_Mgr . AddPermissionToGroup ( " testpermission2.1 " , " TestGroup2 " ) ;
2014-08-08 19:30:47 +00:00
m_Mgr . AddPermissionToGroup ( " common " , " TestGroup2 " ) ;
m_Mgr . SetPlayerRank ( UUID , " xoft " , " TestRank1 " ) ;
2014-08-08 08:02:25 +00:00
// Test the added data:
LOG ( " Testing the added data: " ) ;
2014-08-08 19:30:47 +00:00
LOG ( " IsGroupInRank(TestGroup1, TestRank1) = %s " , m_Mgr . IsGroupInRank ( " TestGroup1 " , " TestRank1 " ) ? " true " : " false " ) ;
LOG ( " IsGroupInRank(TestGroup3, TestRank1) = %s " , m_Mgr . IsGroupInRank ( " TestGroup3 " , " TestRank1 " ) ? " true " : " false " ) ;
LOG ( " IsPermissionInGroup(testpermission1.2, TestGroup1) = %s " , m_Mgr . IsPermissionInGroup ( " testpermission1.2 " , " TestGroup1 " ) ? " true " : " false " ) ; // Existing permission, in group
LOG ( " IsPermissionInGroup(testpermission1.2, TestGroup2) = %s " , m_Mgr . IsPermissionInGroup ( " testpermission1.2 " , " TestGroup2 " ) ? " true " : " false " ) ; // Existing permission, not in group
LOG ( " IsPermissionInGroup(testpermission1.9, TestGroup2) = %s " , m_Mgr . IsPermissionInGroup ( " testpermission1.9 " , " TestGroup2 " ) ? " true " : " false " ) ; // Non-existing permission
2014-08-08 08:02:25 +00:00
LOG ( " IsPlayerRankSet(%s) = %s " , UUID . c_str ( ) , m_Mgr . IsPlayerRankSet ( UUID ) ? " true " : " false " ) ;
LOG ( " IsPlayerRankSet(%s1) = %s " , UUID . c_str ( ) , m_Mgr . IsPlayerRankSet ( UUID + " 1 " ) ? " true " : " false " ) ;
LOG ( " GroupExists(TestGroup1) = %s " , m_Mgr . GroupExists ( " TestGroup1 " ) ? " true " : " false " ) ;
LOG ( " GroupExists(TestGroup3) = %s " , m_Mgr . GroupExists ( " TestGroup3 " ) ? " true " : " false " ) ;
2014-08-08 19:30:47 +00:00
LOG ( " RankExists(TestRank1) = %s " , m_Mgr . RankExists ( " TestRank1 " ) ? " true " : " false " ) ;
2014-08-08 08:02:25 +00:00
LOG ( " RankExists(NonexistentRank) = %s " , m_Mgr . RankExists ( " NonexistentRank " ) ? " true " : " false " ) ;
2014-08-08 19:30:47 +00:00
ReportRankGroups ( " TestRank1 " ) ;
2014-08-08 14:38:38 +00:00
ReportRankGroups ( " NonexistentRank " ) ;
ReportGroupPermissions ( " TestGroup1 " ) ;
ReportGroupPermissions ( " NonexistentGroup " ) ;
// Report the contents of the DB:
ReportAll ( ) ;
2014-08-08 08:02:25 +00:00
// Test the assignments above:
LOG ( " After-assignment test: " ) ;
ReportPlayer ( UUID ) ;
2014-08-08 19:30:47 +00:00
// Test removing a permission from a group:
LOG ( " Removing permission testpermission1.3 from group TestGroup1. " ) ;
m_Mgr . RemovePermissionFromGroup ( " testpermission1.3 " , " TestGroup1 " ) ;
ReportGroupPermissions ( " TestGroup1 " ) ;
LOG ( " Removing permission common from group TestGroup1. " ) ;
m_Mgr . RemovePermissionFromGroup ( " common " , " TestGroup1 " ) ;
ReportGroupPermissions ( " TestGroup1 " ) ; // Check that it's not present
ReportGroupPermissions ( " TestGroup2 " ) ; // Check that it's still present here
// Test removing a group from rank:
LOG ( " Removing group TestGroup2 from rank TestRank1. " ) ;
m_Mgr . RemoveGroupFromRank ( " TestGroup2 " , " TestRank1 " ) ;
ReportRankGroups ( " TestRank1 " ) ;
LOG ( " Removing group TestGroup3 from rank TestRank1. " ) ;
m_Mgr . RemoveGroupFromRank ( " TestGroup3 " , " TestRank1 " ) ;
ReportRankGroups ( " TestRank1 " ) ;
// Test re-adding the groups:
LOG ( " Re-adding groups to TestRank1. " ) ;
m_Mgr . AddGroupToRank ( " TestGroup1 " , " TestRank1 " ) ;
m_Mgr . AddGroupToRank ( " TestGroup2 " , " TestRank1 " ) ;
ReportRankGroups ( " TestRank1 " ) ;
// Test removing a group altogether:
LOG ( " Removing group TestGroup2 " ) ;
m_Mgr . RemoveGroup ( " TestGroup2 " ) ;
ReportAll ( ) ;
// Test removing a rank:
LOG ( " Removing rank TestRank2, replacing with rank TestRank1. " ) ;
m_Mgr . RemoveRank ( " TestRank2 " , " TestRank1 " ) ;
ReportAll ( ) ;
LOG ( " Removing rank Test altogether. " ) ;
m_Mgr . RemoveRank ( " Test " , " " ) ;
ReportAll ( ) ;
// Test renaming a rank:
LOG ( " Renaming rank TestRank1 to Test " ) ;
m_Mgr . RenameRank ( " TestRank1 " , " Test " ) ;
ReportRankGroups ( " TestRank1 " ) ;
ReportRankGroups ( " Test " ) ;
LOG ( " Player after renaming: " ) ;
ReportPlayer ( UUID ) ;
// Test renaming a group:
LOG ( " Renaming group TestGroup1 to Test " ) ;
m_Mgr . RenameGroup ( " TestGroup1 " , " Test " ) ;
ReportGroupPermissions ( " TestGroup1 " ) ;
ReportGroupPermissions ( " Test " ) ;
LOG ( " Player after renaming: " ) ;
ReportPlayer ( UUID ) ;
m_Mgr . RenameGroup ( " Test " , " TestGroup1 " ) ;
2014-08-08 08:02:25 +00:00
2014-08-08 19:30:47 +00:00
// Test removing the rank in favor of another one:
m_Mgr . RemoveRank ( " Test " , " TestRank2 " ) ;
LOG ( " After-removal test: " ) ;
ReportPlayer ( UUID ) ;
2014-08-08 08:02:25 +00:00
LOG ( " Done. " ) ;
2014-08-05 16:37:00 +00:00
}
2014-08-08 14:38:38 +00:00
void ReportAll ( void )
{
// Report all ranks:
AStringVector Ranks = m_Mgr . GetAllRanks ( ) ;
LOG ( " All ranks (%u): " , ( unsigned ) Ranks . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Ranks . begin ( ) , end = Ranks . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
// Report all groups:
AStringVector Groups = m_Mgr . GetAllGroups ( ) ;
LOG ( " All groups (%u): " , ( unsigned ) Groups . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Groups . begin ( ) , end = Groups . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
// Report all permissions:
AStringVector Permissions = m_Mgr . GetAllPermissions ( ) ;
LOG ( " All permissions (%u): " , ( unsigned ) Permissions . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Permissions . begin ( ) , end = Permissions . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
}
2014-08-08 08:02:25 +00:00
void ReportPlayer ( const AString & a_PlayerUUID )
2014-08-05 16:37:00 +00:00
{
// Get the player's UUID and rank:
2014-08-08 08:02:25 +00:00
LOG ( " Rank: '%s' " , m_Mgr . GetPlayerRankName ( a_PlayerUUID ) . c_str ( ) ) ;
2014-08-05 16:37:00 +00:00
// List all the permission groups for the player:
2014-08-08 08:02:25 +00:00
AStringVector Groups = m_Mgr . GetPlayerGroups ( a_PlayerUUID ) ;
2014-08-08 14:38:38 +00:00
LOG ( " Groups (%u): " , ( unsigned ) Groups . size ( ) ) ;
2014-08-05 16:37:00 +00:00
for ( AStringVector : : const_iterator itr = Groups . begin ( ) , end = Groups . end ( ) ; itr ! = end ; + + itr )
{
2014-08-08 08:02:25 +00:00
LOG ( " '%s' " , itr - > c_str ( ) ) ;
2014-08-05 16:37:00 +00:00
} // for itr - Groups[]
// List all the permissions for the player:
2014-08-08 08:02:25 +00:00
AStringVector Permissions = m_Mgr . GetPlayerPermissions ( a_PlayerUUID ) ;
2014-08-08 14:38:38 +00:00
LOG ( " Permissions (%u): " , ( unsigned ) Permissions . size ( ) ) ;
2014-08-05 16:37:00 +00:00
for ( AStringVector : : const_iterator itr = Permissions . begin ( ) , end = Permissions . end ( ) ; itr ! = end ; + + itr )
{
2014-08-08 08:02:25 +00:00
LOG ( " '%s' " , itr - > c_str ( ) ) ;
2014-08-05 16:37:00 +00:00
} // for itr - Groups[]
}
2014-08-08 14:38:38 +00:00
void ReportRankGroups ( const AString & a_RankName )
{
AStringVector Groups = m_Mgr . GetRankGroups ( a_RankName ) ;
LOG ( " Groups in rank %s: %u " , a_RankName . c_str ( ) , ( unsigned ) Groups . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Groups . begin ( ) , end = Groups . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
AStringVector Permissions = m_Mgr . GetRankPermissions ( a_RankName ) ;
LOG ( " Permissions in rank %s: %u " , a_RankName . c_str ( ) , ( unsigned ) Permissions . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Permissions . begin ( ) , end = Permissions . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
}
void ReportGroupPermissions ( const AString & a_GroupName )
{
AStringVector Permissions = m_Mgr . GetGroupPermissions ( a_GroupName ) ;
LOG ( " Permissions in group %s: %u " , a_GroupName . c_str ( ) , ( unsigned ) Permissions . size ( ) ) ;
for ( AStringVector : : const_iterator itr = Permissions . begin ( ) , end = Permissions . end ( ) ; itr ! = end ; + + itr )
{
LOG ( " '%s' " , itr - > c_str ( ) ) ;
}
}
2014-08-05 16:37:00 +00:00
protected :
cRankManager m_Mgr ;
} g_RankMgrTest ;
//*/
2014-08-13 07:53:33 +00:00
////////////////////////////////////////////////////////////////////////////////
/** Migrates from groups.ini and users.ini into the rankmanager DB */
class cRankManagerIniMigrator
{
public :
cRankManagerIniMigrator ( cRankManager & a_RankManager , cMojangAPI & a_MojangAPI ) :
m_RankManager ( a_RankManager ) ,
m_MojangAPI ( a_MojangAPI )
{
}
/** Performs the complete migration from INI files to DB. */
bool Migrate ( void )
{
LOGD ( " Reading groups... " ) ;
if ( ! ReadGroups ( ) )
{
return false ;
}
LOGD ( " Cleaning groups inheritance... " ) ;
CleanGroupInheritance ( ) ;
LOGD ( " Creating groups... " ) ;
CreateGroups ( ) ;
LOGD ( " Reading users... " ) ;
if ( ! ReadUsers ( ) )
{
return false ;
}
LOGD ( " Cleaning user groups... " ) ;
CleanUserGroups ( ) ;
LOGD ( " Resolving user UUIDs... " ) ;
ResolveUserUUIDs ( ) ;
LOGD ( " Setting ranks... " ) ;
SetRanks ( ) ;
return true ;
}
protected :
/** Container for a group read from an INI file. */
struct sGroup
{
AString m_Name ;
AString m_Color ;
AStringVector m_Inherits ;
AStringVector m_Permissions ;
sGroup ( void ) { }
sGroup ( const AString & a_Name , const AString & a_Color , const AStringVector & a_Inherits , const AStringVector & a_Permissions ) :
m_Name ( a_Name ) ,
m_Color ( a_Color ) ,
m_Inherits ( a_Inherits ) ,
m_Permissions ( a_Permissions )
{
}
} ;
typedef std : : map < AString , sGroup > sGroupMap ;
/** Container for a single user read from an INI file. */
struct sUser
{
AString m_Name ;
AStringVector m_Groups ;
/** Assigned by ResolveUserUUIDs() */
AString m_UUID ;
sUser ( void ) { }
sUser ( const AString & a_Name , const AStringVector & a_Groups ) :
m_Name ( a_Name ) ,
m_Groups ( a_Groups )
{
}
} ;
typedef std : : map < AString , sUser > sUserMap ;
typedef std : : map < AString , AString > cStringMap ;
/** The parent Rank manager where we will create the groups, ranks and players */
cRankManager & m_RankManager ;
/** The player name to UUID resolver */
cMojangAPI & m_MojangAPI ;
/** List of all groups read from the ini file */
sGroupMap m_Groups ;
/** List of all players read from the ini file. */
sUserMap m_Users ;
/** Maps lists of groups to rank names.
Each group list is either a simple " <Group> " if there ' s only one group ,
or " <PrimaryGroup>,<FirstSecondaryGroup>,<SecondSecondaryGroup>... " , where the secondary groups are
lowercased and alpha - sorted . This makes the group lists comparable for equivalence , simply by comparing
their string names .
The ranks are named " <Group> " for single - group players , and " AutoMigratedRank_N " for the composite ranks ,
where N is a unique number . */
cStringMap m_GroupsToRanks ;
/** Reads the groups from the "groups.ini" file into m_Groups */
bool ReadGroups ( void )
{
// Read the file:
cIniFile Groups ;
if ( ! Groups . ReadFile ( " groups.ini " ) )
{
return false ;
}
// Read all the groups into a map:
int NumGroups = Groups . GetNumKeys ( ) ;
for ( int i = 0 ; i < NumGroups ; i + + )
{
AString GroupName = Groups . GetKeyName ( i ) ;
AString lcGroupName = StrToLower ( GroupName ) ;
if ( m_Groups . find ( lcGroupName ) ! = m_Groups . end ( ) )
{
LOGINFO ( " groups.ini contains a duplicate definition of group %s, ignoring the latter. " , GroupName . c_str ( ) ) ;
continue ;
}
m_Groups [ lcGroupName ] = sGroup (
GroupName ,
Groups . GetValue ( GroupName , " Color " , " " ) ,
StringSplitAndTrim ( Groups . GetValue ( GroupName , " Inherits " ) , " , " ) ,
StringSplitAndTrim ( Groups . GetValue ( GroupName , " Permissions " ) , " , " )
) ;
} // for i - Groups' keys
return true ;
}
/** Removes non-existent groups from all the groups' inheritance */
void CleanGroupInheritance ( void )
{
for ( sGroupMap : : iterator itrG = m_Groups . begin ( ) , endG = m_Groups . end ( ) ; itrG ! = endG ; + + itrG )
{
AStringVector & Inherits = itrG - > second . m_Inherits ;
for ( AStringVector : : iterator itrI = Inherits . begin ( ) ; itrI ! = Inherits . end ( ) ; )
{
AString lcInherits = StrToLower ( * itrI ) ;
if ( m_Groups . find ( lcInherits ) ! = m_Groups . end ( ) )
{
// Inherited group exists, continue checking the next one
+ + itrI ;
continue ;
}
// Inherited group doesn't exist, remove it from the list:
LOGWARNING ( " RankMigrator: Group \" %s \" inherits from a non-existent group \" %s \" , this inheritance will be ignored. " ,
itrG - > second . m_Name . c_str ( ) , itrI - > c_str ( )
) ;
AStringVector : : iterator itrI2 = itrI ;
+ + itrI2 ;
Inherits . erase ( itrI ) ;
itrI = itrI2 ;
} // for itrI - Inherits[]
} // for itrG - m_Groups[]
}
/** Reads the users from the "users.ini" file into m_Users */
bool ReadUsers ( void )
{
// Read the file:
cIniFile Users ;
if ( ! Users . ReadFile ( " users.ini " ) )
{
return false ;
}
// Read all the users into a map:
int NumUsers = Users . GetNumKeys ( ) ;
for ( int i = 0 ; i < NumUsers ; i + + )
{
AString UserName = Users . GetKeyName ( i ) ;
AString lcUserName = StrToLower ( UserName ) ;
if ( m_Users . find ( lcUserName ) ! = m_Users . end ( ) )
{
LOGINFO ( " users.ini contains a duplicate definition of user %s, ignoring the latter. " , UserName . c_str ( ) ) ;
continue ;
}
m_Users [ lcUserName ] = sUser (
UserName ,
StringSplitAndTrim ( Users . GetValue ( UserName , " Groups " , " " ) , " , " )
) ;
} // for i - Users' keys
return true ;
}
/** Removes non-existent groups from each user's definition. */
void CleanUserGroups ( void )
{
for ( sUserMap : : iterator itrU = m_Users . begin ( ) , endU = m_Users . end ( ) ; itrU ! = endU ; + + itrU )
{
AStringVector & Groups = itrU - > second . m_Groups ;
for ( AStringVector : : iterator itrG = Groups . begin ( ) ; itrG ! = Groups . end ( ) ; )
{
AString lcGroup = StrToLower ( * itrG ) ;
if ( m_Groups . find ( lcGroup ) ! = m_Groups . end ( ) )
{
// Assigned group exists, continue checking the next one
+ + itrG ;
continue ;
}
// Assigned group doesn't exist, remove it from the list:
LOGWARNING ( " RankMigrator: User \" %s \" is assigned a non-existent group \" %s \" , this assignment will be ignored. " ,
itrU - > second . m_Name . c_str ( ) , itrG - > c_str ( )
) ;
AStringVector : : iterator itrG2 = itrG ;
+ + itrG2 ;
Groups . erase ( itrG ) ;
itrG = itrG2 ;
} // for itrG - Groups[]
} // for itrU - m_Users[]
}
/** Creates groups based on m_Groups.
Ignores group inheritance . */
void CreateGroups ( void )
{
// Create each group, with its permissions:
for ( sGroupMap : : const_iterator itr = m_Groups . begin ( ) , end = m_Groups . end ( ) ; itr ! = end ; + + itr )
{
m_RankManager . AddGroup ( itr - > second . m_Name ) ;
m_RankManager . AddPermissionsToGroup ( itr - > second . m_Permissions , itr - > second . m_Name ) ;
} // for itr - m_Groups[]
}
/** Resolves the UUID of each user in m_Users.
If a user doesn ' t resolve , they are removed and logged in the console . */
void ResolveUserUUIDs ( void )
{
// Resolve all PlayerNames at once (the API doesn't like single-name queries):
AStringVector PlayerNames ;
for ( sUserMap : : const_iterator itr = m_Users . begin ( ) , end = m_Users . end ( ) ; itr ! = end ; + + itr )
{
PlayerNames . push_back ( itr - > second . m_Name ) ;
}
m_MojangAPI . GetUUIDsFromPlayerNames ( PlayerNames ) ;
// Assign the UUIDs back to players, remove those not resolved:
for ( sUserMap : : iterator itr = m_Users . begin ( ) ; itr ! = m_Users . end ( ) ; )
{
AString UUID = m_MojangAPI . GetUUIDFromPlayerName ( itr - > second . m_Name ) ;
if ( UUID . empty ( ) )
{
LOGWARNING ( " RankMigrator: Cannot resolve player %s to UUID, player will be left unranked " , itr - > second . m_Name . c_str ( ) ) ;
sUserMap : : iterator itr2 = itr ;
+ + itr2 ;
m_Users . erase ( itr ) ;
itr = itr2 ;
}
else
{
itr - > second . m_UUID = UUID ;
+ + itr ;
}
}
}
/** Adds the specified groups to the specified ranks. Recurses on the groups' inheritance. */
void AddGroupsToRank ( const AStringVector & a_Groups , const AString & a_RankName )
{
for ( AStringVector : : const_iterator itr = a_Groups . begin ( ) , end = a_Groups . end ( ) ; itr ! = end ; + + itr )
{
// Normalize the group name:
sGroup & Group = m_Groups [ StrToLower ( * itr ) ] ;
// Avoid loops, check if the group is already added:
if ( m_RankManager . IsGroupInRank ( Group . m_Name , a_RankName ) )
{
continue ;
}
// Add the group, and all the groups it inherits from recursively:
m_RankManager . AddGroupToRank ( Group . m_Name , a_RankName ) ;
AddGroupsToRank ( Group . m_Inherits , a_RankName ) ;
} // for itr - a_Groups[]
}
/** Creates a rank for each player, based on the master groups they are assigned. */
void SetRanks ( void )
{
for ( sUserMap : : const_iterator itr = m_Users . begin ( ) , end = m_Users . end ( ) ; itr ! = end ; + + itr )
{
// Ignore users with no groups:
const AStringVector & Groups = itr - > second . m_Groups ;
if ( Groups . empty ( ) )
{
LOGWARNING ( " RankMigrator: Player %s has no groups assigned to them, skipping the player. " , itr - > second . m_Name . c_str ( ) ) ;
continue ;
}
// Compose the rank name out of group names:
AString RankName ;
for ( AStringVector : : const_iterator itrG = Groups . begin ( ) , endG = Groups . end ( ) ; itrG ! = endG ; + + itrG )
{
AString GroupName = m_Groups [ StrToLower ( * itrG ) ] . m_Name ; // Normalize group name
if ( ! RankName . empty ( ) )
{
RankName . push_back ( ' , ' ) ;
}
RankName . append ( GroupName ) ;
} // for itrG - Groups[]
// Create the rank, with al its groups:
if ( ! m_RankManager . RankExists ( RankName ) )
{
m_RankManager . AddRank ( RankName , " " , " " , m_Groups [ StrToLower ( Groups [ 0 ] ) ] . m_Color ) ;
AddGroupsToRank ( Groups , RankName ) ;
}
// Set the rank to the user:
m_RankManager . SetPlayerRank ( itr - > second . m_UUID , itr - > second . m_Name , RankName ) ;
} // for itr - m_Users[]
}
} ;
////////////////////////////////////////////////////////////////////////////////
// cRankManager:
2014-08-05 16:37:00 +00:00
cRankManager : : cRankManager ( void ) :
2014-08-13 07:53:33 +00:00
m_DB ( " Ranks.sqlite " , SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE ) ,
m_IsInitialized ( false )
{
}
void cRankManager : : Initialize ( cMojangAPI & a_MojangAPI )
2014-08-05 16:37:00 +00:00
{
2014-08-13 07:53:33 +00:00
ASSERT ( ! m_IsInitialized ) ; // Calling Initialize for the second time?
2014-08-05 16:37:00 +00:00
// Create the DB tables, if they don't exist:
2014-08-08 08:02:25 +00:00
m_DB . exec ( " CREATE TABLE IF NOT EXISTS Rank (RankID INTEGER PRIMARY KEY, Name, MsgPrefix, MsgSuffix, MsgNameColorCode) " ) ;
2014-08-05 20:32:26 +00:00
m_DB . exec ( " CREATE TABLE IF NOT EXISTS PlayerRank (PlayerUUID, PlayerName, RankID INTEGER) " ) ;
2014-08-08 07:56:28 +00:00
m_DB . exec ( " CREATE TABLE IF NOT EXISTS PermGroup (PermGroupID INTEGER PRIMARY KEY, Name) " ) ;
m_DB . exec ( " CREATE TABLE IF NOT EXISTS RankPermGroup (RankID INTEGER, PermGroupID INTEGER) " ) ;
m_DB . exec ( " CREATE TABLE IF NOT EXISTS PermissionItem (PermGroupID INTEGER, Permission) " ) ;
2014-08-05 16:37:00 +00:00
2014-08-13 07:53:33 +00:00
m_IsInitialized = true ;
// Check if tables empty, migrate from ini files then
if ( AreDBTablesEmpty ( ) )
{
LOGINFO ( " There are no ranks, migrating old-style INI files to new DB ranks... " ) ;
LOGINFO ( " (This might take a while) " ) ;
cRankManagerIniMigrator Migrator ( * this , a_MojangAPI ) ;
if ( Migrator . Migrate ( ) )
{
LOGINFO ( " Ranks migrated. " ) ;
return ;
}
}
// Migration failed.
2014-08-05 16:37:00 +00:00
// TODO: Check if tables empty, add some defaults then
}
AString cRankManager : : GetPlayerRankName ( const AString & a_PlayerUUID )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
2014-08-05 16:37:00 +00:00
{
2014-08-08 08:02:25 +00:00
SQLite : : Statement stmt ( m_DB , " SELECT Rank.Name FROM Rank LEFT JOIN PlayerRank ON Rank.RankID = PlayerRank.RankID WHERE PlayerRank.PlayerUUID = ? " ) ;
stmt . bind ( 1 , a_PlayerUUID ) ;
stmt . executeStep ( ) ;
if ( stmt . isDone ( ) )
{
// No data returned from the DB
return AString ( ) ;
}
return stmt . getColumn ( 0 ) . getText ( ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Cannot get player rank name: %s " , __FUNCTION__ , ex . what ( ) ) ;
2014-08-05 16:37:00 +00:00
}
2014-08-08 08:02:25 +00:00
return AString ( ) ;
2014-08-05 16:37:00 +00:00
}
2014-08-08 07:56:28 +00:00
AStringVector cRankManager : : GetPlayerGroups ( const AString & a_PlayerUUID )
2014-08-05 16:37:00 +00:00
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-05 16:37:00 +00:00
AStringVector res ;
2014-08-08 08:02:25 +00:00
try
2014-08-05 16:37:00 +00:00
{
2014-08-08 08:02:25 +00:00
// Prepare the DB statement:
SQLite : : Statement stmt ( m_DB ,
" SELECT PermGroup.Name FROM PermGroup "
" LEFT JOIN RankPermGroup "
" ON PermGroup.PermGroupID = RankPermGroup.PermGroupID "
" LEFT JOIN PlayerRank "
" ON PlayerRank.RankID = RankPermGroup.RankID "
" WHERE PlayerRank.PlayerUUID = ? "
) ;
stmt . bind ( 1 , a_PlayerUUID ) ;
// Execute and get results:
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Cannot get player groups: %s " , __FUNCTION__ , ex . what ( ) ) ;
2014-08-05 16:37:00 +00:00
}
return res ;
}
AStringVector cRankManager : : GetPlayerPermissions ( const AString & a_PlayerUUID )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-05 16:37:00 +00:00
AStringVector res ;
2014-08-08 08:02:25 +00:00
try
{
// Prepare the DB statement:
SQLite : : Statement stmt ( m_DB ,
2014-08-08 19:30:47 +00:00
" SELECT DISTINCT(PermissionItem.Permission) FROM PermissionItem "
2014-08-08 08:02:25 +00:00
" LEFT JOIN RankPermGroup "
" ON PermissionItem.PermGroupID = RankPermGroup.PermGroupID "
" LEFT JOIN PlayerRank "
" ON PlayerRank.RankID = RankPermGroup.RankID "
" WHERE PlayerRank.PlayerUUID = ? "
) ;
stmt . bind ( 1 , a_PlayerUUID ) ;
// Execute and get results:
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
2014-08-05 16:37:00 +00:00
{
2014-08-08 08:02:25 +00:00
LOGWARNING ( " %s: Cannot get player permissions: %s " , __FUNCTION__ , ex . what ( ) ) ;
2014-08-05 16:37:00 +00:00
}
return res ;
}
2014-08-08 08:02:25 +00:00
AStringVector cRankManager : : GetRankGroups ( const AString & a_RankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT PermGroup.Name FROM PermGroup "
" LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermGroup.PermGroupID "
" LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID "
" WHERE Rank.Name = ? "
) ;
stmt . bind ( 1 , a_RankName ) ;
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get rank groups from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
AStringVector cRankManager : : GetGroupPermissions ( const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT PermissionItem.Permission FROM PermissionItem "
" LEFT JOIN PermGroup ON PermGroup.PermGroupID = PermissionItem.PermGroupID "
" WHERE PermGroup.Name = ? "
) ;
stmt . bind ( 1 , a_GroupName ) ;
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get group permissions from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
AStringVector cRankManager : : GetRankPermissions ( const AString & a_RankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT PermissionItem.Permission FROM PermissionItem "
" LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermissionItem.PermGroupID "
" LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID "
" WHERE Rank.Name = ? "
) ;
stmt . bind ( 1 , a_RankName ) ;
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get rank permissions from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
AStringVector cRankManager : : GetAllRanks ( void )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT Name FROM Rank " ) ;
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get ranks from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
AStringVector cRankManager : : GetAllGroups ( void )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT Name FROM PermGroup " ) ;
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get groups from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
AStringVector cRankManager : : GetAllPermissions ( void )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
AStringVector res ;
2014-08-08 14:38:38 +00:00
try
{
2014-08-08 19:30:47 +00:00
SQLite : : Statement stmt ( m_DB , " SELECT DISTINCT(Permission) FROM PermissionItem " ) ;
2014-08-08 14:38:38 +00:00
while ( stmt . executeStep ( ) )
{
res . push_back ( stmt . getColumn ( 0 ) . getText ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get permissions from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return res ;
}
2014-08-08 19:30:47 +00:00
bool cRankManager : : GetPlayerMsgVisuals (
2014-08-08 08:02:25 +00:00
const AString & a_PlayerUUID ,
AString & a_MsgPrefix ,
AString & a_MsgSuffix ,
AString & a_MsgNameColorCode
)
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
AStringVector res ;
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT Rank.MsgPrefix, Rank.MsgSuffix, Rank.MsgNameColorCode FROM Rank "
" LEFT JOIN PlayerRank ON Rank.RankID = PlayerRank.RankID "
" WHERE PlayerRank.PlayerUUID = ? "
) ;
stmt . bind ( 1 , a_PlayerUUID ) ;
if ( ! stmt . executeStep ( ) )
{
LOGD ( " %s: Player UUID %s not found in the DB, returning empty values. " , __FUNCTION__ , a_PlayerUUID . c_str ( ) ) ;
a_MsgPrefix . clear ( ) ;
a_MsgSuffix . clear ( ) ;
a_MsgNameColorCode . clear ( ) ;
return false ;
}
a_MsgPrefix = stmt . getColumn ( 0 ) . getText ( ) ;
a_MsgSuffix = stmt . getColumn ( 1 ) . getText ( ) ;
a_MsgNameColorCode = stmt . getColumn ( 2 ) . getText ( ) ;
return true ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get ranks from DB: %s. Returning empty values. " , __FUNCTION__ , ex . what ( ) ) ;
}
a_MsgPrefix . clear ( ) ;
a_MsgSuffix . clear ( ) ;
a_MsgNameColorCode . clear ( ) ;
return false ;
2014-08-08 08:02:25 +00:00
}
void cRankManager : : AddRank (
const AString & a_RankName ,
const AString & a_MsgPrefix ,
const AString & a_MsgSuffix ,
const AString & a_MsgNameColorCode
)
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
// Check if such a rank name is already used:
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( stmt . executeStep ( ) )
{
if ( stmt . getColumn ( 0 ) . getInt ( ) > 0 )
{
// Rank already exists, do nothing:
return ;
}
}
}
// Insert a new rank:
SQLite : : Statement stmt ( m_DB , " INSERT INTO Rank (Name, MsgPrefix, MsgSuffix, MsgNameColorCode) VALUES (?, ?, ?, ?) " ) ;
stmt . bind ( 1 , a_RankName ) ;
stmt . bind ( 2 , a_MsgPrefix ) ;
stmt . bind ( 3 , a_MsgSuffix ) ;
stmt . bind ( 4 , a_MsgNameColorCode ) ;
if ( stmt . exec ( ) < = 0 )
{
LOGWARNING ( " %s: Failed to add a new rank \" %s \" . " , __FUNCTION__ , a_RankName . c_str ( ) ) ;
return ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to add a new rank \" %s \" : %s " , __FUNCTION__ , a_RankName . c_str ( ) , ex . what ( ) ) ;
}
}
void cRankManager : : AddGroup ( const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
// Check if such a rank name is already used:
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( stmt . executeStep ( ) )
{
if ( stmt . getColumn ( 0 ) . getInt ( ) > 0 )
{
// Group already exists, do nothing:
return ;
}
}
}
// Insert a new rank:
SQLite : : Statement stmt ( m_DB , " INSERT INTO PermGroup (Name) VALUES (?) " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( stmt . exec ( ) < = 0 )
{
LOGWARNING ( " %s: Failed to add a new group \" %s \" . " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to add a new group \" %s \" : %s " , __FUNCTION__ , a_GroupName . c_str ( ) , ex . what ( ) ) ;
}
}
bool cRankManager : : AddGroupToRank ( const AString & a_GroupName , const AString & a_RankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Transaction trans ( m_DB ) ;
int GroupID , RankID ;
// Get the group's ID:
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: No such group (%s), aborting. " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return false ;
}
GroupID = stmt . getColumn ( 0 ) ;
}
// Get the rank's ID:
{
SQLite : : Statement stmt ( m_DB , " SELECT RankID FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: No such rank (%s), aborting. " , __FUNCTION__ , a_RankName . c_str ( ) ) ;
return false ;
}
RankID = stmt . getColumn ( 0 ) ;
}
// Check if the group is already there:
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM RankPermGroup WHERE RankID = ? AND PermGroupID = ? " ) ;
stmt . bind ( 1 , RankID ) ;
stmt . bind ( 2 , GroupID ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: Failed to check binding between rank %s and group %s, aborting. " , __FUNCTION__ , a_RankName . c_str ( ) , a_GroupName . c_str ( ) ) ;
return false ;
}
if ( stmt . getColumn ( 0 ) . getInt ( ) > 0 )
{
LOGD ( " %s: Group %s already present in rank %s, skipping and returning success. " ,
__FUNCTION__ , a_GroupName . c_str ( ) , a_RankName . c_str ( )
) ;
return true ;
}
}
// Add the group:
{
SQLite : : Statement stmt ( m_DB , " INSERT INTO RankPermGroup (RankID, PermGroupID) VALUES (?, ?) " ) ;
stmt . bind ( 1 , RankID ) ;
stmt . bind ( 2 , GroupID ) ;
if ( stmt . exec ( ) < = 0 )
{
LOGWARNING ( " %s: Failed to add group %s to rank %s, aborting. " , __FUNCTION__ , a_GroupName . c_str ( ) , a_RankName . c_str ( ) ) ;
return false ;
}
}
// Adding succeeded:
trans . commit ( ) ;
return true ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to add group %s to rank %s: %s " , __FUNCTION__ , a_GroupName . c_str ( ) , a_RankName . c_str ( ) , ex . what ( ) ) ;
}
return false ;
}
bool cRankManager : : AddPermissionToGroup ( const AString & a_Permission , const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
// Wrapp the entire operation into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the group's ID:
int GroupID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: No such group (%s), aborting. " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return false ;
}
GroupID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
// Check if the permission is already present:
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM PermissionItem WHERE PermGroupID = ? AND Permission = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . bind ( 2 , a_Permission ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: Failed to check binding between permission %s and group %s, aborting. " , __FUNCTION__ , a_Permission . c_str ( ) , a_GroupName . c_str ( ) ) ;
return false ;
}
if ( stmt . getColumn ( 0 ) . getInt ( ) > 0 )
{
LOGD ( " %s: Permission %s is already present in group %s, skipping and returning success. " ,
__FUNCTION__ , a_Permission . c_str ( ) , a_GroupName . c_str ( )
) ;
return true ;
}
}
// Add the permission:
{
SQLite : : Statement stmt ( m_DB , " INSERT INTO PermissionItem (Permission, PermGroupID) VALUES (?, ?) " ) ;
stmt . bind ( 1 , a_Permission ) ;
stmt . bind ( 2 , GroupID ) ;
if ( stmt . exec ( ) < = 0 )
{
LOGWARNING ( " %s: Failed to add permission %s to group %s, aborting. " , __FUNCTION__ , a_Permission . c_str ( ) , a_GroupName . c_str ( ) ) ;
return false ;
}
}
// Adding succeeded:
trans . commit ( ) ;
return true ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to add permission %s to group %s: %s " ,
__FUNCTION__ , a_Permission . c_str ( ) , a_GroupName . c_str ( ) , ex . what ( )
) ;
}
return false ;
}
2014-08-13 07:53:33 +00:00
bool cRankManager : : AddPermissionsToGroup ( const AStringVector & a_Permissions , const AString & a_GroupName )
{
ASSERT ( m_IsInitialized ) ;
try
{
// Wrapp the entire operation into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the group's ID:
int GroupID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: No such group (%s), aborting. " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return false ;
}
GroupID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
for ( AStringVector : : const_iterator itr = a_Permissions . begin ( ) , end = a_Permissions . end ( ) ; itr ! = end ; + + itr )
{
// Check if the permission is already present:
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM PermissionItem WHERE PermGroupID = ? AND Permission = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . bind ( 2 , * itr ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: Failed to check binding between permission %s and group %s, aborting. " , __FUNCTION__ , itr - > c_str ( ) , a_GroupName . c_str ( ) ) ;
return false ;
}
if ( stmt . getColumn ( 0 ) . getInt ( ) > 0 )
{
LOGD ( " %s: Permission %s is already present in group %s, skipping and returning success. " ,
__FUNCTION__ , itr - > c_str ( ) , a_GroupName . c_str ( )
) ;
continue ;
}
}
// Add the permission:
{
SQLite : : Statement stmt ( m_DB , " INSERT INTO PermissionItem (Permission, PermGroupID) VALUES (?, ?) " ) ;
stmt . bind ( 1 , * itr ) ;
stmt . bind ( 2 , GroupID ) ;
if ( stmt . exec ( ) < = 0 )
{
LOGWARNING ( " %s: Failed to add permission %s to group %s, skipping. " , __FUNCTION__ , itr - > c_str ( ) , a_GroupName . c_str ( ) ) ;
continue ;
}
}
} // for itr - a_Permissions[]
// Adding succeeded:
trans . commit ( ) ;
return true ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to add permissions to group %s: %s " ,
__FUNCTION__ , a_GroupName . c_str ( ) , ex . what ( )
) ;
}
return false ;
}
2014-08-08 08:02:25 +00:00
void cRankManager : : RemoveRank ( const AString & a_RankName , const AString & a_ReplacementRankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
AStringVector res ;
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the RankID for the rank being removed:
int RemoveRankID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT RankID FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGINFO ( " %s: Rank %s was not found. Skipping. " , __FUNCTION__ , a_RankName . c_str ( ) ) ;
return ;
}
RemoveRankID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
// Get the RankID for the replacement rank:
int ReplacementRankID = - 1 ;
{
SQLite : : Statement stmt ( m_DB , " SELECT RankID FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_ReplacementRankName ) ;
if ( stmt . executeStep ( ) )
{
ReplacementRankID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
}
// Remove the rank's bindings to groups:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM RankPermGroup WHERE RankID = ? " ) ;
stmt . bind ( 1 , RemoveRankID ) ;
stmt . exec ( ) ;
}
// Adjust players:
if ( ReplacementRankID = = - 1 )
{
// No replacement, just delete all the players that have the rank:
SQLite : : Statement stmt ( m_DB , " DELETE FROM PlayerRank WHERE RankID = ? " ) ;
stmt . bind ( 1 , RemoveRankID ) ;
stmt . exec ( ) ;
}
else
{
// Replacement available, change all the player records:
SQLite : : Statement stmt ( m_DB , " UPDATE PlayerRank SET RankID = ? WHERE RankID = ? " ) ;
stmt . bind ( 1 , ReplacementRankID ) ;
stmt . bind ( 2 , RemoveRankID ) ;
stmt . exec ( ) ;
}
// Remove the rank from the DB:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM Rank WHERE RankID = ? " ) ;
stmt . bind ( 1 , RemoveRankID ) ;
stmt . exec ( ) ;
}
trans . commit ( ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to remove rank from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
}
void cRankManager : : RemoveGroup ( const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the ID of the group:
int GroupID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGINFO ( " %s: Group %s was not found, skipping. " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return ;
}
GroupID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
// Remove all permissions from the group:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM PermissionItem WHERE PermGroupID = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . exec ( ) ;
}
// Remove the group from all ranks that contain it:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM RankPermGroup WHERE PermGroupID = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . exec ( ) ;
}
// Remove the group itself:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM PermGroup WHERE PermGroupID = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . exec ( ) ;
}
trans . commit ( ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to remove group %s from DB: %s " , __FUNCTION__ , a_GroupName . c_str ( ) , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
}
2014-08-08 19:30:47 +00:00
void cRankManager : : RemoveGroupFromRank ( const AString & a_GroupName , const AString & a_RankName )
2014-08-08 08:02:25 +00:00
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the IDs of the group and the rank:
int GroupID , RankID ;
{
SQLite : : Statement stmt ( m_DB ,
" SELECT PermGroup.PermGroupID, Rank.RankID FROM PermGroup "
" LEFT JOIN RankPermGroup ON RankPermGroup.PermGroupID = PermGroup.PermGroupID "
" LEFT JOIN Rank ON Rank.RankID = RankPermGroup.RankID "
" WHERE PermGroup.Name = ? AND Rank.Name = ? "
) ;
stmt . bind ( 1 , a_GroupName ) ;
stmt . bind ( 2 , a_RankName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGINFO ( " %s: Group %s was not found in rank %s, skipping. " , __FUNCTION__ , a_GroupName . c_str ( ) , a_RankName . c_str ( ) ) ;
return ;
}
GroupID = stmt . getColumn ( 0 ) . getInt ( ) ;
RankID = stmt . getColumn ( 1 ) . getInt ( ) ;
}
// Remove the group from all ranks that contain it:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM RankPermGroup WHERE PermGroupID = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . exec ( ) ;
}
// Remove the group-to-rank binding:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM RankPermGroup WHERE PermGroupID = ? AND RankID = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . bind ( 1 , RankID ) ;
stmt . exec ( ) ;
}
trans . commit ( ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to remove group %s from rank %s in the DB: %s " , __FUNCTION__ , a_GroupName . c_str ( ) , a_RankName . c_str ( ) , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
}
void cRankManager : : RemovePermissionFromGroup ( const AString & a_Permission , const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the ID of the group:
int GroupID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGINFO ( " %s: Group %s was not found, skipping. " , __FUNCTION__ , a_GroupName . c_str ( ) ) ;
return ;
}
GroupID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
// Remove the permission from the group:
{
SQLite : : Statement stmt ( m_DB , " DELETE FROM PermissionItem WHERE PermGroupID = ? AND Permission = ? " ) ;
stmt . bind ( 1 , GroupID ) ;
stmt . bind ( 2 , a_Permission ) ;
stmt . exec ( ) ;
}
trans . commit ( ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to remove permission %s from group %s in DB: %s " ,
__FUNCTION__ , a_Permission . c_str ( ) , a_GroupName . c_str ( ) , ex . what ( )
) ;
}
2014-08-08 08:02:25 +00:00
}
bool cRankManager : : RenameRank ( const AString & a_OldName , const AString & a_NewName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Check that NewName doesn't exist:
{
SQLite : : Statement stmt ( m_DB , " SELECT RankID FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_NewName ) ;
if ( stmt . executeStep ( ) )
{
LOGD ( " %s: Rank %s is already present, cannot rename %s " , __FUNCTION__ , a_NewName . c_str ( ) , a_OldName . c_str ( ) ) ;
return false ;
}
}
// Rename:
bool res ;
{
SQLite : : Statement stmt ( m_DB , " UPDATE Rank SET Name = ? WHERE Name = ? " ) ;
stmt . bind ( 1 , a_NewName ) ;
stmt . bind ( 2 , a_OldName ) ;
res = ( stmt . exec ( ) > 0 ) ;
}
trans . commit ( ) ;
return res ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to rename rank %s to %s in DB: %s " ,
__FUNCTION__ , a_OldName . c_str ( ) , a_NewName . c_str ( ) , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return false ;
}
bool cRankManager : : RenameGroup ( const AString & a_OldName , const AString & a_NewName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
// Wrap everything into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Check that NewName doesn't exist:
{
SQLite : : Statement stmt ( m_DB , " SELECT PermGroupID FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_NewName ) ;
if ( stmt . executeStep ( ) )
{
LOGD ( " %s: Group %s is already present, cannot rename %s " , __FUNCTION__ , a_NewName . c_str ( ) , a_OldName . c_str ( ) ) ;
return false ;
}
}
// Rename:
bool res ;
{
SQLite : : Statement stmt ( m_DB , " UPDATE PermGroup SET Name = ? WHERE Name = ? " ) ;
stmt . bind ( 1 , a_NewName ) ;
stmt . bind ( 2 , a_OldName ) ;
res = ( stmt . exec ( ) > 0 ) ;
}
trans . commit ( ) ;
return res ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to rename group %s to %s in DB: %s " ,
__FUNCTION__ , a_OldName . c_str ( ) , a_NewName . c_str ( ) , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
return false ;
}
2014-08-08 19:30:47 +00:00
void cRankManager : : SetPlayerRank ( const AString & a_PlayerUUID , const AString & a_PlayerName , const AString & a_RankName )
2014-08-08 08:02:25 +00:00
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
// Wrap the entire operation into a transaction:
SQLite : : Transaction trans ( m_DB ) ;
// Get the rank ID:
int RankID ;
{
SQLite : : Statement stmt ( m_DB , " SELECT RankID FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( ! stmt . executeStep ( ) )
{
LOGWARNING ( " %s: There is no rank %s, aborting. " , __FUNCTION__ , a_RankName . c_str ( ) ) ;
return ;
}
RankID = stmt . getColumn ( 0 ) . getInt ( ) ;
}
// Update the player's rank, if already in DB:
{
2014-08-08 19:30:47 +00:00
SQLite : : Statement stmt ( m_DB , " UPDATE PlayerRank SET RankID = ?, PlayerName = ? WHERE PlayerUUID = ? " ) ;
2014-08-08 08:02:25 +00:00
stmt . bind ( 1 , RankID ) ;
2014-08-08 19:30:47 +00:00
stmt . bind ( 2 , a_PlayerName ) ;
stmt . bind ( 3 , a_PlayerUUID ) ;
2014-08-08 08:02:25 +00:00
if ( stmt . exec ( ) > 0 )
{
// Successfully updated the player's rank
trans . commit ( ) ;
return ;
}
}
// The player is not yet in the DB, add them:
2014-08-08 19:30:47 +00:00
SQLite : : Statement stmt ( m_DB , " INSERT INTO PlayerRank (RankID, PlayerUUID, PlayerName) VALUES (?, ?, ?) " ) ;
2014-08-08 08:02:25 +00:00
stmt . bind ( 1 , RankID ) ;
stmt . bind ( 2 , a_PlayerUUID ) ;
2014-08-08 19:30:47 +00:00
stmt . bind ( 3 , a_PlayerName ) ;
2014-08-08 08:02:25 +00:00
if ( stmt . exec ( ) > 0 )
{
// Successfully added the player
trans . commit ( ) ;
return ;
}
LOGWARNING ( " %s: Failed to set player UUID %s to rank %s. " ,
__FUNCTION__ , a_PlayerUUID . c_str ( ) , a_RankName . c_str ( )
) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to set player UUID %s to rank %s: %s " ,
__FUNCTION__ , a_PlayerUUID . c_str ( ) , a_RankName . c_str ( ) , ex . what ( )
) ;
}
}
void cRankManager : : SetRankVisuals (
const AString & a_RankName ,
const AString & a_MsgPrefix ,
const AString & a_MsgSuffix ,
const AString & a_MsgNameColorCode
)
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 19:30:47 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " UPDATE Rank SET MsgPrefix = ?, MsgSuffix = ?, MsgNameColorCode = ? WHERE Name = ? " ) ;
stmt . bind ( 1 , a_MsgPrefix ) ;
stmt . bind ( 2 , a_MsgSuffix ) ;
2014-08-09 15:36:19 +00:00
stmt . bind ( 3 , a_MsgNameColorCode ) ;
stmt . bind ( 4 , a_RankName ) ;
2014-08-08 19:30:47 +00:00
if ( ! stmt . executeStep ( ) )
{
LOGINFO ( " %s: Rank %s not found, visuals not set. " , __FUNCTION__ , a_RankName . c_str ( ) ) ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get ranks from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
2014-08-08 08:02:25 +00:00
}
2014-08-09 15:36:19 +00:00
bool cRankManager : : GetRankVisuals (
const AString & a_RankName ,
AString & a_MsgPrefix ,
AString & a_MsgSuffix ,
AString & a_MsgNameColorCode
)
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-09 15:36:19 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT MsgPrefix, MsgSuffix, MsgNameColorCode FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( ! stmt . executeStep ( ) )
{
// Rank not found
return false ;
}
a_MsgPrefix = stmt . getColumn ( 0 ) . getText ( ) ;
a_MsgSuffix = stmt . getColumn ( 1 ) . getText ( ) ;
a_MsgNameColorCode = stmt . getColumn ( 2 ) . getText ( ) ;
return true ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to get ranks from DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
return false ;
}
2014-08-08 08:02:25 +00:00
bool cRankManager : : RankExists ( const AString & a_RankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT * FROM Rank WHERE Name = ? " ) ;
stmt . bind ( 1 , a_RankName ) ;
if ( stmt . executeStep ( ) )
{
// The rank was found
return true ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB for rank %s: %s " , __FUNCTION__ , a_RankName . c_str ( ) , ex . what ( ) ) ;
}
return false ;
}
bool cRankManager : : GroupExists ( const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT * FROM PermGroup WHERE Name = ? " ) ;
stmt . bind ( 1 , a_GroupName ) ;
if ( stmt . executeStep ( ) )
{
// The group was found
return true ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB for group %s: %s " , __FUNCTION__ , a_GroupName . c_str ( ) , ex . what ( ) ) ;
}
return false ;
}
bool cRankManager : : IsPlayerRankSet ( const AString & a_PlayerUUID )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Statement stmt ( m_DB , " SELECT * FROM PlayerRank WHERE PlayerUUID = ? " ) ;
stmt . bind ( 1 , a_PlayerUUID ) ;
if ( stmt . executeStep ( ) )
{
// The player UUID was found, they have a rank
return true ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB for player UUID %s: %s " , __FUNCTION__ , a_PlayerUUID . c_str ( ) , ex . what ( ) ) ;
}
return false ;
}
bool cRankManager : : IsGroupInRank ( const AString & a_GroupName , const AString & a_RankName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT * FROM Rank "
" LEFT JOIN RankPermGroup ON Rank.RankID = RankPermGroup.RankID "
" LEFT JOIN PermGroup ON PermGroup.PermGroupID = RankPermGroup.PermGroupID "
" WHERE Rank.Name = ? AND PermGroup.Name = ? "
) ;
stmt . bind ( 1 , a_RankName ) ;
stmt . bind ( 2 , a_GroupName ) ;
if ( stmt . executeStep ( ) )
{
// The group is in the rank
return true ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
return false ;
}
bool cRankManager : : IsPermissionInGroup ( const AString & a_Permission , const AString & a_GroupName )
{
2014-08-13 07:53:33 +00:00
ASSERT ( m_IsInitialized ) ;
2014-08-08 08:02:25 +00:00
try
{
SQLite : : Statement stmt ( m_DB ,
" SELECT * FROM PermissionItem "
" LEFT JOIN PermGroup ON PermGroup.PermGroupID = PermissionItem.PermGroupID "
" WHERE PermissionItem.Permission = ? AND PermGroup.Name = ? "
) ;
stmt . bind ( 1 , a_Permission ) ;
stmt . bind ( 2 , a_GroupName ) ;
if ( stmt . executeStep ( ) )
{
// The permission is in the group
return true ;
}
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
return false ;
}
2014-08-13 07:53:33 +00:00
bool cRankManager : : AreDBTablesEmpty ( void )
{
return (
IsDBTableEmpty ( " Rank " ) & &
IsDBTableEmpty ( " PlayerRank " ) & &
IsDBTableEmpty ( " PermGroup " ) & &
IsDBTableEmpty ( " RankPermGroup " ) & &
IsDBTableEmpty ( " PermissionItem " )
) ;
}
bool cRankManager : : IsDBTableEmpty ( const AString & a_TableName )
{
try
{
SQLite : : Statement stmt ( m_DB , " SELECT COUNT(*) FROM " + a_TableName ) ;
return ( stmt . executeStep ( ) & & ( stmt . getColumn ( 0 ) . getInt ( ) = = 0 ) ) ;
}
catch ( const SQLite : : Exception & ex )
{
LOGWARNING ( " %s: Failed to query DB: %s " , __FUNCTION__ , ex . what ( ) ) ;
}
return false ;
}