Annotate

plugins/muc/occupant.lib.lua @ 12642:9061f9621330

Switch to a new role-based authorization framework, removing is_admin() We began moving away from simple "is this user an admin?" permission checks before 0.12, with the introduction of mod_authz_internal and the ability to dynamically change the roles of individual users. The approach in 0.12 still had various limitations however, and apart from the introduction of roles other than "admin" and the ability to pull that info from storage, not much actually changed. This new framework shakes things up a lot, though aims to maintain the same functionality and behaviour on the surface for a default Prosody configuration. That is, if you don't take advantage of any of the new features, you shouldn't notice any change. The biggest change visible to developers is that usermanager.is_admin() (and the auth provider is_admin() method) have been removed. Gone. Completely. Permission checks should now be performed using a new module API method: module:may(action_name, context) This method accepts an action name, followed by either a JID (string) or (preferably) a table containing 'origin'/'session' and 'stanza' fields (e.g. the standard object passed to most events). It will return true if the action should be permitted, or false/nil otherwise. Modules should no longer perform permission checks based on the role name. E.g. a lot of code previously checked if the user's role was prosody:admin before permitting some action. Since many roles might now exist with similar permissions, and the permissions of prosody:admin may be redefined dynamically, it is no longer suitable to use this method for permission checks. Use module:may(). If you start an action name with ':' (recommended) then the current module's name will automatically be used as a prefix. To define a new permission, use the new module API: module:default_permission(role_name, action_name) module:default_permissions(role_name, { action_name[, action_name...] }) This grants the specified role permission to execute the named action(s) by default. This may be overridden via other mechanisms external to your module. The built-in roles that developers should use are: - prosody:user (normal user) - prosody:admin (host admin) - prosody:operator (global admin) The new prosody:operator role is intended for server-wide actions (such as shutting down Prosody). Finally, all usage of is_admin() in modules has been fixed by this commit. Some of these changes were trickier than others, but no change is expected to break existing deployments. EXCEPT: mod_auth_ldap no longer supports the ldap_admin_filter option. It's very possible nobody is using this, but if someone is then we can later update it to pull roles from LDAP somehow.
author Matthew Wild <mwild1@gmail.com>
date Wed, 15 Jun 2022 12:15:01 +0100
parent 7086:6cc7c9da29ed
child 12977:74b9e05af71e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
1 local pairs = pairs;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
2 local setmetatable = setmetatable;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
3 local st = require "util.stanza";
6271
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
4 local util = module:require "muc/util";
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
5
6271
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
6 local function get_filtered_presence(stanza)
006b0e0f0de2 plugins/muc: Move 'x' filtering from occupant to util
daurnimator <quae@daurnimator.com>
parents: 6251
diff changeset
7 return util.filter_muc_x(st.clone(stanza));
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
8 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
9
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
10 local occupant_mt = {};
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
11 occupant_mt.__index = occupant_mt;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
12
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
13 local function new_occupant(bare_real_jid, nick)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
14 return setmetatable({
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
15 bare_jid = bare_real_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
16 nick = nick; -- in-room jid
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
17 sessions = {}; -- hash from real_jid to presence stanzas. stanzas should not be modified
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
18 role = nil;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
19 jid = nil; -- Primary session
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
20 }, occupant_mt);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
21 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
22
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
23 -- Deep copy an occupant
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
24 local function copy_occupant(occupant)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
25 local sessions = {};
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
26 for full_jid, presence_stanza in pairs(occupant.sessions) do
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
27 -- Don't keep unavailable presences, as they'll accumulate; unless they're the primary session
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
28 if presence_stanza.attr.type ~= "unavailable" or full_jid == occupant.jid then
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
29 sessions[full_jid] = presence_stanza;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
30 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
31 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
32 return setmetatable({
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
33 bare_jid = occupant.bare_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
34 nick = occupant.nick;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
35 sessions = sessions;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
36 role = occupant.role;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
37 jid = occupant.jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
38 }, occupant_mt);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
39 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
40
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
41 -- finds another session to be the primary (there might not be one)
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
42 function occupant_mt:choose_new_primary()
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
43 for jid, pr in self:each_session() do
6251
41a5e5205fd9 plugins/muc/occupant: Check for type == nil rather than type ~= unavailable
daurnimator <quae@daurnimator.com>
parents: 6210
diff changeset
44 if pr.attr.type == nil then
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
45 return jid;
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
46 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
47 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
48 return nil;
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
49 end
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
50
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
51 function occupant_mt:set_session(real_jid, presence_stanza, replace_primary)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
52 local pr = get_filtered_presence(presence_stanza);
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
53 pr.attr.from = self.nick;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
54 pr.attr.to = real_jid;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
55
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
56 self.sessions[real_jid] = pr;
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
57 if replace_primary then
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
58 self.jid = real_jid;
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
59 elseif self.jid == nil or (pr.attr.type == "unavailable" and self.jid == real_jid) then
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
60 -- Only leave an unavailable presence as primary when there are no other options
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
61 self.jid = self:choose_new_primary() or real_jid;
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
62 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
63 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
64
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
65 function occupant_mt:remove_session(real_jid)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
66 -- Delete original session
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
67 self.sessions[real_jid] = nil;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
68 if self.jid == real_jid then
6210
e9d62fff82a8 plugins/muc/occupant.lib: Don't allow an unavailable session to be the primary jid
daurnimator <quae@daurnimator.com>
parents: 6179
diff changeset
69 self.jid = self:choose_new_primary();
6179
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
70 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
71 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
72
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
73 function occupant_mt:each_session()
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
74 return pairs(self.sessions)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
75 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
76
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
77 function occupant_mt:get_presence(real_jid)
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
78 return self.sessions[real_jid or self.jid]
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
79 end
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
80
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
81 return {
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
82 new = new_occupant;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
83 copy = copy_occupant;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
84 mt = occupant_mt;
e488a90195bc plugins/muc: Massive refactor
daurnimator <quae@daurnimator.com>
parents:
diff changeset
85 }