from PLC.Faults import *
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
-from PLC.Persons import Person, Persons
from PLC.Auth import Auth
+from PLC.Table import Row
+from PLC.Persons import Person, Persons
from PLC.sendmail import sendmail
+from PLC.TagTypes import TagTypes
+from PLC.PersonTags import PersonTags, PersonTag
+from PLC.Namespace import email_to_hrn
related_fields = Person.related_fields.keys()
-can_update = lambda (field, value): field in \
- ['first_name', 'last_name', 'title', 'email',
+can_update = ['first_name', 'last_name', 'title', 'email',
'password', 'phone', 'url', 'bio', 'accepted_aup',
'enabled'] + related_fields
"""
Updates a person. Only the fields specified in person_fields are
updated, all other fields are left untouched.
-
+
Users and techs can only update themselves. PIs can only update
themselves and other non-PIs at their sites.
roles = ['admin', 'pi', 'user', 'tech']
- person_fields = dict(filter(can_update, Person.fields.items() + Person.related_fields.items()))
+ accepted_fields = Row.accepted_fields(can_update,Person.fields)
+ # xxx check the related_fields feature
+ accepted_fields.update(Person.related_fields)
+ accepted_fields.update(Person.tags)
accepts = [
Auth(),
Mixed(Person.fields['person_id'],
Person.fields['email']),
- person_fields
+ accepted_fields
]
returns = Parameter(int, '1 if successful')
def call(self, auth, person_id_or_email, person_fields):
- person_fields = dict(filter(can_update, person_fields.items()))
+ # split provided fields
+ [native,related,tags,rejected] = Row.split_fields(person_fields,[Person.fields,Person.related_fields,Person.tags])
+
+ # type checking
+ native = Row.check_fields (native, self.accepted_fields)
+ if rejected:
+ raise PLCInvalidArgument, "Cannot update Person column(s) %r"%rejected
+
+ # Authenticated function
+ assert self.caller is not None
# Get account information
persons = Persons(self.api, [person_id_or_email])
if not persons:
- raise PLCInvalidArgument, "No such account"
+ raise PLCInvalidArgument, "No such account %s"%person_id_or_email
person = persons[0]
if person['peer_id'] is not None:
- raise PLCInvalidArgument, "Not a local account"
-
- # Authenticated function
- assert self.caller is not None
+ raise PLCInvalidArgument, "Not a local account %s"%person_id_or_email
# Check if we can update this account
if not self.caller.can_update(person):
raise PLCPermissionDenied, "Not allowed to update specified account"
-
- # Make requested associations
- for field in related_fields:
- if field in person_fields:
- person.associate(auth, field, person_fields[field])
- person_fields.pop(field)
-
- person.update(person_fields)
- person.update_last_updated(False)
- person.sync()
-
- if 'enabled' in person_fields:
- To = [("%s %s" % (person['first_name'], person['last_name']), person['email'])]
- Cc = []
- if person['enabled']:
- Subject = "PlanetLab account enabled"
- Body = "Your PlanetLab account has been enabled. You should now be allowd to access you account"
- else:
- Subject = "PlanetLab account disabled"
- Body = "Your PlanetLab account has been disabled. Please contact your PI or PlanetLab support for more information"
- sendmail(self.api, To = To, Cc = Cc, Subject = Subject, Body = Body)
-
-
- # Logging variables
- self.event_objects = {'Person': [person['person_id']]}
+
+ # Make requested associations
+ for k,v in related.iteritems():
+ person.associate (auth, k, v)
+
+ person.update(native)
+ person.update_last_updated(False)
+ person.sync(commit=True)
+
+ # send a mail
+ if 'enabled' in person_fields:
+ To = [("%s %s" % (person['first_name'], person['last_name']), person['email'])]
+ Cc = []
+ if person['enabled']:
+ Subject = "%s account enabled" % (self.api.config.PLC_NAME)
+ Body = "Your %s account has been enabled. Please visit %s to access your account." % (self.api.config.PLC_NAME, self.api.config.PLC_WWW_HOST)
+ else:
+ Subject = "%s account disabled" % (self.api.config.PLC_NAME)
+ Body = "Your %s account has been disabled. Please contact your PI or PlanetLab support for more information" % (self.api.config.PLC_NAME)
+ sendmail(self.api, To = To, Cc = Cc, Subject = Subject, Body = Body)
+
+ # if email was modifed make sure to update the hrn tag
+ if 'email' in native:
+ hrn_tag=PersonTags(self.api,{'tagname':'hrn','person_id':person['person_id']})
+ if hrn_tag:
+ old_hrn = hrn_tag[0]['value']
+ root_auth = self.api.config.PLC_HRN_ROOT
+ login_base = old_hrn.split('.')[-2]
+ hrn=email_to_hrn("%s.%s"%(root_auth,login_base),person['email'])
+ tags['hrn'] = hrn
+
+ for (tagname,value) in tags.iteritems():
+ # the tagtype instance is assumed to exist, just check that
+ tag_types = TagTypes(self.api,{'tagname':tagname})
+ if not tag_types:
+ raise PLCInvalidArgument,"No such TagType %s"%tagname
+ tag_type = tag_types[0]
+ person_tags=PersonTags(self.api,{'tagname':tagname,'person_id':person['person_id']})
+ if not person_tags:
+ person_tag = PersonTag(self.api)
+ person_tag['person_id'] = person['person_id']
+ person_tag['tag_type_id'] = tag_type['tag_type_id']
+ person_tag['tagname'] = tagname
+ person_tag['value'] = value
+ person_tag.sync()
+ else:
+ person_tag = person_tags[0]
+ person_tag['value'] = value
+ person_tag.sync()
+
+ # Logging variables
+ self.event_objects = {'Person': [person['person_id']]}
# Redact password
if 'password' in person_fields:
person_fields['password'] = "Removed by API"
self.message = 'Person %d updated: %s.' % \
(person['person_id'], person_fields.keys())
- if 'enabled' in person_fields:
- self.message += ' Person enabled'
+ if 'enabled' in person_fields:
+ self.message += ' Person enabled'
return 1