diff --git a/builtin/game/auth.lua b/builtin/game/auth.lua index 7a6be8788..4d5178ba7 100644 --- a/builtin/game/auth.lua +++ b/builtin/game/auth.lua @@ -125,6 +125,21 @@ core.builtin_auth_handler = { core.get_password_hash(name, core.settings:get("default_password"))) end + + -- Run grant callbacks + for priv, _ in pairs(privileges) do + if not core.auth_table[name].privileges[priv] then + core.run_priv_callbacks(name, priv, nil, "grant") + end + end + + -- Run revoke callbacks + for priv, _ in pairs(core.auth_table[name].privileges) do + if not privileges[priv] then + core.run_priv_callbacks(name, priv, nil, "revoke") + end + end + core.auth_table[name].privileges = privileges core.notify_authentication_modified(name) save_auth_file() diff --git a/builtin/game/chatcommands.lua b/builtin/game/chatcommands.lua index 183e06a03..05b814d6f 100644 --- a/builtin/game/chatcommands.lua +++ b/builtin/game/chatcommands.lua @@ -132,6 +132,9 @@ local function handle_grant_command(caller, grantname, grantprivstr) if privs_unknown ~= "" then return false, privs_unknown end + for priv, _ in pairs(grantprivs) do + core.run_priv_callbacks(grantname, priv, caller, "grant") + end core.set_player_privs(grantname, privs) core.log("action", caller..' granted ('..core.privs_to_string(grantprivs, ', ')..') privileges to '..grantname) if grantname ~= caller then @@ -193,12 +196,18 @@ core.register_chatcommand("revoke", { end end if revoke_priv_str == "all" then + revoke_privs = privs privs = {} else for priv, _ in pairs(revoke_privs) do privs[priv] = nil end end + + for priv, _ in pairs(revoke_privs) do + core.run_priv_callbacks(revoke_name, priv, name, "revoke") + end + core.set_player_privs(revoke_name, privs) core.log("action", name..' revoked (' ..core.privs_to_string(revoke_privs, ', ') diff --git a/builtin/game/register.lua b/builtin/game/register.lua index ec6f28097..87d1c5659 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -65,14 +65,14 @@ local function check_modname_prefix(name) error("Name " .. name .. " does not follow naming conventions: " .. "\"" .. expected_prefix .. "\" or \":\" prefix required") end - + -- Enforce that the name only contains letters, numbers and underscores. local subname = name:sub(#expected_prefix+1) if subname:find("[^%w_]") then error("Name " .. name .. " does not follow naming conventions: " .. "contains unallowed characters") end - + return name end end @@ -435,6 +435,17 @@ function core.run_callbacks(callbacks, mode, ...) return ret end +function core.run_priv_callbacks(name, priv, caller, method) + if not core.registered_privileges[priv]["on_" .. method] or + core.registered_privileges[priv]["on_" .. method](name, caller) then + for _, func in ipairs(core["registered_on_priv_" .. method]) do + if not func(name, caller) then + break + end + end + end +end + -- -- Callback registration -- @@ -553,10 +564,11 @@ core.registered_craft_predicts, core.register_craft_predict = make_registration( core.registered_on_protection_violation, core.register_on_protection_violation = make_registration() core.registered_on_item_eats, core.register_on_item_eat = make_registration() core.registered_on_punchplayers, core.register_on_punchplayer = make_registration() +core.registered_on_priv_grant, core.register_on_priv_grant = make_registration() +core.registered_on_priv_revoke, core.register_on_priv_revoke = make_registration() -- -- Compatibility for on_mapgen_init() -- core.register_on_mapgen_init = function(func) func(core.get_mapgen_params()) end - diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 5b071d626..6ff9c9433 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2446,6 +2446,12 @@ Call these functions only at load time! * `definition`: `{ description = "description text", give_to_singleplayer = boolean}` the default of `give_to_singleplayer` is true * To allow players with `basic_privs` to grant, see `basic_privs` minetest.conf setting. + * `on_grant(name, granter_name)`: Called when given to player `name` by `granter_name`. + `granter_name` will be nil if the priv was granted by a mod. + * `on_revoke(name, revoker_name)`: Called when taken from player `name` by `revoker_name`. + `revoker_name` will be nil if the priv was revoked by a mod + * Note that the above two callbacks will be called twice if a player is responsible - + once with the player name, and then with a nil player name. * `minetest.register_authentication_handler(handler)` * See `minetest.builtin_auth_handler` in `builtin.lua` for reference