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