====
[plcapi.git] / PLC / Persons.py
index f4346ce..8cd2856 100644 (file)
@@ -4,9 +4,6 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
-# $URL$
-#
 
 from types import StringTypes
 try:
 
 from types import StringTypes
 try:
@@ -19,7 +16,6 @@ import re
 import crypt
 
 from PLC.Faults import *
 import crypt
 
 from PLC.Faults import *
-from PLC.Debug import log
 from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Table import Row, Table
 from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Table import Row, Table
@@ -81,7 +77,7 @@ class Person(Row):
         Validate email address. Stolen from Mailman.
         """
         email = email.lower()
         Validate email address. Stolen from Mailman.
         """
         email = email.lower()
-        invalid_email = PLCInvalidArgument("Invalid e-mail address")
+        invalid_email = PLCInvalidArgument("Invalid e-mail address %s"%email)
 
         if not email:
             raise invalid_email
 
         if not email:
             raise invalid_email
@@ -146,8 +142,8 @@ class Person(Row):
 
         if 'pi' in self['roles']:
             if set(self['site_ids']).intersection(person['site_ids']):
 
         if 'pi' in self['roles']:
             if set(self['site_ids']).intersection(person['site_ids']):
-                # Can update person is neither a PI or ADMIN
-                return (not (('pi' in person['roles']) or ('admin' in person['roles'])))
+                # non-admin users cannot update a person who is neither a PI or ADMIN
+                return (not set(['pi','admin']).intersection(person['roles']))
 
         return False
 
 
         return False
 
@@ -158,7 +154,7 @@ class Person(Row):
 
         1. We are the person.
         2. We are an admin.
 
         1. We are the person.
         2. We are an admin.
-        3. We are a PI and the person is at one of our sites.
+        3. We are a PI or Tech and the person is at one of our sites.
         """
 
         assert isinstance(person, Person)
         """
 
         assert isinstance(person, Person)
@@ -166,10 +162,10 @@ class Person(Row):
         if self.can_update(person):
             return True
 
         if self.can_update(person):
             return True
 
-        if 'pi' in self['roles']:
+        # pis and techs can see all people on their site
+        if set(['pi','tech']).intersection(self['roles']):
             if set(self['site_ids']).intersection(person['site_ids']):
             if set(self['site_ids']).intersection(person['site_ids']):
-                # Can view people with equal or higher role IDs
-                return 'admin' not in person['roles']
+                return True
 
         return False
 
 
         return False
 
@@ -362,7 +358,14 @@ class Person(Row):
 
         # Mark as deleted
         self['deleted'] = True
 
         # Mark as deleted
         self['deleted'] = True
-        self.sync(commit)
+
+        # delete will fail if timestamp fields aren't validated, so lets remove them
+        for field in ['verification_expires', 'date_created', 'last_updated']:
+            if field in self:
+                self.pop(field)
+
+        # don't validate, so duplicates can be consistently removed
+        self.sync(commit, validate=False)
 
 class Persons(Table):
     """
 
 class Persons(Table):
     """
@@ -389,13 +392,14 @@ class Persons(Table):
                 person_filter = Filter(Person.fields, {'person_id': ints, 'email': strs})
                 sql += " AND (%s) %s" % person_filter.sql(api, "OR")
             elif isinstance(person_filter, dict):
                 person_filter = Filter(Person.fields, {'person_id': ints, 'email': strs})
                 sql += " AND (%s) %s" % person_filter.sql(api, "OR")
             elif isinstance(person_filter, dict):
-                person_filter = Filter(Person.fields, person_filter)
+                allowed_fields=dict(Person.fields.items()+Person.tags.items())
+                person_filter = Filter(allowed_fields, person_filter)
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
             elif isinstance (person_filter, StringTypes):
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
             elif isinstance (person_filter, StringTypes):
-                person_filter = Filter(Person.fields, {'email':[person_filter]})
+                person_filter = Filter(Person.fields, {'email':person_filter})
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
-            elif isinstance (person_filter, int):
-                person_filter = Filter(Person.fields, {'person_id':[person_filter]})
+            elif isinstance (person_filter, (int, long)):
+                person_filter = Filter(Person.fields, {'person_id':person_filter})
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong person filter %r"%person_filter
                 sql += " AND (%s) %s" % person_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong person filter %r"%person_filter