Anton Tarasenko
2 years ago
8 changed files with 571 additions and 93 deletions
@ -1,25 +0,0 @@ |
|||||||
; In this config you can add several different user groups by adding |
|
||||||
; `[<group_name> UserGroup]` section for rach group. Every user can belong to |
|
||||||
; several different groups. |
|
||||||
; `priority` describes how important the group is. For example, if a user |
|
||||||
; belongs to two different groups and both groups have different access rights |
|
||||||
; for a certain command - the one with the highest priority will be chosen by |
|
||||||
; default. |
|
||||||
; You can specify several `user` entries with players stead id to add user to |
|
||||||
; the certain group. |
|
||||||
|
|
||||||
[admin UserGroup] |
|
||||||
priority=400 |
|
||||||
;user= |
|
||||||
|
|
||||||
[moderator UserGroup] |
|
||||||
priority=200 |
|
||||||
;user= |
|
||||||
|
|
||||||
[trusted UserGroup] |
|
||||||
priority=100 |
|
||||||
;user= |
|
||||||
|
|
||||||
[wanted UserGroup] |
|
||||||
priority=0 |
|
||||||
;user= |
|
@ -0,0 +1,17 @@ |
|||||||
|
[default Users] |
||||||
|
useDatabase=false |
||||||
|
databaseLink="[local]database:/users" |
||||||
|
userGroup=admin |
||||||
|
userGroup=moderator |
||||||
|
userGroup=trusted |
||||||
|
|
||||||
|
[admin UserGroup] |
||||||
|
;user= |
||||||
|
|
||||||
|
[moderator UserGroup] |
||||||
|
;user= |
||||||
|
|
||||||
|
[trusted UserGroup] |
||||||
|
;user= |
||||||
|
|
||||||
|
; ?wanted, banned? |
@ -0,0 +1,87 @@ |
|||||||
|
/** |
||||||
|
* Config object for `Users_Feature`. |
||||||
|
* Copyright 2022 Anton Tarasenko |
||||||
|
*------------------------------------------------------------------------------ |
||||||
|
* This file is part of Acedia. |
||||||
|
* |
||||||
|
* Acedia is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* Acedia is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||||
|
*/ |
||||||
|
class Users extends FeatureConfig |
||||||
|
perobjectconfig |
||||||
|
config(AcediaUsers); |
||||||
|
|
||||||
|
var public config bool useDatabase; |
||||||
|
var public config string databaseLink; |
||||||
|
var public config array<string> localUserGroup; |
||||||
|
|
||||||
|
protected function HashTable ToData() |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local HashTable data; |
||||||
|
local ArrayList userGroupList; |
||||||
|
|
||||||
|
data = __().collections.EmptyHashTable(); |
||||||
|
data.SetBool(P("useDatabase"), useDatabase, false); |
||||||
|
data.SetString(P("databaseLink"), databaseLink); |
||||||
|
userGroupList = _.collections.EmptyArrayList(); |
||||||
|
for (i = 0; i < localUserGroup.length; i += 1) { |
||||||
|
userGroupList.AddString(localUserGroup[i]); |
||||||
|
} |
||||||
|
data.SetItem(P("userGroups"), userGroupList); |
||||||
|
userGroupList.FreeSelf(); |
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
protected function FromData(HashTable source) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local ArrayList userGroupList; |
||||||
|
|
||||||
|
if (source == none) { |
||||||
|
return; |
||||||
|
} |
||||||
|
useDatabase = source.GetBool(P("useDatabase")); |
||||||
|
databaseLink = source.GetString( |
||||||
|
P("databaseLink"), |
||||||
|
"[local]database:/users"); |
||||||
|
userGroupList = source.GetArrayList(P("userGroups")); |
||||||
|
localUserGroup.length = 0; |
||||||
|
if (userGroupList == none) { |
||||||
|
return; |
||||||
|
} |
||||||
|
for (i = 0; i < userGroupList.GetLength(); i += 1) { |
||||||
|
localUserGroup[localUserGroup.length] = userGroupList.GetString(i); |
||||||
|
} |
||||||
|
userGroupList.FreeSelf(); |
||||||
|
} |
||||||
|
|
||||||
|
protected function DefaultIt() |
||||||
|
{ |
||||||
|
useDatabase = false; |
||||||
|
databaseLink = "[local]database:/users"; |
||||||
|
localUserGroup.length = 0; |
||||||
|
localUserGroup[0] = "admin"; |
||||||
|
localUserGroup[1] = "moderator"; |
||||||
|
localUserGroup[2] = "trusted"; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
configName = "AcediaUsers" |
||||||
|
useDatabase = false |
||||||
|
databaseLink = "[local]database:/users" |
||||||
|
localUserGroup(0) = "admin" |
||||||
|
localUserGroup(1) = "moderator" |
||||||
|
localUserGroup(2) = "trusted" |
||||||
|
} |
@ -0,0 +1,251 @@ |
|||||||
|
/** |
||||||
|
* ??? |
||||||
|
* Copyright 2022 Anton Tarasenko |
||||||
|
*------------------------------------------------------------------------------ |
||||||
|
* This file is part of Acedia. |
||||||
|
* |
||||||
|
* Acedia is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, version 3 of the License, or |
||||||
|
* (at your option) any later version. |
||||||
|
* |
||||||
|
* Acedia is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. |
||||||
|
*/ |
||||||
|
class Users_Feature extends Feature; |
||||||
|
|
||||||
|
var private /*config*/ bool useDatabase; |
||||||
|
var private /*config*/ string databaseLink; |
||||||
|
var private /*config*/ array<string> userGroup; |
||||||
|
|
||||||
|
// Defines order |
||||||
|
var private array<Text> loadedUserGroups; |
||||||
|
// `HashTable` (with group name keys) that stores `HashTable`s used as |
||||||
|
// a set data structure (has user id as keys and always `none` as a value). |
||||||
|
var private HashTable loadedGroupToUsersMap; |
||||||
|
|
||||||
|
protected function SwapConfig(FeatureConfig config) |
||||||
|
{ |
||||||
|
local Users newConfig; |
||||||
|
|
||||||
|
newConfig = Users(config); |
||||||
|
if (newConfig == none) { |
||||||
|
return; |
||||||
|
} |
||||||
|
useDatabase = newConfig.useDatabase; |
||||||
|
databaseLink = newConfig.databaseLink; |
||||||
|
userGroup = newConfig.localUserGroup; |
||||||
|
} |
||||||
|
|
||||||
|
private final function LoadLocalData() |
||||||
|
{ |
||||||
|
LoadLocalGroupNames(); |
||||||
|
LoadLocalGroupToUserMap(); |
||||||
|
} |
||||||
|
|
||||||
|
private final function LoadLocalGroupNames() |
||||||
|
{ |
||||||
|
local int i, j; |
||||||
|
local bool isDuplicate; |
||||||
|
local Text nextUserGroup; |
||||||
|
|
||||||
|
_.memory.FreeMany(loadedUserGroups); |
||||||
|
loadedUserGroups.length = 0; |
||||||
|
for (i = 0; i < userGroup.length; i += 1) |
||||||
|
{ |
||||||
|
isDuplicate = false; |
||||||
|
nextUserGroup = _.text.FromString(userGroup[i]); |
||||||
|
for(j = 0; j < loadedUserGroups.length; j += 1) |
||||||
|
{ |
||||||
|
if (loadedUserGroups[j].Compare(nextUserGroup, SCASE_INSENSITIVE)) |
||||||
|
{ |
||||||
|
isDuplicate = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isDuplicate) |
||||||
|
{ |
||||||
|
loadedUserGroups[loadedUserGroups.length] = |
||||||
|
nextUserGroup.LowerCopy(); |
||||||
|
} |
||||||
|
nextUserGroup.FreeSelf(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private final function LoadLocalGroupToUserMap() |
||||||
|
{ |
||||||
|
local int i, j; |
||||||
|
local Text newSteamID; |
||||||
|
local HashTable newPlayerSet; |
||||||
|
local UserGroup nextGroupConfig; |
||||||
|
local array<string> nextGroupUserArray; |
||||||
|
|
||||||
|
_.memory.Free(loadedGroupToUsersMap); |
||||||
|
loadedGroupToUsersMap = _.collections.EmptyHashTable(); |
||||||
|
class'UserGroup'.static.Initialize(); |
||||||
|
// Go over every group |
||||||
|
for (i = 0; i < loadedUserGroups.length; i += 1) |
||||||
|
{ |
||||||
|
nextGroupConfig = UserGroup( |
||||||
|
class'UserGroup'.static.GetConfigInstance(loadedUserGroups[i])); |
||||||
|
if (nextGroupConfig == none) |
||||||
|
{ |
||||||
|
// !!! Log missing group |
||||||
|
continue; |
||||||
|
} |
||||||
|
// Copy player IDs from `string` array into `HashTable` |
||||||
|
// that is serving as a set data structure |
||||||
|
newPlayerSet = _.collections.EmptyHashTable(); |
||||||
|
nextGroupUserArray = nextGroupConfig.user; |
||||||
|
for (j = 0; j < nextGroupUserArray.length; j += 1) |
||||||
|
{ |
||||||
|
newSteamID = _.text.FromString(nextGroupUserArray[j]); |
||||||
|
newPlayerSet.SetItem(newSteamID, none); |
||||||
|
newSteamID.FreeSelf(); |
||||||
|
} |
||||||
|
loadedGroupToUsersMap.SetItem(loadedUserGroups[i], newPlayerSet); |
||||||
|
newPlayerSet.FreeSelf(); |
||||||
|
nextGroupConfig.FreeSelf(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private final function SaveLocalData() |
||||||
|
{ |
||||||
|
local Text nextGroup, activeConfigName; |
||||||
|
local Users currentConfig; |
||||||
|
local HashTableIterator iter; |
||||||
|
|
||||||
|
if (useDatabase) return; |
||||||
|
if (loadedGroupToUsersMap == none) return; |
||||||
|
|
||||||
|
userGroup.length = 0; |
||||||
|
iter = HashTableIterator(loadedGroupToUsersMap.Iterate()); |
||||||
|
while (!iter.HasFinished()) |
||||||
|
{ |
||||||
|
nextGroup = Text(iter.GetKey()); |
||||||
|
if (nextGroup != none) |
||||||
|
{ |
||||||
|
userGroup[userGroup.length] = nextGroup.ToString(); |
||||||
|
nextGroup.FreeSelf(); |
||||||
|
} |
||||||
|
iter.Next(); |
||||||
|
} |
||||||
|
iter.FreeSelf(); |
||||||
|
activeConfigName = GetCurrentConfig(); |
||||||
|
if (activeConfigName != none) |
||||||
|
{ |
||||||
|
currentConfig = Users(class'Users'.static |
||||||
|
.GetConfigInstance(activeConfigName)); |
||||||
|
} |
||||||
|
if (currentConfig != none) |
||||||
|
{ |
||||||
|
currentConfig.localUserGroup = userGroup; |
||||||
|
// !!! save config !!! |
||||||
|
} |
||||||
|
_.memory.Free(currentConfig); |
||||||
|
_.memory.Free(activeConfigName); |
||||||
|
} |
||||||
|
|
||||||
|
public final function array<Text> GetGroupsForUserID(UserID user) |
||||||
|
{ |
||||||
|
return GetLocalGroupsForUserID(user); |
||||||
|
} |
||||||
|
|
||||||
|
private final function array<Text> GetLocalGroupsForUserID(UserID id) |
||||||
|
{ |
||||||
|
local Text steamID; |
||||||
|
local array<Text> result; |
||||||
|
local HashTableIterator iter; |
||||||
|
local Text nextGroup; |
||||||
|
local HashTable nextGroupUsers; |
||||||
|
|
||||||
|
if (loadedGroupToUsersMap == none) return result; |
||||||
|
if (id == none) return result; |
||||||
|
steamID = id.GetSteamID64String(); |
||||||
|
if (steamID == none) return result; |
||||||
|
|
||||||
|
iter = HashTableIterator(loadedGroupToUsersMap.Iterate()); |
||||||
|
while (!iter.HasFinished()) |
||||||
|
{ |
||||||
|
nextGroup = Text(iter.GetKey()); |
||||||
|
nextGroupUsers = HashTable(iter.Get()); |
||||||
|
if ( nextGroup != none && nextGroupUsers != none |
||||||
|
&& nextGroupUsers.HasKey(steamID)) |
||||||
|
{ |
||||||
|
result[result.length] = nextGroup.Copy(); |
||||||
|
} |
||||||
|
iter.Next(); |
||||||
|
_.memory.Free(nextGroup); |
||||||
|
_.memory.Free(nextGroupUsers); |
||||||
|
} |
||||||
|
steamID.FreeSelf(); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public final function array<Text> GetGroupsForUser(User user) |
||||||
|
{ |
||||||
|
return GetLocalGroupsForUser(user); |
||||||
|
} |
||||||
|
|
||||||
|
private final function array<Text> GetLocalGroupsForUser(User user) |
||||||
|
{ |
||||||
|
local UserID id; |
||||||
|
local array<Text> result; |
||||||
|
|
||||||
|
if (user == none) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
id = user.GetID(); |
||||||
|
result = GetLocalGroupsForUserID(id); |
||||||
|
_.memory.Free(id); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public final function array<UserID> GetUserIDsInGroup(Text groupName) |
||||||
|
{ |
||||||
|
return GetUserIDsInLocalGroup(groupName); |
||||||
|
} |
||||||
|
|
||||||
|
private final function array<UserID> GetUserIDsInLocalGroup(Text groupName) |
||||||
|
{ |
||||||
|
local int i; |
||||||
|
local Text lowerCaseGroupName; |
||||||
|
local HashTable groupUsers; |
||||||
|
local array<Text> groupUserNames; |
||||||
|
local UserID nextUserID; |
||||||
|
local array<UserID> result; |
||||||
|
|
||||||
|
if (loadedGroupToUsersMap == none) return result; |
||||||
|
if (groupName == none) return result; |
||||||
|
|
||||||
|
lowerCaseGroupName = groupName.LowerCopy(); |
||||||
|
groupUsers = loadedGroupToUsersMap.GetHashTable(lowerCaseGroupName); |
||||||
|
lowerCaseGroupName.FreeSelf(); |
||||||
|
if (groupUsers == none) { |
||||||
|
groupUserNames = groupUsers.GetTextKeys(); |
||||||
|
} |
||||||
|
_.memory.Free(groupUsers); |
||||||
|
for (i = 0; i < groupUserNames.length; i += 1) |
||||||
|
{ |
||||||
|
nextUserID = UserID(_.memory.Allocate(class'UserID')); |
||||||
|
nextUserID.Initialize(groupUserNames[i]); |
||||||
|
if (nextUserID.IsInitialized()) { |
||||||
|
result[result.length] = nextUserID; |
||||||
|
} |
||||||
|
else { |
||||||
|
nextUserID.FreeSelf(); |
||||||
|
} |
||||||
|
} |
||||||
|
_.memory.FreeMany(groupUserNames); |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
defaultproperties |
||||||
|
{ |
||||||
|
configClass = class'Users' |
||||||
|
} |
Loading…
Reference in new issue