Compare commits

...

4 Commits

Author SHA1 Message Date
Brandon Sturgeon
fe5aedc7c9
Simplify the purpose of PostCommandCalled (#87) 2022-09-14 16:46:17 -07:00
Brandon Sturgeon
e4272fe742
Add ULibPostCommandCalled (#80)
* Add hook for post command called

* Document the hide param

* Change tenses in defines

* Update versions

* Fix version numbers
2022-08-04 20:53:15 -07:00
Zach P
8f86a5a188
Merge Master branch updates into Experimental Branch (#84)
* Update CHANGELOG.md

* Fix Weapon SetClipErrors (#76)

* fix: result isn't used in this context.

* fix: the docs say ply, we use ply.

* perf: we don't need to call that twice.

* fix: printname isn't a name, it's class. localise class.

* fix: fix weapon error if not given.

replace printname with class.
only call getweapon if we can't get it through give.

* fix: Make sure SetClip1 and SetClip2 actually exist before we call them.

* WTF (#63)

* Update CHANGELOG.md

* Update ulib.build

* Update addon.txt

* Update defines.lua

Co-authored-by: Joshua Piper <32164094+JoshPiper@users.noreply.github.com>
Co-authored-by: Deyvan <51455765+Deyvan@users.noreply.github.com>
2022-08-04 20:27:34 -07:00
Joshua Piper
d325fc72d2
Migrate UCL user store from flat file to SQLite. (#74)
* feat: add db creation and user saving

* fix: change protected term (group) to usergroup

* fix: sqlstr only escapes single quotes

* feat: load the users.

* chore: thonk?

* fix: when adding a user, only save once.

* feat: make userInfo opt

* feat: function to delete a stored user.

* feat: save for the remainder of operations

* fix: only try loading from the db if we've not just created it.

* fix: switch to json for an odd sqlite saving error

* feat: properly migrate.

* fix: we should be using the same noMount setting for both read and existance?

* fix(comment): Minor fix for the comment.

* fix: make that local, since we're not calling it for testing now.

* fix: remove the old file write, no longer required.

* feat: add function to delete all stored db users.

* feat: allow db data to be checked on load.
2022-08-04 19:30:34 -07:00
9 changed files with 188 additions and 54 deletions

View File

@ -1,5 +1,10 @@
# ULib Changelog
## v2.71 - *(00/00/0000)*
* [FIX] Fixed some issues in player.lua with SetClip errors. (Thanks, JoshPiper)
* [FIX] Cleaned up some code in player.lua to be more aligned with our docs. (Thanks, JoshPiper)
* [FIX] Added returns to some fallback functions in sh_ucl.lua (Thanks, Deyvan)
## v2.70 - *(08/04/2022)*
* [ADD] Hook when a new, previously unknown access is registered. UCLChanged is now called as well.
* [CHANGE] Moved bans to SQLite.

View File

@ -1,7 +1,7 @@
"AddonInfo"
{
"name" "ULib"
"version" "2.63d"
"version" "2.71"
"up_date" "00/00/00"
"author_name" "Team Ulysses"
"author_email" "teamulysses@ulyssesmod.net"

View File

@ -69,6 +69,7 @@ local function sayCmdCheck( ply, strText, bTeam )
local hide = data.hide
ULib.pcallError( fn, ply, match:Trim(), argv, args )
if hide then return "" end
end

View File

@ -207,26 +207,27 @@ end
Updates player object to store health and armor. Has no effect unless ULib.Spawn is used later.
]]
function ULib.getSpawnInfo( player )
local result = {}
function ULib.getSpawnInfo( ply )
local t = {}
player.ULibSpawnInfo = t
t.health = player:Health()
t.armor = player:Armor()
if player:GetActiveWeapon():IsValid() then
t.curweapon = player:GetActiveWeapon():GetClass()
ply.ULibSpawnInfo = t
t.health = ply:Health()
t.armor = ply:Armor()
local wep = ply:GetActiveWeapon()
if IsValid( wep ) then
t.curweapon = wep:GetClass()
end
local weapons = player:GetWeapons()
local data = {}
local weapons = ply:GetWeapons()
for _, weapon in ipairs( weapons ) do
printname = weapon:GetClass()
data[ printname ] = {}
data[ printname ].clip1 = weapon:Clip1()
data[ printname ].clip2 = weapon:Clip2()
data[ printname ].ammo1 = player:GetAmmoCount( weapon:GetPrimaryAmmoType() )
data[ printname ].ammo2 = player:GetAmmoCount( weapon:GetSecondaryAmmoType() )
local class = weapon:GetClass()
data[ class ] = {}
data[ class ].clip1 = weapon:Clip1()
data[ class ].clip2 = weapon:Clip2()
data[ class ].ammo1 = ply:GetAmmoCount( weapon:GetPrimaryAmmoType() )
data[ class ].ammo2 = ply:GetAmmoCount( weapon:GetSecondaryAmmoType() )
end
t.data = data
end
@ -238,13 +239,24 @@ local function doWeapons( player, t )
player:StripAmmo()
player:StripWeapons()
for printname, data in pairs( t.data ) do
player:Give( printname )
local weapon = player:GetWeapon( printname )
weapon:SetClip1( data.clip1 )
weapon:SetClip2( data.clip2 )
player:SetAmmo( data.ammo1, weapon:GetPrimaryAmmoType() )
player:SetAmmo( data.ammo2, weapon:GetSecondaryAmmoType() )
for class, data in pairs( t.data ) do
local weapon = player:Give( class )
if not IsValid( weapon ) then
weapon = player:GetWeapon( class )
end
if IsValid( weapon ) then
if weapon.SetClip1 then
weapon:SetClip1( data.clip1 )
end
if weapon.SetClip2 then
weapon:SetClip2( data.clip2 )
end
player:SetAmmo( data.ammo1, weapon:GetPrimaryAmmoType() )
player:SetAmmo( data.ammo2, weapon:GetSecondaryAmmoType() )
end
end
if t.curweapon then

View File

@ -110,12 +110,60 @@ function ucl.saveGroups()
end
function ucl.saveUsers()
for _, userInfo in pairs( ucl.users ) do
table.sort( userInfo.allow )
table.sort( userInfo.deny )
for steamid, userInfo in pairs( ucl.users ) do
ucl.saveUser(steamid, userInfo)
end
end
local isFirstTimeDBSetup = false
local function generateUserDB()
if not sql.TableExists("ulib_users") then
sql.Query([[
CREATE TABLE IF NOT EXISTS ulib_users (
steamid TEXT NOT NULL PRIMARY KEY,
name TEXT NULL,
usergroup TEXT NOT NULL DEFAULT "user",
allow TEXT,
deny TEXT
);
]])
isFirstTimeDBSetup = true
end
end
generateUserDB()
local function escape(str)
return sql.SQLStr(str, true)
end
function ucl.saveUser( steamid, userInfo )
if not userInfo then
userInfo = ucl.users[ steamid ]
end
ULib.fileWrite( ULib.UCL_USERS, ULib.makeKeyValues( ucl.users ) )
table.sort( userInfo.allow )
table.sort( userInfo.deny )
local allow, deny = util.TableToJSON( userInfo.allow ), util.TableToJSON( userInfo.deny )
sql.Query(string.format([[
REPLACE INTO ulib_users
(steamid, name, usergroup, allow, deny)
VALUES
('%s', '%s', '%s', '%s', '%s');
]], escape( steamid ), escape( userInfo.name or "" ), escape( userInfo.group ), escape( allow ), escape( deny )))
end
function ucl.deleteUser( steamid )
sql.Query(string.format([[
DELETE FROM
ulib_users
WHERE
steamid = '%s'
]], escape( steamid )))
end
function ucl.deleteUsers()
sql.Query([[DELETE FROM ulib_users;]])
end
local function reloadGroups()
@ -212,24 +260,62 @@ local function reloadGroups()
end
reloadGroups()
local function reloadUsers()
-- Try to read from the safest locations first
local noMount = true
local path = ULib.UCL_USERS
if not ULib.fileExists( path, noMount ) then
ULib.fileWrite( path, "" )
local function loadUsersFromDB()
-- No cap, the sqlite errors should always be reset when making a new query.
sql.m_strError = nil
local users = sql.Query( "SELECT * FROM ulib_users;" )
if not users then
local err = sql.LastError()
if err then
Msg( "The users database failed to load.\n" )
Msg( "Error while querying database was: " .. err .. "\n" )
return false
else
return {}
end
end
local out = {}
for _, row in ipairs(users) do
out[row.steamid] = {name = row.name, group = row.usergroup, allow = util.JSONToTable(row.allow) or {}, deny = util.JSONToTable(row.deny) or {}}
end
return out
end
local function reloadUsers()
local runningFromDB = false
local needsBackup = false
local err
ucl.users, err = ULib.parseKeyValues( ULib.removeCommentHeader( ULib.fileRead( path, true ) or "", "/" ) )
-- Start by trying to read from the DB.
if not isFirstTimeDBSetup then
ucl.users = loadUsersFromDB()
if ucl.users then
runningFromDB = true
end
end
-- Next, read from the users file.
if not runningFromDB then
local noMount = true
local path = ULib.UCL_USERS
if not ULib.fileExists( path, noMount ) then
ULib.fileWrite( path, "" )
end
ucl.users, err = ULib.parseKeyValues( ULib.removeCommentHeader( ULib.fileRead( path, noMount ) or "", "/" ) )
end
-- Check to make sure it passes a basic validity test
if not ucl.users then
needsBackup = true
-- Totally messed up! Clear it.
ucl.users = {}
if runningFromDB then
ucl.deleteUsers()
end
else
for id, userInfo in pairs( ucl.users ) do
if type( id ) ~= "string" then
@ -288,11 +374,20 @@ local function reloadUsers()
end
if needsBackup then
Msg( "Users file was not formatted correctly. Attempting to fix and backing up original\n" )
if err then
Msg( "Error while reading users file was: " .. err .. "\n" )
if runningFromDB then
Msg( "There was bad data returned from the database. Attempting to fix, though some data may be lost.\n" )
ucl.deleteUsers()
else
Msg( "Users file was not formatted correctly. Attempting to fix and backing up original\n" )
if err then
Msg( "Error while reading users file was: " .. err .. "\n" )
end
Msg( "Original file was backed up to " .. ULib.backupFile( ULib.UCL_USERS ) .. "\n" )
end
Msg( "Original file was backed up to " .. ULib.backupFile( ULib.UCL_USERS ) .. "\n" )
ucl.saveUsers()
elseif isFirstTimeDBSetup then
isFirstTimeDBSetup = false
Msg( "Migrating users file to users database.\n" )
ucl.saveUsers()
end
end
@ -723,7 +818,7 @@ function ucl.addUser( id, allows, denies, group, from_CAMI )
if denies == ULib.DEFAULT_GRANT_ACCESS.deny then denies = table.Copy( denies ) end -- Otherwise we'd be changing all guest access
if group and not ucl.groups[ group ] then return error( "Group does not exist for adding user to (" .. group .. ")", 2 ) end
-- Lower case'ify
-- This doesn't do anything?
for k, v in ipairs( allows ) do allows[ k ] = v end
for k, v in ipairs( denies ) do denies[ k ] = v end
@ -732,7 +827,7 @@ function ucl.addUser( id, allows, denies, group, from_CAMI )
if ucl.users[ id ] and ucl.users[ id ].group then oldgroup = ucl.users[ id ].group end
ucl.users[ id ] = { allow=allows, deny=denies, group=group, name=name }
ucl.saveUsers()
ucl.saveUser( id, ucl.users[ id ] )
local ply = ULib.getPlyByID( id )
if ply then
@ -864,7 +959,26 @@ function ucl.userAllow( id, access, revoke, deny )
ULib.queueFunctionCall( hook.Call, ULib.HOOK_UCLAUTH, _, ply ) -- Inform the masses
end
ucl.saveUsers()
local saveId
if ucl.users[ id ] then
saveId = id
else
local data = ucl.authed[ uid ]
for checkId, check in pairs( ucl.users ) do
if check == data then
saveId = checkId
break
end
end
end
if saveId then
ucl.saveUser( id, ucl.users[ id ] )
else
Msg( "There was an error while changing user access.\n" )
Msg( "The user ID could not be found, so the user could not be saved\n" )
end
hook.Call( ULib.HOOK_USER_ACCESS_CHANGE, _, id, access, revoke, deny )
hook.Call( ULib.HOOK_UCLCHANGED )
@ -908,18 +1022,18 @@ function ucl.removeUser( id, from_CAMI )
for _, index in ipairs( checkIndexes ) do
if ucl.users[ index ] then
changed = true
changed = index
ucl.users[ index ] = nil
break -- Only match the first one
end
end
else
changed = true
changed = id
ucl.users[ id ] = nil
end
if changed then -- If the user is only added to the default garry file, then nothing changed
ucl.saveUsers()
ucl.deleteUser( changed )
hook.Call( ULib.HOOK_USER_REMOVED, _, id, userInfo )
end
@ -1031,7 +1145,9 @@ function ucl.probe( ply )
-- Update their name
ucl.authed[ uid ].name = ply:Nick()
ucl.saveUsers()
local sid = ply:SteamID()
ucl.saveUser( sid )
match = true
break

View File

@ -948,8 +948,8 @@ local function translateCmdCallback( ply, commandName, argv )
end
end
cmd:call( isOpposite, unpack( args ) )
hook.Call( ULib.HOOK_POST_TRANSLATED_COMMAND, _, ply, commandName, args )
local callResult = cmd:call( isOpposite, unpack( args ) )
hook.Call( ULib.HOOK_POST_TRANSLATED_COMMAND, _, ply, commandName, args, callResult )
end
local function translateAutocompleteCallback( commandName, args )

View File

@ -7,7 +7,7 @@
ULib = ULib or {}
ULib.RELEASE = false -- Don't access these two directly, use ULib.pluginVersionStr("ULib")
ULib.VERSION = 2.70
ULib.VERSION = 2.72
ULib.AUTOMATIC_UPDATE_CHECKS = true
ULib.ACCESS_ALL = "user"
@ -167,10 +167,12 @@ ULib.HOOK_PLAYER_TARGETS = "ULibPlayerTargets" -- Exactly the same as the above
ply - The player that executed the command.
commandName - The command that's being executed.
translated_args - A table of the translated arguments, as passed into the callback function itself.
callResult - The return value of the command function.
Revisions:
v2.40 - Initial
v2.72 - Add the callResult parameter
]]
ULib.HOOK_POST_TRANSLATED_COMMAND = "ULibPostTranslatedCommand"
@ -467,6 +469,4 @@ if SERVER then
util.AddNetworkString( "tsayc" )
util.AddNetworkString( "ulib_repWriteCvar" )
util.AddNetworkString( "ulib_repChangeCvar" )
end

View File

@ -223,7 +223,7 @@ function meta:IsAdmin()
if ucl.groups[ ULib.ACCESS_ADMIN ] then
return self:CheckGroup( ULib.ACCESS_ADMIN )
else -- Group doesn't exist, fall back on garry's method
origIsAdmin( self )
return origIsAdmin( self )
end
end
@ -248,7 +248,7 @@ function meta:IsSuperAdmin()
if ucl.groups[ ULib.ACCESS_SUPERADMIN ] then
return self:CheckGroup( ULib.ACCESS_SUPERADMIN )
else -- Group doesn't exist, fall back on garry's method
origIsSuperAdmin( self )
return origIsSuperAdmin( self )
end
end

View File

@ -1 +1 @@
1644541484
1659669671