mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-17 23:52:46 +01:00
Finally passes all tests.
This commit is contained in:
parent
9fee5f17a9
commit
959459d063
194
src/ircdb.py
194
src/ircdb.py
@ -42,11 +42,12 @@ import world
|
|||||||
import ircutils
|
import ircutils
|
||||||
|
|
||||||
def fromChannelCapability(capability):
|
def fromChannelCapability(capability):
|
||||||
|
assert isChannelCapability(capability)
|
||||||
return capability.split('.', 1)
|
return capability.split('.', 1)
|
||||||
|
|
||||||
def isChannelCapability(capability):
|
def isChannelCapability(capability):
|
||||||
if '.' in capability:
|
if '.' in capability:
|
||||||
(channel, capability) = fromChannelCapability(capability)
|
(channel, capability) = capability.split('.', 1)
|
||||||
return ircutils.isChannel(channel)
|
return ircutils.isChannel(channel)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
@ -66,21 +67,100 @@ def makeAntiCapability(capability):
|
|||||||
else:
|
else:
|
||||||
return '!' + capability
|
return '!' + capability
|
||||||
|
|
||||||
|
def unAntiCapability(capability):
|
||||||
|
assert isAntiCapability(capability)
|
||||||
|
if isChannelCapability(capability):
|
||||||
|
(channel, capability) = fromChannelCapability(capability)
|
||||||
|
return '.'.join((channel, capability[1:]))
|
||||||
|
else:
|
||||||
|
return capability[1:]
|
||||||
|
|
||||||
|
def invertCapability(capability):
|
||||||
|
if isAntiCapability(capability):
|
||||||
|
return unAntiCapability(capability)
|
||||||
|
else:
|
||||||
|
return makeAntiCapability(capability)
|
||||||
|
|
||||||
_normal = string.maketrans('\r\n', ' ')
|
_normal = string.maketrans('\r\n', ' ')
|
||||||
def normalize(s):
|
def normalize(s):
|
||||||
return s.translate(_normal)
|
return s.translate(_normal)
|
||||||
|
|
||||||
|
|
||||||
|
class CapabilitySet(set):
|
||||||
|
def __init__(self, capabilities=()):
|
||||||
|
set.__init__(self)
|
||||||
|
for capability in capabilities:
|
||||||
|
self.add(capability)
|
||||||
|
|
||||||
|
def add(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
inverted = invertCapability(capability)
|
||||||
|
if set.__contains__(self, inverted):
|
||||||
|
set.remove(self, inverted)
|
||||||
|
set.add(self, capability)
|
||||||
|
|
||||||
|
def remove(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
set.remove(self, capability)
|
||||||
|
|
||||||
|
def __contains__(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
if set.__contains__(self, capability):
|
||||||
|
return True
|
||||||
|
if set.__contains__(self, invertCapability(capability)):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
if set.__contains__(self, capability):
|
||||||
|
return True
|
||||||
|
elif set.__contains__(self, invertCapability(capability)):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise KeyError, capability
|
||||||
|
|
||||||
|
def repr(self):
|
||||||
|
return '%s([%r])' % (self.__class__.__name__, ', '.join(self))
|
||||||
|
|
||||||
|
class UserCapabilitySet(CapabilitySet):
|
||||||
|
def __contains__(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
if CapabilitySet.__contains__(self, 'owner'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return CapabilitySet.__contains__(self, capability)
|
||||||
|
|
||||||
|
def check(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
if capability == 'owner':
|
||||||
|
if CapabilitySet.__contains__(self, 'owner'):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if 'owner' in self:
|
||||||
|
if isAntiCapability(capability):
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return CapabilitySet.check(self, capability)
|
||||||
|
|
||||||
|
def add(self, capability):
|
||||||
|
capability = ircutils.toLower(capability)
|
||||||
|
assert capability != '!owner', '"!owner" disallowed.'
|
||||||
|
CapabilitySet.add(self, capability)
|
||||||
|
|
||||||
class IrcUser(object):
|
class IrcUser(object):
|
||||||
"""This class holds the capabilities and authentications for a user.
|
"""This class holds the capabilities and authentications for a user.
|
||||||
"""
|
"""
|
||||||
def __init__(self, ignore=False, password='', auth=None,
|
def __init__(self, ignore=False, password='', auth=None,
|
||||||
capabilities=None, hostmasks=None):
|
capabilities=(), hostmasks=None):
|
||||||
self.auth = auth # The (time, hostmask) a user authenticated under.
|
self.auth = auth # The (time, hostmask) a user authenticated under.
|
||||||
self.ignore = ignore # A boolean deciding if the person is ignored.
|
self.ignore = ignore # A boolean deciding if the person is ignored.
|
||||||
self.password = password # password (plaintext? hashed?)
|
self.password = password # password (plaintext? hashed?)
|
||||||
self.capabilities = set()
|
self.capabilities = UserCapabilitySet()
|
||||||
if capabilities is not None:
|
|
||||||
for capability in capabilities:
|
for capability in capabilities:
|
||||||
self.capabilities.add(capability)
|
self.capabilities.add(capability)
|
||||||
if hostmasks is None:
|
if hostmasks is None:
|
||||||
@ -102,20 +182,13 @@ class IrcUser(object):
|
|||||||
self.capabilities.remove(capability)
|
self.capabilities.remove(capability)
|
||||||
|
|
||||||
def checkCapability(self, capability):
|
def checkCapability(self, capability):
|
||||||
if 'owner' in self.capabilities:
|
if self.ignore:
|
||||||
if isAntiCapability(capability):
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
elif self.ignore:
|
|
||||||
if isAntiCapability(capability):
|
if isAntiCapability(capability):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
elif capability in self.capabilities:
|
|
||||||
return True
|
|
||||||
else:
|
else:
|
||||||
return False
|
return self.capabilities.check(capability)
|
||||||
|
|
||||||
def setPassword(self, password):
|
def setPassword(self, password):
|
||||||
self.password = password
|
self.password = password
|
||||||
@ -177,10 +250,9 @@ class IrcChannel(object):
|
|||||||
else:
|
else:
|
||||||
self.ignores = ignores
|
self.ignores = ignores
|
||||||
if capabilities is None:
|
if capabilities is None:
|
||||||
self.capabilities = set()
|
self.capabilities = CapabilitySet()
|
||||||
else:
|
else:
|
||||||
self.capabilities = capabilities
|
self.capabilities = capabilities
|
||||||
|
|
||||||
for capability in self.defaultOff:
|
for capability in self.defaultOff:
|
||||||
if capability not in self.capabilities:
|
if capability not in self.capabilities:
|
||||||
self.capabilities.add(makeAntiCapability(capability))
|
self.capabilities.add(makeAntiCapability(capability))
|
||||||
@ -222,13 +294,10 @@ class IrcChannel(object):
|
|||||||
|
|
||||||
def checkCapability(self, capability):
|
def checkCapability(self, capability):
|
||||||
if capability in self.capabilities:
|
if capability in self.capabilities:
|
||||||
return True
|
return self.capabilities.check(capability)
|
||||||
|
else:
|
||||||
if isAntiCapability(capability):
|
if isAntiCapability(capability):
|
||||||
return not self.defaultAllow
|
return not self.defaultAllow
|
||||||
else:
|
|
||||||
anticapability = makeAntiCapability(capability)
|
|
||||||
if anticapability in self.capabilities:
|
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
return self.defaultAllow
|
return self.defaultAllow
|
||||||
|
|
||||||
@ -421,74 +490,53 @@ def checkIgnored(hostmask, recipient='', users=users, channels=channels):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def checkCapability(hostmask, capability, users=users, channels=channels):
|
def checkCapability(hostmask, capability, users=users, channels=channels):
|
||||||
"""checkCapability(hostmask, recipient, capability) -> True/False
|
|
||||||
|
|
||||||
Checks if the user represented by hostmask has capability with recipient.
|
|
||||||
"""
|
|
||||||
###
|
|
||||||
# This is a hard function to write correctly.
|
|
||||||
#
|
|
||||||
# Basically, we want to return whether or not a user has a certain
|
|
||||||
# capability in a given channel. This should be easy, but the various
|
|
||||||
# different cases are all hard to get right.
|
|
||||||
|
|
||||||
if world.startup:
|
if world.startup:
|
||||||
# Are we in special startup mode?
|
|
||||||
if isAntiCapability(capability):
|
if isAntiCapability(capability):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
u = users.getUser(hostmask)
|
u = users.getUser(hostmask)
|
||||||
except KeyError: # the user isn't in the database.
|
except KeyError:
|
||||||
# First, check to see if we're asking for a channel capability:
|
|
||||||
if isChannelCapability(capability):
|
if isChannelCapability(capability):
|
||||||
# If it is, we'll check the channel.
|
|
||||||
try:
|
|
||||||
(channel, capability) = fromChannelCapability(capability)
|
(channel, capability) = fromChannelCapability(capability)
|
||||||
except ValueError: # unpack list of wrong size
|
try:
|
||||||
debug.msg('Invalid channel capability in checkCapability')
|
|
||||||
return False # stupid, invalid capability.
|
|
||||||
# Now, go fetch the channel and check to see what it thinks about
|
|
||||||
# said capability.
|
|
||||||
c = channels.getChannel(channel)
|
c = channels.getChannel(channel)
|
||||||
# Channels have their own defaults, so we can just directly return
|
if capability in c.capabilities:
|
||||||
# what the channel has to say about the capability.
|
|
||||||
return c.checkCapability(capability)
|
return c.checkCapability(capability)
|
||||||
else: # It's not a channel capability.
|
else:
|
||||||
# If it's not a channel, then the only thing we have to go by is
|
return c.defaultAllow
|
||||||
# conf.defaultCapabilities.
|
except KeyError:
|
||||||
return (capability in conf.defaultCapabilities)
|
pass
|
||||||
# Good, the user exists.
|
if capability in conf.defaultCapabilities:
|
||||||
# First, we check to see if it's an owner -- if it is, it should have all
|
return True
|
||||||
# capabilities and should not have any negative capabilities.
|
elif invertCapability(capability) in conf.defaultCapabilities:
|
||||||
if u.checkCapability('owner'):
|
|
||||||
if isAntiCapability(capability):
|
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return conf.defaultAllow
|
||||||
# Now, we need to check if it's a channel capability or not.
|
if capability in u.capabilities:
|
||||||
if isChannelCapability(capability):
|
|
||||||
# First check to see if the user has the capability already; if so,
|
|
||||||
# it can be returned without checking the channel.
|
|
||||||
if u.checkCapability(capability):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
# User doesn't have the capability. Check the channel.
|
|
||||||
try:
|
|
||||||
(channel, capability) = fromChannelCapability(capability)
|
|
||||||
except ValueError:
|
|
||||||
debug.msg('Invalid channel capability in checkCapability')
|
|
||||||
return False # stupid, invalid capability.
|
|
||||||
c = channels.getChannel(channel)
|
|
||||||
# And return the channel's opinion.
|
|
||||||
return c.checkCapability(capability)
|
|
||||||
else: # It's not a channel capability.
|
|
||||||
# Just check the user.
|
|
||||||
try:
|
|
||||||
return u.checkCapability(capability)
|
return u.checkCapability(capability)
|
||||||
|
else:
|
||||||
|
if isChannelCapability(capability):
|
||||||
|
(channel, capability) = fromChannelCapability(capability)
|
||||||
|
try:
|
||||||
|
c = channels.getChannel(channel)
|
||||||
|
if capability in c.capabilities:
|
||||||
|
return c.checkCapability(capability)
|
||||||
|
else:
|
||||||
|
return c.defaultAllow
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return (capability in conf.defaultCapabilities)
|
pass
|
||||||
|
if capability in conf.defaultCapabilities:
|
||||||
|
return True
|
||||||
|
elif invertCapability(capability) in conf.defaultCapabilities:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return conf.defaultAllow
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def checkCapabilities(hostmask, capabilities, requireAll=False):
|
def checkCapabilities(hostmask, capabilities, requireAll=False):
|
||||||
"""Checks that a user has capabilities in a list.
|
"""Checks that a user has capabilities in a list.
|
||||||
|
Loading…
Reference in New Issue
Block a user