VirtualMailManager/domain.py
branchv0.6.x
changeset 441 1af5fe0683ce
parent 417 8209da83e256
child 447 c31d604e26d3
equal deleted inserted replaced
440:1a08fe35b496 441:1af5fe0683ce
    16      ACCOUNT_AND_ALIAS_PRESENT, DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, \
    16      ACCOUNT_AND_ALIAS_PRESENT, DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, \
    17      DOMAIN_INVALID, DOMAIN_TOO_LONG, NO_SUCH_DOMAIN, VMM_ERROR
    17      DOMAIN_INVALID, DOMAIN_TOO_LONG, NO_SUCH_DOMAIN, VMM_ERROR
    18 from VirtualMailManager.errors import VMMError, DomainError as DomErr
    18 from VirtualMailManager.errors import VMMError, DomainError as DomErr
    19 from VirtualMailManager.pycompat import all, any
    19 from VirtualMailManager.pycompat import all, any
    20 from VirtualMailManager.quotalimit import QuotaLimit
    20 from VirtualMailManager.quotalimit import QuotaLimit
       
    21 from VirtualMailManager.serviceset import ServiceSet
    21 from VirtualMailManager.transport import Transport
    22 from VirtualMailManager.transport import Transport
    22 
    23 
    23 
    24 
    24 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'
    25 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'
    25 RE_DOMAIN = re.compile(r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$")
    26 RE_DOMAIN = re.compile(r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$")
    27 cfg_dget = lambda option: None
    28 cfg_dget = lambda option: None
    28 
    29 
    29 
    30 
    30 class Domain(object):
    31 class Domain(object):
    31     """Class to manage e-mail domains."""
    32     """Class to manage e-mail domains."""
    32     __slots__ = ('_directory', '_gid', '_name', '_qlimit', '_transport',
    33     __slots__ = ('_directory', '_gid', '_name', '_qlimit', '_services',
    33                  '_dbh', '_new')
    34                  '_transport', '_dbh', '_new')
    34 
    35 
    35     def __init__(self, dbh, domainname):
    36     def __init__(self, dbh, domainname):
    36         """Creates a new Domain instance.
    37         """Creates a new Domain instance.
    37 
    38 
    38         Loads all relevant data from the database, if the domain could be
    39         Loads all relevant data from the database, if the domain could be
    51         """
    52         """
    52         self._name = check_domainname(domainname)
    53         self._name = check_domainname(domainname)
    53         self._dbh = dbh
    54         self._dbh = dbh
    54         self._gid = 0
    55         self._gid = 0
    55         self._qlimit = None
    56         self._qlimit = None
       
    57         self._services = None
    56         self._transport = None
    58         self._transport = None
    57         self._directory = None
    59         self._directory = None
    58         self._new = True
    60         self._new = True
    59         self._load()
    61         self._load()
    60 
    62 
    64 
    66 
    65         Raises a DomainError if Domain._name isn't the primary name of the
    67         Raises a DomainError if Domain._name isn't the primary name of the
    66         domain.
    68         domain.
    67         """
    69         """
    68         dbc = self._dbh.cursor()
    70         dbc = self._dbh.cursor()
    69         dbc.execute('SELECT dd.gid, qid, tid, domaindir, is_primary FROM '
    71         dbc.execute('SELECT dd.gid, qid, ssid, tid, domaindir, is_primary '
    70                     'domain_data dd, domain_name dn WHERE domainname = %s AND '
    72                     'FROM domain_data dd, domain_name dn WHERE domainname = '
    71                     'dn.gid = dd.gid', (self._name,))
    73                     '%s AND dn.gid = dd.gid', (self._name,))
    72         result = dbc.fetchone()
    74         result = dbc.fetchone()
    73         dbc.close()
    75         dbc.close()
    74         if result:
    76         if result:
    75             if not result[4]:
    77             if not result[5]:
    76                 raise DomErr(_(u"The domain '%s' is an alias domain.") %
    78                 raise DomErr(_(u"The domain '%s' is an alias domain.") %
    77                              self._name, DOMAIN_ALIAS_EXISTS)
    79                              self._name, DOMAIN_ALIAS_EXISTS)
    78             self._gid, self._directory = result[0], result[3]
    80             self._gid, self._directory = result[0], result[4]
    79             self._qlimit = QuotaLimit(self._dbh, qid=result[1])
    81             self._qlimit = QuotaLimit(self._dbh, qid=result[1])
    80             self._transport = Transport(self._dbh, tid=result[2])
    82             self._services = ServiceSet(self._dbh, ssid=result[2])
       
    83             self._transport = Transport(self._dbh, tid=result[3])
    81             self._new = False
    84             self._new = False
    82 
    85 
    83     def _set_gid(self):
    86     def _set_gid(self):
    84         """Sets the ID of the domain - if not set yet."""
    87         """Sets the ID of the domain - if not set yet."""
    85         assert self._gid == 0
    88         assert self._gid == 0
   120         updated.
   123         updated.
   121 
   124 
   122         Arguments:
   125         Arguments:
   123 
   126 
   124         `column` : basestring
   127         `column` : basestring
   125           Name of the table column. Currently: qid and tid
   128           Name of the table column. Currently: qid, ssid and tid
   126         `value` : long
   129         `value` : long
   127           The referenced key
   130           The referenced key
   128         `force` : bool
   131         `force` : bool
   129           enforce the new setting also for existing users. Default: `False`
   132           enforce the new setting also for existing users. Default: `False`
   130         """
   133         """
   131         if column not in ('qid', 'tid'):
   134         if column not in ('qid', 'ssid', 'tid'):
   132             raise ValueError('Unknown column: %r' % column)
   135             raise ValueError('Unknown column: %r' % column)
   133         dbc = self._dbh.cursor()
   136         dbc = self._dbh.cursor()
   134         dbc.execute('UPDATE domain_data SET %s = %%s WHERE gid = %%s' % column,
   137         dbc.execute('UPDATE domain_data SET %s = %%s WHERE gid = %%s' % column,
   135                     (value, self._gid))
   138                     (value, self._gid))
   136         if dbc.rowcount > 0:
   139         if dbc.rowcount > 0:
   161     def quotalimit(self):
   164     def quotalimit(self):
   162         """The Domain's quota limit."""
   165         """The Domain's quota limit."""
   163         return self._qlimit
   166         return self._qlimit
   164 
   167 
   165     @property
   168     @property
       
   169     def serviceset(self):
       
   170         """The Domain's serviceset."""
       
   171         return self._services
       
   172 
       
   173     @property
   166     def transport(self):
   174     def transport(self):
   167         """The Domain's transport."""
   175         """The Domain's transport."""
   168         return self._transport
   176         return self._transport
   169 
   177 
   170     def set_directory(self, basedir):
   178     def set_directory(self, basedir):
   195             raise DomErr(_(u"The domain '%s' already exists.") % self._name,
   203             raise DomErr(_(u"The domain '%s' already exists.") % self._name,
   196                          DOMAIN_EXISTS)
   204                          DOMAIN_EXISTS)
   197         assert isinstance(quotalimit, QuotaLimit)
   205         assert isinstance(quotalimit, QuotaLimit)
   198         self._qlimit = quotalimit
   206         self._qlimit = quotalimit
   199 
   207 
       
   208     def set_serviceset(self, serviceset):
       
   209         """Set the services for the new Domain.
       
   210 
       
   211         Argument:
       
   212 
       
   213        `serviceset` : VirtualMailManager.serviceset.ServiceSet
       
   214          The service set for the new Domain.
       
   215         """
       
   216         if not self._new:
       
   217             raise DomErr(_(u"The domain '%s' already exists.") % self._name,
       
   218                          DOMAIN_EXISTS)
       
   219         assert isinstance(serviceset, ServiceSet)
       
   220         self._services = serviceset
       
   221 
   200     def set_transport(self, transport):
   222     def set_transport(self, transport):
   201         """Set the transport for the new Domain.
   223         """Set the transport for the new Domain.
   202 
   224 
   203         Argument:
   225         Argument:
   204 
   226 
   214     def save(self):
   236     def save(self):
   215         """Stores the new domain in the database."""
   237         """Stores the new domain in the database."""
   216         if not self._new:
   238         if not self._new:
   217             raise DomErr(_(u"The domain '%s' already exists.") % self._name,
   239             raise DomErr(_(u"The domain '%s' already exists.") % self._name,
   218                          DOMAIN_EXISTS)
   240                          DOMAIN_EXISTS)
   219         assert all((self._directory, self._qlimit, self._transport))
   241         assert all((self._directory, self._qlimit, self._services,
   220         dbc = self._dbh.cursor()
   242                     self._transport))
   221         dbc.execute('INSERT INTO domain_data (gid, qid, tid, domaindir) '
   243         dbc = self._dbh.cursor()
   222                     'VALUES (%s, %s, %s, %s)', (self._gid, self._qlimit.qid,
   244         dbc.execute('INSERT INTO domain_data (gid, qid, ssid, tid, domaindir) '
   223                     self._transport.tid, self._directory))
   245                     'VALUES (%s, %s, %s, %s, %s)', (self._gid,
       
   246                     self._qlimit.qid, self._services.ssid, self._transport.tid,
       
   247                     self._directory))
   224         dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary) '
   248         dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary) '
   225                     'VALUES (%s, %s, TRUE)', (self._name, self._gid))
   249                     'VALUES (%s, %s, TRUE)', (self._name, self._gid))
   226         self._dbh.commit()
   250         self._dbh.commit()
   227         dbc.close()
   251         dbc.close()
   228         self._new = False
   252         self._new = False
   249             dbc.execute("DELETE FROM %s WHERE gid = %u" % (tbl, self._gid))
   273             dbc.execute("DELETE FROM %s WHERE gid = %u" % (tbl, self._gid))
   250         self._dbh.commit()
   274         self._dbh.commit()
   251         dbc.close()
   275         dbc.close()
   252         self._gid = 0
   276         self._gid = 0
   253         self._directory = self._qlimit = self._transport = None
   277         self._directory = self._qlimit = self._transport = None
       
   278         self._services = None
   254         self._new = True
   279         self._new = True
   255 
   280 
   256     def update_quotalimit(self, quotalimit, force=False):
   281     def update_quotalimit(self, quotalimit, force=False):
   257         """Update the quota limit of the Domain.
   282         """Update the quota limit of the Domain.
   258 
   283 
   274         assert isinstance(quotalimit, QuotaLimit)
   299         assert isinstance(quotalimit, QuotaLimit)
   275         if not force and quotalimit == self._qlimit:
   300         if not force and quotalimit == self._qlimit:
   276             return
   301             return
   277         self._update_tables('qid', quotalimit.qid, force)
   302         self._update_tables('qid', quotalimit.qid, force)
   278         self._qlimit = quotalimit
   303         self._qlimit = quotalimit
       
   304 
       
   305     def update_serviceset(self, serviceset, force=False):
       
   306         """Assign a different set of services to the Domain,
       
   307 
       
   308         If *force* is `True` the *serviceset* will be also assigned to
       
   309         all existing accounts of the Domain.  Otherwise the *serviceset*
       
   310         will be only the 'default' for accounts created from now on.
       
   311 
       
   312         Arguments:
       
   313         `serviceset` : VirtualMailManager.serviceset.ServiceSet
       
   314           the new set of services
       
   315         `force`
       
   316           enforce the serviceset for all accounts, default `False`
       
   317         """
       
   318         self._chk_state()
       
   319         assert isinstance(serviceset, ServiceSet)
       
   320         if not force and serviceset == self._services:
       
   321             return
       
   322         self._update_tables('ssid', serviceset.ssid, force)
       
   323         self._services = serviceset
   279 
   324 
   280     def update_transport(self, transport, force=False):
   325     def update_transport(self, transport, force=False):
   281         """Sets a new transport for the Domain.
   326         """Sets a new transport for the Domain.
   282 
   327 
   283         If *force* is `True` the new *transport* will be assigned to all
   328         If *force* is `True` the new *transport* will be assigned to all