Updated ircdb to have persistent user ids.

This commit is contained in:
Jeremy Fincher 2003-09-12 20:06:58 +00:00
parent a0e0ca2c5f
commit 41d266f207
13 changed files with 261 additions and 237 deletions

View File

@ -148,7 +148,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
actions=actions+%s""", actions=actions+%s""",
smileys, frowns, chars, words, int(isAction)) smileys, frowns, chars, words, int(isAction))
try: try:
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
return return
cursor.execute("""SELECT COUNT(*) cursor.execute("""SELECT COUNT(*)
@ -181,7 +181,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
cursor.execute("""UPDATE channel_stats SET joins=joins+1""") cursor.execute("""UPDATE channel_stats SET joins=joins+1""")
try: try:
if ircutils.isUserHostmask(msg.prefix): if ircutils.isUserHostmask(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.prefix name = msg.prefix
cursor.execute("""UPDATE user_stats cursor.execute("""UPDATE user_stats
@ -198,7 +198,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
cursor.execute("""UPDATE channel_stats SET parts=parts+1""") cursor.execute("""UPDATE channel_stats SET parts=parts+1""")
try: try:
if ircutils.isUserHostmask(msg.prefix): if ircutils.isUserHostmask(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.prefix name = msg.prefix
cursor.execute("UPDATE user_stats SET parts=parts+1 WHERE name=%s", cursor.execute("UPDATE user_stats SET parts=parts+1 WHERE name=%s",
@ -214,7 +214,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
cursor.execute("""UPDATE channel_stats SET topics=topics+1""") cursor.execute("""UPDATE channel_stats SET topics=topics+1""")
try: try:
if ircutils.isUserHostmask(msg.prefix): if ircutils.isUserHostmask(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.prefix name = msg.prefix
cursor.execute("""UPDATE user_stats cursor.execute("""UPDATE user_stats
@ -231,7 +231,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
cursor.execute("""UPDATE channel_stats SET modes=modes+1""") cursor.execute("""UPDATE channel_stats SET modes=modes+1""")
try: try:
if ircutils.isUserHostmask(msg.prefix): if ircutils.isUserHostmask(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.prefix name = msg.prefix
cursor.execute("""UPDATE user_stats cursor.execute("""UPDATE user_stats
@ -248,7 +248,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
cursor.execute("""UPDATE channel_stats SET kicks=kicks+1""") cursor.execute("""UPDATE channel_stats SET kicks=kicks+1""")
try: try:
if ircutils.isUserHostmask(msg.prefix): if ircutils.isUserHostmask(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.prefix name = msg.prefix
cursor.execute("""UPDATE user_stats cursor.execute("""UPDATE user_stats
@ -258,7 +258,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
pass pass
try: try:
kicked = msg.args[1] kicked = msg.args[1]
name = ircdb.users.getUserName(irc.state.nickToHostmask(kicked)) name = ircdb.users.getUser(irc.state.nickToHostmask(kicked)).name
cursor.execute("""UPDATE user_stats cursor.execute("""UPDATE user_stats
SET kicked=kicked+1 SET kicked=kicked+1
WHERE name=%s""", name) WHERE name=%s""", name)
@ -278,7 +278,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
if not ircdb.users.hasUser(name): if not ircdb.users.hasUser(name):
try: try:
hostmask = irc.state.nickToHostmask(name) hostmask = irc.state.nickToHostmask(name)
name = ircdb.users.getUserName(hostmask) name = ircdb.users.getUser(hostmask).name
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
@ -369,7 +369,7 @@ class ChannelDB(callbacks.PrivmsgCommandAndRegexp, ChannelDBHandler):
if not ircdb.users.hasUser(name): if not ircdb.users.hasUser(name):
hostmask = irc.state.nickToHostmask(name) hostmask = irc.state.nickToHostmask(name)
try: try:
name = ircdb.users.getUserName(hostmask) name = ircdb.users.getUser(hostmask).name
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return

View File

@ -144,7 +144,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
irc.error(msg, conf.replyNoCapability % capability) irc.error(msg, conf.replyNoCapability % capability)
return return
if ircdb.users.hasUser(msg.prefix): if ircdb.users.hasUser(msg.prefix):
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
else: else:
name = msg.nick name = msg.nick
cursor.execute("""INSERT INTO factoids VALUES cursor.execute("""INSERT INTO factoids VALUES
@ -364,6 +364,7 @@ class Factoids(ChannelDBHandler, callbacks.Privmsg):
utils.nItems(cursor.rowcount, 'key')) utils.nItems(cursor.rowcount, 'key'))
else: else:
irc.reply(msg, s) irc.reply(msg, s)
Class = Factoids Class = Factoids
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -262,7 +262,7 @@ class FunDB(callbacks.Privmsg):
(table, s) = privmsgs.getArgs(args, needed=2) (table, s) = privmsgs.getArgs(args, needed=2)
table = table.lower() table = table.lower()
try: try:
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
irc.error(msg, conf.replyNotRegistered) irc.error(msg, conf.replyNotRegistered)
return return
@ -295,7 +295,7 @@ class FunDB(callbacks.Privmsg):
(table, id) = privmsgs.getArgs(args, needed=2) (table, id) = privmsgs.getArgs(args, needed=2)
table = table.lower() table = table.lower()
try: try:
ircdb.users.getUserName(msg.prefix) ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
irc.error(msg, conf.replyNotRegistered) irc.error(msg, conf.replyNotRegistered)
return return
@ -464,7 +464,7 @@ class FunDB(callbacks.Privmsg):
irc.queueMsg(ircmsgs.action(channel, '%s for %s (#%s)' %\ irc.queueMsg(ircmsgs.action(channel, '%s for %s (#%s)' %\
(praise, reason, id))) (praise, reason, id)))
else: else:
irc.queueMsg(ircmsgs.action(channel, '%s (#%s)' % (praise, id))) irc.queueMsg(ircmsgs.action(channel, '%s (#%s)' %(praise, id)))
raise callbacks.CannotNest raise callbacks.CannotNest
def addword(self, irc, msg, args): def addword(self, irc, msg, args):

View File

@ -84,7 +84,7 @@ class Topic(callbacks.Privmsg):
return return
currentTopic = irc.state.getTopic(channel) currentTopic = irc.state.getTopic(channel)
try: try:
name = ircdb.users.getUserName(msg.prefix) name = ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
name = msg.nick name = msg.nick
formattedTopic = self.topicFormatter % (topic, name) formattedTopic = self.topicFormatter % (topic, name)
@ -166,7 +166,7 @@ class Topic(callbacks.Privmsg):
else: else:
(topic, name) = match.groups() (topic, name) = match.groups()
try: try:
senderName = ircdb.users.getUserName(msg.prefix) senderName = ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
@ -208,7 +208,7 @@ class Topic(callbacks.Privmsg):
else: else:
(topic, name) = match.groups() (topic, name) = match.groups()
try: try:
username = ircdb.users.getUserName(msg.prefix) username = ircdb.users.getUser(msg.prefix).name
except KeyError: except KeyError:
username = msg.nick username = msg.nick
if name and name != username and \ if name and name != username and \

View File

@ -130,8 +130,7 @@ if __name__ == '__main__':
filenames.extend(os.listdir(dir)) filenames.extend(os.listdir(dir))
plugins = [] plugins = []
for filename in filenames: for filename in filenames:
if filename.endswith('.py') and \ if filename.endswith('.py') and filename[0].isupper():
filename.lower() != filename:
plugins.append(os.path.splitext(filename)[0]) plugins.append(os.path.splitext(filename)[0])
plugins.sort() plugins.sort()
if yn('Would you like to see a list of the available modules?') == 'y': if yn('Would you like to see a list of the available modules?') == 'y':
@ -201,12 +200,13 @@ if __name__ == '__main__':
if yn('Would you like to add an owner user?') == 'y': if yn('Would you like to add an owner user?') == 'y':
owner = something('What should the owner\'s username be?') owner = something('What should the owner\'s username be?')
password = something('What should the owner\'s password be?') password = something('What should the owner\'s password be?')
user = ircdb.IrcUser() (id, user) = ircdb.users.newUser()
user.setPassword(password) user.setPassword(password)
user.names.add(owner)
user.addCapability('owner') user.addCapability('owner')
while yn('Would you like to add a hostmask for the owner?') == 'y': while yn('Would you like to add a hostmask for the owner?') == 'y':
user.addHostmask(something('What hostmask?')) user.addHostmask(something('What hostmask?'))
ircdb.users.setUser(owner, user) ircdb.users.setUser(id, user)
### ###
# Configuration variables in conf.py. # Configuration variables in conf.py.

View File

@ -136,9 +136,10 @@ class AdminCommands(privmsgs.CapabilityCheckingPrivmsg):
if ircdb.checkCapability(msg.prefix, capability) or \ if ircdb.checkCapability(msg.prefix, capability) or \
'!' in capability: '!' in capability:
try: try:
u = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
u.addCapability(capability) user = ircdb.users.getUser(id)
ircdb.users.setUser(name, u) user.addCapability(capability)
ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
@ -156,9 +157,10 @@ class AdminCommands(privmsgs.CapabilityCheckingPrivmsg):
if ircdb.checkCapability(msg.prefix, capability) or \ if ircdb.checkCapability(msg.prefix, capability) or \
'!' in capability: '!' in capability:
try: try:
u = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
u.addCapability(capability) user = ircdb.users.getUser(id)
ircdb.users.setUser(name, u) user.addCapability(capability)
ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)

View File

@ -256,9 +256,10 @@ class ChannelCommands(callbacks.Privmsg):
capability = ircdb.makeChannelCapability(channel, capability) capability = ircdb.makeChannelCapability(channel, capability)
if ircdb.checkCapability(msg.prefix, neededcapability): if ircdb.checkCapability(msg.prefix, neededcapability):
try: try:
u = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
u.addCapability(capability) user = ircdb.users.getUser(id)
ircdb.users.setUser(name, u) user.addCapability(capability)
ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
@ -280,9 +281,10 @@ class ChannelCommands(callbacks.Privmsg):
capability = ircdb.makeChannelCapability(channel, capability) capability = ircdb.makeChannelCapability(channel, capability)
if ircdb.checkCapability(msg.prefix, neededcapability): if ircdb.checkCapability(msg.prefix, neededcapability):
try: try:
u = ircdb.users.getUser(name) id = ircdb.users.getUser(name)
u.removeCapability(capability) user = ircdb.users.getUser(id)
ircdb.users.setUser(name, u) user.removeCapability(capability)
ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)

View File

@ -36,6 +36,7 @@ Provides commands useful to users in general. This plugin is loaded by default.
import string import string
import conf import conf
import utils
import ircdb import ircdb
import ircutils import ircutils
import privmsgs import privmsgs
@ -61,16 +62,20 @@ class UserCommands(callbacks.Privmsg):
if ircutils.isChannel(msg.args[0]): if ircutils.isChannel(msg.args[0]):
irc.error(msg, conf.replyRequiresPrivacy) irc.error(msg, conf.replyRequiresPrivacy)
return return
if ircdb.users.hasUser(name): try:
irc.error(msg, 'That name is already registered.') ircdb.users.getUserId(name)
irc.error(msg, 'That name is alrady assigned to someone.')
return return
except KeyError:
pass
if ircutils.isUserHostmask(name): if ircutils.isUserHostmask(name):
irc.error(msg, 'Hostmasks aren\'t valid usernames.') irc.error(msg, 'Hostmasks aren\'t valid usernames.')
return return
user = ircdb.IrcUser() (id, user) = ircdb.users.newUser()
user.name = name
user.setPassword(password) user.setPassword(password)
user.addHostmask(msg.prefix) user.addHostmask(msg.prefix)
ircdb.users.setUser(name, user) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
def addhostmask(self, irc, msg, args): def addhostmask(self, irc, msg, args):
@ -92,20 +97,20 @@ class UserCommands(callbacks.Privmsg):
irc.error(msg, s) irc.error(msg, s)
return return
try: try:
user = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
try: try:
name = ircdb.users.getUserName(hostmask) _ = ircdb.users.getUserId(hostmask)
s = 'That hostmask is already registered to %s.' % name irc.error(msg, 'That hostmask is already registered.')
irc.error(msg, s)
return return
except KeyError: except KeyError:
pass pass
if user.checkHostmask(msg.prefix) or user.checkPassword(password): if user.checkHostmask(msg.prefix) or user.checkPassword(password):
user.addHostmask(hostmask) user.addHostmask(hostmask)
ircdb.users.setUser(name, user) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
else: else:
irc.error(msg, conf.replyIncorrectAuth) irc.error(msg, conf.replyIncorrectAuth)
@ -122,13 +127,14 @@ class UserCommands(callbacks.Privmsg):
if not self._checkNotChannel(irc, msg, password): if not self._checkNotChannel(irc, msg, password):
return return
try: try:
user = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
if user.checkHostmask(msg.prefix) or user.checkPassword(password): if user.checkHostmask(msg.prefix) or user.checkPassword(password):
user.removeHostmask(hostmask) user.removeHostmask(hostmask)
ircdb.users.setUser(name, user) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
else: else:
irc.error(msg, conf.replyIncorrectAuth) irc.error(msg, conf.replyIncorrectAuth)
@ -144,13 +150,14 @@ class UserCommands(callbacks.Privmsg):
if not self._checkNotChannel(irc, msg, oldpassword+newpassword): if not self._checkNotChannel(irc, msg, oldpassword+newpassword):
return return
try: try:
user = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
if user.checkPassword(oldpassword): if user.checkPassword(oldpassword):
user.setPassword(newpassword) user.setPassword(newpassword)
ircdb.users.setUser(name, user) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
else: else:
irc.error(msg, conf.replyIncorrectAuth) irc.error(msg, conf.replyIncorrectAuth)
@ -169,8 +176,8 @@ class UserCommands(callbacks.Privmsg):
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
try: try:
name = ircdb.users.getUserName(hostmask) user = ircdb.users.getUser(hostmask)
irc.reply(msg, name) irc.reply(msg, user.name)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
@ -197,11 +204,7 @@ class UserCommands(callbacks.Privmsg):
isn't specified, returns the hostmasks of the user calling the command. isn't specified, returns the hostmasks of the user calling the command.
""" """
if not args: if not args:
try: name = msg.prefix
name = ircdb.users.getUserName(msg.prefix)
except KeyError:
irc.error(msg, conf.replyNoUser)
return
else: else:
name = privmsgs.getArgs(args) name = privmsgs.getArgs(args)
try: try:
@ -219,13 +222,14 @@ class UserCommands(callbacks.Privmsg):
if not self._checkNotChannel(irc, msg): if not self._checkNotChannel(irc, msg):
return return
try: try:
u = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
if u.checkPassword(password): if user.checkPassword(password):
u.setAuth(msg.prefix) user.setAuth(msg.prefix)
ircdb.users.setUser(name, u) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
else: else:
irc.error(msg, conf.replyIncorrectAuth) irc.error(msg, conf.replyIncorrectAuth)
@ -236,13 +240,13 @@ class UserCommands(callbacks.Privmsg):
Un-identifies the user. Un-identifies the user.
""" """
try: try:
u = ircdb.users.getUser(msg.prefix) id = ircdb.users.getUserId(msg.prefix)
name = ircdb.users.getUserName(msg.prefix) user = ircdb.users.getUser(id)
except KeyError: except KeyError:
irc.error(msg, conf.replyNoUser) irc.error(msg, conf.replyNoUser)
return return
u.unsetAuth() user.unsetAuth()
ircdb.users.setUser(name, u) ircdb.users.setUser(id, user)
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
def whoami(self, irc, msg, args): def whoami(self, irc, msg, args):
@ -251,8 +255,8 @@ class UserCommands(callbacks.Privmsg):
Returns the name of the user calling the command. Returns the name of the user calling the command.
""" """
try: try:
name = ircdb.users.getUserName(msg.prefix) user = ircdb.users.getUser(msg.prefix)
irc.reply(msg, name) irc.reply(msg, user.name)
except KeyError: except KeyError:
irc.error(msg, conf.replyNotRegistered) irc.error(msg, conf.replyNotRegistered)

View File

@ -182,7 +182,8 @@ Name: """ % (world.version, sys.version.translate(string.ascii, '\r\n'))
try: try:
name = self.buffer name = self.buffer
self.buffer = '' self.buffer = ''
self.u = ircdb.users.getUser(name) id = ircdb.users.getUserId(name)
self.u = ircdb.users.getUser(id)
self.prompt = 'Password: ' self.prompt = 'Password: '
except KeyError: except KeyError:
self.push('Unknown user.\n') self.push('Unknown user.\n')

View File

@ -34,11 +34,11 @@ from fix import *
import os import os
import sets import sets
import time import time
import atexit
import string import string
import conf import conf
import debug import debug
import utils
import world import world
import ircutils import ircutils
@ -158,9 +158,10 @@ class UserCapabilitySet(CapabilitySet):
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='', name='',
capabilities=(), hostmasks=None): capabilities=(), hostmasks=None):
self.auth = auth # The (time, hostmask) a user authenticated under. self.auth = None # The (time, hostmask) a user authenticated under
self.name = name # The name of the user.
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 = UserCapabilitySet() self.capabilities = UserCapabilitySet()
@ -172,10 +173,10 @@ class IrcUser(object):
self.hostmasks = hostmasks self.hostmasks = hostmasks
def __repr__(self): def __repr__(self):
return '%s(ignore=%s, auth=%r, password=%r, '\ return '%s(ignore=%s, password=%r, name=%r, '\
'capabilities=%r, hostmasks=%r)\n' %\ 'capabilities=%r, hostmasks=%r)\n' %\
(self.__class__.__name__, self.ignore, self.auth, (self.__class__.__name__, self.ignore, self.password,
self.password, self.capabilities, self.hostmasks) self.name, self.capabilities, self.hostmasks)
def addCapability(self, capability): def addCapability(self, capability):
self.capabilities.add(capability) self.capabilities.add(capability)
@ -315,103 +316,139 @@ class IrcChannel(object):
return True return True
return False return False
class UsersDB(object):
class UsersDictionary(object):
def __init__(self, filename): def __init__(self, filename):
self.filename = filename self.filename = filename
fd = file(filename, 'r') if os.path.exists(filename):
s = fd.read() fd = file(filename, 'r')
fd.close() s = fd.read()
Set = sets.Set fd.close()
ignore(Set) # Make PyChecker happy. IrcSet = ircutils.IrcSet
self.dict = eval(normalize(s)) (self.nextId, self.users) = eval(normalize(s))
self.cache = {} # hostmasks to nicks.
self.revcache = ircutils.IrcDict() # nicks to hostmasks.
def resetCache(self, s):
if s in self.cache:
# it's a hostmask.
name = self.cache[s]
del self.cache[s]
else: else:
# it's already a name. self.nextId = 1
name = s self.users = [IrcUser(capabilities=['owner'],
# name should always be in self.revcache, this should never KeyError. password=utils.mktemp())]
if name in self.revcache: self._nameCache = {}
for hostmask in self.revcache[name]: self._hostmaskCache = {}
del self.cache[hostmask]
del self.revcache[name]
def setCache(self, hostmask, name):
self.cache[hostmask] = name
self.revcache.setdefault(name, []).append(hostmask)
def getUser(self, s):
if ircutils.isUserHostmask(s):
name = self.getUserName(s)
else:
name = s
return self.dict[name]
def setUser(self, s, u):
# First, invalidate the cache for this user.
self.resetCache(s)
if ircutils.isUserHostmask(s):
name = self.getUserName(s)
else:
name = s
for hostmask in u.hostmasks:
try:
username = self.getUserName(hostmask)
if username != name:
raise ValueError, 'User has hostmasks already matching ' \
'another user\'s hostmasks.'
except KeyError:
pass
self.dict[name] = u
def hasUser(self, s):
return (s in self.dict)
def delUser(self, s):
if ircutils.isUserHostmask(s):
name = self.getUserName(s)
else:
name = s
self.resetCache(name)
try:
del self.dict[name]
except KeyError:
pass
def getUserName(self, s):
assert ircutils.isUserHostmask(s), 'string must be a hostmask'
if s in self.cache:
return self.cache[s]
else:
for (name, user) in self.dict.iteritems():
if user.checkHostmask(s):
self.cache[s] = name
self.revcache.setdefault(name,[]).append(s)
return name
raise KeyError, s
def flush(self):
fd = file(self.filename, 'w')
fd.write(repr(self.dict))
fd.close()
def reload(self): def reload(self):
self.__init__(self.filename) self.__init__(self.filename)
def flush(self):
fd = file(self.filename, 'w')
fd.write(repr((self.nextId, self.users)))
fd.close()
def getUserId(self, s):
if ircutils.isUserHostmask(s):
try:
return self._hostmaskCache[s]
except KeyError:
ids = []
for (id, user) in enumerate(self.users):
if user is None:
continue
if user.checkHostmask(s):
ids.append(id)
if len(ids) == 1:
id = ids[0]
self._hostmaskCache[s] = id
self._hostmaskCache.setdefault(id, sets.Set()).add(s)
return id
elif len(ids) == 0:
raise KeyError, s
else:
raise ValueError, 'Ids %r matched.' % ids
else: # Not a hostmask, must be a name.
try:
return self._nameCache[s]
except KeyError:
for (id, user) in enumerate(self.users):
if user is None:
continue
if s == user.name:
self._nameCache[s] = id
self._nameCache.setdefault(id, sets.Set()).add(s)
return id
else:
raise KeyError, s
def getUser(self, id):
if not isinstance(id, int):
# Must be a string. Get the UserId first.
id = self.getUserId(id)
try:
ret = self.users[id]
if ret is None:
raise KeyError, id
return ret
except IndexError:
raise KeyError, id
def hasUser(self, id):
try:
self.getUser(id)
return True
except KeyError:
return False
def setUser(self, id, user):
assert isinstance(id, int), 'setUser takes an integer userId.'
if not 0 <= id < len(self.users) or self.users[id] is None:
raise KeyError, id
try:
if self.getUserId(user.name) != id:
raise ValueError, \
'%s is already registered to someone else.' % user.name
except KeyError:
pass
for hostmask in user.hostmasks:
try:
if self.getUserId(hostmask) != id:
raise ValueError, \
'%s is already registered to someone else.'% hostmask
except KeyError:
continue
if id in self._nameCache:
for name in self._nameCache[id]:
del self._nameCache[name]
del self._nameCache[id]
if id in self._hostmaskCache:
for hostmask in self._hostmaskCache[id]:
del self._hostmaskCache[hostmask]
del self._hostmaskCache[id]
### FIXME: what if the new hostmasks overlap with another hostmask?
self.users[id] = user
def delUser(self, id):
if not 0 <= id < len(self.users) or self.users[id] is None:
raise KeyError, id
self.users[id] = None
for name in self._nameCache.get(id, []):
del self._nameCache[name]
for hostmask in self._hostmaskCache.get(id, []):
del self._hostmaskCache[hostmask]
def newUser(self):
user = IrcUser()
id = self.nextId
self.nextId += 1
self.users.append(user)
return (id, user)
class ChannelsDictionary(object): class ChannelsDictionary(object):
def __init__(self, filename): def __init__(self, filename):
self.filename = filename self.filename = filename
fd = file(filename, 'r') if os.path.exists(filename):
s = fd.read() fd = file(filename, 'r')
fd.close() s = fd.read()
Set = sets.Set fd.close()
self.dict = eval(normalize(s)) Set = sets.Set
self.dict = eval(normalize(s))
else:
self.dict = {}
def getChannel(self, channel): def getChannel(self, channel):
channel = channel.lower() channel = channel.lower()
@ -438,26 +475,9 @@ class ChannelsDictionary(object):
### ###
# Later, I might add some special handling for botnet. # Later, I might add some special handling for botnet.
### ###
if not os.path.exists(conf.userfile): users = UsersDB(conf.userfile)
fd = open(conf.userfile, 'w')
fd.write('{}')
fd.close()
users = UsersDictionary(conf.userfile)
if not os.path.exists(conf.channelfile):
fd = file(conf.channelfile, 'w')
fd.write('{}')
fd.close()
channels = ChannelsDictionary(conf.channelfile) channels = ChannelsDictionary(conf.channelfile)
def flushUsers():
for (name, u) in users.dict.iteritems():
u.unsetAuth()
users.flush()
atexit.register(flushUsers)
atexit.register(channels.flush)
world.flushers.append(users.flush) world.flushers.append(users.flush)
world.flushers.append(channels.flush) world.flushers.append(channels.flush)
@ -473,7 +493,8 @@ def checkIgnored(hostmask, recipient='', users=users, channels=channels):
if ircutils.hostmaskPatternEqual(ignore, hostmask): if ircutils.hostmaskPatternEqual(ignore, hostmask):
return True return True
try: try:
user = users.getUser(hostmask) id = users.getUserId(hostmask)
user = users.getUser(id)
except KeyError: except KeyError:
# If there's no user... # If there's no user...
if ircutils.isChannel(recipient): if ircutils.isChannel(recipient):
@ -507,7 +528,8 @@ def checkCapability(hostmask, capability, users=users, channels=channels):
#debug.printf('world.startup is active.') #debug.printf('world.startup is active.')
return _x(capability, True) return _x(capability, True)
try: try:
u = users.getUser(hostmask) id = users.getUserId(hostmask)
u = users.getUser(id)
except KeyError: except KeyError:
#debug.printf('user could not be found.') #debug.printf('user could not be found.')
if isChannelCapability(capability): if isChannelCapability(capability):
@ -582,13 +604,5 @@ def checkCapabilities(hostmask, capabilities, requireAll=False):
else: else:
return False return False
def getUser(irc, s):
if ircutils.isUserHostmask(s):
return users.getUserName(s)
else:
if users.hasUser(s):
return s
else:
return users.getUserName(irc.state.nickToHostmask(s))
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:

View File

@ -438,8 +438,10 @@ class Irc(object):
# it to abuse our 'owner' power we give to ourselves. Ergo, on # it to abuse our 'owner' power we give to ourselves. Ergo, on
# outgoing messages that change our nick, we pre-emptively # outgoing messages that change our nick, we pre-emptively
# delete the 'owner' user we setup for ourselves. # delete the 'owner' user we setup for ourselves.
if ircdb.users.hasUser(self.nick): user = ircdb.users.getUser(0)
ircdb.users.delUser(self.nick) user.unsetAuth()
user.hostmasks = []
ircdb.users.setUser(0, user)
return msg return msg
else: else:
return None return None
@ -455,10 +457,10 @@ class Irc(object):
args=msg.args) args=msg.args)
# First, make sure self.nick is always consistent with the server. # First, make sure self.nick is always consistent with the server.
if msg.command == 'NICK' and msg.nick == self.nick: if msg.command == 'NICK' and msg.nick == self.nick:
if ircdb.users.hasUser(self.nick): user = ircdb.users.getUser(0)
ircdb.users.delUser(self.nick) user.unsetAuth()
if ircdb.users.hasUser(self.prefix): user.hostmasks = []
ircdb.users.delUser(self.prefix) ircdb.users.setUser(0, user)
self.nick = msg.args[0] self.nick = msg.args[0]
(nick, user, domain) = ircutils.splitHostmask(msg.prefix) (nick, user, domain) = ircutils.splitHostmask(msg.prefix)
self.prefix = '%s!%s@%s' % (self.nick, user, domain) self.prefix = '%s!%s@%s' % (self.nick, user, domain)
@ -472,17 +474,12 @@ class Irc(object):
self.sendMsg(ircmsgs.nick(self._nickmods.pop(0) % self.nick)) self.sendMsg(ircmsgs.nick(self._nickmods.pop(0) % self.nick))
if msg.nick == self.nick: if msg.nick == self.nick:
self.prefix = msg.prefix self.prefix = msg.prefix
if ircdb.users.hasUser(self.nick): user = ircdb.users.getUser(0)
u = ircdb.users.getUser(self.nick) user.hostmasks = []
if not u.hasHostmask(msg.prefix): user.name = self.nick
u.addHostmask(msg.prefix) user.addHostmask(msg.prefix)
ircdb.users.setUser(self.nick, u) user.setPassword(utils.mktemp())
else: ircdb.users.setUser(0, user)
u = ircdb.IrcUser(capabilities=['owner'],
password=utils.mktemp(),
hostmasks=[msg.prefix])
ircdb.users.setUser(self.nick, u)
atexit.register(lambda: catch(ircdb.users.delUser(self.nick)))
if msg.command == 'ERROR': if msg.command == 'ERROR':
if msg.args[0].startswith('Closing Link'): if msg.args[0].startswith('Closing Link'):
if hasattr(self.driver, 'scheduleReconnect'): if hasattr(self.driver, 'scheduleReconnect'):

View File

@ -103,7 +103,8 @@ class MyShell(Shell):
debug.printf(repr(username)) debug.printf(repr(username))
debug.printf(repr(password)) debug.printf(repr(password))
try: try:
u = ircdb.users.getUser(username) id = ircdb.users.getUserId(username)
u = ircdb.users.getUser(id)
debug.printf(u) debug.printf(u)
if u.checkPassword(password) and u.checkCapability('owner'): if u.checkPassword(password) and u.checkCapability('owner'):
debug.printf('returning True') debug.printf('returning True')

View File

@ -255,34 +255,32 @@ class IrcChannelTestCase(unittest.TestCase):
c.removeBan(banmask) c.removeBan(banmask)
self.failIf(c.checkIgnored(prefix)) self.failIf(c.checkIgnored(prefix))
class UsersDictionaryTestCase(unittest.TestCase): class UsersDBTestCase(unittest.TestCase):
filename = 'UsersDictionaryTestCase.conf' filename = 'UsersDBTestCase.conf'
def setUp(self): def setUp(self):
fd = file(self.filename, 'w') try:
fd.write('{}\n') os.remove(self.filename)
fd.close() except:
self.users = ircdb.UsersDictionary(self.filename) pass
self.users = ircdb.UsersDB(self.filename)
def tearDown(self):
os.remove(self.filename)
def testGetSetDelUser(self): def testGetSetDelUser(self):
self.assertRaises(KeyError, self.users.getUser, 'foo') self.assertRaises(KeyError, self.users.getUser, 'foo')
self.assertRaises(KeyError, self.users.getUser, 'foo!bar@baz') self.assertRaises(KeyError, self.users.getUser, 'foo!bar@baz')
u = ircdb.IrcUser() (id, u) = self.users.newUser()
hostmask = 'foo!bar@baz' hostmask = 'foo!bar@baz'
banmask = ircutils.banmask(hostmask) banmask = ircutils.banmask(hostmask)
u.addHostmask(banmask) u.addHostmask(banmask)
self.users.setUser('foo', u) u.name = 'foo'
self.users.setUser(id, u)
self.assertEqual(self.users.getUser('foo'), u) self.assertEqual(self.users.getUser('foo'), u)
self.assertEqual(self.users.getUser(hostmask), u) self.assertEqual(self.users.getUser(hostmask), u)
self.assertEqual(self.users.getUser(banmask), u) self.assertEqual(self.users.getUser(banmask), u)
# The UsersDictionary shouldn't allow users to be added whose hostmasks # The UsersDB shouldn't allow users to be added whose hostmasks
# match another user's already in the database. # match another user's already in the database.
self.assertRaises(ValueError, self.users.setUser, 'bar', u) (id, u2) = self.users.newUser()
u.removeHostmask(banmask) u2.addHostmask('*!*@*')
u.addHostmask('*!*@*') self.assertRaises(ValueError, self.users.setUser, id, u2)
self.assertRaises(ValueError, self.users.setUser, 'biff', u)
class CheckCapabilityTestCase(unittest.TestCase): class CheckCapabilityTestCase(unittest.TestCase):
@ -304,40 +302,44 @@ class CheckCapabilityTestCase(unittest.TestCase):
channelanticap = ircdb.IrcChannel() channelanticap = ircdb.IrcChannel()
channelanticap.addCapability(anticap) channelanticap.addCapability(anticap)
def setUp(self): def setUp(self):
fd = file(self.filename, 'w') try:
fd.write('{}\n') os.remove(self.filename)
fd.close() except:
self.users = ircdb.UsersDictionary(self.filename) pass
self.users = ircdb.UsersDB(self.filename)
self.channels = ircdb.ChannelsDictionary(self.filename) self.channels = ircdb.ChannelsDictionary(self.filename)
owner = ircdb.IrcUser() (id, owner) = self.users.newUser()
owner.name = 'owner'
owner.addCapability('owner') owner.addCapability('owner')
owner.addHostmask(self.owner) owner.addHostmask(self.owner)
self.users.setUser('owner', owner) self.users.setUser(id, owner)
nothing = ircdb.IrcUser() (id, nothing) = self.users.newUser()
nothing.name = 'nothing'
nothing.addHostmask(self.nothing) nothing.addHostmask(self.nothing)
self.users.setUser('nothing', nothing) self.users.setUser(id, nothing)
justfoo = ircdb.IrcUser() (id, justfoo) = self.users.newUser()
justfoo.name = 'justfoo'
justfoo.addCapability(self.cap) justfoo.addCapability(self.cap)
justfoo.addHostmask(self.justfoo) justfoo.addHostmask(self.justfoo)
self.users.setUser('justfoo', justfoo) self.users.setUser(id, justfoo)
antifoo = ircdb.IrcUser() (id, antifoo) = self.users.newUser()
antifoo.name = 'antifoo'
antifoo.addCapability(self.anticap) antifoo.addCapability(self.anticap)
antifoo.addHostmask(self.antifoo) antifoo.addHostmask(self.antifoo)
self.users.setUser('antifoo', antifoo) self.users.setUser(id, antifoo)
justchanfoo = ircdb.IrcUser() (id, justchanfoo) = self.users.newUser()
justchanfoo.name = 'justchanfoo'
justchanfoo.addCapability(self.chancap) justchanfoo.addCapability(self.chancap)
justchanfoo.addHostmask(self.justchanfoo) justchanfoo.addHostmask(self.justchanfoo)
self.users.setUser('justchanfoo', justchanfoo) self.users.setUser(id, justchanfoo)
antichanfoo = ircdb.IrcUser() (id, antichanfoo) = self.users.newUser()
antichanfoo.name = 'antichanfoo'
antichanfoo.addCapability(self.antichancap) antichanfoo.addCapability(self.antichancap)
antichanfoo.addHostmask(self.antichanfoo) antichanfoo.addHostmask(self.antichanfoo)
self.users.setUser('antichanfoo', antichanfoo) self.users.setUser(id, antichanfoo)
channel = ircdb.IrcChannel() channel = ircdb.IrcChannel()
self.channels.setChannel(self.channel, channel) self.channels.setChannel(self.channel, channel)
def tearDown(self):
os.remove(self.filename)
def checkCapability(self, hostmask, capability): def checkCapability(self, hostmask, capability):
return ircdb.checkCapability(hostmask, capability, return ircdb.checkCapability(hostmask, capability,
self.users, self.channels) self.users, self.channels)