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 'tenant_id': Parameter(str, "Tenant identifier"),
38 'last_updated': Parameter(int, "Date and time of last update", ro = True),
39 'date_created': Parameter(int, "Date and time when account was created", ro = True),
40 'roles': Parameter([str], "List of roles"),
41 'keys': Parameter([int], "List of key identifiers"),
42 'slices': 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.id == person.id:
77 if 'admin' in self['roles']:
80 if 'pi' in self['roles']:
81 if set(self['tenants']).intersection(person['tenants']):
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.users.create(**self)
123 roles = self.api.client_shell.keystone.roles.roles_for_user(self.object, self.tenant)
124 return [role.name for role in roles]
126 def get_tenants(self):
129 tenants = [self.tenantId]
132 class Persons(NovaTable):
134 Representation of row(s) from the persons table in the
138 def __init__(self, api, person_filter = None, columns = None):
140 if not person_filter:
141 persons = self.api.client_shell.keystone.users.findall()
142 elif isinstance(person_filter, (list, tuple, set)):
143 # Separate the list into integers and strings
144 persons = self.api.client_shell.keystone.users.findall()
145 persons = [person for person in persons if person.id in person_filter]
146 elif isinstance(person_filter, dict):
147 persons = self.api.client_shell.keystone.users.findall(**person_filter)
148 elif isinstance (person_filter, StringTypes):
149 persons = [self.api.client_shell.keystone.users.find(id=person_filter)]
151 raise PLCInvalidArgument, "Wrong person filter %r"%person_filter
153 for person in persons:
154 person = Person(self.api, object = person)
157 person.tenant = self.api.client_shell.keystone.tenants.find(id=person.tenantId)
158 person['roles'] = person.get_roles()
159 person['tenants'] = person.get_tenants()