mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-23 19:19:31 +01:00
Relay: rework to use the permission system
This defines the following permissions: Granted to opers by default: - relay.create - relay.destroy - relay.claim - relay.link - relay.delink - relay.linkacl.view - relay.linkacl Granted to all users by default: - relay.linked And the following which is not explicitly granted: - relay.savedb Closes #325.
This commit is contained in:
parent
93ca62aa49
commit
2d20256ed8
17
docs/relay-permissions.md
Normal file
17
docs/relay-permissions.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## Relay Permissions
|
||||||
|
|
||||||
|
Relay defines the following permissions, which can be customized by defining the `permissions:` configuration block (see [example-permissions.yml](../example-permissions.yml) for examples).
|
||||||
|
|
||||||
|
By default, the following permissions are given to opers:
|
||||||
|
|
||||||
|
- `relay.create`
|
||||||
|
- `relay.destroy`
|
||||||
|
- `relay.claim`
|
||||||
|
- `relay.link`
|
||||||
|
- `relay.delink`
|
||||||
|
- `relay.linkacl.view`
|
||||||
|
- `relay.linkacl`
|
||||||
|
|
||||||
|
The following permissions are given to all users:
|
||||||
|
|
||||||
|
- `relay.linked`
|
@ -4,14 +4,14 @@
|
|||||||
# Permissions work by mapping hostmasks or exttargets to list of permissions, allowing
|
# Permissions work by mapping hostmasks or exttargets to list of permissions, allowing
|
||||||
# you to fine tune which users have access to which commands.
|
# you to fine tune which users have access to which commands.
|
||||||
|
|
||||||
# The permissions API is new, and optional for plugins. Currently, only Automode uses it.
|
# The permissions API is new, and optional for plugins. Currently, only Automode and Relay use it.
|
||||||
|
|
||||||
# If you do not specify any permissions block in your configuration, PyLink will default to a
|
# If you do not specify any permissions block in your configuration, PyLink will default to a
|
||||||
# permission set defined by plugins, which usually correspond to the list below, but can be
|
# permission set defined by plugins, which usually correspond to the list below, but can be
|
||||||
# changed on every release.
|
# changed on every release.
|
||||||
|
|
||||||
# This determines whether we should merge the plugin-default permissions with the ones specified
|
# This determines whether we should merge plugins' built-in default permissions with the ones specified
|
||||||
# in the permissions: block. Disabling this allows you greater control over the permissions
|
# in the following permissions: block. Disabling this allows you greater control over the permissions
|
||||||
# PyLink gives, but you should check this file on every major update to see if any new permissions
|
# PyLink gives, but you should check this file on every major update to see if any new permissions
|
||||||
# were added for commands. Otherwise, commands that were available before may cease to function!
|
# were added for commands. Otherwise, commands that were available before may cease to function!
|
||||||
permissions_merge_defaults: true
|
permissions_merge_defaults: true
|
||||||
@ -28,6 +28,10 @@ permissions:
|
|||||||
- automode.manage.relay_owned
|
- automode.manage.relay_owned
|
||||||
- automode.sync.relay_owned
|
- automode.sync.relay_owned
|
||||||
- automode.list
|
- automode.list
|
||||||
|
|
||||||
|
# These allow opers to manage Relay links on their network.
|
||||||
|
|
||||||
|
|
||||||
"$pylinkacc":
|
"$pylinkacc":
|
||||||
# Those with an admin login in PyLink can do anything.
|
# Those with an admin login in PyLink can do anything.
|
||||||
- "*"
|
- "*"
|
||||||
|
@ -8,6 +8,7 @@ from collections import defaultdict
|
|||||||
from pylinkirc import utils, world, conf
|
from pylinkirc import utils, world, conf
|
||||||
from pylinkirc.log import log
|
from pylinkirc.log import log
|
||||||
from pylinkirc.coremods import control
|
from pylinkirc.coremods import control
|
||||||
|
from pylinkirc.coremods import permissions
|
||||||
|
|
||||||
### GLOBAL (statekeeping) VARIABLES
|
### GLOBAL (statekeeping) VARIABLES
|
||||||
relayusers = defaultdict(dict)
|
relayusers = defaultdict(dict)
|
||||||
@ -20,6 +21,11 @@ save_delay = conf.conf['bot'].get('save_delay', 300)
|
|||||||
db = {}
|
db = {}
|
||||||
dbname = utils.getDatabaseName('pylinkrelay')
|
dbname = utils.getDatabaseName('pylinkrelay')
|
||||||
|
|
||||||
|
default_permissions = {"*!*@*": ['relay.linked'],
|
||||||
|
"$ircop": ['relay.create', 'relay.linkacl*',
|
||||||
|
'relay.destroy', 'relay.link', 'relay.delink',
|
||||||
|
'relay.claim']}
|
||||||
|
|
||||||
### INTERNAL FUNCTIONS
|
### INTERNAL FUNCTIONS
|
||||||
|
|
||||||
def initializeAll(irc):
|
def initializeAll(irc):
|
||||||
@ -53,6 +59,8 @@ def main(irc=None):
|
|||||||
|
|
||||||
log.debug('relay.main: scheduling export loop')
|
log.debug('relay.main: scheduling export loop')
|
||||||
|
|
||||||
|
permissions.addDefaultPermissions(default_permissions)
|
||||||
|
|
||||||
if irc is not None:
|
if irc is not None:
|
||||||
# irc is defined when the plugin is reloaded. Otherwise, it means that we've just started the
|
# irc is defined when the plugin is reloaded. Otherwise, it means that we've just started the
|
||||||
# server. Iterate over all connected networks and initialize their relay users.
|
# server. Iterate over all connected networks and initialize their relay users.
|
||||||
@ -77,10 +85,13 @@ def die(sourceirc):
|
|||||||
relayservers.clear()
|
relayservers.clear()
|
||||||
relayusers.clear()
|
relayusers.clear()
|
||||||
|
|
||||||
# 3) Export the relay links database.
|
# 3) Unload our permissions.
|
||||||
|
permissions.removeDefaultPermissions(default_permissions)
|
||||||
|
|
||||||
|
# 4) Export the relay links database.
|
||||||
exportDB()
|
exportDB()
|
||||||
|
|
||||||
# 4) Kill the scheduling for any other exports.
|
# 5) Kill the scheduling for any other exports.
|
||||||
global exportdb_timer
|
global exportdb_timer
|
||||||
if exportdb_timer:
|
if exportdb_timer:
|
||||||
log.debug("Relay: cancelling exportDB timer thread %s due to die()", threading.get_ident())
|
log.debug("Relay: cancelling exportDB timer thread %s due to die()", threading.get_ident())
|
||||||
@ -1562,7 +1573,7 @@ def create(irc, source, args):
|
|||||||
irc.reply('Error: You must be in %r to complete this operation.' % channel)
|
irc.reply('Error: You must be in %r to complete this operation.' % channel)
|
||||||
return
|
return
|
||||||
|
|
||||||
irc.checkAuthenticated(source)
|
permissions.checkPermissions(irc, source, ['relay.create'])
|
||||||
|
|
||||||
# Check to see whether the channel requested is already part of a different
|
# Check to see whether the channel requested is already part of a different
|
||||||
# relay.
|
# relay.
|
||||||
@ -1601,12 +1612,12 @@ def destroy(irc, source, args):
|
|||||||
irc.reply('Error: Invalid channel %r.' % channel)
|
irc.reply('Error: Invalid channel %r.' % channel)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check for different permissions based on whether we're destroying a local channel or
|
||||||
|
# a remote one.
|
||||||
if network == irc.name:
|
if network == irc.name:
|
||||||
# If we're destroying a channel on the current network, only oper is needed.
|
permissions.checkPermissions(irc, source, ['relay.destroy'])
|
||||||
irc.checkAuthenticated(source)
|
|
||||||
else:
|
else:
|
||||||
# Otherwise, we'll need to be logged in as admin.
|
permissions.checkPermissions(irc, source, ['relay.destroy.remote'])
|
||||||
irc.checkAuthenticated(source, allowOper=False)
|
|
||||||
|
|
||||||
entry = (network, channel)
|
entry = (network, channel)
|
||||||
|
|
||||||
@ -1670,7 +1681,7 @@ def link(irc, source, args):
|
|||||||
irc.reply('Error: You must be in %r to complete this operation.' % localchan)
|
irc.reply('Error: You must be in %r to complete this operation.' % localchan)
|
||||||
return
|
return
|
||||||
|
|
||||||
irc.checkAuthenticated(source)
|
permissions.checkPermissions(irc, source, ['relay.link'])
|
||||||
|
|
||||||
if remotenet not in world.networkobjects:
|
if remotenet not in world.networkobjects:
|
||||||
irc.reply('Error: No network named %r exists.' % remotenet)
|
irc.reply('Error: No network named %r exists.' % remotenet)
|
||||||
@ -1727,7 +1738,9 @@ def delink(irc, source, args):
|
|||||||
remotenet = args[1]
|
remotenet = args[1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
remotenet = None
|
remotenet = None
|
||||||
irc.checkAuthenticated(source)
|
|
||||||
|
permissions.checkPermissions(irc, source, ['relay.delink'])
|
||||||
|
|
||||||
if not utils.isChannel(channel):
|
if not utils.isChannel(channel):
|
||||||
irc.reply('Error: Invalid channel %r.' % channel)
|
irc.reply('Error: Invalid channel %r.' % channel)
|
||||||
return
|
return
|
||||||
@ -1843,7 +1856,7 @@ def linkacl(irc, source, args):
|
|||||||
Allows blocking / unblocking certain networks from linking to a relayed channel, based on a blacklist.
|
Allows blocking / unblocking certain networks from linking to a relayed channel, based on a blacklist.
|
||||||
LINKACL LIST returns a list of blocked networks for a channel, while the ALLOW and DENY subcommands allow manipulating this blacklist."""
|
LINKACL LIST returns a list of blocked networks for a channel, while the ALLOW and DENY subcommands allow manipulating this blacklist."""
|
||||||
missingargs = "Error: Not enough arguments. Needs 2-3: subcommand (ALLOW/DENY/LIST), channel, remote network (for ALLOW/DENY)."
|
missingargs = "Error: Not enough arguments. Needs 2-3: subcommand (ALLOW/DENY/LIST), channel, remote network (for ALLOW/DENY)."
|
||||||
irc.checkAuthenticated(source)
|
|
||||||
try:
|
try:
|
||||||
cmd = args[0].lower()
|
cmd = args[0].lower()
|
||||||
channel = irc.toLower(args[1])
|
channel = irc.toLower(args[1])
|
||||||
@ -1858,10 +1871,12 @@ def linkacl(irc, source, args):
|
|||||||
irc.reply('Error: No such relay %r exists.' % channel)
|
irc.reply('Error: No such relay %r exists.' % channel)
|
||||||
return
|
return
|
||||||
if cmd == 'list':
|
if cmd == 'list':
|
||||||
|
permissions.checkPermissions(irc, source, ['relay.linkacl.view'])
|
||||||
s = 'Blocked networks for \x02%s\x02: \x02%s\x02' % (channel, ', '.join(db[relay]['blocked_nets']) or '(empty)')
|
s = 'Blocked networks for \x02%s\x02: \x02%s\x02' % (channel, ', '.join(db[relay]['blocked_nets']) or '(empty)')
|
||||||
irc.reply(s)
|
irc.reply(s)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
permissions.checkPermissions(irc, source, ['relay.linkacl'])
|
||||||
try:
|
try:
|
||||||
remotenet = args[2]
|
remotenet = args[2]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -1922,7 +1937,7 @@ def save(irc, source, args):
|
|||||||
"""takes no arguments.
|
"""takes no arguments.
|
||||||
|
|
||||||
Saves the relay database to disk."""
|
Saves the relay database to disk."""
|
||||||
irc.checkAuthenticated(source)
|
permissions.checkPermissions(irc, source, ['relay.savedb'])
|
||||||
exportDB()
|
exportDB()
|
||||||
irc.reply('Done.')
|
irc.reply('Done.')
|
||||||
|
|
||||||
@ -1933,13 +1948,14 @@ def claim(irc, source, args):
|
|||||||
Sets the CLAIM for a channel to a case-sensitive list of networks. If no list of networks is given, shows which networks have claim over the channel. A single hyphen (-) can also be given as a list of networks to remove claim from the channel entirely.
|
Sets the CLAIM for a channel to a case-sensitive list of networks. If no list of networks is given, shows which networks have claim over the channel. A single hyphen (-) can also be given as a list of networks to remove claim from the channel entirely.
|
||||||
|
|
||||||
CLAIM is a way of enforcing network ownership for a channel, similarly to Janus. Unless the list is empty, only networks on the CLAIM list for a channel (plus the creating network) are allowed to override kicks, mode changes, and topic changes in it - attempts from other networks' opers to do this are simply blocked or reverted."""
|
CLAIM is a way of enforcing network ownership for a channel, similarly to Janus. Unless the list is empty, only networks on the CLAIM list for a channel (plus the creating network) are allowed to override kicks, mode changes, and topic changes in it - attempts from other networks' opers to do this are simply blocked or reverted."""
|
||||||
irc.checkAuthenticated(source)
|
|
||||||
try:
|
try:
|
||||||
channel = irc.toLower(args[0])
|
channel = irc.toLower(args[0])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
irc.reply("Error: Not enough arguments. Needs 1-2: channel, list of networks (optional).")
|
irc.reply("Error: Not enough arguments. Needs 1-2: channel, list of networks (optional).")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
permissions.checkPermissions(irc, source, ['relay.claim'])
|
||||||
|
|
||||||
# We override getRelay() here to limit the search to the current network.
|
# We override getRelay() here to limit the search to the current network.
|
||||||
relay = (irc.name, channel)
|
relay = (irc.name, channel)
|
||||||
if relay not in db:
|
if relay not in db:
|
||||||
|
Loading…
Reference in New Issue
Block a user