Limnoria-doc/use/capabilities.rst

267 lines
12 KiB
ReStructuredText
Raw Normal View History

.. _capabilities:
2011-06-30 16:49:28 +02:00
************
2011-06-30 16:21:24 +02:00
Capabilities
2011-06-30 16:49:28 +02:00
************
2011-06-30 16:21:24 +02:00
Introduction
------------
Ok, some explanation of the capabilities system is probably in order. With
most IRC bots (including the ones I've written myself prior to this one) "what
a user can do" is set in one of two ways. On the *really* simple bots, each
user has a numeric "level" and commands check to see if a user has a "high
enough level" to perform some operation. On bots that are slightly more
complicated, users have a list of "flags" whose meanings are hardcoded, and the
bot checks to see if a user possesses the necessary flag before performing some
operation. Both methods, IMO, are rather arbitrary, and force the user and the
programmer to be unduly confined to less expressive constructs.
This bot is different. Every user has a set of "capabilities" that is
consulted every time they give the bot a command. Commands, rather than
checking for a user level of 100, or checking if the user has an 'o' flag, are
instead able to check if a user has the 'owner' capability. At this point such
a difference might not seem revolutionary, but at least we can already tell
that this method is self-documenting, and easier for users and developers to
understand what's truly going on.
User Capabilities
-----------------
What the heck can these capabilities DO?
If that was all, well, the capability system would be *cool*, but not many
people would say it was *awesome*. But it **is** awesome! Several things are
happening behind the scenes that make it awesome, and these are things that
couldn't happen if the bot was using numeric userlevels or single-character
flags. First, whenever a user issues the bot a command, the command dispatcher
checks to make sure the user doesn't have the "anticapability" for that
command. An anticapability is a capability that, instead of saying "what a
user can do", says what a user *cannot* do. It's formed rather simply by
adding a dash ('-') to the beginning of a capability; 'rot13' is a capability,
and '-rot13' is an anticapability.
Anyway, when a user issues the bot a command, perhaps 'calc' or 'help', the bot
first checks to make sure the user doesn't have the '-calc' or the '-help'
(anti)capabilities before even considering responding to the user. So commands
can be turned on or off on a *per user* basis, offering fine-grained control
not often (if at all!) seen in other bots. This can be further refined by
limiting the (anti)capability to a command in a specific plugin or even an
entire plugin. For example, the rot13 command is in the Filter plugin. If a
user should be able to use another rot13 command, but not the one in the Format
plugin, they would simply need to be given '-Format.rot13' anticapability.
Similarly, if a user were to be banned from using the Filter plugin altogether,
they would simply need to be given the '-Filter' anticapability.
Channel Capabilities
--------------------
What if #linux wants completely different capabilities from #windows?
But that's not all! The capabilities system also supports *channel*
capabilities, which are capabilities that only apply to a specific channel;
they're of the form '#channel,capability'. Whenever a user issues a command to
the bot in a channel, the command dispatcher also checks to make sure the user
doesn't have the anticapability for that command *in that channel*, and if the
user does, the bot won't respond to the user in the channel. Thus now, in
addition to having the ability to turn individual commands on or off for an
individual user, we can now turn commands on or off for an individual user on
an individual channel!
So when a user 'foo' sends a command 'bar' to the bot on channel '#baz', first
the bot checks to see if the user has the anticapability for the command by
itself, '-bar'. If so, it errors right then and there, telling the user that
2020-05-13 19:56:44 +02:00
they lacks the 'bar' capability. If the user doesn't have that anticapability,
2011-06-30 16:21:24 +02:00
then the bot checks to see if the user issued the command over a channel, and
if so, checks to see if the user has the antichannelcapability for that
2014-08-28 13:43:41 +02:00
command, '#baz,-bar'. If so, again, it tells the user that they lack the 'bar'
2011-06-30 16:21:24 +02:00
capability. If neither of these anticapabilities are present, then the bot
just responds to the user like normal.
Default Capabilities
--------------------
So what capabilities am I dealing with already?
There are several default capabilities the bot uses. The most important of
these is the 'owner' capability. This capability allows the person having it
to use *any* command. It's best to keep this capability reserved to people who
actually have access to the shell the bot is running on. It's so important, in
fact, that the bot will not allow you to add it with a command--you'll have you
edit the users file directly to give it to someone.
There is also the 'admin' capability for non-owners that are highly trusted to
administer the bot appropriately. They can do things such as change the bot's
nick, cause the bot to ignore a given user, make the bot join or part channels,
etc. They generally cannot do administration related to channels, which is
reserved for people with the next capability.
People who are to administer channels with the bot should have the
'#channel,op' capability--whatever channel they are to administrate, they
should have that channel capability for 'op'. For example, since I want
2014-08-28 13:43:41 +02:00
inkedmn to be an administrator in #supybot, I'll give them the '#supybot,op'
capability. This is in addition to their 'admin' capability, since the 'admin'
2011-06-30 16:21:24 +02:00
capability doesn't give the person having it control over channels.
'#channel,op' is used for such things as giving/receiving ops, kickbanning
people, lobotomizing the bot, ignoring users in the channel, and managing the
channel capabilities. The '#channel,op' capability is also basically the
equivalent of the 'owner' capability for capabilities involving
#channel--basically anyone with the #channel,op capability is considered to
have all positive capabilities and no negative capabilities for #channel.
One other globally important capability exists: 'trusted'. This is a command
that basically says "This user can be trusted not to try and crash the bot." It
allows users to call commands like 'icalc' in the 'Math' plugin, which can
cause the bot to begin a calculation that could potentially never return (a
calculation like '10**10**10**10'). Another command that requires the 'trusted'
capability is the 're' command in the 'Utilities' plugin, which (due to the
regular expression implementation in Python (and any other language that uses
NFA regular expressions, like Perl or Ruby or Lua or ...) which can allow a
regular expression to take exponential time to process). Consider what would
happen if someone gave the bot the command 're [format join "" s/./ [dict go]
/] [dict go]' It would basically replace every character in the output of
'dict go' (14,896 characters!) with the entire output of 'dict go', resulting
in 221MB of memory allocated! And that's not even the worst example!
2020-05-13 20:48:04 +02:00
Managing capabilities
---------------------
User Capabilities
^^^^^^^^^^^^^^^^^
User capabilities are controlled with the ``admin capability <add|remove>``
and ``channel capability <add|remove>``. Their difference is that the
first one is only restricted to those who have the admin capability.
To make user1 admin, I would run::
admin capability add user1 admin
If the bot joins on a channel where there should be ops who should't have
power over any other channel, I would run::
channel capability add #channel user2 op
Note that admins cannot give anyone capability which they don't have by
themselves first, so user1 couldn't use ``channel capability add`` unless
they were made #channel,op first. The command::
admin capability add user2 #channel,op
has the same effect as ``channel capability add``, but it requires user
to have the admin capability in addition to #channel,op.
If there is abusive user who shouldn't have op capability but still does
for one reason or another, I could run either::
channel capability add user3 -op
or::
channel capability remove user3 op
Anticapabilities are checked before normal capabilities so the first
command would work even if user3 still had the op capability. Removing
capability which isn't given to user or channel adds anti-capability
automatically.
User capabilities can be viewed with ``user capabilities`` command.
Channel
^^^^^^^
Channel capabilities affect everyone on the current channel including
unidentified users. They are controlled with the ``channel capability <set|unset>`` commands.
If I wanted to make everyone on the channel able to voice themselves or get
automatically voiced by the AutoMode plugin, I would start by unsetting the
default anticapability and setting the capability.::
channel capability unset -voice
channel capability set voice
Now anyone on the channel can voice themselves or if AutoMode plugin is
configured to voice voiced people, the will automatically get voiced on
join.
If there was unwanted plugin or plugin which output was causing spam, Games
for example, I could add anticapability for it and prevent the whole plugin
from being used.::
channel capability set -Games
Note that I didn't specify any separate command after Games.
Default
^^^^^^^
Default capabilities affect everyone whether they are identified or not.
They are controlled by the ``owner defaultcapability <add|remove>`` command
and they arecommonly used for preventing users from adding/removing akas,
using Unix Progstats which disabling is asked about in supybot-wizard or
registering to the bot using anticapabilities.::
defaultcapability add -aka.add
defaultcapability add -aka.remove
defaultcapability add -user.register
defaultcapability add -unix.progstats
To undo this I would simply do the opposite.::
defaultcapability remove -aka.add
defaultcapability remove -aka.remove
defaultcapability remove -user.register
defaultcapability remove -unix.progstats
2020-05-13 19:56:44 +02:00
Defaultcapabilities can be restored with either of these two commands::
config setdefault capabilities
config capabilities [config default capabilities]
Example
-------
To make all this less abstract, here is a popular example of what
capabilities are used for: disabling a plugin or command for everyone
but a select group of people
Allowing only user ``foo`` to use the ``Games`` plugin, globally::
defaultcapability add -games
admin capability add foo games
And to undo it::
defaultcapability remove -Games
admin capability remove foo Games
Same, but only on ``#channel``::
channel capability set #channel -games
channel capability add #channel foo games
channel capability unset #channel -games
channel capability remove #channel foo games
And to forbid only the ``dice`` command of the ``Games`` plugin instead of the
entire plugin, you would use the same commands, but with ``-games.dice`` and
``games.dice`` instead of ``-games`` and ``games``.
2011-06-30 16:21:24 +02:00
Final Word
----------
2020-05-13 19:56:44 +02:00
From a programmer's perspective, capabilities are flexible and easy to use. Any
2011-06-30 16:21:24 +02:00
command can check if a user has any capability, even ones not thought of when
the bot was originally written. Plugins can easily add their own
capabilities--it's as easy as just checking for a capability and documenting
somewhere that a user needs that capability to do something.
From an user's perspective, capabilities remove a lot of the mystery and
esotery of bot control, in addition to giving a bot owner absolutely
finegrained control over what users are allowed to do with the bot.
Additionally, defaults can be set by the bot owner for both individual channels
2014-08-28 13:43:41 +02:00
and for the bot as a whole, letting an end-user set the policy they want the bot
to follow for users that haven't yet registered in their user database. It's
2011-06-30 16:21:24 +02:00
really a revolution!