--- /dev/null
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.Filter import Filter
+from PLC.Auth import Auth
+from PLC.Persons import Person, Persons
+from PLC.Sites import Site, Sites
+from PLC.Slices import Slice, Slices
+from PLC.Keys import Key, Keys
+
+class GetSliceKeys(Method):
+ """
+ Returns an array of structs containing public key info for users in
+ the specified slices. If slice_filter is specified and is an array
+ of slice identifiers or slice names, or a struct of slice
+ attributes, only slices matching the filter will be returned. If
+ return_fields is specified, only the specified details will be
+ returned.
+
+ Users may only query slices of which they are members. PIs may
+ query any of the slices at their sites. Admins and nodes may query
+ any slice. If a slice that cannot be queried is specified in
+ slice_filter, details about that slice will not be returned.
+ """
+
+ roles = ['admin', 'pi', 'user', 'node']
+
+ accepts = [
+ Auth(),
+ Mixed([Mixed(Slice.fields['slice_id'],
+ Slice.fields['name'])],
+ Filter(Slice.fields)),
+ Parameter([str], "List of fields to return", nullok = True)
+ ]
+
+ returns = [
+ {
+ 'slice_id': Slice.fields['slice_id'],
+ 'name': Slice.fields['name'],
+ 'person_id': Person.fields['person_id'],
+ 'email': Person.fields['email'],
+ 'key': Key.fields['key']
+ }]
+
+ def call(self, auth, slice_filter = None, return_fields = None):
+ slice_fields = ['slice_id', 'name']
+ person_fields = ['person_id', 'email']
+ key_fields = ['key']
+
+ # If we are not admin, make sure to return only viewable
+ # slices.
+ if isinstance(self.caller, Person) and \
+ 'admin' not in self.caller['roles']:
+ # Get slices that we are able to view
+ valid_slice_ids = self.caller['slice_ids']
+ if 'pi' in self.caller['roles'] and self.caller['site_ids']:
+ sites = Sites(self.api, self.caller['site_ids'])
+ for site in sites:
+ valid_slice_ids += site['slice_ids']
+
+ if not valid_slice_ids:
+ return []
+
+ if slice_filter is None:
+ slice_filter = valid_slice_ids
+
+ if return_fields:
+ slice_return_fields = filter(lambda field: field in slice_fields, return_fields)
+ person_return_fields = filter(lambda field: field in person_fields, return_fields)
+ key_return_fields = filter(lambda field: field in key_fields, return_fields)
+ else:
+ slice_return_fields = slice_fields
+ person_return_fields = person_fields
+ key_return_fields = key_fields
+
+ # Must query at least Slice.slice_id, Slice.person_ids,
+ # and Person.person_id and Person.key_ids so we can join data correctly
+ slice_added_fields = set(['slice_id', 'person_ids']).difference(slice_return_fields)
+ slice_return_fields += slice_added_fields
+ person_added_fields = set(['person_id', 'key_ids']).difference(person_return_fields)
+ person_return_fields += person_added_fields
+ key_added_fields = set(['key_id']).difference(key_return_fields)
+ key_return_fields += key_added_fields
+
+ # Get the slices
+ all_slices = Slices(self.api, slice_filter, slice_return_fields).dict('slice_id')
+ slice_ids = all_slices.keys()
+ slices = all_slices.values()
+
+ # Filter out slices that are not viewable
+ if isinstance(self.caller, Person) and \
+ 'admin' not in self.caller['roles']:
+ slices = filter(lambda slice: slice['slice_id'] in valid_slice_ids, slices)
+
+ # Get the persons
+ person_ids = set()
+ for slice in slices:
+ person_ids.update(slice['person_ids'])
+
+ all_persons = Persons(self.api, list(person_ids), person_return_fields).dict('person_id')
+ person_ids = all_persons.keys()
+ persons = all_persons.values()
+
+ # Get the keys
+ key_ids = set()
+ for person in persons:
+ key_ids.update(person['key_ids'])
+
+ all_keys = Keys(self.api, list(key_ids), key_return_fields).dict('key_id')
+ key_ids = all_keys.keys()
+ keys = all_keys.values()
+
+ # Create slice_keys list
+ slice_keys = []
+ slice_fields = list(set(slice_return_fields).difference(slice_added_fields))
+ person_fields = list(set(person_return_fields).difference(person_added_fields))
+ key_fields = list(set(key_return_fields).difference(key_added_fields))
+
+ for slice in slices:
+ slice_key = dict.fromkeys(slice_fields + person_fields + key_fields)
+ if not slice['person_ids']:
+ continue
+ for person_id in slice['person_ids']:
+ person = all_persons[person_id]
+ if not person['key_ids']:
+ continue
+ for key_id in person['key_ids']:
+ key = all_keys[key_id]
+ slice_key.update(dict(filter(lambda (k, v): k in slice_fields, slice.items())))
+ slice_key.update(dict(filter(lambda (k, v): k in person_fields, person.items())))
+ slice_key.update(dict(filter(lambda (k, v): k in key_fields, key.items())))
+ slice_keys.append(slice_key.copy())
+
+ return slice_keys
+