diff options
Diffstat (limited to 'lua')
| -rw-r--r-- | lua/autorun/cl_nadmin.lua | 374 | ||||
| -rw-r--r-- | lua/autorun/sh_cami.lua | 559 | ||||
| -rw-r--r-- | lua/autorun/sh_nadmin.lua | 174 | ||||
| -rw-r--r-- | lua/autorun/sv_nadmin.lua | 233 | ||||
| -rw-r--r-- | lua/vgui/dtiltedlabel.lua | 39 |
5 files changed, 1379 insertions, 0 deletions
diff --git a/lua/autorun/cl_nadmin.lua b/lua/autorun/cl_nadmin.lua new file mode 100644 index 0000000..31f7730 --- /dev/null +++ b/lua/autorun/cl_nadmin.lua @@ -0,0 +1,374 @@ +AddCSLuaFile() +if SERVER then return end +local nadmin = include("sh_nadmin.lua") + +--Functions +local add_group_to_groupsheet +local remove_group_from_groupsheet + +--Override what print() does, just for this file +local oldprint = print +local print = function(...) + local args = {...} + table.insert(args,1,"[NADMIN]") + oldprint(unpack(args)) +end +--The variables that hold things +--local groups = nadmin.groups +--local players = nadmin.players +--local privileges = nadmin.privileges + +local usergroup_dropdowns = {} +local function add_usergroup_to_usergroup_dropdowns(name) + for k,v in pairs(usergroup_dropdowns) do + if v:IsValid() then + v:AddChoice(name) + else + usergroup_dropdowns[k] = nil + end + end +end +local function delete_usergroup_from_usergroup_dropdowns(group) + for _,v in pairs(usergroup_dropdowns) do + print("Looking at object:",v) + table.RemoveByValue(v.Choices, name) + if v.Menu then + v.Menu:Remove() + v.Menu = nil + end + if v:GetText() == group.group.Name then + v:SetText(group.group.MinAccess) + end + end +end +net.Receive("nadmin_init_privileges", function(len) + print("got privileges") + nadmin.privileges = net.ReadTable() +end) +net.Receive("nadmin_init_players", function(len) + print("got players") + nadmin.players = net.ReadTable() +end) +net.Receive("nadmin_init_groups", function(len) + print("got groups") + nadmin.groups = net.ReadTable() + PrintTable(nadmin.groups) +end) + +net.Receive("nadmin_update_privilege", function(len) + local exists = net.ReadBool() + local privilege = net.ReadTable() + if exists then + nadmin.privileges[privilege.Name] = privilege + else + nadmin.privileges[privilege.Name] = nil + end +end) +net.Receive("nadmin_create_group", function(len) + local name = net.ReadString() + local inherits = net.ReadString() + local source = net.ReadString() + nadmin.groups[name] = { + name = name, + group = { + Name = name, + Inherits = inherits + }, + privileges = {}, + nadmin = source == "nadmin", + src = source + } + add_group_to_groupsheet(nadmin.groups[name]) + add_usergroup_to_usergroup_dropdowns(name) + CAMI.RegisterUsergroup(nadmin.groups[name].group, "nadmin") +end) +net.Receive("nadmin_update_group", function(len) + local name = net.ReadString() + local privilege = net.ReadString() + local exists = net.ReadBool() + if exists then + nadmin.groups[name].privileges[privilege] = exists + else + nadmin.groups[name].privileges[privilege] = nil + end +end) +net.Receive("nadmin_delete_group", function(len) + local name = net.ReadString() + remove_group_from_groupsheet(nadmin.groups[name]) + delete_usergroup_from_usergroup_dropdowns(nadmin.groups[name]) + nadmin.groups[name] = nil + CAMI.UnregisterUsergroup(name,"nadmin") +end) +net.Receive("nadmin_update_player", function(len) + local player = net.ReadEntity() + local group = net.ReadString() + local sid = player:SteamID64() + print("At time of nadmin_update_player, player is", player) + nadmin.players[sid] = nadmin.players[sid] or {} + nadmin.players[sid].group = group + nadmin.players[sid].last_name = player:Name() + if nadmin.players[sid].combo then + nadmin.players[sid].combo:SetValue(group) + end + if nadmin.players[sid].line then + nadmin.players[sid].line:SetColumnText(2,player:Name()) + end + CAMI.SignalSteamIDUserGroupChanged(sid,group,"nadmin") +end) + +concommand.Add("cl_print_privileges", function(ply,cmd,args) + PrintTable(nadmin.privileges) +end) +concommand.Add("cl_print_groups", function(ply,cmd,args) + print("NAdmin groups:",nadmin.groups) + PrintTable(nadmin.groups) + print("Local groups:",groups) + PrintTable(nadmin.groups) +end) +concommand.Add("cl_print_players", function(ply,cmd,args) + PrintTable(nadmin.players) +end) + +local function create_usergroup_combo(parent) + local ret = vgui.Create("DComboBox",parent) + for groupname, _ in pairs(nadmin.groups) do + ret:AddChoice(groupname) + end + table.insert(usergroup_dropdowns, ret) + return ret +end + +local nadmin_frame,users_tbl,groups_tbl = nil,nil,nil +local users_sheet,groups_sheet = nil,nil +--ply :: entity +local function add_user_to_usersheet(steamid,ply) + if not nadmin_frame then return end + local player_ent = player.GetBySteamID64(steamid) + local line = users_tbl:AddLine(steamid, ply.last_name, ply.group) + local dropdown = create_usergroup_combo(line) + if nadmin.players[steamid] then + dropdown:SetValue(nadmin.players[steamid].group) + else + dropdown:SetValue("user") + end + dropdown.OnSelect = function(self, index, value) + net.Start("nadmin_request_set_user_group") + net.WriteEntity(player_ent) + net.WriteString(value) + net.SendToServer() + end + line:SetColumnText(3,dropdown) + ply.combo = dropdown --Update the combo box when someone else updates the group + ply.line = line +end + +--ply :: entity +local function remove_user_from_usersheet(ply) + if not nadmin_frame then return end + if not ply.line then return end + users_tbl:RemoveLine(ply.line.m_iID) +end + +local privilege_checkboxes = {} +local function add_privilege_to_groupsheet(privilege) + local ordered_privileges = {} + for _,privilege in pairs(nadmin.privileges) do + table.insert(ordered_privileges,privilege) + end + table.sort(ordered_privileges, function(a,b) return a.Name > b.Name end) + local privilege_num = 0 + for num,ordered_privilege in pairs(ordered_privileges) do + if ordered_privilege == privilege then + privilege_num = num + break + end + end + local column = groups_tbl:AddColumn(privilege.Name) + column.DoClick = function(self) + local explain_frame = vgui.Create("DFrame") + explain_frame:SetTitle(privilege.Name) + local description = vgui.Create("DLabel",explain_frame) + description:SetWrap(true) + if privilege.Description then + description:SetText(privilege.Description) + else + description:SetText("This privilege does not have a description") + end + explain_frame:SetSize(ScrW() / 6, ScrH() / 4) + explain_frame:SetPos(ScrW() / 4 + 100,ScrH() / 4 + 50) + explain_frame:MakePopup() + description:Dock(FILL) + end + column:SetWrap(true) + for groupname,group in pairs(nadmin.groups) do + local checkbox = vgui.Create("DCheckBox", group.line) + privilege_checkboxes[groupname] = checkbox + print("Group:") + PrintTable(group) + if group.nadmin then + checkbox:SetChecked(group.privileges[privilege.Name]) + checkbox.OnChange = function(self,value) + net.Start("nadmin_request_update_group") + net.WriteString(groupname) + net.WriteString(privilege.Name) + net.WriteBool(value) + net.SendToServer() + end + else + checkbox:SetDisabled(true) + end + group.line:SetColumnText(privilege_num + 2,checkbox) + end +end + +local function remove_privilege_from_groupsheet(privilege) + +end + +add_group_to_groupsheet = function(group) + if not groups_tbl then return end + local line = groups_tbl:AddLine(group.group.Name) + local ordered_privileges = {} + for _,privilege in pairs(nadmin.privileges) do + table.insert(ordered_privileges,privilege) + end + table.sort(ordered_privileges, function(a,b) return a.Name > b.Name end) + local delete_group_button = vgui.Create("DButton",line) + delete_group_button:SetText("-") + delete_group_button:SetEnabled(group.nadmin) + delete_group_button.DoClick = function(self) + net.Start("nadmin_request_delete_group")--(group :: string) + net.WriteString(group.group.Name) + net.SendToServer() + end + line:SetColumnText(2,delete_group_button) + for n,privilege_name in pairs(ordered_privileges) do + local privilege_checkbox = vgui.Create("DCheckBox",line) + line:SetColumnText(n + 2,privilege_checkbox) + if group.nadmin then + privilege_checkbox:SetChecked(group.privileges[privilege_name]) + privilege_checkbox.OnChange = function(self,val) + net.Start("nadmin_request_update_group") --(group :: string, privilege :: string, set :: bool) + net.WriteString(group.group.Name) + net.WriteString(privilege_name.Name) + net.WriteBool(val) + net.SendToServer() + end + else + privilege_checkbox:SetDisabled(true) + end + end + group.line = line + group.line_id = #groups_tbl.Lines +end + +function remove_group_from_groupsheet(group) + groups_tbl:RemoveLine(group.line_id) +end + +local function create_new_group_dialog() + local dialog = vgui.Create("DFrame") + dialog:SetTitle("Create Group") + + local inherits_label = vgui.Create("DLabel",dialog) + inherits_label:Dock(TOP) + inherits_label:SetText("Inherits from") + + local inherits = create_usergroup_combo(dialog) + inherits:Dock(TOP) + + local groupname_label = vgui.Create("DLabel",dialog) + groupname_label:Dock(TOP) + groupname_label:SetText("Group Name") + + local groupname = vgui.Create("DTextEntry",dialog) + groupname:Dock(TOP) + + local createbtn = vgui.Create("DButton",dialog) + createbtn:SetText("Create Group") + createbtn.DoClick = function(self) + net.Start("nadmin_request_create_group") + net.WriteString(groupname:GetText()) + net.WriteString(inherits:GetText()) + net.SendToServer() + dialog:Close() + end + createbtn:Dock(BOTTOM) + + dialog:SetSize(250,150) + dialog:Center() + dialog:MakePopup() +end + +local function create_nadmin_panel() + if nadmin_frame ~= nil and nadmin_frame:IsValid() then + nadmin_frame:SetVisible(true) + return + end + + nadmin_frame = vgui.Create("DFrame") + nadmin_frame:SetTitle("nAdmin") + nadmin_frame.OnClose = function(self) + self:SetVisible(false) + return false + end + nadmin_frame:SetSizable(true) + local prop_sheet = vgui.Create("DPropertySheet",nadmin_frame) + prop_sheet:Dock(FILL) + users_tbl = vgui.Create("DListView",prop_sheet) + users_tbl:AddColumn("SteamID") + users_tbl:AddColumn("Name") + users_tbl:AddColumn("Group") + for steamid,player in pairs(nadmin.players) do + add_user_to_usersheet(steamid,player) + end + + prop_sheet:AddSheet("Users",users_tbl,nil,true,true,"Sets users to particular groups") + + users_tbl:Dock(FILL) + + local groups_scroller = vgui.Create("DHorizontalScroller",prop_sheet) + groups_tbl = vgui.Create("DListView",groups_scroller) + groups_scroller:Dock(FILL) + local gcol = groups_tbl:AddColumn("Group") + local dcol = groups_tbl:AddColumn("Delete") + gcol:SetEnabled(false) + dcol:SetEnabled(false) + local tot_columns = 0 + local tot_width = 0 + --Don't do anything if the user clicks the Group or Delete headers + for _,v in pairs(groups_tbl.Columns) do + v.DoClick = function() end + end + local add_line = groups_tbl:AddLine("") + local add_btn = vgui.Create("DButton",add_line) + add_btn:SetText("+") + add_btn.DoClick = function(self) + create_new_group_dialog() + end + add_line:SetColumnText(1,add_btn) + for groupname,group in pairs(nadmin.groups) do + tot_columns = tot_columns + 1 + add_group_to_groupsheet(group) + tot_width = tot_width + string.len(groupname)*30 --10 pixels for each character? + end + + for privilegename, privilege in pairs(nadmin.privileges) do + add_privilege_to_groupsheet(privilege) + end + groups_tbl:SetWidth(tot_width) + prop_sheet:AddSheet("Groups",groups_scroller,nil,true,true,"Set the privileges for a group") + groups_scroller:AddPanel(groups_tbl) + + nadmin_frame:SetSize(ScrW() / 2, ScrH() / 2) + nadmin_frame:SetPos(ScrW() / 4, ScrH() / 4) + nadmin_frame:MakePopup() +end + +concommand.Add("cl_nadmin", function(ply,cmd,args) + create_nadmin_panel() +end) +concommand.Add("cl_nadmin_new", function(ply,cmd,args) + nadmin_frame = nil + create_nadmin_panel() +end) diff --git a/lua/autorun/sh_cami.lua b/lua/autorun/sh_cami.lua new file mode 100644 index 0000000..c395901 --- /dev/null +++ b/lua/autorun/sh_cami.lua @@ -0,0 +1,559 @@ +AddCSLuaFile() +--[[ +CAMI - Common Admin Mod Interface. +Copyright 2019 CAMI Contributors + +Makes admin mods intercompatible and provides an abstract privilege interface +for third party addons. + +Follows the specification on this page: +https://github.com/glua/CAMI/blob/master/README.md + +Structures: + CAMI_USERGROUP, defines the charactaristics of a usergroup: + { + Name + string + The name of the usergroup + Inherits + string + The name of the usergroup this usergroup inherits from + } + + CAMI_PRIVILEGE, defines the charactaristics of a privilege: + { + Name + string + The name of the privilege + MinAccess + string + One of the following three: user/admin/superadmin + Description + string + optional + A text describing the purpose of the privilege + HasAccess + function( + privilege :: CAMI_PRIVILEGE, + actor :: Player, + target :: Player + ) :: bool + optional + Function that decides whether a player can execute this privilege, + optionally on another player (target). + } + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +-- Version number in YearMonthDay format. +local version = 20190102 + +if CAMI and CAMI.Version >= version then return end + +CAMI = CAMI or {} +CAMI.Version = version + +--[[ +usergroups + Contains the registered CAMI_USERGROUP usergroup structures. + Indexed by usergroup name. +]] +local usergroups = CAMI.GetUsergroups and CAMI.GetUsergroups() or { + user = { + Name = "user", + Inherits = "user" + }, + admin = { + Name = "admin", + Inherits = "user" + }, + superadmin = { + Name = "superadmin", + Inherits = "admin" + } +} + +--[[ +privileges + Contains the registered CAMI_PRIVILEGE privilege structures. + Indexed by privilege name. +]] +local privileges = CAMI.GetPrivileges and CAMI.GetPrivileges() or {} + +--[[ +CAMI.RegisterUsergroup + Registers a usergroup with CAMI. + + Parameters: + usergroup + CAMI_USERGROUP + (see CAMI_USERGROUP structure) + source + any + Identifier for your own admin mod. Can be anything. + Use this to make sure CAMI.RegisterUsergroup function and the + CAMI.OnUsergroupRegistered hook don't cause an infinite loop + + + + Return value: + CAMI_USERGROUP + The usergroup given as argument. +]] +function CAMI.RegisterUsergroup(usergroup, source) + usergroups[usergroup.Name] = usergroup + + hook.Call("CAMI.OnUsergroupRegistered", nil, usergroup, source) + return usergroup +end + +--[[ +CAMI.UnregisterUsergroup + Unregisters a usergroup from CAMI. This will call a hook that will notify + all other admin mods of the removal. + + Call only when the usergroup is to be permanently removed. + + Parameters: + usergroupName + string + The name of the usergroup. + source + any + Identifier for your own admin mod. Can be anything. + Use this to make sure CAMI.UnregisterUsergroup function and the + CAMI.OnUsergroupUnregistered hook don't cause an infinite loop + + Return value: + bool + Whether the unregistering succeeded. +]] +function CAMI.UnregisterUsergroup(usergroupName, source) + if not usergroups[usergroupName] then return false end + + local usergroup = usergroups[usergroupName] + usergroups[usergroupName] = nil + + hook.Call("CAMI.OnUsergroupUnregistered", nil, usergroup, source) + + return true +end + +--[[ +CAMI.GetUsergroups + Retrieves all registered usergroups. + + Return value: + Table of CAMI_USERGROUP, indexed by their names. +]] +function CAMI.GetUsergroups() + return usergroups +end + +--[[ +CAMI.GetUsergroup + Receives information about a usergroup. + + Return value: + CAMI_USERGROUP + Returns nil when the usergroup does not exist. +]] +function CAMI.GetUsergroup(usergroupName) + return usergroups[usergroupName] +end + +--[[ +CAMI.UsergroupInherits + Returns true when usergroupName1 inherits usergroupName2. + Note that usergroupName1 does not need to be a direct child. + Every usergroup trivially inherits itself. + + Parameters: + usergroupName1 + string + The name of the usergroup that is queried. + usergroupName2 + string + The name of the usergroup of which is queried whether usergroupName + inherits from. + + Return value: + bool + Whether usergroupName1 inherits usergroupName2. +]] +function CAMI.UsergroupInherits(usergroupName1, usergroupName2) + repeat + if usergroupName1 == usergroupName2 then return true end + + usergroupName1 = usergroups[usergroupName1] and + usergroups[usergroupName1].Inherits or + usergroupName1 + until not usergroups[usergroupName1] or + usergroups[usergroupName1].Inherits == usergroupName1 + + -- One can only be sure the usergroup inherits from user if the + -- usergroup isn't registered. + return usergroupName1 == usergroupName2 or usergroupName2 == "user" +end + +--[[ +CAMI.InheritanceRoot + All usergroups must eventually inherit either user, admin or superadmin. + Regardless of what inheritance mechism an admin may or may not have, this + always applies. + + This method always returns either user, admin or superadmin, based on what + usergroups eventually inherit. + + Parameters: + usergroupName + string + The name of the usergroup of which the root of inheritance is + requested + + Return value: + string + The name of the root usergroup (either user, admin or superadmin) +]] +function CAMI.InheritanceRoot(usergroupName) + if not usergroups[usergroupName] then return end + + local inherits = usergroups[usergroupName].Inherits + while inherits ~= usergroups[usergroupName].Inherits do + usergroupName = usergroups[usergroupName].Inherits + end + + return usergroupName +end + +--[[ +CAMI.RegisterPrivilege + Registers a privilege with CAMI. + Note: do NOT register all your admin mod's privileges with this function! + This function is for third party addons to register privileges + with admin mods, not for admin mods sharing the privileges amongst one + another. + + Parameters: + privilege + CAMI_PRIVILEGE + See CAMI_PRIVILEGE structure. + + Return value: + CAMI_PRIVILEGE + The privilege given as argument. +]] +function CAMI.RegisterPrivilege(privilege) + privileges[privilege.Name] = privilege + + hook.Call("CAMI.OnPrivilegeRegistered", nil, privilege) + + return privilege +end + +--[[ +CAMI.UnregisterPrivilege + Unregisters a privilege from CAMI. This will call a hook that will notify + all other admin mods of the removal. + + Call only when the privilege is to be permanently removed. + + Parameters: + privilegeName + string + The name of the privilege. + + Return value: + bool + Whether the unregistering succeeded. +]] +function CAMI.UnregisterPrivilege(privilegeName) + if not privileges[privilegeName] then return false end + + local privilege = privileges[privilegeName] + privileges[privilegeName] = nil + + hook.Call("CAMI.OnPrivilegeUnregistered", nil, privilege) + + return true +end + +--[[ +CAMI.GetPrivileges + Retrieves all registered privileges. + + Return value: + Table of CAMI_PRIVILEGE, indexed by their names. +]] +function CAMI.GetPrivileges() + return privileges +end + +--[[ +CAMI.GetPrivilege + Receives information about a privilege. + + Return value: + CAMI_PRIVILEGE when the privilege exists. + nil when the privilege does not exist. +]] +function CAMI.GetPrivilege(privilegeName) + return privileges[privilegeName] +end + +--[[ +CAMI.PlayerHasAccess + Queries whether a certain player has the right to perform a certain action. + + Parameters: + actorPly + Player + The player of which is requested whether they have the privilege. + privilegeName + string + The name of the privilege. + callback + function(bool, string) or nil + This function will be called with the answer. The bool signifies the + yes or no answer as to whether the player is allowed. The string + will optionally give a reason. + + Give an explicit nil here to get an answer immediately + Important note: May throw an error when the admin mod doesn't + give an answer immediately! + targetPly + Optional. + The player on which the privilege is executed. + extraInfoTbl + Optional. + Table containing extra information. + Officially supported members: + Fallback + string + Either of user/admin/superadmin. When no admin mod replies, + the decision is based on the admin status of the user. + Defaults to admin if not given. + IgnoreImmunity + bool + Ignore any immunity mechanisms an admin mod might have. + CommandArguments + table + Extra arguments that were given to the privilege command. + + Return value: + If callback is specified: + None + Otherwise: + hasAccess + bool + Whether the player has access + reason + Optional. + The reason why a player does or does not have access. +]] +-- Default access handler +local defaultAccessHandler = {["CAMI.PlayerHasAccess"] = + function(_, actorPly, privilegeName, callback, _, extraInfoTbl) + -- The server always has access in the fallback + if not IsValid(actorPly) then return callback(true, "Fallback.") end + + local priv = privileges[privilegeName] + + local fallback = extraInfoTbl and ( + not extraInfoTbl.Fallback and actorPly:IsAdmin() or + extraInfoTbl.Fallback == "user" and true or + extraInfoTbl.Fallback == "admin" and actorPly:IsAdmin() or + extraInfoTbl.Fallback == "superadmin" and actorPly:IsSuperAdmin()) + + + if not priv then return callback(fallback, "Fallback.") end + + callback( + priv.MinAccess == "user" or + priv.MinAccess == "admin" and actorPly:IsAdmin() or + priv.MinAccess == "superadmin" and actorPly:IsSuperAdmin() + , "Fallback.") + end, + ["CAMI.SteamIDHasAccess"] = + function(_, _, _, callback) + callback(false, "No information available.") + end +} +function CAMI.PlayerHasAccess(actorPly, privilegeName, callback, targetPly, +extraInfoTbl) + local hasAccess, reason = nil, nil + local callback_ = callback or function(hA, r) hasAccess, reason = hA, r end + + hook.Call("CAMI.PlayerHasAccess", defaultAccessHandler, actorPly, + privilegeName, callback_, targetPly, extraInfoTbl) + + if callback ~= nil then return end + + if hasAccess == nil then + local err = [[The function CAMI.PlayerHasAccess was used to find out + whether Player %s has privilege "%s", but an admin mod did not give an + immediate answer!]] + error(string.format(err, + actorPly:IsPlayer() and actorPly:Nick() or tostring(actorPly), + privilegeName)) + end + + return hasAccess, reason +end + +--[[ +CAMI.GetPlayersWithAccess + Finds the list of currently joined players who have the right to perform a + certain action. + NOTE: this function will NOT return an immediate result! + The result is in the callback! + + Parameters: + privilegeName + string + The name of the privilege. + callback + function(players) + This function will be called with the list of players with access. + targetPly + Optional. + The player on which the privilege is executed. + extraInfoTbl + Optional. + Table containing extra information. + Officially supported members: + Fallback + string + Either of user/admin/superadmin. When no admin mod replies, + the decision is based on the admin status of the user. + Defaults to admin if not given. + IgnoreImmunity + bool + Ignore any immunity mechanisms an admin mod might have. + CommandArguments + table + Extra arguments that were given to the privilege command. +]] +function CAMI.GetPlayersWithAccess(privilegeName, callback, targetPly, +extraInfoTbl) + local allowedPlys = {} + local allPlys = player.GetAll() + local countdown = #allPlys + + local function onResult(ply, hasAccess, _) + countdown = countdown - 1 + + if hasAccess then table.insert(allowedPlys, ply) end + if countdown == 0 then callback(allowedPlys) end + end + + for _, ply in ipairs(allPlys) do + CAMI.PlayerHasAccess(ply, privilegeName, + function(...) onResult(ply, ...) end, + targetPly, extraInfoTbl) + end +end + +--[[ +CAMI.SteamIDHasAccess + Queries whether a player with a steam ID has the right to perform a certain + action. + Note: the player does not need to be in the server for this to + work. + + Note: this function does NOT return an immediate result! + The result is in the callback! + + Parameters: + actorSteam + Player + The SteamID of the player of which is requested whether they have + the privilege. + privilegeName + string + The name of the privilege. + callback + function(bool, string) + This function will be called with the answer. The bool signifies the + yes or no answer as to whether the player is allowed. The string + will optionally give a reason. + targetSteam + Optional. + The SteamID of the player on which the privilege is executed. + extraInfoTbl + Optional. + Table containing extra information. + Officially supported members: + IgnoreImmunity + bool + Ignore any immunity mechanisms an admin mod might have. + CommandArguments + table + Extra arguments that were given to the privilege command. + + Return value: + None, the answer is given in the callback function in order to allow + for the admin mod to perform e.g. a database lookup. +]] +function CAMI.SteamIDHasAccess(actorSteam, privilegeName, callback, +targetSteam, extraInfoTbl) + hook.Call("CAMI.SteamIDHasAccess", defaultAccessHandler, actorSteam, + privilegeName, callback, targetSteam, extraInfoTbl) +end + +--[[ +CAMI.SignalUserGroupChanged + Signify that your admin mod has changed the usergroup of a player. This + function communicates to other admin mods what it thinks the usergroup + of a player should be. + + Listen to the hook to receive the usergroup changes of other admin mods. + + Parameters: + ply + Player + The player for which the usergroup is changed + old + string + The previous usergroup of the player. + new + string + The new usergroup of the player. + source + any + Identifier for your own admin mod. Can be anything. +]] +function CAMI.SignalUserGroupChanged(ply, old, new, source) + hook.Call("CAMI.PlayerUsergroupChanged", nil, ply, old, new, source) +end + +--[[ +CAMI.SignalSteamIDUserGroupChanged + Signify that your admin mod has changed the usergroup of a disconnected + player. This communicates to other admin mods what it thinks the usergroup + of a player should be. + + Listen to the hook to receive the usergroup changes of other admin mods. + + Parameters: + ply + string + The steam ID of the player for which the usergroup is changed + old + string + The previous usergroup of the player. + new + string + The new usergroup of the player. + source + any + Identifier for your own admin mod. Can be anything. +]] +function CAMI.SignalSteamIDUserGroupChanged(steamId, old, new, source) + hook.Call("CAMI.SteamIDUsergroupChanged", nil, steamId, old, new, source) +end diff --git a/lua/autorun/sh_nadmin.lua b/lua/autorun/sh_nadmin.lua new file mode 100644 index 0000000..392daec --- /dev/null +++ b/lua/autorun/sh_nadmin.lua @@ -0,0 +1,174 @@ +include("sh_cami.lua") +AddCSLuaFile() +local nadmin = {} + +--[[ +Groups is a table of +["group_name"] = { + nadmin :: bool --Wether the group was created by nAdmin or not + --nAdmin will only allow you to delete groups + --that were created with it. You cannot delete + --groups that were created with another mod. + + group :: CAMI_USERGROUP -- the usergroup table given by CAMI, + -- see sh_cami.lua for details. + + src :: string --The source of the usergroup, can be "cami", nAdmin, + --or the name of the mod that introduced the usergroup. + + privileges :: table --An array of ["privilege_name"] = true, for + --each privilege the group has +} +]] +nadmin.groups = {} +for _,v in pairs(CAMI.GetUsergroups()) do + print("Initalizing usergroups, this usergroup was",v) + PrintTable(v) + nadmin.groups[v.Name] = { + nadmin = false, + group = v, + src = "cami", + privileges = {}, + } + for _,privilege in pairs(CAMI.GetPrivileges()) do + if privilege.MinAccess == v.Name then + nadmin.groups[v.Name].privileges[privilege.Name] = true + end + end +end +--[[ +Players is a table of +[player_steamid] = { + group :: CAMI_USERGROUP --The usergroup table given by CAMI that + --the player is a part of, see sh_cami.lua for + --details + + last_name :: string --The last name that the player joined the server + --with, this is used to set player's permissions + --even when the player is offline. +]] +nadmin.players = {} +nadmin.privileges = CAMI.GetPrivileges() + +function nadmin.AddUserGroup(src,usergroup) + nadmin.groups[usergroup.Name] = { + nadmin = src == "nadmin", + group = usergroup, + src = src, + privileges = {} + } +end + +function nadmin.DeleteUserGroup(name,src) + nadmin.groups[name] = nil +end + +function nadmin.save_config() + if not SERVER then return end + local file_parts = {"return {"} + + --Save groups + table.insert(file_parts,"groups = {") + for groupname, group in pairs(nadmin.groups) do + if group.nadmin then + local privileges_tbl = {} + for privilege_name,_ in pairs(group.privileges) do + table.insert(privileges_tbl,string.format("[%q] = true",privilege_name)) + end + table.insert(file_parts,string.format([[ + [%q] = { + name = %q, + inherits = %q, + privileges = {%s} + },]],groupname, group.group.Name, group.group.Inherits, table.concat(privileges_tbl,","))) + end + end + table.insert(file_parts,"},") + + --Save players + table.insert(file_parts,"players = {") + for playerid, player in pairs(nadmin.players) do + table.insert(file_parts,string.format([[ + [%q] = { + last_name = %q, + group = %q + },]], playerid, player.last_name, player.group)) + end + table.insert(file_parts,"},") + + --Finish off + table.insert(file_parts,"}") + --And save to file + file.Write("nadmin.txt",table.concat(file_parts,"\n")) +end + +--Notify client of changes to the groups table +hook.Add("CAMI.OnUsergroupRegistered","nadmin_OnUserGroupRegistered",function(usergroup,src) + print("hook nadmin_OnUserGroupRegistered called, src was", src) + src = src or "" + print("Usergroup was:",usergroup, usergroup.Name, usergroup.Inherits) + nadmin.AddUserGroup(src,usergroup) + if SERVER then + net.Start("nadmin_create_group") + net.WriteString(usergroup.Name) + net.WriteString(usergroup.Inherits or "users") --Some mods call this hook without an "Inherits" + net.WriteString(src) + net.Broadcast() + nadmin.save_config() + end +end) + +hook.Add("CAMI.OnUsergroupUnregistered","nadmin_OnUserGroupUnregistered",function(usergroup,src) + nadmin.DeleteUserGroup(usergroup.Name, src) + if SERVER then + net.Start("nadmin_delete_group") + net.WriteString(usergroup.Name) + net.Broadcast() + nadmin.save_config() + end +end) + +hook.Add("CAMI.PlayerUsergroupChanged","nadmin_PlayerUsergroupChanged",function(ply,from,to,src) + local sid = ply:SteamID64() + nadmin.players[sid] = nadmin.players[sid] or {} + nadmin.players[sid].group = to + if SERVER then + net.Start("nadmin_update_player") + net.WriteEntity(ply) + net.WriteString(to) + net.Broadcast() + nadmin.save_config() + end +end) + +hook.Add("CAMI.OnPrivilegeRegistered", "nadmin_OnPrivilegeRegistered", function(privilege) + nadmin.privileges[privilege.Name] = privilege + nadmin.save_config() +end) + +hook.Add("CAMI.OnPrivilegeUnregistered", "nadmin_OnPrivilegeUnregistered", function(privilege) + nadmin.privileges[privilege.Name] = nil +end) + +hook.Add("CAMI.PlayerHasAccess","nadmin_PlayerHasAccess",function(ply,name,callback,target,extra) + if (not ply) or (not ply:IsValid()) then return end + print("At time of PlayerHasAccess call, players was",nadmin.players, "for", ply) + local sid = ply:SteamID64() + if not nadmin.players[sid] then return end + local group = nadmin.players[ply:SteamID64()].group + if group and type(group) == "table" and group.nadmin and group.privileges[name] then + return true + end +end) + +hook.Add("CAMI.SteamIDHasAccess","nadmin_SteamIDHasAccess",function(id,privilege,callback,target,extra) + local group = nadmin.players[id].group + if group and group.nadmin and group.privileges[privilege] then + return true + end +end) + +--nadmin.groups = groups +--nadmin.players = players +--nadmin.privileges = privileges +return nadmin diff --git a/lua/autorun/sv_nadmin.lua b/lua/autorun/sv_nadmin.lua new file mode 100644 index 0000000..b581711 --- /dev/null +++ b/lua/autorun/sv_nadmin.lua @@ -0,0 +1,233 @@ +if CLIENT then return end +include("sh_cami.lua") +local nadmin = include("sh_nadmin.lua") + +--Override what print() does, just for this file +local oldprint = print +print = function(...) + local args = {...} + table.insert(args,1,"[NADMIN]") + oldprint(unpack(args)) +end +for _,v in pairs({ + --Server to client + "nadmin_update_privilege", -- (exists :: bool, privilege :: CAMI_PRIVILEGE) + + "nadmin_create_group", -- (name :: string, inherits :: string, source :: string) + "nadmin_update_group", -- (name :: string, privilege :: string, exists :: bool) + "nadmin_delete_group", -- (name :: string) + + "nadmin_update_player", -- (entity :: player, group :: string) + + "nadmin_init_privileges", -- (privileges :: table) + "nadmin_init_players", -- (players :: table) + "nadmin_init_groups", -- (groups :: table) + + --Client to server + "nadmin_request_set_user_group", --(player :: entity, group :: string) + "nadmin_request_create_group", --(group :: string, inherits :: string) + "nadmin_request_update_group", --(group :: string, privilege :: string, set :: bool) + "nadmin_request_delete_group", --(group :: string) +}) do + util.AddNetworkString(v) +end +--Load saved groups & privileges +local groups = nadmin.groups +local players = nadmin.players +local privileges = nadmin.privileges +--Delete the HasAccess functions +for _,privilege in pairs(privileges) do + privilege.HasAccess = nil +end +if file.Exists("nadmin.txt","DATA") then + local func, err = CompileString(file.Read("nadmin.txt","DATA"), "nadmin.txt") + local func_sandboxed = setfenv(func,{}) --Empty environment, you can't even print from inside (you could do an infinite loop, I guess) + local succ, nadmindata = pcall(func_sandboxed) + if not succ then + error("Failed to load groups:", nadmindata) + return --stop loading the file + end + local mygroups, myplayers = nadmindata.groups, nadmindata.players + for groupname, group in pairs(mygroups) do + local camigroup = { + Name = group.name, + Inherits = group.inherits, + } + CAMI.RegisterUsergroup(camigroup) + groups[groupname] = { + nadmin = true, + group = camigroup, + src = "nadmin", + privileges = group.privileges + } + end +end + +--[[ +Creates a new group that players can be +added to. All groups must inherit from a +group, except for the "user" "admin" and +"superadmin" groups. +]] +--(group :: string, inherits :: string) +local function create_usergroup(name,inherits) + local group = { + Name = name, + Inherits = inherits + } + CAMI.RegisterUsergroup(group, "nadmin") + nadmin.save_config() +end + +--[[ +Edits the privileges on a usergroup. +Players added to the usergroup will +now have the privilege set. +]] +--name :: string, privilegename :: string, set :: bool +local function edit_usergroup(name,privilegename,set) + if set then + groups[name].privileges[privilegename] = set + else + groups[name].privileges[privilegename] = nil + end + net.Start("nadmin_update_group") + net.WriteString(name) + net.WriteString(privilegename) + net.WriteBool(set) + net.Broadcast() + nadmin.save_config() +end + +--[[ +Deletes a usergroup. Any players assigned +to the deleted group will be reassigned +to the usergroup that the deleted group +inherited from. Any groups that inherited +from the usergroup in the heiarchy will +inherit from the group the usergroup +inherited from. +]] +--(group :: string) +local function delete_usergroup(name) + local inherited_from_name = groups[name].group.Inherits + local inherited_from = groups[inherited_from_name] + local group = groups[name] + for _,v in pairs(players) do + if v.group == groups[name] then + v.group = inherited_from + end + end + for _,v in pairs(groups) do + if v.group.Inherits == group then + v.group.Inherits = inherited_from + end + end + CAMI.UnregisterUsergroup(group, "nadmin") + groups[name] = nil +end + +local function set_user_to_group(ply,group) + local id,name = ply:SteamID64(), ply:Name() + players[id] = { + group = group, + last_name = name + } + net.Start("nadmin_update_player") + net.WriteEntity(ply) + net.WriteString(group) + net.Broadcast() + nadmin.save_config() +end + +local function send_init_info(ply) + net.Start("nadmin_init_privileges") + local light_privileges = {} + for privilege_name,privilege in pairs(privileges) do + light_privileges[privilege_name] = { + Description = privilege.Description, + MinAccess = privilege.MinAccess, + Name = privilege.Name + } + end + net.WriteTable(light_privileges) + net.Send(ply) + + net.Start("nadmin_init_players") + net.WriteTable(players) + net.Send(ply) + + net.Start("nadmin_init_groups") + net.WriteTable(groups) + net.Send(ply) +end + +net.Receive("nadmin_request_set_user_group",function(len,ply) + if not ply:IsSuperAdmin() then return end + local player = net.ReadEntity() + local group = net.ReadString() + set_user_to_group(player,group) +end) + +net.Receive("nadmin_request_create_group",function(len,ply) + if not ply:IsSuperAdmin() then return end + local groupname = net.ReadString() + local inherits = net.ReadString() + create_usergroup(groupname,inherits) +end) + +net.Receive("nadmin_request_update_group",function(len,ply) + if not ply:IsSuperAdmin() then return end + local groupname = net.ReadString() + local privilegename = net.ReadString() + local set = net.ReadBool() + edit_usergroup(groupname,privilegename,set) +end) + +net.Receive("nadmin_request_delete_group", function(len,ply) + if not ply:IsSuperAdmin() then return end + local group = net.ReadString() + delete_usergroup(group) +end) + +hook.Add("PlayerInitialSpawn","nadmin_init_tables",function(ply) + timer.Simple(5,function() + if players[ply:SteamID64()] == nil then + local igroup = "user" + if ply:IsSuperAdmin() then igroup = "superadmin" + elseif ply:IsAdmin() then igroup = "admin" end + players[ply:SteamID64()] = { + group = igroup, + last_name = ply:Name() + } + set_user_to_group(ply,igroup) + end + if ply:IsSuperAdmin() then + send_init_info(ply) + end + end) +end) + +concommand.Add("sv_resave", function(ply,cmd,args) + if not ply:IsSuperAdmin() then return end + nadmin.save_config() +end) + +concommand.Add("sv_print_privileges", function(ply,cmd,args) + if not ply:IsSuperAdmin() then return end + PrintTable(privileges) +end) +concommand.Add("sv_print_groups", function(ply,cmd,args) + if not ply:IsSuperAdmin() then return end + PrintTable(groups) +end) +concommand.Add("sv_print_players", function(ply,cmd,args) + if not ply:IsSuperAdmin() then return end + PrintTable(players) +end) +concommand.Add("sv_resend_init",function(ply,cmd,args) + if not ply:IsSuperAdmin() then return end + send_init_info(ply) +end) +--Reset the print function +print = oldprint diff --git a/lua/vgui/dtiltedlabel.lua b/lua/vgui/dtiltedlabel.lua new file mode 100644 index 0000000..a0aaf7d --- /dev/null +++ b/lua/vgui/dtiltedlabel.lua @@ -0,0 +1,39 @@ +local PANEL = {} +local base = vgui.GetControlTable("DLabel") +setmetatable(PANEL,{__index=base}) + +--Function stolen from the lua wiki +function draw.TextRotated( text, x, y, color, font, ang ) + render.PushFilterMag( TEXFILTER.ANISOTROPIC ) + render.PushFilterMin( TEXFILTER.ANISOTROPIC ) + surface.SetFont( font ) + surface.SetTextColor( color ) + surface.SetTextPos( 0, 0 ) + local textWidth, textHeight = surface.GetTextSize( text ) + local rad = -math.rad( ang ) + x = x - ( math.cos( rad ) * textWidth / 2 + math.sin( rad ) * textHeight / 2 ) + y = y + ( math.sin( rad ) * textWidth / 2 + math.cos( rad ) * textHeight / 2 ) + local m = Matrix() + m:SetAngles( Angle( 0, ang, 0 ) ) + m:SetTranslation( Vector( x, y, 0 ) ) + cam.PushModelMatrix( m ) + surface.DrawText( text ) + cam.PopModelMatrix() + render.PopFilterMag() + render.PopFilterMin() +end +function PANEL:Paint(w,h) + local x,y = self:LocalToScreen(0,0) + print("x",x,"y",y) + draw.TextRotated(self:GetText(),0,y,Color(0,0,0,255),"DermaDefault",-45) +end +function PANEL:GetHeaderHeight() + return 0--10 * #(self.Header:GetText()) +end +function PANEL:Init() + + --self.Header = vgui.Create( "DButton", self ) + --self.Header.DoClick = function() self:DoClick() end + --self.Header.DoRightClick = function() self:DoRightClick() end +end +vgui.Register("DTiltedLabel", PANEL, "DLabel") |
