Software /
code /
prosody-modules
Comparison
mod_compat_roles/mod_compat_roles.lua @ 4983:7c77058a1ac5
mod_compat_roles: New module providing compat shim for trunk's new role API
The new role API is translated to is_admin() calls on older versions. On newer
versions (which have the role API) this module does nothing.
It allows modules to drop their use of is_admin() (which is not available in
trunk) and switch to the new role API, while remaining compatible with
previous Prosody versions.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 11 Aug 2022 17:49:33 +0100 |
child | 5097:d414fa8b37dc |
comparison
equal
deleted
inserted
replaced
4982:8a4b17e2e984 | 4983:7c77058a1ac5 |
---|---|
1 -- Export a module:may() that works on Prosody 0.12 and earlier | |
2 -- (i.e. backed by is_admin). | |
3 | |
4 -- This API is safe because Prosody 0.12 and earlier do not support | |
5 -- per-session roles - all authorization is based on JID alone. It is not | |
6 -- safe on versions that support per-session authorization. | |
7 | |
8 module:set_global(); | |
9 | |
10 local moduleapi = require "core.moduleapi"; | |
11 | |
12 -- If module.may already exists, abort | |
13 if moduleapi.may then return; end | |
14 | |
15 local jid_split = require "util.jid".split; | |
16 local um_is_admin = require "core.usermanager".is_admin; | |
17 | |
18 local function get_jid_role_name(jid, host) | |
19 if um_is_admin(jid, "*") then | |
20 return "prosody:operator"; | |
21 elseif um_is_admin(jid, host) then | |
22 return "prosody:admin"; | |
23 end | |
24 return nil; | |
25 end | |
26 | |
27 local function get_user_role_name(username, host) | |
28 return get_jid_role_name(username.."@"..host, host); | |
29 end | |
30 | |
31 -- permissions[host][permission_name] = permitted_role_name | |
32 local permissions = {}; | |
33 | |
34 local function role_may(role_name, permission) | |
35 local role_permissions = permissions[role_name]; | |
36 if not role_permissions then | |
37 return false; | |
38 end | |
39 return not not permissions[role_name][permission]; | |
40 end | |
41 | |
42 function moduleapi.may(self, action, context) | |
43 if action:byte(1) == 58 then -- action begins with ':' | |
44 action = self.name..action; -- prepend module name | |
45 end | |
46 if type(context) == "string" then -- check JID permissions | |
47 local role; | |
48 local node, host = jid_split(context); | |
49 if host == self.host then | |
50 role = get_user_role_name(node, self.host); | |
51 else | |
52 role = get_jid_role_name(context, self.host); | |
53 end | |
54 if not role then | |
55 self:log("debug", "Access denied: JID <%s> may not %s (no role found)", context, action); | |
56 return false; | |
57 end | |
58 | |
59 local permit = role_may(role, action); | |
60 if not permit then | |
61 self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", context, action, role.name); | |
62 end | |
63 return permit; | |
64 end | |
65 | |
66 local session = context.origin or context.session; | |
67 if type(session) ~= "table" then | |
68 error("Unable to identify actor session from context"); | |
69 end | |
70 if session.type == "s2sin" or (session.type == "c2s" and session.host ~= self.host) then | |
71 local actor_jid = context.stanza.attr.from; | |
72 local role_name = get_jid_role_name(actor_jid); | |
73 if not role_name then | |
74 self:log("debug", "Access denied: JID <%s> may not %s (no role found)", actor_jid, action); | |
75 return false; | |
76 end | |
77 local permit = role_may(role_name, action, context); | |
78 if not permit then | |
79 self:log("debug", "Access denied: JID <%s> may not %s (not permitted by role %s)", actor_jid, action, role_name); | |
80 end | |
81 return permit; | |
82 end | |
83 end | |
84 | |
85 function moduleapi.default_permission(self, role_name, permission) | |
86 local r = permissions[self.host][role_name]; | |
87 if not r then | |
88 r = {}; | |
89 permissions[self.host][role_name] = r; | |
90 end | |
91 r[permission] = true; | |
92 end | |
93 | |
94 function moduleapi.default_permissions(self, role_name, permission_list) | |
95 for _, permission in ipairs(permission_list) do | |
96 self:default_permission(role_name, permission); | |
97 end | |
98 end | |
99 | |
100 function module.add_host(host_module) | |
101 permissions[host_module.host] = {}; | |
102 function host_module.unload() | |
103 permissions[host_module.host] = nil; | |
104 end | |
105 end |