- returns user public key information
[plcapi.git] / PLC / Methods / GetSliceKeys.py
1 from PLC.Method import Method
2 from PLC.Parameter import Parameter, Mixed
3 from PLC.Filter import Filter
4 from PLC.Auth import Auth
5 from PLC.Persons import Person, Persons
6 from PLC.Sites import Site, Sites
7 from PLC.Slices import Slice, Slices
8 from PLC.Keys import Key, Keys
9
10
11 slice_fields = ['slice_id', 'name']
12 person_fields = ['person_id', 'email']
13 key_fields = ['key']
14
15 class GetSliceKeys(Method):
16     """
17     Returns an array of structs containing details about users/public keys 
18     in slices. If slice_filter is specified and is an array of slice 
19     identifiers or slice names, or a struct of slice attributes, only 
20     slices matching the filter will be returned. If return_fields is 
21     specified, only the specified details will be returned.
22
23     Users may only query slices of which they are members. PIs may
24     query any of the slices at their sites. Admins and nodes may query
25     any slice. If a slice that cannot be queried is specified in
26     slice_filter, details about that slice will not be returned.
27     """
28
29     roles = ['admin', 'pi', 'user', 'node']
30
31     accepts = [
32         Auth(),
33         Mixed([Mixed(Slice.fields['slice_id'],
34                      Slice.fields['name'])],
35               Filter(Slice.fields)),
36         Parameter([str], "List of fields to return", nullok = True)
37         ]
38
39     returns = [
40         {
41         'slice_id': Slice.fields['slice_id'],
42         'name': Slice.fields['name'], 
43         'person_id': Person.fields['person_id'], 
44         'email': Person.fields['email'],
45         'key': Key.fields['key']
46         }]
47
48     def call(self, auth, slice_filter = None, return_fields = None):
49         slice_fields = ['slice_id', 'name']
50         person_fields = ['person_id', 'email']
51         key_fields = ['key']
52
53         # If we are not admin, make sure to return only viewable
54         # slices.
55         if isinstance(self.caller, Person) and \
56            'admin' not in self.caller['roles']:
57             # Get slices that we are able to view
58             valid_slice_ids = self.caller['slice_ids']
59             if 'pi' in self.caller['roles'] and self.caller['site_ids']:
60                 sites = Sites(self.api, self.caller['site_ids'])
61                 for site in sites:
62                     valid_slice_ids += site['slice_ids']
63
64             if not valid_slice_ids:
65                 return []
66
67             if slice_filter is None:
68                 slice_filter = valid_slice_ids
69
70         if return_fields:
71             slice_return_fields = filter(lambda field: field in slice_fields, return_fields)
72             person_return_fields = filter(lambda field: field in person_fields, return_fields)
73             key_return_fields = filter(lambda field: field in key_fields, return_fields)
74         else:
75             slice_return_fields = slice_fields
76             person_return_fields = person_fields
77             key_return_fields = key_fields
78
79         # Must query at least Slice.slice_id, Slice.person_ids, 
80         # and Person.person_id and Person.key_ids so we can join data correctly
81         slice_added_fields = set(['slice_id', 'person_ids']).difference(slice_return_fields)
82         slice_return_fields += slice_added_fields
83         person_added_fields = set(['person_id', 'key_ids']).difference(person_return_fields)
84         person_return_fields += person_added_fields
85         key_added_fields = set(['key_id']).difference(key_return_fields)
86         key_return_fields += key_added_fields
87
88         # Get the slices
89         all_slices = Slices(self.api, slice_filter, slice_return_fields).dict('slice_id')
90         slice_ids = all_slices.keys()
91         slices = all_slices.values()
92
93         # Filter out slices that are not viewable
94         if isinstance(self.caller, Person) and \
95            'admin' not in self.caller['roles']:
96             slices = filter(lambda slice: slice['slice_id'] in valid_slice_ids, slices)
97         
98         # Get the persons
99         person_ids = set()
100         for slice in slices:
101             person_ids.update(slice['person_ids'])
102
103         all_persons = Persons(self.api, list(person_ids), person_return_fields).dict('person_id')
104         person_ids = all_persons.keys()
105         persons = all_persons.values()
106         
107         # Get the keys
108         key_ids = set()
109         for person in persons:
110             key_ids.update(person['key_ids'])
111         
112         all_keys = Keys(self.api, list(key_ids), key_return_fields).dict('key_id')
113         key_ids = all_keys.keys()
114         keys = all_keys.values()
115
116         # Create slice_keys list
117         slice_keys = []
118         slice_fields = list(set(slice_return_fields).difference(slice_added_fields))
119         person_fields = list(set(person_return_fields).difference(person_added_fields))
120         key_fields = list(set(key_return_fields).difference(key_added_fields))
121
122         for slice in slices:
123             slice_key = dict.fromkeys(slice_fields + person_fields + key_fields)
124             if not slice['person_ids']:
125                 continue
126             for person_id in slice['person_ids']:
127                 person = all_persons[person_id]
128                 if not person['key_ids']:
129                     continue
130                 for key_id in person['key_ids']:
131                     key = all_keys[key_id]
132                     slice_key.update(dict(filter(lambda (k, v): k in slice_fields, slice.items())))
133                     slice_key.update(dict(filter(lambda (k, v): k in person_fields, person.items())))
134                     slice_key.update(dict(filter(lambda (k, v): k in key_fields, key.items())))
135                     slice_keys.append(slice_key.copy())
136
137         return slice_keys       
138