3
0
mirror of https://github.com/jlu5/PyLink.git synced 2025-02-09 02:54:14 +01:00

core: move isOper, checkAuthenticated to Irc (#199)

This commit is contained in:
James Lu 2016-04-30 16:54:11 -07:00
parent 4bd4c23a08
commit 2fe2e9c8c4
9 changed files with 75 additions and 75 deletions

View File

@ -15,6 +15,7 @@ import threading
import ssl import ssl
import hashlib import hashlib
from copy import deepcopy from copy import deepcopy
import inspect
from log import * from log import *
import world import world
@ -26,6 +27,13 @@ import structures
class ProtocolError(Exception): class ProtocolError(Exception):
pass pass
class NotAuthenticatedError(Exception):
"""
Exception raised by checkAuthenticated() when a user fails authentication
requirements.
"""
pass
### Internal classes (users, servers, channels) ### Internal classes (users, servers, channels)
class Irc(): class Irc():
@ -469,7 +477,7 @@ class Irc():
for func in world.commands[cmd]: for func in world.commands[cmd]:
try: try:
func(self, source, cmd_args) func(self, source, cmd_args)
except utils.NotAuthenticatedError: except NotAuthenticatedError:
self.msg(self.called_by or source, 'Error: You are not authorized to perform this operation.') self.msg(self.called_by or source, 'Error: You are not authorized to perform this operation.')
except Exception as e: except Exception as e:
log.exception('Unhandled exception caught in command %r', cmd) log.exception('Unhandled exception caught in command %r', cmd)
@ -848,6 +856,33 @@ class Irc():
return '%s!%s@%s' % (nick, ident, host) return '%s!%s@%s' % (nick, ident, host)
def isOper(self, uid, allowAuthed=True, allowOper=True):
"""
Returns whether the given user has operator status on PyLink. This can be achieved
by either identifying to PyLink as admin (if allowAuthed is True),
or having user mode +o set (if allowOper is True). At least one of
allowAuthed or allowOper must be True for this to give any meaningful
results.
"""
if uid in self.users:
if allowOper and ("o", None) in self.users[uid].modes:
return True
elif allowAuthed and self.users[uid].identified:
return True
return False
def checkAuthenticated(self, uid, allowAuthed=True, allowOper=True):
"""
Checks whether the given user has operator status on PyLink, raising
NotAuthenticatedError and logging the access denial if not.
"""
lastfunc = inspect.stack()[1][3]
if not self.isOper(uid, allowAuthed=allowAuthed, allowOper=allowOper):
log.warning('(%s) Access denied for %s calling %r', self.name,
self.getHostmask(uid), lastfunc)
raise NotAuthenticatedError("You are not authenticated!")
return True
class IrcUser(): class IrcUser():
"""PyLink IRC user class.""" """PyLink IRC user class."""
def __init__(self, nick, ts, uid, ident='null', host='null', def __init__(self, nick, ts, uid, ident='null', host='null',

View File

@ -221,7 +221,7 @@ def shutdown(irc, source, args):
"""takes no arguments. """takes no arguments.
Exits PyLink by disconnecting all networks.""" Exits PyLink by disconnecting all networks."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
u = irc.users[source] u = irc.users[source]
log.info('(%s) SHUTDOWN requested by "%s!%s@%s", exiting...', irc.name, u.nick, log.info('(%s) SHUTDOWN requested by "%s!%s@%s", exiting...', irc.name, u.nick,
@ -233,7 +233,7 @@ def load(irc, source, args):
"""<plugin name>. """<plugin name>.
Loads a plugin from the plugin folder.""" Loads a plugin from the plugin folder."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
name = args[0] name = args[0]
except IndexError: except IndexError:
@ -262,7 +262,7 @@ def unload(irc, source, args):
"""<plugin name>. """<plugin name>.
Unloads a currently loaded plugin.""" Unloads a currently loaded plugin."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
name = args[0] name = args[0]
except IndexError: except IndexError:
@ -386,7 +386,7 @@ def rehash(irc, source, args):
Reloads the configuration file for PyLink, (dis)connecting added/removed networks. Reloads the configuration file for PyLink, (dis)connecting added/removed networks.
Plugins must be manually reloaded.""" Plugins must be manually reloaded."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
_rehash() _rehash()
except Exception as e: # Something went wrong, abort. except Exception as e: # Something went wrong, abort.

View File

@ -16,7 +16,7 @@ def spawnclient(irc, source, args):
Admin-only. Spawns the specified PseudoClient on the PyLink server. Admin-only. Spawns the specified PseudoClient on the PyLink server.
Note: this doesn't check the validity of any fields you give it!""" Note: this doesn't check the validity of any fields you give it!"""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
nick, ident, host = args[:3] nick, ident, host = args[:3]
except ValueError: except ValueError:
@ -29,7 +29,7 @@ def quit(irc, source, args):
"""<target> [<reason>] """<target> [<reason>]
Admin-only. Quits the PyLink client with nick <target>, if one exists.""" Admin-only. Quits the PyLink client with nick <target>, if one exists."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
nick = args[0] nick = args[0]
@ -55,7 +55,7 @@ def joinclient(irc, source, args):
"""[<target>] <channel1>,[<channel2>], etc. """[<target>] <channel1>,[<channel2>], etc.
Admin-only. Joins <target>, the nick of a PyLink client, to a comma-separated list of channels. If <target> is not given, it defaults to the main PyLink client.""" Admin-only. Joins <target>, the nick of a PyLink client, to a comma-separated list of channels. If <target> is not given, it defaults to the main PyLink client."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
# Check if the first argument is an existing PyLink client. If it is not, # Check if the first argument is an existing PyLink client. If it is not,
@ -100,7 +100,7 @@ def nick(irc, source, args):
"""[<target>] <newnick> """[<target>] <newnick>
Admin-only. Changes the nick of <target>, a PyLink client, to <newnick>. If <target> is not given, it defaults to the main PyLink client.""" Admin-only. Changes the nick of <target>, a PyLink client, to <newnick>. If <target> is not given, it defaults to the main PyLink client."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
nick = args[0] nick = args[0]
@ -134,7 +134,7 @@ def part(irc, source, args):
"""[<target>] <channel1>,[<channel2>],... [<reason>] """[<target>] <channel1>,[<channel2>],... [<reason>]
Admin-only. Parts <target>, the nick of a PyLink client, from a comma-separated list of channels. If <target> is not given, it defaults to the main PyLink client.""" Admin-only. Parts <target>, the nick of a PyLink client, from a comma-separated list of channels. If <target> is not given, it defaults to the main PyLink client."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
nick = args[0] nick = args[0]
@ -180,7 +180,7 @@ def msg(irc, source, args):
"""[<source>] <target> <text> """[<source>] <target> <text>
Admin-only. Sends message <text> from <source>, where <source> is the nick of a PyLink client. If <source> is not given, it defaults to the main PyLink client.""" Admin-only. Sends message <text> from <source>, where <source> is the nick of a PyLink client. If <source> is not given, it defaults to the main PyLink client."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
# Because we want the source nick to be optional, this argument parsing gets a bit tricky. # Because we want the source nick to be optional, this argument parsing gets a bit tricky.
try: try:

View File

@ -18,7 +18,7 @@ def status(irc, source, args):
irc.reply('You are identified as \x02%s\x02.' % identified) irc.reply('You are identified as \x02%s\x02.' % identified)
else: else:
irc.reply('You are not identified as anyone.') irc.reply('You are not identified as anyone.')
irc.reply('Operator access: \x02%s\x02' % bool(utils.isOper(irc, source))) irc.reply('Operator access: \x02%s\x02' % bool(irc.isOper(source)))
def listcommands(irc, source, args): def listcommands(irc, source, args):
"""takes no arguments. """takes no arguments.
@ -81,7 +81,7 @@ def showuser(irc, source, args):
u = irc.nickToUid(target) or target u = irc.nickToUid(target) or target
# Only show private info if the person is calling 'showuser' on themselves, # Only show private info if the person is calling 'showuser' on themselves,
# or is an oper. # or is an oper.
verbose = utils.isOper(irc, source) or u == source verbose = irc.isOper(source) or u == source
if u not in irc.users: if u not in irc.users:
irc.reply('Error: Unknown user %r.' % target) irc.reply('Error: Unknown user %r.' % target)
return return
@ -127,7 +127,7 @@ def showchan(irc, source, args):
f = lambda s: irc.msg(source, s) f = lambda s: irc.msg(source, s)
c = irc.channels[channel] c = irc.channels[channel]
# Only show verbose info if caller is oper or is in the target channel. # Only show verbose info if caller is oper or is in the target channel.
verbose = source in c.users or utils.isOper(irc, source) verbose = source in c.users or irc.isOper(source)
secret = ('s', None) in c.modes secret = ('s', None) in c.modes
if secret and not verbose: if secret and not verbose:
# Hide secret channels from normal users. # Hide secret channels from normal users.
@ -178,7 +178,7 @@ def loglevel(irc, source, args):
Sets the log level to the given <level>. <level> must be either DEBUG, INFO, WARNING, ERROR, or CRITICAL. Sets the log level to the given <level>. <level> must be either DEBUG, INFO, WARNING, ERROR, or CRITICAL.
If no log level is given, shows the current one.""" If no log level is given, shows the current one."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
level = args[0].upper() level = args[0].upper()
try: try:

View File

@ -21,7 +21,7 @@ def _exec(irc, source, args):
Admin-only. Executes <code> in the current PyLink instance. This command performs backslash escaping of characters, so things like \\n and \\ will work. Admin-only. Executes <code> in the current PyLink instance. This command performs backslash escaping of characters, so things like \\n and \\ will work.
\x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02""" \x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02"""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
# Allow using \n in the code, while escaping backslashes correctly otherwise. # Allow using \n in the code, while escaping backslashes correctly otherwise.
args = bytes(' '.join(args), 'utf-8').decode("unicode_escape") args = bytes(' '.join(args), 'utf-8').decode("unicode_escape")
@ -40,7 +40,7 @@ def _eval(irc, source, args):
Admin-only. Evaluates the given Python expression and returns the result. Admin-only. Evaluates the given Python expression and returns the result.
\x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02""" \x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02"""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
args = ' '.join(args) args = ' '.join(args)
if not args.strip(): if not args.strip():
@ -58,7 +58,7 @@ def raw(irc, source, args):
Admin-only. Sends raw text to the uplink IRC server. Admin-only. Sends raw text to the uplink IRC server.
\x02**WARNING: THIS CAN BREAK YOUR NETWORK IF USED IMPROPERLY!**\x02""" \x02**WARNING: THIS CAN BREAK YOUR NETWORK IF USED IMPROPERLY!**\x02"""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
args = ' '.join(args) args = ' '.join(args)
if not args.strip(): if not args.strip():
@ -77,7 +77,7 @@ def inject(irc, source, args):
Admin-only. Injects raw text into the running PyLink protocol module, replying with the hook data returned. Admin-only. Injects raw text into the running PyLink protocol module, replying with the hook data returned.
\x02**WARNING: THIS CAN BREAK YOUR NETWORK IF USED IMPROPERLY!**\x02""" \x02**WARNING: THIS CAN BREAK YOUR NETWORK IF USED IMPROPERLY!**\x02"""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
args = ' '.join(args) args = ' '.join(args)
if not args.strip(): if not args.strip():

View File

@ -16,7 +16,7 @@ def disconnect(irc, source, args):
Disconnects the network <network>. When all networks are disconnected, PyLink will automatically exit. Disconnects the network <network>. When all networks are disconnected, PyLink will automatically exit.
Note: This does not affect the autoreconnect settings of any network, so the network will likely just reconnect unless autoconnect is disabled (see the 'autoconnect' command).""" Note: This does not affect the autoreconnect settings of any network, so the network will likely just reconnect unless autoconnect is disabled (see the 'autoconnect' command)."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
netname = args[0] netname = args[0]
network = world.networkobjects[netname] network = world.networkobjects[netname]
@ -39,7 +39,7 @@ def connect(irc, source, args):
"""<network> """<network>
Initiates a connection to the network <network>.""" Initiates a connection to the network <network>."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
netname = args[0] netname = args[0]
network = world.networkobjects[netname] network = world.networkobjects[netname]
@ -69,7 +69,7 @@ def autoconnect(irc, source, args):
Sets the autoconnect time for <network> to <seconds>. Sets the autoconnect time for <network> to <seconds>.
You can disable autoconnect for a network by setting <seconds> to a negative value.""" You can disable autoconnect for a network by setting <seconds> to a negative value."""
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
try: try:
netname = args[0] netname = args[0]
seconds = float(args[1]) seconds = float(args[1])
@ -91,7 +91,7 @@ def remote(irc, source, args):
"""<network> <command> """<network> <command>
Runs <command> on the remote network <network>. No replies are sent back due to protocol limitations.""" Runs <command> on the remote network <network>. No replies are sent back due to protocol limitations."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
netname = args[0] netname = args[0]

View File

@ -22,7 +22,7 @@ def checkban(irc, source, args):
"""<banmask (nick!user@host or user@host)> [<nick or hostmask to check>] """<banmask (nick!user@host or user@host)> [<nick or hostmask to check>]
Oper only. If a nick or hostmask is given, return whether the given banmask will match it. Otherwise, returns a list of connected users that would be affected by such a ban, up to 50 results.""" Oper only. If a nick or hostmask is given, return whether the given banmask will match it. Otherwise, returns a list of connected users that would be affected by such a ban, up to 50 results."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
if ircmatch is None: if ircmatch is None:
irc.reply("Error: missing ircmatch module (install it via 'pip install ircmatch').") irc.reply("Error: missing ircmatch module (install it via 'pip install ircmatch').")
@ -87,7 +87,7 @@ def jupe(irc, source, args):
Oper-only, jupes the given server.""" Oper-only, jupes the given server."""
# Check that the caller is either opered or logged in as admin. # Check that the caller is either opered or logged in as admin.
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
try: try:
servername = args[0] servername = args[0]
@ -114,7 +114,7 @@ def kick(irc, source, args):
"""<source> <channel> <user> [<reason>] """<source> <channel> <user> [<reason>]
Admin only. Kicks <user> from <channel> via <source>, where <source> is either the nick of a PyLink client or the SID of a PyLink server.""" Admin only. Kicks <user> from <channel> via <source>, where <source> is either the nick of a PyLink client or the SID of a PyLink server."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
sourcenick = args[0] sourcenick = args[0]
channel = args[1] channel = args[1]
@ -155,7 +155,7 @@ def kill(irc, source, args):
"""<source> <target> [<reason>] """<source> <target> [<reason>]
Admin only. Kills <target> via <source>, where <source> is either the nick of a PyLink client or the SID of a PyLink server.""" Admin only. Kills <target> via <source>, where <source> is either the nick of a PyLink client or the SID of a PyLink server."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
sourcenick = args[0] sourcenick = args[0]
target = args[1] target = args[1]
@ -194,7 +194,7 @@ def mode(irc, source, args):
Oper-only, sets modes <modes> on the target channel.""" Oper-only, sets modes <modes> on the target channel."""
# Check that the caller is either opered or logged in as admin. # Check that the caller is either opered or logged in as admin.
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
try: try:
target, modes = args[0], args[1:] target, modes = args[0], args[1:]
@ -232,7 +232,7 @@ def topic(irc, source, args):
"""<channel> <topic> """<channel> <topic>
Admin only. Updates the topic in a channel.""" Admin only. Updates the topic in a channel."""
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
try: try:
channel = args[0] channel = args[0]
topic = ' '.join(args[1:]) topic = ' '.join(args[1:])

View File

@ -1235,7 +1235,7 @@ def create(irc, source, args):
if source not in irc.channels[channel].users: if source not in irc.channels[channel].users:
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
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
# 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.
@ -1276,10 +1276,10 @@ def destroy(irc, source, args):
if network == irc.name: if network == irc.name:
# If we're destroying a channel on the current network, only oper is needed. # If we're destroying a channel on the current network, only oper is needed.
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
else: else:
# Otherwise, we'll need to be logged in as admin. # Otherwise, we'll need to be logged in as admin.
utils.checkAuthenticated(irc, source, allowOper=False) irc.checkAuthenticated(source, allowOper=False)
entry = (network, channel) entry = (network, channel)
@ -1320,7 +1320,7 @@ def link(irc, source, args):
if source not in irc.channels[localchan].users: if source not in irc.channels[localchan].users:
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
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
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)
return return
@ -1363,7 +1363,7 @@ def delink(irc, source, args):
remotenet = args[1] remotenet = args[1]
except IndexError: except IndexError:
remotenet = None remotenet = None
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
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
@ -1421,7 +1421,7 @@ def linked(irc, source, args):
if ('s', None) in c.modes or ('p', None) in c.modes: if ('s', None) in c.modes or ('p', None) in c.modes:
# Only show secret channels to opers, and tag them with # Only show secret channels to opers, and tag them with
# [secret]. # [secret].
if utils.isOper(irc, source): if irc.isOper(source):
s += '\x02[secret]\x02 ' s += '\x02[secret]\x02 '
else: else:
continue continue
@ -1434,7 +1434,7 @@ def linked(irc, source, args):
irc.msg(source, s) irc.msg(source, s)
if utils.isOper(irc, source): if irc.isOper(source):
s = '' s = ''
# If the caller is an oper, we can show the hostmasks of people # If the caller is an oper, we can show the hostmasks of people
@ -1460,7 +1460,7 @@ def linkacl(irc, source, args):
Allows blocking / unblocking certain networks from linking to a relay, based on a blacklist. Allows blocking / unblocking certain networks from linking to a relay, 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)."
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
try: try:
cmd = args[0].lower() cmd = args[0].lower()
channel = utils.toLower(irc, args[1]) channel = utils.toLower(irc, args[1])
@ -1530,7 +1530,7 @@ def showuser(irc, source, args):
relay = getRelay((irc.name, ch)) relay = getRelay((irc.name, ch))
if relay: if relay:
relaychannels.append(''.join(relay)) relaychannels.append(''.join(relay))
if relaychannels and (utils.isOper(irc, source) or u == source): if relaychannels and (irc.isOper(source) or u == source):
irc.msg(source, "\x02Relay channels\x02: %s" % ' '.join(relaychannels)) irc.msg(source, "\x02Relay channels\x02: %s" % ' '.join(relaychannels))
@utils.add_cmd @utils.add_cmd
@ -1538,7 +1538,7 @@ def save(irc, source, args):
"""takes no arguments. """takes no arguments.
Saves the relay database to disk.""" Saves the relay database to disk."""
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
exportDB() exportDB()
irc.reply('Done.') irc.reply('Done.')
@ -1549,7 +1549,7 @@ 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."""
utils.checkAuthenticated(irc, source) irc.checkAuthenticated(source)
try: try:
channel = utils.toLower(irc, args[0]) channel = utils.toLower(irc, args[0])
except IndexError: except IndexError:

View File

@ -7,7 +7,6 @@ framework.
import string import string
import re import re
import inspect
import importlib import importlib
import os import os
@ -15,13 +14,6 @@ from log import log
import world import world
import conf import conf
class NotAuthenticatedError(Exception):
"""
Exception raised by checkAuthenticated() when a user fails authentication
requirements.
"""
pass
class IncrementalUIDGenerator(): class IncrementalUIDGenerator():
""" """
Incremental UID Generator module, adapted from InspIRCd source: Incremental UID Generator module, adapted from InspIRCd source:
@ -132,33 +124,6 @@ def applyModes(irc, target, changedmodes):
log.warning("(%s) utils.applyModes is deprecated. Use irc.applyModes() instead!", irc.name) log.warning("(%s) utils.applyModes is deprecated. Use irc.applyModes() instead!", irc.name)
return irc.applyModes(target, changedmodes) return irc.applyModes(target, changedmodes)
def isOper(irc, uid, allowAuthed=True, allowOper=True):
"""
Returns whether the given user has operator status on PyLink. This can be achieved
by either identifying to PyLink as admin (if allowAuthed is True),
or having user mode +o set (if allowOper is True). At least one of
allowAuthed or allowOper must be True for this to give any meaningful
results.
"""
if uid in irc.users:
if allowOper and ("o", None) in irc.users[uid].modes:
return True
elif allowAuthed and irc.users[uid].identified:
return True
return False
def checkAuthenticated(irc, uid, allowAuthed=True, allowOper=True):
"""
Checks whether the given user has operator status on PyLink, raising
NotAuthenticatedError and logging the access denial if not.
"""
lastfunc = inspect.stack()[1][3]
if not isOper(irc, uid, allowAuthed=allowAuthed, allowOper=allowOper):
log.warning('(%s) Access denied for %s calling %r', irc.name,
getHostmask(irc, uid), lastfunc)
raise NotAuthenticatedError("You are not authenticated!")
return True
def loadModuleFromFolder(name, folder): def loadModuleFromFolder(name, folder):
""" """
Imports and returns a module, if existing, from a specific folder. Imports and returns a module, if existing, from a specific folder.