From 104c0cef4b3e31873ac8963525a4630f7e74db98 Mon Sep 17 00:00:00 2001 From: James Lu Date: Thu, 25 Aug 2016 00:45:28 -0700 Subject: [PATCH] automode: switch from irc.checkAuthenticated to new-style permissions --- plugins/automode.py | 49 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/plugins/automode.py b/plugins/automode.py index 5f1609d..c7a676f 100644 --- a/plugins/automode.py +++ b/plugins/automode.py @@ -8,6 +8,7 @@ import json from pylinkirc import utils, conf, world from pylinkirc.log import log +from pylinkirc.coremods import permissions mydesc = ("The \x02Automode\x02 plugin provides simple channel ACL management by giving prefix modes " "to users matching hostmasks or exttargets.") @@ -95,6 +96,35 @@ def die(sourceirc): utils.unregisterService('automode') +def checkAccess(irc, uid, channel, command): + """Checks the caller's access to Automode.""" + # Automode defines the following permissions, where is either "manage", "list", + # "sync", or "clear": + # - automode. OR automode..*: ability to automode on all channels. + # - automode..relay_owned: ability to automode on channels owned via Relay. + # If Relay isn't loaded, this permission check FAILS. + # - automode..#channel: ability to automode on the given channel. + # - automode.savedb: ability to save the automode DB. + log.debug('(%s) Automode: checking access for %s/%s for %s capability on %s', irc.name, uid, + irc.getHostmask(uid), command, channel) + + baseperm = 'automode.%s' % command + try: + # First, check the catch all and channel permissions. + return permissions.checkPermissions(irc, uid, [baseperm, baseperm+'.*', '%s.%s' % (command, channel)]) + except utils.NotAuthorizedError: + log.debug('(%s) Automode: falling back to automode.%s.relay_owned', irc.name, command) + permissions.checkPermissions(irc, uid, [baseperm+'.relay_owned']) + + relay = world.plugins.get('relay') + if relay is None: + raise utils.NotAuthorizedError("You are not authorized to use Automode when Relay is " + "disabled. You are missing one of the following " + "permissions: %s or %s.%s" % (baseperm, baseperm, channel)) + elif (irc.name, channel) not in relay.db: + raise utils.NotAuthorizedError("The network you are on does not own the relay channel %s." % channel) + return True + def setacc(irc, source, args): """ @@ -106,7 +136,7 @@ def setacc(irc, source, args): SET #channel $oper:Network?Administrator qo SET #staffchan $channel:#mainchan:op o """ - irc.checkAuthenticated(source, allowOper=False) + try: channel, mask, modes = args except ValueError: @@ -120,6 +150,8 @@ def setacc(irc, source, args): # Store channels case insensitively channel = irc.toLower(channel) + checkAccess(irc, source, channel, 'manage') + # Database entries for any network+channel pair are automatically created using # defaultdict. Note: string keys are used here instead of tuples so they can be # exported easily as JSON. @@ -138,8 +170,6 @@ def delacc(irc, source, args): Removes the Automode entry for the given mask on the given channel, if one exists. """ - irc.checkAuthenticated(source, allowOper=False) - try: channel, mask = args channel = irc.toLower(channel) @@ -147,6 +177,8 @@ def delacc(irc, source, args): reply(irc, "Error: Invalid arguments given. Needs 2: channel, mask") return + checkAccess(irc, source, channel, 'manage') + dbentry = db.get(irc.name+channel) if dbentry is None: @@ -173,12 +205,14 @@ def listacc(irc, source, args): """ Lists all Automode entries for the given channel.""" - irc.checkAuthenticated(source) try: channel = irc.toLower(args[0]) except IndexError: reply(irc, "Error: Invalid arguments given. Needs 1: channel.") return + + checkAccess(irc, source, channel, 'list') + dbentry = db.get(irc.name+channel) if not dbentry: reply(irc, "Error: No Automode access entries exist for \x02%s\x02." % channel) @@ -199,7 +233,7 @@ def save(irc, source, args): """takes no arguments. Saves the Automode database to disk.""" - irc.checkAuthenticated(source) + permissions.checkPermissions(irc, source, ['automode.savedb']) exportDB() reply(irc, 'Done.') modebot.add_cmd(save) @@ -247,13 +281,13 @@ def syncacc(irc, source, args): Syncs Automode access lists to the channel. """ - irc.checkAuthenticated(source, allowOper=False) try: channel = irc.toLower(args[0]) except IndexError: reply(irc, "Error: Invalid arguments given. Needs 1: channel.") return + checkAccess(irc, source, channel, 'sync') match(irc, channel) reply(irc, 'Done.') @@ -267,7 +301,6 @@ def clearacc(irc, source, args): Removes all Automode entries for the given channel. """ - irc.checkAuthenticated(source, allowOper=False) try: channel = irc.toLower(args[0]) @@ -275,6 +308,8 @@ def clearacc(irc, source, args): reply(irc, "Error: Invalid arguments given. Needs 1: channel.") return + checkAccess(irc, source, channel, 'clear') + if db.get(irc.name+channel): log.debug("Automode: purging channel pair %s/%s", irc.name, channel) del db[irc.name+channel]