annotate mod_protect_last_admin/mod_protect_last_admin.lua @ 6326:2623515d8507

mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
author Matthew Wild <mwild1@gmail.com>
date Thu, 25 Sep 2025 18:21:27 +0100
parents
children 4f6fb56572f7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6326
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 module:set_global();
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local um = require "prosody.core.usermanager";
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5 local set = require "prosody.util.set";
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 local protected_roles = module:get_option_set("protect_last_admin_roles", { "prosody:admin", "prosody:operator" });
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local function other_protected_users(username, host)
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 local protected_users = set.new();
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 for protected_role in protected_roles do
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 local users = um.get_users_with_role(protected_role, host);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 module:log("debug", "Role %s: %s", protected_role, require "util.serialization".serialize(users, "debug"));
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 protected_users:add_list(um.get_users_with_role(protected_role, host));
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 protected_users:remove(username);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 return not protected_users:empty();
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 function check_last_admin(event)
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 local username, host = event.username, event.host;
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 local current_role = um.get_user_role(username, host);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 if not current_role then
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 module:log("warn", "Couldn't detect role for %s@%s", username, host);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 return;
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 module:log("debug", "Checking whether to allow this event...");
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 if event.role_name and protected_roles:contains(event.role_name) then
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 module:log("debug", "Permitting role change to %s", event.role_name);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 return; -- Switching to another protected role is fine
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 if not protected_roles:contains(current_role.name) then
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 module:log("debug", "Permitting event, role %s is not protected", current_role.name);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 return; -- This is not a protected user
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 if not other_protected_users(username, host) then
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 event.reason = "Cannot remove the only administrator";
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 return false;
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 module:log("debug", "Permitting event, no reason not to!");
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 end
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 module:hook("pre-delete-user", check_last_admin);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 module:hook("pre-disable-user", check_last_admin);
2623515d8507 mod_protect_last_admin: New module to ensure the last admin account on a server cannot be demoted or removed
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 module:hook("pre-user-role-change", check_last_admin);