from PLC.Faults import *
from PLC.Debug import log
from PLC.Parameter import Parameter, Mixed
-from PLC.Table import Row, Table
+from PLC.Messages import Message, Messages
from PLC.Roles import Role, Roles
from PLC.Keys import Key, Keys
-from PLC.Messages import Message, Messages
-from PLC.NovaTable import NovaObject, NovaTable
+from PLC.Storage.AlchemyObject import AlchemyObj
-class Person(NovaObject):
+class Person(AlchemyObj):
"""
Representation of a row in the persons table. To use, optionally
instantiate with a dict of values. Update as you would a
dict. Commit to the database with sync().
"""
+ tablename = 'persons'
+
fields = {
- 'person_id': Parameter(str, "User identifier"),
- 'name': Parameter(str, "Given name", max = 128),
+ 'person_id': Parameter(int, "User identifier", primary_key=True),
+ 'keystone_id': Parameter(int, "Keystone 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),
'email': Parameter(str, "Primary e-mail address", max = 254),
+ 'phone': Parameter(str, "Telephone number", max = 64, nullok = True),
+ 'url': Parameter(str, "Home page", max = 254, nullok = True),
+ 'bio': Parameter(str, "Biography", max = 254, nullok = True),
'enabled': Parameter(bool, "Has been enabled"),
'password': Parameter(str, "Account password in crypt() form", max = 254),
- 'tenant_ids': Parameter(str, "Site identifier"),
- #'last_updated': Parameter(int, "Date and time of last update"),
- #'date_created': Parameter(int, "Date and time when account was created"),
+ '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", joined=True),
'roles': Parameter([str], "List of roles", joined=True),
- 'key_ids': Parameter([str], "List of key identifiers", joined=True),
+ 'site_ids': Parameter([int], "List of site identifiers", joined=True),
+ 'key_ids': Parameter([int], "List of key identifiers", joined=True),
'slice_ids': Parameter([int], "List of slice identifiers", joined=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),
+ 'person_tag_ids' : Parameter ([int], "List of tags attached to this person", joined=True),
}
def validate_email(self, email):
return True
if 'pi' in self['roles']:
- if set(self['tenants']).intersection(person['tenants']):
+ if set(self['site_ids']).intersection(person['site_ids']):
# non-admin users cannot update a person who is neither a PI or ADMIN
return (not set(['pi','admin']).intersection(person['roles']))
return False
- #add_role = Row.add_object(Role, 'person_role')
- #remove_role = Row.remove_object(Role, 'person_role')
+ def add_role(self, role_name, login_base=None):
+ user = self.api.client_shell.keystone.users.find(id=self['keystone_id'])
+ roles = Roles(self.api, {'name': role_name})
+ if not roles:
+ raise PLCInvalidArgument, "Role %s not found" % role_name
+ role = roles[0]
+
+ if login_base:
+ # add role at the requested site
+ tenant = self.api.client_shell.keystone.tenants.find(name=login_base)
+ self.api.client_shell.keystone.roles.add_user_role(user, role, tenant)
+ else:
+ from PLC.Sites import Sites
+ # add role to at all of users sites
+ if not self['site_ids']:
+ raise PLCInvalidArgument, "Cannot add role unless user already belongs to a site or a valid site is specified"
+ for site_id in self['site_ids']:
+ sites = Sites(self.api, {'site_id': site_id})
+ site = sites[0]
+ tenant = self.api.client_shell.keystone.tenants.find(id=site['tenant_id'])
+ self.api.client_shell.keystone.roles.add_user_role(user, role, tenant)
+
+ def remove_role(self, role_name, login_base=None):
+ user = self.api.client_shell.keystone.users.find(id=self['keystone_id'])
+ roles = Roles(self.api, {'name': role_name})
+ if not roles:
+ raise PLCInvalidArgument, "Role %s not found" % role_name
+ role = roles[0]
+
+ if login_base:
+ # add role at the requested site
+ tenant = self.api.client_shell.keystone.tenants.find(name=login_base)
+ self.api.client_shell.keystone.roles.add_user_role(user, role, tenant)
+ else:
+ from PLC.Sites import Sites
+ # add role to at all of users sites
+ if not self['site_ids']:
+ raise PLCInvalidArgument, "Cannot add role unless user already belongs to a site or a valid site
+ is specified"
+ for site_id in self['site_ids']:
+ sites = Sites(self.api, {'site_id': site_id})
+ site = sites[0]
+ tenant = self.api.client_shell.keystone.tenants.find(id=site['tenant_id'])
+ self.api.client_shell.keystone.roles.remove_user_role(user, role, tenant)
#add_key = Row.add_object(Key, 'person_key')
#remove_key = Row.remove_object(Key, 'person_key')
- def sync(self, insert=False, validate=True):
- NovaObject.sync(self, insert, validate)
- if insert == True or 'person_id' not in self:
+ def sync(self, commit=True, validate=True):
+ AlchemyObj.sync(self, commit=commit, validate=validate)
+ nova_fields = ['enabled', 'email', 'password']
+ nova_can_update = lambda (field, value): field in nova_fields
+ nova_person = dict(filter(nova_can_update, self.items()))
+ nova_person['name'] = "%s %s" % (self.get('first_name', ''), self.get('last_name', ''))
+ if 'person_id' not in self:
self.object = self.api.client_shell.keystone.users.create(**self)
+ self['keystone_id'] = self.object.id
+ AlchemyObj.insert(self, dict(self))
+ else:
+ self.object = self.api.client_shell.keystone.users.update(self['person_id'], nova_person)
+ AlchemyObj.update(self, {'person_id': self['person_id']}, dict(self))
+
def delete(self):
+ assert 'person_id' in self
+ assert 'keystone_id' in self
+
+ # delete keystone record
+ nova_user = self.api.client_shell.keystone.users.find(id=self['keystone_id'])
+ self.api.client_shell.keystone.users.delete(nova_user)
+
# delete relationships
SlicePerson().delete.filter({'person_id': self['person_id']})
- # delete nova object
- user = self.api.client_shell.keystone.users.find(**self)
- self.api.client_shell.keystone.users.delete(user)
+ # delete person
+ AlchemyObj.delete(self, dict(self))
- def get_roles(self):
- roles = []
- if self.tenant:
- roles = self.api.client_shell.keystone.roles.roles_for_user(self.object, self.tenant)
- return [role.name for role in roles]
-
def get_tenants_ids(self):
tenants = []
if self.tenantId:
def get_key_ids(self):
return []
-class Persons(NovaTable):
+class Persons(list):
"""
Representation of row(s) from the persons table in the
database.
def __init__(self, api, person_filter = None, columns = None):
self.api = api
if not person_filter:
- persons = self.api.client_shell.keystone.users.findall()
+ #persons = self.api.client_shell.keystone.users.findall()
+ persons = Person().select()
elif isinstance(person_filter, (list, tuple, set)):
- # Separate the list into integers and strings
- persons = self.api.client_shell.keystone.users.findall()
- persons = [person for person in persons if person.id in person_filter]
+ ints = filter(lambda x: isinstance(x, (int, long)), person_filter)
+ strs = filter(lambda x: isinstance(x, StringTypes), person_filter)
+ person_filter = {'person_id': ints, 'email': strs}
+ persons = Person().select(filter=person_filter)
elif isinstance(person_filter, dict):
- persons = self.api.client_shell.keystone.users.findall(**person_filter)
+ persons = Person().select(filter=person_filter)
+ #persons = self.api.client_shell.keystone.users.findall(**person_filter)
elif isinstance (person_filter, StringTypes):
- persons = [self.api.client_shell.keystone.users.find(id=person_filter)]
+ persons = Person().select(filter={'email': person_filter})
else:
raise PLCInvalidArgument, "Wrong person filter %r"%person_filter
for person in persons:
- person = Person(self.api, object = person)
- person.tenant=None
- if person.tenantId:
- person.tenant = self.api.client_shell.keystone.tenants.find(id=person.tenantId)
+ keystone_user = self.api.client_shell.keystone.persons.find(id=person['keystone_id'])
+ tenant = self.api.client_shell.keystone.tenants.find(id=keystone_user.tenantId)
if not columns or 'roles' in columns:
+ roles = self.api.client_shell.keystone.roles.roles_for_user(keystone_user, tenant)
person['roles'] = person.get_roles()
if not columns or 'tenant_ids' in columns:
person['tenant_ids'] = person.get_tenants_ids()