3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-27 13:09:23 +01:00

permissions, automode: work on default permissions & add example permissions config (#190)

- Fix possible type errors in add/removeDefaultPermissions by converting permlist values to sets.
- Fix wrong permission string being checked in automode.<command>.#channel
- automode: register and unregister default permissions on load/unload.
- permissions: add an 'also_show' argument to checkPermissions(), to display alternative permissions that weren't directly checked.
This commit is contained in:
James Lu 2016-08-25 11:41:37 -07:00
parent 03a780f397
commit f890ddac1b
3 changed files with 57 additions and 8 deletions

View File

@ -7,7 +7,7 @@ import threading
# Global variables: these store mappings of hostmasks/exttargets to lists of permissions each target has.
default_permissions = defaultdict(set)
permissions = defaultdict(set)
permissions = defaultdict(set, {'$pylinkacc': {'*'}})
# Only allow one thread to change the permissions index at once.
permissions_lock = threading.Lock()
@ -23,7 +23,12 @@ def resetPermissions():
with permissions_lock:
global permissions
log.debug('permissions.resetPermissions: old perm list: %s', permissions)
permissions = conf.conf.get('permissions', default_permissions)
if not conf.conf.get('permissions_merge_defaults', True):
log.debug('permissions.resetPermissions: clearing perm list due to permissions_merge_defaults set False.')
permissions.clear()
permissions.update(conf.conf.get('permissions', default_permissions))
log.debug('permissions.resetPermissions: new perm list: %s', permissions)
def addDefaultPermissions(perms):
@ -31,16 +36,16 @@ def addDefaultPermissions(perms):
with permissions_lock:
global permissions
for target, permlist in perms.items():
permissions[target] |= permlist
permissions[target] |= set(permlist)
def removeDefaultPermissions(perms):
"""Remove default permissions from the index."""
with permissions_lock:
global permissions
for target, permlist in perms.items():
permissions[target] -= permlist
permissions[target] -= set(permlist)
def checkPermissions(irc, uid, perms):
def checkPermissions(irc, uid, perms, also_show=[]):
"""
Checks permissions of the caller. If the caller has any of the permissions listed in perms,
this function returns True. Otherwise, NotAuthorizedError is raised.
@ -58,7 +63,7 @@ def checkPermissions(irc, uid, perms):
if any(irc.matchHost(perm, p) for p in perms):
return True
raise utils.NotAuthorizedError("You are missing one of the following permissions: %s" %
(', '.join(perms)))
(', '.join(perms+also_show)))
# This is called on first import.

35
example-permissions.yml Normal file
View File

@ -0,0 +1,35 @@
# This file is an example of the permissions system in PyLink. Should you wish,
# you may copy the contents of this file and paste it into the configuration you're
# using.
# Permissions work by mapping hostmasks or exttargets to list of permissions, allowing
# 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.
# 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
# changed on every release.
# This determines whether we should merge the plugin-default permissions with the ones specified
# in the 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
# were added for commands. Otherwise, commands that were available before may cease to function!
permissions_merge_defaults: true
permissions:
# Note: It is a good idea to quote any exttargets or hostmasks so the configuration parser knows
# they are raw strings.
"$ircop":
# The default set of Automode permissions allow you to manage any channels you own in Relay.
# If Relay is not loaded, this check will fail. This has the ability of allowing local opers
# to manage their channels, but not abusing Automode to hack modes in other networks' relay
# channels.
- automode.manage.relay_owned
- automode.sync.relay_owned
"*!*@*":
# Everyone can use /msg Automode list on any channel.
- automode.list
"$pylinkacc":
# Those with an admin login in PyLink can do anything.
- "*"

View File

@ -24,6 +24,10 @@ exportdb_timer = None
save_delay = conf.conf['bot'].get('save_delay', 300)
# The default set of Automode permissions.
default_permissions = {"$ircop": ['automode.manage.relay_owned', 'automode.sync.relay_owned'],
"*!*@*": ['automode.list']}
def loadDB():
"""Loads the Automode database, silently creating a new one if this fails."""
global db
@ -66,6 +70,9 @@ def main(irc=None):
# Schedule periodic exports of the automode database.
scheduleExport(starting=True)
# Register our permissions.
permissions.addDefaultPermissions(default_permissions)
# Queue joins to all channels where Automode has entries.
for entry in db:
netname, channel = entry.split('#', 1)
@ -94,6 +101,7 @@ def die(sourceirc):
log.debug("Automode: cancelling exportDB timer thread %s due to die()", threading.get_ident())
exportdb_timer.cancel()
permissions.removeDefaultPermissions(default_permissions)
utils.unregisterService('automode')
def checkAccess(irc, uid, channel, command):
@ -111,10 +119,11 @@ def checkAccess(irc, uid, channel, command):
baseperm = 'automode.%s' % command
try:
# First, check the catch all and channel permissions.
return permissions.checkPermissions(irc, uid, [baseperm, baseperm+'.*', '%s.%s' % (command, channel)])
perms = [baseperm, baseperm+'.*', '%s.%s' % (baseperm, channel)]
return permissions.checkPermissions(irc, uid, perms)
except utils.NotAuthorizedError:
log.debug('(%s) Automode: falling back to automode.%s.relay_owned', irc.name, command)
permissions.checkPermissions(irc, uid, [baseperm+'.relay_owned'])
permissions.checkPermissions(irc, uid, [baseperm+'.relay_owned'], also_show=perms)
relay = world.plugins.get('relay')
if relay is None: