* 'create_tables.pgsql'
authorPascal Volk <neverseen@users.sourceforge.net>
Sun, 02 Mar 2008 20:22:00 +0000
changeset 9 e3d3dbeb5b84
parent 8 7e3ce56f49e6
child 10 8f6e34549c26
* 'create_tables.pgsql' - Added view vmm_domain_info * 'VirtualMailManager/Alias.py' - Removed attribute Alias._aid - Removed parameter basedir from Alias.__init__() and Alias._setAddr() * 'VirtualMailManager/MailLocation.py' - Fixed typo in MailLocation.__init__() * 'VirtualMailManager/Account.py' - Integrated Transport- and MailLocation-stuff - Removed attributes: Account._base and Account._home * 'VirtualMailManager/VirtualMailManager.py' - some small fixes * 'VirtualMailManager/Domain.py' - Added Transport-stuff * 'vmm.cfg' - 'Added option transport in section misc'
ChangeLog
TODO
VirtualMailManager/Account.py
VirtualMailManager/Alias.py
VirtualMailManager/Config.py
VirtualMailManager/Domain.py
VirtualMailManager/MailLocation.py
VirtualMailManager/VirtualMailManager.py
create_tables.pgsql
vmm.cfg
--- a/ChangeLog	Sat Feb 02 19:48:17 2008 +0000
+++ b/ChangeLog	Sun Mar 02 20:22:00 2008 +0000
@@ -1,4 +1,17 @@
 === 0.0.0 ===
+2008-03-02  Pascal Volk <neverseen@users.sourceforge.net>
+
+	* create_tables.pgsql: Added view vmm_domain_info
+	* VirtualMailManager/Alias.py: Removed attribute Alias._aid
+	Removed parameter basedir from Alias.__init__() and Alias._setAddr()
+	* VirtualMailManager/MailLocation.py: Fixed typo in MailLocation.__init__()
+	* VirtualMailManager/Account.py: Integrated Transport- and
+	MailLocation-stuff
+	Removed attributes: Account._base and Account._home
+	* VirtualMailManager/VirtualMailManager.py: some small fixes
+	* VirtualMailManager/Domain.py: Added Transport-stuff
+	* vmm.cfg: Added option transport in section misc
+
 2008-02-02  Pascal Volk  <neverseen@users.sourceforge.net>
 
 	* create_tables: Renamed table maildir to maillocation
--- a/TODO	Sat Feb 02 19:48:17 2008 +0000
+++ b/TODO	Sun Mar 02 20:22:00 2008 +0000
@@ -1,9 +1,6 @@
 # $Id$
 
 - general
-    - add transport to user tbl (per account) / fall back transport via dom tbl
-    - make default transport configurable via vmm.cfg (for domains and
-      accounts
     - write manpages
 
 - vmm
--- a/VirtualMailManager/Account.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/Account.py	Sun Mar 02 20:22:00 2008 +0000
@@ -15,21 +15,23 @@
 
 from Exceptions import VMMAccountException
 from Domain import Domain
+from Transport import Transport
+from MailLocation import MailLocation
 import constants.ERROR as ERR
 
 class Account:
     """Class to manage e-mail accounts."""
-    def __init__(self, dbh, basedir, address, password=None):
+    def __init__(self, dbh, address, password=None):
         self._dbh = dbh
-        self._base = basedir
         self._base = None
         self._addr = address
         self._localpart = None
         self._name = None
         self._uid = 0
         self._gid = 0
+        self._mid = 0
+        self._tid = 0
         self._passwd = password
-        self._home = None
         self._setAddr(address)
         self._exists()
         if self._isAlias():
@@ -39,35 +41,37 @@
 
     def _exists(self):
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT uid FROM users WHERE gid=%s AND local_part=%s",
+        dbc.execute("SELECT uid, mid, tid FROM users \
+WHERE gid=%s AND local_part=%s",
                 self._gid, self._localpart)
-        uid = dbc.fetchone()
+        result = dbc.fetchone()
         dbc.close()
-        if uid is not None:
-            self._uid = uid[0]
+        if result is not None:
+            self._uid, self._mid, self._tid = result
             return True
         else:
             return False
 
     def _isAlias(self):
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT id FROM alias WHERE gid=%s AND address=%s",
+        dbc.execute("SELECT gid FROM alias WHERE gid=%s AND address=%s",
                 self._gid, self._localpart)
-        aid = dbc.fetchone()
+        gid = dbc.fetchone()
         dbc.close()
-        if aid is not None:
+        if gid is not None:
             return True
         else:
             return False
 
     def _setAddr(self, address):
         self._localpart, d = address.split('@')
-        dom = Domain(self._dbh, d, self._base)
+        dom = Domain(self._dbh, d)
         self._gid = dom.getID()
-        self._base = dom.getDir()
         if self._gid == 0:
             raise VMMAccountException(("Domain »%s« doesn't exist." % d,
                 ERR.NO_SUCH_DOMAIN))
+        self._base = dom.getDir()
+        self._tid = dom.getTransportID()
 
     def _setID(self):
         dbc = self._dbh.cursor()
@@ -75,9 +79,9 @@
         self._uid = dbc.fetchone()[0]
         dbc.close()
 
-    def _prepare(self):
+    def _prepare(self, maillocation):
         self._setID()
-        self._home = "%i" % self._uid
+        self._mid = MailLocation(self._dbh, maillocation=maillocation).getID()
 
     def _switchState(self, state):
         if not isinstance(state, bool):
@@ -110,13 +114,13 @@
     def disable(self):
         self._switchState(True)
 
-    def save(self, mail):
+    def save(self, maillocation):
         if self._uid < 1:
-            self._prepare()
+            self._prepare(maillocation)
             dbc = self._dbh.cursor()
             dbc.execute("""INSERT INTO users (local_part, passwd, uid, gid,\
- home, mail) VALUES (%s, %s, %s, %s, %s, %s)""", self._localpart,
-                    self._passwd, self._uid, self._gid, self._home, mail)
+ mid, tid) VALUES (%s, %s, %s, %s, %s, %s)""", self._localpart, self._passwd,
+                    self._uid, self._gid, self._mid, self._tid )
             self._dbh.commit()
             dbc.close()
         else:
@@ -142,7 +146,7 @@
 
     def getInfo(self):
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT name, uid, gid, home, mail, disabled FROM users\
+        dbc.execute("SELECT name, uid, gid, mid, tid, disabled FROM users\
  WHERE local_part=%s AND gid=%s", self._localpart, self._gid)
         info = dbc.fetchone()
         dbc.close()
@@ -150,14 +154,18 @@
             raise VMMAccountException(("Account doesn't exists",
                 ERR.NO_SUCH_ACCOUNT))
         else:
-            keys = ['name', 'uid', 'gid', 'home', 'mail', 'disabled']
+            keys = ['name', 'uid', 'gid', 'maildir', 'transport', 'disabled']
             info = dict(zip(keys, info))
             if bool(info['disabled']):
                 info['disabled'] = 'Yes'
             else:
                 info['disabled'] = 'No'
             info['address'] = self._addr
-            info['home'] = '%s/%s' % (self._base, info['home'])
+            info['maildir'] = '%s/%s/%s' % (self._base, info['uid'],
+                    MailLocation(self._dbh,
+                        mid=info['maildir']).getMailLocation())
+            info['transport'] = Transport(self._dbh,
+                    tid=info['transport']).getTransport()
             return info
 
     def delete(self):
--- a/VirtualMailManager/Alias.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/Alias.py	Sun Mar 02 20:22:00 2008 +0000
@@ -19,7 +19,7 @@
 
 class Alias:
     """Class to manage e-mail accounts."""
-    def __init__(self, dbh, address, basedir, destination=None):
+    def __init__(self, dbh, address, destination=None):
         if address == destination:
             raise VMMAliasException(('Address and destination are identical.',
                 ERR.ALIAS_ADDR_DEST_IDENTICAL))
@@ -28,8 +28,8 @@
         self._dest = destination
         self._localpart = None
         self._gid = 0
-        self._aid = 0
-        self._setAddr(basedir)
+        self._isNew = False
+        self._setAddr()
         if not self._dest is None:
             self._exists()
         if self._isAccount():
@@ -39,15 +39,14 @@
 
     def _exists(self):
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT id FROM alias WHERE gid=%s AND address=%s\
+        dbc.execute("SELECT gid FROM alias WHERE gid=%s AND address=%s\
  AND destination=%s", self._gid, self._localpart, self._dest)
-        aid = dbc.fetchone()
+        gid = dbc.fetchone()
         dbc.close()
-        if aid is not None:
-            self._aid = aid[0]
-            return True
+        if gid is None:
+            self._isNew = True
         else:
-            return False
+            self._isNew = False
 
     def _isAccount(self):
         dbc = self._dbh.cursor()
@@ -60,9 +59,9 @@
         else:
             return False
         
-    def _setAddr(self, basedir):
+    def _setAddr(self):
         self._localpart, d = self._addr.split('@')
-        dom = Domain(self._dbh, d, basedir)
+        dom = Domain(self._dbh, d)
         self._gid = dom.getID()
         if self._gid == 0:
             raise VMMAliasException(("Domain »%s« doesn't exist." % d,
@@ -72,7 +71,7 @@
         if self._dest is None:
            raise VMMAliasException(('No destination address for alias denoted.',
                ERR.ALIAS_MISSING_DEST))
-        if self._aid < 1:
+        if self._isNew:
             dbc = self._dbh.cursor()
             dbc.execute("INSERT INTO alias (gid, address, destination) VALUES\
  (%s, %s, %s)", self._gid, self._localpart, self._dest)
--- a/VirtualMailManager/Config.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/Config.py	Sun Mar 02 20:22:00 2008 +0000
@@ -69,7 +69,8 @@
         self.__miscopts = [
                 ['passwdscheme', 'CRAM-MD5'],
                 ['gid_mail', 8],
-                ['forcedel', 'false']
+                ['forcedel', 'false'],
+                ['transport', 'dovecot:']
                 ]
 
     def load(self):
--- a/VirtualMailManager/Domain.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/Domain.py	Sun Mar 02 20:22:00 2008 +0000
@@ -17,24 +17,25 @@
 
 from Exceptions import VMMDomainException
 import constants.ERROR as ERR
+from Transport import Transport
 
 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'
 
 class Domain:
     """Class to manage e-mail domains."""
-    def __init__(self, dbh, domainname, basedir, transport=None):
+    def __init__(self, dbh, domainname, basedir=None, transport=None):
         """Creates a new Domain instance.
         
         Keyword arguments:
         dbh -- a pyPgSQL.PgSQL.connection
         domainname -- name of the domain (str)
-        transport -- see transport(5), default 'dovecot:'  (str)
+        transport -- default vmm.cfg/misc/transport  (str)
         """
         self._dbh = dbh
         self._name = domainname
         self._basedir = basedir
-        if transport is None:
-            self._transport = 'dovecot:'
+        if transport is not None:
+            self._transport = Transport(self._dbh, transport=transport)
         else:
             self._transport = transport
         self._id = 0
@@ -48,12 +49,13 @@
         will be returned.
         """
         dbc = self._dbh.cursor()
-        dbc.execute("SELECT gid, domaindir FROM domains WHERE domainname=%s",
+        dbc.execute("SELECT gid,tid,domaindir FROM domains WHERE domainname=%s",
                 self._name)
         result = dbc.fetchone()
         dbc.close()
         if result is not None:
-            self._id, self._domaindir = result[0], result[1]
+            self._id, self._domaindir = result[0], result[2]
+            self._transport = Transport(self._dbh, tid=result[1])
             return True
         else:
             return False
@@ -122,8 +124,8 @@
         if self._id < 1:
             self._prepare()
             dbc = self._dbh.cursor()
-            dbc.execute("INSERT INTO domains (gid, domainname, transport,\
- domaindir) VALUES (%s, %s, %s, %s)", self._id, self._name, self._transport,
+            dbc.execute("INSERT INTO domains (gid, domainname, tid, domaindir)\
+ VALUES (%s, %s, %s, %s)", self._id, self._name, self._transport.getID(),
                 self._domaindir)
             self._dbh.commit()
             dbc.close()
@@ -158,9 +160,10 @@
         transport -- the new transport (str)
         """
         if self._id > 0:
+            trsp = Transport(self._dbh, transport=transport)
             dbc = self._dbh.cursor()
-            dbc.execute("UPDATE domains SET transport=%s WHERE gid=%s",
-                    transport, self._id)
+            dbc.execute("UPDATE domains SET tid=%s WHERE gid=%s", trsp.getID(),
+                    self._id)
             if dbc.rowcount > 0:
                 self._dbh.commit()
             dbc.close()
@@ -176,15 +179,20 @@
         """Returns the directory of the domain."""
         return self._domaindir
 
+    def getTransport(self):
+        """Returns domain's transport."""
+        return self._transport.getTransport()
+
+    def getTransportID(self):
+        """Returns the ID from the domain's transport."""
+        return self._transport.getID()
+
     def getInfo(self):
         """Returns a dictionary with information about the domain."""
         sql = """\
-SELECT gid, domainname, transport, domaindir, count(uid) AS accounts, aliases
-  FROM domains
-       LEFT JOIN users USING (gid)
-       LEFT JOIN vmm_alias_count USING (gid)
- WHERE gid = %i
-GROUP BY gid, domainname, transport, domaindir, aliases""" % self._id
+SELECT gid, domainname, transport, domaindir, accounts, aliases
+  FROM vmm_domain_info
+ WHERE gid = %i""" % self._id
         dbc = self._dbh.cursor()
         dbc.execute(sql)
         info = dbc.fetchone()
--- a/VirtualMailManager/MailLocation.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/MailLocation.py	Sun Mar 02 20:22:00 2008 +0000
@@ -36,7 +36,7 @@
                 ERR.MAILLOCATION_INIT))
         elif mid is not None:
             try:
-                self.__id = long(tid)
+                self.__id = long(mid)
             except ValueError:
                 raise MLE(('mid must be an int/long.', ERR.MAILLOCATION_INIT))
             self._loadByID()
--- a/VirtualMailManager/VirtualMailManager.py	Sat Feb 02 19:48:17 2008 +0000
+++ b/VirtualMailManager/VirtualMailManager.py	Sun Mar 02 20:22:00 2008 +0000
@@ -192,8 +192,7 @@
         self.__dbConnect()
         if not password is None:
             password = self.__pwhash(password)
-        return Account(self.__dbh, self.__Cfg.get('maildir', 'base'), address,
-                password)
+        return Account(self.__dbh, address, password)
 
     def __getAlias(self, address, destination=None):
         address = self.__chkEmailAddress(address)
@@ -203,11 +202,12 @@
             else:
                 destination = self.__chkLocalpart(destination)
         self.__dbConnect()
-        return Alias(self.__dbh, address, self.__Cfg.get('maildir', 'base'),
-                destination)
+        return Alias(self.__dbh, address, destination)
 
     def __getDomain(self, domainname, transport=None):
         domainname = self.__chkDomainname(domainname)
+        if transport is None:
+            transport = self.__Cfg.get('misc', 'transport')
         self.__dbConnect()
         return Domain(self.__dbh, domainname,
                 self.__Cfg.get('maildir', 'base'), transport)
@@ -422,7 +422,7 @@
         acc = self.__getAccount(emailaddress)
         info = acc.getInfo()
         if self.__Cfg.getboolean('maildir', 'diskusage') or diskusage:
-            info['disk usage'] = self.__getDiskUsage('%(home)s/%(mail)s' % info)
+            info['disk usage'] = self.__getDiskUsage('%(maildir)s' % info)
         return info
 
     def user_password(self, emailaddress, password):
--- a/create_tables.pgsql	Sat Feb 02 19:48:17 2008 +0000
+++ b/create_tables.pgsql	Sun Mar 02 20:22:00 2008 +0000
@@ -134,3 +134,12 @@
     SELECT count(DISTINCT address) AS aliases, gid
       FROM alias 
   GROUP BY gid;
+
+CREATE OR REPLACE VIEW vmm_domain_info AS
+    SELECT gid, domainname, transport, domaindir, count(uid) AS accounts,
+           aliases
+      FROM domains
+           LEFT JOIN transport USING (tid)
+           LEFT JOIN users USING (gid)
+           LEFT JOIN vmm_alias_count USING (gid)
+  GROUP BY gid, domainname, transport, domaindir, aliases;
--- a/vmm.cfg	Sat Feb 02 19:48:17 2008 +0000
+++ b/vmm.cfg	Sun Mar 02 20:22:00 2008 +0000
@@ -22,7 +22,7 @@
 [maildir]
 ; The base directory for all domains/accounts (String)
 base = /home/mail
-; name of the  Maildir folder
+; default name of the  Maildir folder
 folder = Maildir
 ; Permissions for maildirs (Int)
 ; octal 0700 -> decimal 448
@@ -61,6 +61,8 @@
 gid_mail = 8
 ; force deletion of accounts and aliases (Boolean)
 forcedel = false
+; default transport for domains and accounts
+transport = dovecot:
 
 #
 # Configuration state