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