- changed gpg_verify() calling convention
[plcapi.git] / PLC / Persons.py
index 822a27f..ff1b6cb 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: Persons.py,v 1.20 2006/11/24 12:06:00 thierry Exp $
+# $Id: Persons.py,v 1.32 2007/01/11 05:37:55 mlhuang Exp $
 #
 
 from types import StringTypes
@@ -16,11 +16,13 @@ import re
 import crypt
 
 from PLC.Faults import *
+from PLC.Debug import log
 from PLC.Parameter import Parameter
 from PLC.Filter import Filter
 from PLC.Table import Row, Table
+from PLC.Roles import Role, Roles
 from PLC.Keys import Key, Keys
-import PLC.Sites
+from PLC.Messages import Message, Messages
 
 class Person(Row):
     """
@@ -31,9 +33,9 @@ class Person(Row):
 
     table_name = 'persons'
     primary_key = 'person_id'
-    join_tables = ['person_role', 'person_site', 'slice_person', 'person_session']
+    join_tables = ['person_key', 'person_role', 'person_site', 'slice_person', 'person_session', 'peer_person']
     fields = {
-        'person_id': Parameter(int, "Account identifier"),
+        'person_id': Parameter(int, "User identifier"),
         'first_name': Parameter(str, "Given name", max = 128),
         'last_name': Parameter(str, "Surname", max = 128),
         'title': Parameter(str, "Title", max = 128, nullok = True),
@@ -43,31 +45,32 @@ class Person(Row):
         'bio': Parameter(str, "Biography", max = 254, nullok = True),
         'enabled': Parameter(bool, "Has been enabled"),
         'password': Parameter(str, "Account password in crypt() form", max = 254),
-        'last_updated': Parameter(int, "Date and time of last update", ro = True),
+        'verification_key': Parameter(str, "Reset password key", max = 254, nullok = True),
+       'verification_expires': Parameter(int, "Date and time when verification_key expires", nullok = True),
+       'last_updated': Parameter(int, "Date and time of last update", ro = True),
         'date_created': Parameter(int, "Date and time when account was created", ro = True),
         'role_ids': Parameter([int], "List of role identifiers"),
         'roles': Parameter([str], "List of roles"),
         'site_ids': Parameter([int], "List of site identifiers"),
         'key_ids': Parameter([int], "List of key identifiers"),
         'slice_ids': Parameter([int], "List of slice identifiers"),
-        'peer_id': Parameter(int, "Peer at which this slice was created", nullok = True),
+        'peer_id': Parameter(int, "Peer to which this user belongs", nullok = True),
+        'peer_person_id': Parameter(int, "Foreign user identifier at peer", nullok = True),
         }
 
     # for Cache
     class_key = 'email'
     foreign_fields = ['first_name', 'last_name', 'title', 'email', 'phone', 'url',
-                     'bio', 'enabled', 'password', 'last_updated', 'date_created']
-    #foreign_xrefs = { 'Node' : { 'field' : 'node_ids' ,
-    #                 'table': 'slice_node' } }
-    foreign_xrefs = {
-       'Key' : { 'field' : 'key_ids', 'table' : 'person_key' } ,
-       'Site' : { 'field' : 'site_ids', 'table' : 'person_site'},
-#        'key_ids': Parameter([int], "List of key identifiers"),
+                     'bio', 'enabled', 'password', ]
+    # forget about these ones, they are read-only anyway
+    # handling them causes Cache to re-sync all over again 
+    # 'last_updated', 'date_created'
+    foreign_xrefs = [
+        {'field' : 'key_ids',  'class': 'Key',  'table' : 'person_key' } ,
+        {'field' : 'site_ids', 'class': 'Site', 'table' : 'person_site'},
+#       xxx this is not handled by Cache yet
 #        'role_ids': Parameter([int], "List of role identifiers"),
-#        'roles': Parameter([str], "List of roles"),
-#        'site_ids': Parameter([int], "List of site identifiers"),
-#        'slice_ids': Parameter([int], "List of slice identifiers"),
-}
+]
 
     def validate_email(self, email):
         """
@@ -91,7 +94,7 @@ class Person(Row):
         rest = email[at_sign+1:]
         domain = rest.split('.')
 
-        # This means local, unqualified addresses, are no allowed
+        # This means local, unqualified addresses, are not allowed
         if not domain:
             raise invalid_email
         if len(domain) < 2:
@@ -121,6 +124,10 @@ class Person(Row):
             salt = md5.md5(salt).hexdigest()[:8] 
             return crypt.crypt(password.encode(self.api.encoding), magic + salt + "$")
 
+    validate_date_created = Row.validate_timestamp
+    validate_last_updated = Row.validate_timestamp
+    validate_verification_expires = Row.validate_timestamp
+
     def can_update(self, person):
         """
         Returns true if we can update the specified person. We can
@@ -169,97 +176,18 @@ class Person(Row):
 
         return False
 
-    def add_role(self, role_id, commit = True):
-        """
-        Add role to existing account.
-        """
-
-        assert 'person_id' in self
-
-        person_id = self['person_id']
-
-        if role_id not in self['role_ids']:
-            self.api.db.do("INSERT INTO person_role (person_id, role_id)" \
-                           " VALUES(%(person_id)d, %(role_id)d)",
-                           locals())
-
-            if commit:
-                self.api.db.commit()
-
-            self['role_ids'].append(role_id)
-
-    def remove_role(self, role_id, commit = True):
-        """
-        Remove role from existing account.
-        """
-
-        assert 'person_id' in self
-
-        person_id = self['person_id']
-
-        if role_id in self['role_ids']:
-            self.api.db.do("DELETE FROM person_role" \
-                           " WHERE person_id = %(person_id)d" \
-                           " AND role_id = %(role_id)d",
-                           locals())
-
-            if commit:
-                self.api.db.commit()
-
-            self['role_ids'].remove(role_id)
-    def add_key(self, key, commit = True):
-        """
-        Add key to existing account.
-        """
-
-        assert 'person_id' in self
-        assert isinstance(key, Key)
-        assert 'key_id' in key
-
-        person_id = self['person_id']
-        key_id = key['key_id']
-
-        if key_id not in self['key_ids']:
-            self.api.db.do("INSERT INTO person_key (person_id, key_id)" \
-                           " VALUES(%(person_id)d, %(key_id)d)",
-                           locals())
-
-            if commit:
-                self.api.db.commit()
-
-            self['key_ids'].append(key_id)
-
-    def remove_key(self, key, commit = True):
-        """
-        Remove key from existing account.
-        """
-
-        assert 'person_id' in self
-        assert isinstance(key, Key)
-        assert 'key_id' in key
-
-        person_id = self['person_id']
-        key_id = key['key_id']
-
-        if key_id in self['key_ids']:
-            self.api.db.do("DELETE FROM person_key" \
-                           " WHERE person_id = %(person_id)d" \
-                           " AND key_id = %(key_id)d",
-                           locals())
-
-            if commit:
-                self.api.db.commit()
+    add_role = Row.add_object(Role, 'person_role')
+    remove_role = Row.remove_object(Role, 'person_role')
 
-            self['key_ids'].remove(key_id)
+    add_key = Row.add_object(Key, 'person_key')
+    remove_key = Row.remove_object(Key, 'person_key')
 
     def set_primary_site(self, site, commit = True):
         """
-        Set the primary site for an existing account.
+        Set the primary site for an existing user.
         """
 
         assert 'person_id' in self
-        assert isinstance(site, PLC.Sites.Site)
         assert 'site_id' in site
 
         person_id = self['person_id']
@@ -284,7 +212,7 @@ class Person(Row):
 
     def delete(self, commit = True):
         """
-        Delete existing account.
+        Delete existing user.
         """
 
         # Delete all keys