remove the 'name' field from the slice record before updateing. Cant allow user to...
[sfa.git] / sfa / methods / update.py
1 ### $Id$
2 ### $URL$
3
4 from sfa.util.faults import *
5 from sfa.util.method import Method
6 from sfa.util.parameter import Parameter, Mixed
7 from sfa.trust.auth import Auth
8 from sfa.util.record import GeniRecord
9 from sfa.trust.certificate import Keypair, convert_public_key
10 from sfa.trust.gid import *
11 from sfa.util.debug import log
12
13 class update(Method):
14     """
15     Update an object in the registry. Currently, this only updates the
16     PLC information associated with the record. The Geni fields (name, type,
17     GID) are fixed.
18     
19     @param cred credential string specifying rights of the caller
20     @param record a record dictionary to be updated
21
22     @return 1 if successful, faults otherwise 
23     """
24
25     interfaces = ['registry']
26     
27     accepts = [
28         Parameter(str, "Credential string"),
29         Parameter(dict, "Record dictionary to be updated")
30         ]
31
32     returns = Parameter(int, "1 if successful")
33     
34     def call(self, cred, record_dict):
35         self.api.auth.check(cred, "update")
36         record = GeniRecord(dict = record_dict)
37         type = record.get_type()
38         self.api.auth.verify_object_permission(record.get_name())
39         auth_name = self.api.auth.get_authority(record.get_name())
40         if not auth_name:
41             auth_name = record.get_name()
42         table = self.api.auth.get_auth_table(auth_name)
43
44         # make sure the record exists
45         existing_record_list = table.resolve(type, record.get_name())
46         if not existing_record_list:
47             raise RecordNotFound(record.get_name())
48         existing_record = existing_record_list[0]
49
50         # Update_membership needs the membership lists in the existing record
51         # filled in, so it can see if members were added or removed
52         self.api.fill_record_info(existing_record)
53
54          # Use the pointer from the existing record, not the one that the user
55         # gave us. This prevents the user from inserting a forged pointer
56         pointer = existing_record.get_pointer()
57
58         # update the PLC information that was specified with the record
59
60         if (type == "authority"):
61             self.api.plshell.UpdateSite(self.api.plauth, pointer, record)
62
63         elif type == "slice":
64             hrn=record.get_name()
65             pl_record=self.api.geni_fields_to_pl_fields(type, hrn, record)
66             if 'name' in pl_record:
67                 pl_record.pop('name')
68             self.api.plshell.UpdateSlice(self.api.plauth, pointer, pl_record)
69
70         elif type == "user":
71             # SMBAKER: UpdatePerson only allows a limited set of fields to be
72             #    updated. Ideally we should have a more generic way of doing
73             #    this. I copied the field names from UpdatePerson.py...
74             update_fields = {}
75             all_fields = record
76             for key in all_fields.keys():
77                 if key in ['first_name', 'last_name', 'title', 'email',
78                            'password', 'phone', 'url', 'bio', 'accepted_aup',
79                            'enabled']:
80                     update_fields[key] = all_fields[key]
81             self.api.plshell.UpdatePerson(self.api.plauth, pointer, update_fields)
82
83             if 'key' in record and record['key']:
84                 # must check this key against the previous one if it exists
85                 persons = self.api.plshell.GetPersons(self.api.plauth, [pointer], ['key_ids'])
86                 person = persons[0]
87                 keys = person['key_ids']
88                 keys = self.api.plshell.GetKeys(self.api.plauth, person['key_ids'])
89                 key_exists = False
90                 if isinstance(record['key'], list):
91                     new_key = record['key'][0]
92                 else:
93                     new_key = record['key']
94   
95                 # Delete all stale keys
96                 for key in keys:
97                     if record['key'] != key['key']:
98                         self.api.plshell.DeleteKey(self.api.plauth, key['key_id'])
99                     else:
100                         key_exists = True
101                 if not key_exists:
102                     self.api.plshell.AddPersonKey(self.api.plauth, pointer, {'key_type': 'ssh', 'key': new_key})
103
104                 # find the existing geni record
105                 hrn = record['hrn']
106                 auth_name = self.api.auth.get_authority(hrn)
107                 auth_info = self.api.auth.get_auth_info(auth_name)
108                 table = self.api.auth.get_auth_table(auth_name)
109                 person_records = table.resolve('user', hrn)
110                 person_record = person_records[0]
111                 
112                 # update the openssl key and gid
113                 pkey = convert_public_key(new_key)
114                 uuid = create_uuid()
115                 gid_object = self.api.auth.hierarchy.create_gid(hrn, uuid, pkey)
116                 gid = gid_object.save_to_string(save_parents=True)
117                 record['gid'] = gid
118                 record.set_gid(gid)
119                 table.update(record)
120                  
121         elif type == "node":
122             self.api.plshell.UpdateNode(self.api.plauth, pointer, record)
123
124         else:
125             raise UnknownGeniType(type)
126
127         # update membership for researchers, pis, owners, operators
128         self.api.update_membership(existing_record, record)
129
130         return 1