1 from PLC.Faults import *
2 from PLC.Method import Method
3 from PLC.Parameter import Parameter, Mixed
4 from PLC.Auth import Auth
5 from PLC.Table import Row
6 from PLC.Persons import Person, Persons
7 from PLC.sendmail import sendmail
8 from PLC.TagTypes import TagTypes
9 from PLC.PersonTags import PersonTags, PersonTag
10 from PLC.Namespace import email_to_hrn
12 related_fields = list(Person.related_fields.keys())
13 can_update = ['first_name', 'last_name', 'title', 'email',
14 'password', 'phone', 'url', 'bio', 'accepted_aup',
15 'enabled'] + related_fields
17 class UpdatePerson(Method):
19 Updates a person. Only the fields specified in person_fields are
20 updated, all other fields are left untouched.
22 Users and techs can only update themselves. PIs can only update
23 themselves and other non-PIs at their sites.
25 Returns 1 if successful, faults otherwise.
28 roles = ['admin', 'pi', 'user', 'tech']
30 accepted_fields = Row.accepted_fields(can_update,Person.fields)
31 # xxx check the related_fields feature
32 accepted_fields.update(Person.related_fields)
33 accepted_fields.update(Person.tags)
37 Mixed(Person.fields['person_id'],
38 Person.fields['email']),
42 returns = Parameter(int, '1 if successful')
44 def call(self, auth, person_id_or_email, person_fields):
45 # split provided fields
46 [native,related,tags,rejected] = Row.split_fields(person_fields,[Person.fields,Person.related_fields,Person.tags])
49 native = Row.check_fields (native, self.accepted_fields)
51 raise PLCInvalidArgument("Cannot update Person column(s) %r"%rejected)
53 # Authenticated function
54 assert self.caller is not None
56 # Get account information
57 persons = Persons(self.api, [person_id_or_email])
59 raise PLCInvalidArgument("No such account %s"%person_id_or_email)
62 if person['peer_id'] is not None:
63 raise PLCInvalidArgument("Not a local account %s"%person_id_or_email)
65 # Check if we can update this account
66 if not self.caller.can_update(person):
67 raise PLCPermissionDenied("Not allowed to update specified account")
69 # Make requested associations
70 for k,v in related.items():
71 person.associate (auth, k, v)
74 person.update_last_updated(False)
75 person.sync(commit=True)
78 if 'enabled' in person_fields:
79 To = [("%s %s" % (person['first_name'], person['last_name']), person['email'])]
82 Subject = "%s account enabled" % (self.api.config.PLC_NAME)
83 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)
85 Subject = "%s account disabled" % (self.api.config.PLC_NAME)
86 Body = "Your %s account has been disabled. Please contact your PI or PlanetLab support for more information" % (self.api.config.PLC_NAME)
87 sendmail(self.api, To = To, Cc = Cc, Subject = Subject, Body = Body)
89 # if email was modifed make sure to update the hrn tag
91 hrn_tag=PersonTags(self.api,{'tagname':'hrn','person_id':person['person_id']})
93 old_hrn = hrn_tag[0]['value']
94 root_auth = self.api.config.PLC_HRN_ROOT
95 login_base = old_hrn.split('.')[-2]
96 hrn=email_to_hrn("%s.%s"%(root_auth,login_base),person['email'])
99 for (tagname,value) in tags.items():
100 # the tagtype instance is assumed to exist, just check that
101 tag_types = TagTypes(self.api,{'tagname':tagname})
103 raise PLCInvalidArgument("No such TagType %s"%tagname)
104 tag_type = tag_types[0]
105 person_tags=PersonTags(self.api,{'tagname':tagname,'person_id':person['person_id']})
107 person_tag = PersonTag(self.api)
108 person_tag['person_id'] = person['person_id']
109 person_tag['tag_type_id'] = tag_type['tag_type_id']
110 person_tag['tagname'] = tagname
111 person_tag['value'] = value
114 person_tag = person_tags[0]
115 person_tag['value'] = value
119 self.event_objects = {'Person': [person['person_id']]}
122 if 'password' in person_fields:
123 person_fields['password'] = "Removed by API"
124 self.message = 'Person %d updated: %s.' % \
125 (person['person_id'], list(person_fields.keys()))
126 if 'enabled' in person_fields:
127 self.message += ' Person enabled'