2 # Functions for interacting with the persons table in the database
5 from types import StringTypes
7 from hashlib import md5
11 from random import Random
15 from PLC.Faults import *
16 from PLC.Debug import log
17 from PLC.Parameter import Parameter, Mixed
18 from PLC.Table import Row, Table
19 from PLC.Roles import Role, Roles
20 from PLC.Keys import Key, Keys
21 from PLC.Messages import Message, Messages
22 from PLC.NovaTable import NovaObject, NovaTable
24 class Person(NovaObject):
26 Representation of a row in the persons table. To use, optionally
27 instantiate with a dict of values. Update as you would a
28 dict. Commit to the database with sync().
32 'id': Parameter(str, "User identifier"),
33 'name': Parameter(str, "Given name", max = 128),
34 'email': Parameter(str, "Primary e-mail address", max = 254),
35 'enabled': Parameter(bool, "Has been enabled"),
36 'password': Parameter(str, "Account password in crypt() form", max = 254),
37 'last_updated': Parameter(int, "Date and time of last update", ro = True),
38 'date_created': Parameter(int, "Date and time when account was created", ro = True),
39 'roles': Parameter([str], "List of roles"),
40 'site_ids': Parameter([int], "List of site identifiers"),
41 'key_ids': Parameter([int], "List of key identifiers"),
42 'slice_ids': Parameter([int], "List of slice identifiers"),
45 def validate_email(self, email):
47 Validate email address. Stolen from Mailman.
50 invalid_email = PLCInvalidArgument("Invalid e-mail address")
55 email_re = re.compile('\A[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9._\-]+\.[a-zA-Z]+\Z')
56 if not email_re.match(email):
61 def can_update(self, person):
63 Returns true if we can update the specified person. We can
68 3. We are a PI and the person is a user or tech or at
72 assert isinstance(person, Person)
74 if self['person_id'] == person['person_id']:
77 if 'admin' in self['roles']:
80 if 'pi' in self['roles']:
81 if set(self['site_ids']).intersection(person['site_ids']):
82 # non-admin users cannot update a person who is neither a PI or ADMIN
83 return (not set(['pi','admin']).intersection(person['roles']))
87 def can_view(self, person):
89 Returns true if we can view the specified person. We can
94 3. We are a PI or Tech and the person is at one of our sites.
97 assert isinstance(person, Person)
99 if self.can_update(person):
102 # pis and techs can see all people on their site
103 if set(['pi','tech']).intersection(self['roles']):
104 if set(self['site_ids']).intersection(person['site_ids']):
109 add_role = Row.add_object(Role, 'person_role')
110 remove_role = Row.remove_object(Role, 'person_role')
112 add_key = Row.add_object(Key, 'person_key')
113 remove_key = Row.remove_object(Key, 'person_key')
115 def sync(self, insert=False, validate=True):
116 NovaObject.sync(self, insert, validate)
117 if insert == True or id not in self:
118 self.object = self.api.client_shell.keystone.tenants.create(**self)
121 class Persons(NovaTable):
123 Representation of row(s) from the persons table in the
127 def __init__(self, api, person_filter = None, columns = None):
129 if not person_filter:
130 persons = self.api.client_shell.keystone.users.findall()
131 elif isinstance(person_filter, (list, tuple, set)):
132 # Separate the list into integers and strings
133 persons = self.api.client_shell.keystone.users.findall()
134 persons = [person for person in persons if person.id in site_filter]
135 elif isinstance(person_filter, dict):
136 persons = [self.api.client_shell.keystone.users.findall(**site_filter)]
137 elif isinstance (person_filter, StringTypes):
138 persons = [self.api.client_shell.keystone.users.find(**site_filter)]
140 raise PLCInvalidArgument, "Wrong person filter %r"%person_filter
142 for person in persons:
143 person = Person(self.api, object = person)