From 12fb4f9520991c6cf0a5e31594bd1d709a958540 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Thu, 9 Aug 2012 14:36:09 -0400 Subject: [PATCH] Starting work on PermissionsDB. --- earwigbot/config/__init__.py | 11 +++++-- earwigbot/config/node.py | 18 +++++++++-- earwigbot/config/permissions.py | 68 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 earwigbot/config/permissions.py diff --git a/earwigbot/config/__init__.py b/earwigbot/config/__init__.py index b491b76..be29d29 100644 --- a/earwigbot/config/__init__.py +++ b/earwigbot/config/__init__.py @@ -43,6 +43,7 @@ except ImportError: from earwigbot.config.formatter import BotFormatter from earwigbot.config.node import ConfigNode +from earwigbot.config.permissions import PermissionsDB from earwigbot.exceptions import NoConfigError __all__ = ["BotConfig"] @@ -77,8 +78,10 @@ class BotConfig(object): def __init__(self, root_dir, level): self._root_dir = root_dir self._logging_level = level - self._config_path = path.join(self._root_dir, "config.yml") - self._log_dir = path.join(self._root_dir, "logs") + self._config_path = path.join(self.root_dir, "config.yml") + self._log_dir = path.join(self.root_dir, "logs") + perms_file = path.join(self.root_dir, "permissions.db") + self._permissions = PermissionsDB(perms_file) self._decryption_cipher = None self._data = None @@ -291,6 +294,10 @@ class BotConfig(object): for node, nodes in self._decryptable_nodes: self._decrypt(node, nodes) + if self.irc: + self.irc["permissions"] = self._permissions + self._permissions.load() + def decrypt(self, node, *nodes): """Decrypt an object in our config tree. diff --git a/earwigbot/config/node.py b/earwigbot/config/node.py index a5746e2..36f7a1e 100644 --- a/earwigbot/config/node.py +++ b/earwigbot/config/node.py @@ -26,9 +26,14 @@ class ConfigNode(object): def __init__(self): self._data = {} - def __iter__(self): - for key in self._data: - yield key + def __repr__(self): + return self._data + + def __nonzero__(self): + return bool(self._data) + + def __len__(self): + retrun len(self._data) def __getitem__(self, key): return self._data[key] @@ -42,6 +47,13 @@ class ConfigNode(object): def __setattr__(self, key, item): self._data[key] = item + def __iter__(self): + for key in self._data: + yield key + + def __contains__(self, item): + return item in self._data + def _dump(self): data = self._data.copy() for key, val in data.iteritems(): diff --git a/earwigbot/config/permissions.py b/earwigbot/config/permissions.py new file mode 100644 index 0000000..d3f6a30 --- /dev/null +++ b/earwigbot/config/permissions.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2009-2012 Ben Kurtovic +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sqlite3 as sqlite +from threading import Lock + +__all__ = ["PermissionsDB"] + +class PermissionsDB(object): + def __init__(self, dbfile): + self._dbfile = dbfile + self._db_access_lock = Lock() + self._data = {} + + def __repr__(self): + """Return the canonical string representation of the PermissionsDB.""" + res = "PermissionsDB(dbfile={0!r})" + return res.format(self._dbfile) + + def __str__(self): + """Return a nice string representation of the PermissionsDB.""" + return "".format(self._dbfile) + + def _create(self, conn): + """Initialize the permissions database with its necessary tables.""" + query = """CREATE TABLE users (user_nick, user_ident, user_host, + user_rank)""" + conn.execute(query) + + def load(self): + """Load permissions from an existing database, or create a new one.""" + query = "SELECT user_nick, user_ident, user_host, user_rank FROM users" + self._data = {} + with sqlite.connect(self._dbfile) as conn, self._db_access_lock: + try: + for nick, ident, host, rank in conn.execute(query): + try: + self._data[rank].append(_User(nick, ident, host)) + except KeyError: + self._data[rank] = [_User(nick, ident, host)] + except sqlite.OperationalError: + self._create(conn) + + +class _User(object): + def __init__(self, nick, ident, host): + self.nick = nick + self.ident = ident + self.host = host