Mercurial > prosody-hg
annotate plugins/adhoc/mod_adhoc.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 |
| parents | 0c1684c65716 |
| children | 74b9e05af71e |
| rev | line source |
|---|---|
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1 -- Copyright (C) 2009 Thilo Cestonaro |
|
4291
122f142da281
mod_adhoc: Add support for commands only executable by global administrators
Florian Zeitz <florob@babelmonkeys.de>
parents:
3511
diff
changeset
|
2 -- Copyright (C) 2009-2011 Florian Zeitz |
|
3456
1201a743fe63
mod_adhoc: Code restructuring
Florian Zeitz <florob@babelmonkeys.de>
parents:
3286
diff
changeset
|
3 -- |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 -- This file is MIT/X11 licensed. Please see the |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
5 -- COPYING file in the source package for more information. |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
6 -- |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
7 |
|
9331
2f634cc02eac
mod_adhoc: Use util.iterators.sorted_pairs() to sort commands
Matthew Wild <mwild1@gmail.com>
parents:
9222
diff
changeset
|
8 local it = require "util.iterators"; |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 local st = require "util.stanza"; |
|
10542
f1886a48a6d4
mod_adhoc: Remove unused variable [luacheck]
Kim Alvefur <zash@zash.se>
parents:
9571
diff
changeset
|
10 local jid_host = require "util.jid".host; |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 local adhoc_handle_cmd = module:require "adhoc".handle_cmd; |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 local xmlns_cmd = "http://jabber.org/protocol/commands"; |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 local commands = {}; |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 module:add_feature(xmlns_cmd); |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
17 local function check_permissions(event, node, command) |
|
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
18 return (command.permission == "check" and module:may("mod_adhoc:"..node, event)) |
|
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
19 or (command.permission == "local_user" and jid_host(event.stanza.attr.from) == module.host) |
|
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
20 or (command.permission == "any"); |
|
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
21 end |
|
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
22 |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
23 module:hook("host-disco-info-node", function (event) |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
24 local stanza, origin, reply, node = event.stanza, event.origin, event.reply, event.node; |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
25 if commands[node] then |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
26 local command = commands[node]; |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
27 if check_permissions(event, node, command) then |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
28 reply:tag("identity", { name = command.name, |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
29 category = "automation", type = "command-node" }):up(); |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
30 reply:tag("feature", { var = xmlns_cmd }):up(); |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
31 reply:tag("feature", { var = "jabber:x:data" }):up(); |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
32 event.exists = true; |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
33 else |
|
6841
be87ab2d611c
plugins: Explicitly return to halt event propagation (session.send sometimes does not return true)
Kim Alvefur <zash@zash.se>
parents:
5762
diff
changeset
|
34 origin.send(st.error_reply(stanza, "auth", "forbidden", "This item is not available to you")); |
|
be87ab2d611c
plugins: Explicitly return to halt event propagation (session.send sometimes does not return true)
Kim Alvefur <zash@zash.se>
parents:
5762
diff
changeset
|
35 return true; |
|
3457
24d2c9be0149
mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents:
3456
diff
changeset
|
36 end |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
37 elseif node == xmlns_cmd then |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
38 reply:tag("identity", { name = "Ad-Hoc Commands", |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
39 category = "automation", type = "command-list" }):up(); |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
40 event.exists = true; |
|
3457
24d2c9be0149
mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents:
3456
diff
changeset
|
41 end |
|
24d2c9be0149
mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents:
3456
diff
changeset
|
42 end); |
|
24d2c9be0149
mod_adhoc: Answer disco#info (This is a MUST in XEP-0050)
Florian Zeitz <florob@babelmonkeys.de>
parents:
3456
diff
changeset
|
43 |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
44 module:hook("host-disco-items-node", function (event) |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
45 local reply, disco_node = event.reply, event.node; |
|
8460
77e59f8057bf
mod_adhoc: Rename variable to avoid name clash [luacheck]
Kim Alvefur <zash@zash.se>
parents:
6841
diff
changeset
|
46 if disco_node ~= xmlns_cmd then |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
47 return; |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
48 end |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
49 |
|
9331
2f634cc02eac
mod_adhoc: Use util.iterators.sorted_pairs() to sort commands
Matthew Wild <mwild1@gmail.com>
parents:
9222
diff
changeset
|
50 for node, command in it.sorted_pairs(commands) do |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
51 if check_permissions(event, node, command) then |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
52 reply:tag("item", { name = command.name, |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
53 node = node, jid = module:get_host() }); |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
54 reply:up(); |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 end |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 end |
|
5761
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
57 event.exists = true; |
|
91f8cd53584c
mod_adhoc: Use mod_disco for disco handling
Florian Zeitz <florob@babelmonkeys.de>
parents:
5760
diff
changeset
|
58 end); |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
60 module:hook("iq-set/host/"..xmlns_cmd..":command", function (event) |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 local origin, stanza = event.origin, event.stanza; |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
62 local node = stanza.tags[1].attr.node |
|
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
63 local command = commands[node]; |
|
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
64 if command then |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
65 if not check_permissions(event, node, command) then |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
66 origin.send(st.error_reply(stanza, "auth", "forbidden", "You don't have permission to execute this command"):up() |
|
12642
9061f9621330
Switch to a new role-based authorization framework, removing is_admin()
Matthew Wild <mwild1@gmail.com>
parents:
12430
diff
changeset
|
67 :add_child(command:cmdtag("canceled") |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
68 :tag("note", {type="error"}):text("You don't have permission to execute this command"))); |
|
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
69 return true |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 end |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
71 -- User has permission now execute the command |
|
12430
0c1684c65716
mod_adhoc: Simplify variable references
Kim Alvefur <zash@zash.se>
parents:
12387
diff
changeset
|
72 adhoc_handle_cmd(command, origin, stanza); |
|
9222
fe8abac62682
mod_adhoc: Simplify iq handling by hooking on iq-set/ instead of iq/.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
8563
diff
changeset
|
73 return true; |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 end |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 end, 500); |
|
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 |
|
4450
15547fba1f09
mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents:
4291
diff
changeset
|
77 local function adhoc_added(event) |
|
15547fba1f09
mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents:
4291
diff
changeset
|
78 local item = event.item; |
|
12387
05c250fa335a
Spelling: Fix various spelling mistakes (thanks timeless)
Kim Alvefur <zash@zash.se>
parents:
11209
diff
changeset
|
79 -- Dang this was noisy |
|
11209
f6661fac7e9a
mod_adhoc: Log commands provided at debug level
Kim Alvefur <zash@zash.se>
parents:
10565
diff
changeset
|
80 module:log("debug", "Command added by mod_%s: %q, %q", item._provided_by or "<unknown module>", item.name, item.node); |
|
3231
ad3fbed1dda5
mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents:
3220
diff
changeset
|
81 commands[item.node] = item; |
|
ad3fbed1dda5
mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents:
3220
diff
changeset
|
82 end |
|
ad3fbed1dda5
mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents:
3220
diff
changeset
|
83 |
|
4450
15547fba1f09
mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents:
4291
diff
changeset
|
84 local function adhoc_removed(event) |
|
3220
b3772f9bc359
mod_adhoc: Imported from prosody-modules, thanks Florob!
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 commands[event.item.node] = nil; |
|
4450
15547fba1f09
mod_adhoc: Use module:handle_items()
Matthew Wild <mwild1@gmail.com>
parents:
4291
diff
changeset
|
86 end |
|
3231
ad3fbed1dda5
mod_adhoc: Scan through list of items on load, in case items have been added before we were loaded
Matthew Wild <mwild1@gmail.com>
parents:
3220
diff
changeset
|
87 |
|
9571
5c475f6e89a4
mod_adhoc: Add compat marker for older handling of adhoc items
Kim Alvefur <zash@zash.se>
parents:
9331
diff
changeset
|
88 module:handle_items("adhoc", adhoc_added, adhoc_removed); -- COMPAT pre module:provides() introduced in 0.9 |
|
4926
58714123f600
mod_adhoc, mod_admin_adhoc, mod_announce: Use module:provides() to manage Ad-Hoc commands
Florian Zeitz <florob@babelmonkeys.de>
parents:
4450
diff
changeset
|
89 module:handle_items("adhoc-provider", adhoc_added, adhoc_removed); |
