StringTypes has gone
[plcapi.git] / PLC / Methods / RetrieveSlicePersonKeys.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.Slices import Slice, Slices
6 from PLC.Persons import Person, Persons
7 from PLC.Keys import Key, Keys
8 from functools import reduce
9
10 class RetrieveSlicePersonKeys(Method):
11     """
12     This method exposes the public ssh keys for people in a slice
13     It expects a slice name or id, and returns a dictionary on emails.
14     This method is designed to help third-party software authenticate
15     users (e.g. the OMF Experiment Controller).
16     For this reason it is accessible with anonymous authentication.
17     """
18
19     roles = ['admin', 'pi', 'user', 'tech', 'anonymous' ]
20
21     applicable_fields = {
22         'slice_id' : Slice.fields['slice_id'],
23         'name' : Slice.fields['name'],
24         }
25
26     accepts = [
27         Auth(),
28         Mixed(Slice.fields['slice_id'],
29               Slice.fields['name']),
30         Filter(Person.fields),
31         ]
32
33     returns = Parameter (dict, " ssh keys hashed on emails")
34
35     def call(self, auth, slice_id_or_name, person_filter=None):
36
37         if person_filter is None: person_filter = {}
38
39         # the people in the slice
40         slice=Slices (self.api, slice_id_or_name, ['person_ids'])[0]
41         slice_person_ids = slice['person_ids']
42
43         # if caller has not specified person_id, use slice_person_ids
44         if 'person_id' not in person_filter:
45             person_filter['person_id']=slice_person_ids
46         # otherwise, compute intersection
47         else:
48             caller_provided = person_filter['person_id']
49             if not isinstance (caller_provided,list):
50                 caller_provided = [ caller_provided, ]
51             person_filter['person_id'] = list ( set(caller_provided).intersection(slice_person_ids) )
52
53         def merge (l1,l2): return l1+l2
54
55         persons = Persons (self.api, person_filter, ['email','key_ids'] )
56         key_id_to_email_hash = \
57             dict ( reduce ( merge , [ [ (kid,p['email']) for kid in p['key_ids']] for p in persons ] ) )
58
59         all_key_ids = reduce (merge, [ p['key_ids'] for p in persons ] )
60
61         all_keys = Keys (self.api, all_key_ids)
62
63         result={}
64         for key in all_keys:
65             key_id=key['key_id']
66             email = key_id_to_email_hash[key_id]
67             if email not in result: result[email]=[]
68             result[email].append (key['key'])
69
70         return  result