Mercurial > prosody-modules
annotate mod_protect_last_admin/mod_protect_last_admin.lua @ 6513:5fb466693e85
mod_storage_xmlarchive: Ensure list index files are removed
using os.remove() on the list files leaves the new index files behind
since util.datamanager does not know they are removed.
Thanks Link Mauve
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 07 Apr 2026 21:10:54 +0200 |
| 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); |
