Mercurial > prosody-modules
annotate mod_protect_last_admin/mod_protect_last_admin.lua @ 6556:7477e97a9045
mod_firewall: Apply pre-reload state before re-reading config
This change makes load/reload a bit more robust. module.load() runs before
module.restore() and it reads from the config and updates the state (if
needed).
However, after this, module.restore() could run and apply the old state again.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Sun, 24 May 2026 20:03:20 +0100 |
| parents | d1f64ffca879 |
| children |
| 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 |
|
6327
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
9 local errors = require "prosody.util.error".init(module.name, { |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
10 ["cannot-remove-only-admin"] = { |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
11 code = 400; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
12 type = "cancel"; |
|
6328
187b957dc528
mod_protect_last_admin: Switch to service-unavailable rather than policy-violation
Matthew Wild <mwild1@gmail.com>
parents:
6327
diff
changeset
|
13 condition = "service-unavailable"; |
|
6327
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
14 text = "Cannot remove the only administrator"; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
15 extra = { |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
16 namespace = "https://prosody.im/protocol/errors"; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
17 condition = "cannot-remove-only-admin"; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
18 }; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
19 }; |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
20 }); |
|
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
21 |
|
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
|
22 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
|
23 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
|
24 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
|
25 local users = um.get_users_with_role(protected_role, host); |
|
6437
d1f64ffca879
mod_protect_last_admin: Replace util.serialization.serialize with %q
Link Mauve <linkmauve@linkmauve.fr>
parents:
6328
diff
changeset
|
26 module:log("debug", "Role %s: %q", protected_role, users); |
|
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
|
27 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
|
28 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
|
29 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
|
30 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
|
31 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
|
32 |
|
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 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
|
34 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
|
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 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
|
37 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
|
38 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
|
39 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
|
40 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
|
41 |
|
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 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
|
43 |
|
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 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
|
45 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
|
46 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
|
47 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
|
48 |
|
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 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
|
50 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
|
51 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
|
52 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
|
53 |
|
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
|
54 if not other_protected_users(username, host) then |
|
6327
4f6fb56572f7
mod_protect_last_admin: Return util.error object to provide more information
Matthew Wild <mwild1@gmail.com>
parents:
6326
diff
changeset
|
55 event.reason = errors.new("cannot-remove-only-admin"); |
|
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
|
56 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
|
57 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
|
58 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
|
59 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
|
60 |
|
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
|
61 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
|
62 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
|
63 module:hook("pre-user-role-change", check_last_admin); |
