VirtualMailManager/account.py
branchv0.6.x
changeset 539 5806fb74130b
parent 532 2bb40aaef94e
child 543 1b3bdce0bf87
equal deleted inserted replaced
538:1f9ea5658627 539:5806fb74130b
    30 
    30 
    31 
    31 
    32 class Account(object):
    32 class Account(object):
    33     """Class to manage e-mail accounts."""
    33     """Class to manage e-mail accounts."""
    34     __slots__ = ('_addr', '_dbh', '_domain', '_mail', '_new', '_passwd',
    34     __slots__ = ('_addr', '_dbh', '_domain', '_mail', '_new', '_passwd',
    35                  '_qlimit', '_services', '_transport', '_uid')
    35                  '_qlimit', '_services', '_transport', '_note', '_uid')
    36 
    36 
    37     def __init__(self, dbh, address):
    37     def __init__(self, dbh, address):
    38         """Creates a new Account instance.
    38         """Creates a new Account instance.
    39 
    39 
    40         When an account with the given *address* could be found in the
    40         When an account with the given *address* could be found in the
    61         self._uid = 0
    61         self._uid = 0
    62         self._mail = None
    62         self._mail = None
    63         self._qlimit = None
    63         self._qlimit = None
    64         self._services = None
    64         self._services = None
    65         self._transport = None
    65         self._transport = None
       
    66         self._note = None
    66         self._passwd = None
    67         self._passwd = None
    67         self._new = True
    68         self._new = True
    68         self._load()
    69         self._load()
    69 
    70 
    70     def __nonzero__(self):
    71     def __nonzero__(self):
    71         """Returns `True` if the Account is known, `False` if it's new."""
    72         """Returns `True` if the Account is known, `False` if it's new."""
    72         return not self._new
    73         return not self._new
    73 
    74 
    74     def _load(self):
    75     def _load(self):
    75         """Load 'uid', 'mid', 'qid', 'ssid'  and 'tid' from the database and
    76         """Load 'uid', 'mid', 'qid', 'ssid', 'tid' and 'note' from the
    76         set _new to `False` - if the user could be found. """
    77         database and set _new to `False` - if the user could be found. """
    77         dbc = self._dbh.cursor()
    78         dbc = self._dbh.cursor()
    78         dbc.execute('SELECT uid, mid, qid, ssid, tid FROM users WHERE gid = '
    79         dbc.execute('SELECT uid, mid, qid, ssid, tid, note FROM users '
    79                     '%s AND local_part = %s', (self._domain.gid,
    80                     'WHERE gid = %s AND local_part = %s',
    80                                                self._addr.localpart))
    81                     (self._domain.gid, self._addr.localpart))
    81         result = dbc.fetchone()
    82         result = dbc.fetchone()
    82         dbc.close()
    83         dbc.close()
    83         if result:
    84         if result:
    84             self._uid, _mid, _qid, _ssid, _tid = result
    85             self._uid, _mid, _qid, _ssid, _tid, _note = result
    85 
    86 
    86             def load_helper(ctor, own, field, dbresult):
    87             def load_helper(ctor, own, field, dbresult):
    87                 cur = None if own is None else getattr(own, field)
    88                 cur = None if own is None else getattr(own, field)
    88                 if cur != dbresult:
    89                 if cur != dbresult:
    89                     kwargs = { field : dbresult }
    90                     kwargs = { field : dbresult }
    94             self._services = load_helper(ServiceSet, self._services, 'ssid',
    95             self._services = load_helper(ServiceSet, self._services, 'ssid',
    95                                          _ssid)
    96                                          _ssid)
    96             self._transport = load_helper(Transport, self._transport, 'tid',
    97             self._transport = load_helper(Transport, self._transport, 'tid',
    97                                           _tid)
    98                                           _tid)
    98             self._mail = MailLocation(self._dbh, mid=_mid)
    99             self._mail = MailLocation(self._dbh, mid=_mid)
       
   100             self._note = _note
    99             self._new = False
   101             self._new = False
   100 
   102 
   101     def _set_uid(self):
   103     def _set_uid(self):
   102         """Set the unique ID for the new Account."""
   104         """Set the unique ID for the new Account."""
   103         assert self._uid == 0
   105         assert self._uid == 0
   191     def mail_location(self):
   193     def mail_location(self):
   192         """The Account's MailLocation."""
   194         """The Account's MailLocation."""
   193         return self._mail
   195         return self._mail
   194 
   196 
   195     @property
   197     @property
       
   198     def note(self):
       
   199         """The Account's note."""
       
   200         return self._note
       
   201 
       
   202     @property
   196     def uid(self):
   203     def uid(self):
   197         """The Account's unique ID."""
   204         """The Account's unique ID."""
   198         return self._uid
   205         return self._uid
   199 
   206 
   200     def set_password(self, password):
   207     def set_password(self, password):
   213                        ACCOUNT_EXISTS)
   220                        ACCOUNT_EXISTS)
   214         if not isinstance(password, basestring) or not password:
   221         if not isinstance(password, basestring) or not password:
   215             raise AErr(_(u"Could not accept password: '%s'") % password,
   222             raise AErr(_(u"Could not accept password: '%s'") % password,
   216                        ACCOUNT_MISSING_PASSWORD)
   223                        ACCOUNT_MISSING_PASSWORD)
   217         self._passwd = password
   224         self._passwd = password
       
   225 
       
   226     def set_note(self, note):
       
   227         """Set the account's (optional) note.
       
   228 
       
   229         Argument:
       
   230 
       
   231         `note` : basestring or None
       
   232           The note, or None to remove
       
   233         """
       
   234         assert note is None or isinstance(note, basestring)
       
   235         self._note = note
   218 
   236 
   219     def save(self):
   237     def save(self):
   220         """Save the new Account in the database."""
   238         """Save the new Account in the database."""
   221         if not self._new:
   239         if not self._new:
   222             raise AErr(_(u"The account '%s' already exists.") % self._addr,
   240             raise AErr(_(u"The account '%s' already exists.") % self._addr,
   226                        ACCOUNT_MISSING_PASSWORD)
   244                        ACCOUNT_MISSING_PASSWORD)
   227         self._prepare(MailLocation(self._dbh, mbfmt=cfg_dget('mailbox.format'),
   245         self._prepare(MailLocation(self._dbh, mbfmt=cfg_dget('mailbox.format'),
   228                                    directory=cfg_dget('mailbox.root')))
   246                                    directory=cfg_dget('mailbox.root')))
   229         dbc = self._dbh.cursor()
   247         dbc = self._dbh.cursor()
   230         dbc.execute('INSERT INTO users (local_part, passwd, uid, gid, mid, '
   248         dbc.execute('INSERT INTO users (local_part, passwd, uid, gid, mid, '
   231                     'qid, ssid, tid) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
   249                     'qid, ssid, tid, note) '
       
   250                     'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)',
   232                     (self._addr.localpart,
   251                     (self._addr.localpart,
   233                      pwhash(self._passwd, user=self._addr), self._uid,
   252                      pwhash(self._passwd, user=self._addr), self._uid,
   234                      self._domain.gid, self._mail.mid,
   253                      self._domain.gid, self._mail.mid,
   235                      self._qlimit.qid if self._qlimit else None,
   254                      self._qlimit.qid if self._qlimit else None,
   236                      self._services.ssid if self._services else None,
   255                      self._services.ssid if self._services else None,
   237                      self._transport.tid if self._transport else None))
   256                      self._transport.tid if self._transport else None,
       
   257                      self._note))
   238         self._dbh.commit()
   258         self._dbh.commit()
   239         dbc.close()
   259         dbc.close()
   240         self._new = False
   260         self._new = False
   241 
   261 
   242     def modify(self, field, value):
   262     def modify(self, field, value):
   243         """Update the Account's *field* to the new *value*.
   263         """Update the Account's *field* to the new *value*.
   244 
   264 
   245         Possible values for *field* are: 'name', 'password'.
   265         Possible values for *field* are: 'name', 'password', 'note'.
   246 
   266 
   247         Arguments:
   267         Arguments:
   248 
   268 
   249         `field` : basestring
   269         `field` : basestring
   250           The attribute name: 'name' or 'password'
   270           The attribute name: 'name', 'password' or 'note'
   251         `value` : basestring
   271         `value` : basestring
   252           The new value of the attribute.
   272           The new value of the attribute.
   253         """
   273         """
   254         if field not in ('name', 'password'):
   274         if field not in ('name', 'password', 'note'):
   255             raise AErr(_(u"Unknown field: '%s'") % field, INVALID_ARGUMENT)
   275             raise AErr(_(u"Unknown field: '%s'") % field, INVALID_ARGUMENT)
   256         self._chk_state()
   276         self._chk_state()
   257         dbc = self._dbh.cursor()
   277         dbc = self._dbh.cursor()
   258         if field == 'password':
   278         if field == 'password':
   259             dbc.execute('UPDATE users SET passwd = %s WHERE uid = %s',
   279             dbc.execute('UPDATE users SET passwd = %s WHERE uid = %s',
   260                         (pwhash(value, user=self._addr), self._uid))
   280                         (pwhash(value, user=self._addr), self._uid))
   261         else:
   281         else:
   262             dbc.execute('UPDATE users SET name = %s WHERE uid = %s',
   282             dbc.execute('UPDATE users SET %s = %%s WHERE uid = %%s' % field,
   263                         (value, self._uid))
   283                         (value, self._uid))
   264         if dbc.rowcount > 0:
   284         if dbc.rowcount > 0:
   265             self._dbh.commit()
   285             self._dbh.commit()
   266         dbc.close()
   286         dbc.close()
   267 
   287 
   375             else:
   395             else:
   376                 info['ql_bytes'] = self._domain.quotalimit.bytes
   396                 info['ql_bytes'] = self._domain.quotalimit.bytes
   377                 info['ql_messages'] = self._domain.quotalimit.messages
   397                 info['ql_messages'] = self._domain.quotalimit.messages
   378                 info['ql_domaindefault'] = True
   398                 info['ql_domaindefault'] = True
   379             info['transport'] = self._get_info_transport()
   399             info['transport'] = self._get_info_transport()
       
   400             info['note'] = self._note
   380             info['uid'] = self._uid
   401             info['uid'] = self._uid
   381             return info
   402             return info
   382         # nearly impossibleā€½
   403         # nearly impossibleā€½
   383         raise AErr(_(u"Could not fetch information for account: '%s'") %
   404         raise AErr(_(u"Could not fetch information for account: '%s'") %
   384                    self._addr, NO_SUCH_ACCOUNT)
   405                    self._addr, NO_SUCH_ACCOUNT)