Add on_grant and on_revoke callbacks (#4713)
authorrubenwardy <rubenwardy@gmail.com>
Sat, 26 Aug 2017 06:17:05 +0000 (07:17 +0100)
committerLoïc Blot <nerzhul@users.noreply.github.com>
Sat, 26 Aug 2017 06:17:05 +0000 (08:17 +0200)
* Add register_on_priv_grant/revoke, and on_grant/revoke to privs. Call from /grant and /revoke

* Call on_grant and on_revoke callbacks from set_privs

builtin/game/auth.lua
builtin/game/chatcommands.lua
builtin/game/register.lua
doc/lua_api.txt

index 7a6be8788a81231699e8590bda58366b1452c154..4d5178ba7a95ff260c74f2d9cc9d81e65da5535f 100644 (file)
@@ -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()
index 183e06a03c15249e1154456df99d54f7ff39a5a9..05b814d6fdd30b92f563079104335eea32f4fd56 100644 (file)
@@ -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, ', ')
index ec6f28097c8543698e8d9bceb20def960c1f0ea2..87d1c5659fa34fccad057e77470220a9fec25182 100644 (file)
@@ -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
-
index 5b071d626330ac59ef9bfd65b36aa0374fa77ad5..6ff9c9433695f7b3f451332d8c1979a4ce146dae 100644 (file)
@@ -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