64dcbde17ab2dbd2b29f1e85333d4d21164321ca
[unfold.git] / portal / projectrequestview.py
1 import json
2 import time
3 import re
4
5 from django.shortcuts           import render
6 from django.contrib.sites.models import Site
7
8 from manifold.core.query        import Query
9 from manifoldapi.manifoldapi    import execute_admin_query, execute_query
10
11 from unfold.loginrequired       import LoginRequiredAutoLogoutView
12
13 from portal.actions import create_pending_project, create_pending_join, sfa_add_authority, authority_add_pis, is_pi
14 from portal.models import PendingProject, PendingJoin
15
16 from myslice.theme import ThemeView
17 from myslice.settings import logger
18
19 class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
20     template_name = 'projectrequest_view.html'
21     
22     def getAuthorities(self, request):
23         authorities_query = Query.get('authority').select('name', 'authority_hrn')
24         authorities = execute_admin_query(request, authorities_query)
25         if authorities is not None:
26             # Remove the root authority from the list
27             matching = [s for s in authorities if "." in s['authority_hrn']]
28             authorities = sorted(matching, key=lambda k: k['authority_hrn'])
29             authorities = sorted(matching, key=lambda k: k['name'])
30         return authorities
31     
32     def getUserAuthority(self, request):
33         # Get user_email (XXX Would deserve to be simplified)
34         user_query  = Query().get('local:user').select('email','config')
35         user_details = execute_query(request, user_query)
36         for user_detail in user_details:
37             user_config = json.loads(user_detail['config'])
38             user_authority = user_config.get('authority','N/A')
39         return user_authority
40     
41     def getUserHrn(self, request):
42         user_hrn = None
43         
44         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
45         account_details = execute_query(request, account_query)
46
47         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
48         platform_details = execute_query(request, platform_query)
49         
50         # getting user_hrn from local:account
51         for account_detail in account_details:
52             for platform_detail in platform_details:
53                 if platform_detail['platform_id'] == account_detail['platform_id']:
54                     # taking user_hrn only from myslice account
55                     # NOTE: we should later handle accounts filter_by auth_type= managed OR user
56                     if 'myslice' in platform_detail['platform']:
57                         account_config = json.loads(account_detail['config'])
58                         user_hrn = account_config.get('user_hrn','N/A')
59         return user_hrn        
60
61     def getUserEmail(self, request):
62         # Get user_email (XXX Would deserve to be simplified)
63         user_query  = Query().get('local:user').select('email','config')
64         user_details = execute_query(request, user_query)
65         user_email = user_details[0].get('email')
66         return user_email
67                    
68     def post(self, request):
69         return self.handle_request(request, 'POST')
70
71     def get(self, request):
72         return self.handle_request(request, 'GET')
73
74     def handle_request(self, wsgi_request, method):
75         errors = []
76         authority_hrn = None
77         authority_name = None
78         
79         #errors.append(wsgi_request.POST)
80
81         user_hrn = self.getUserHrn(wsgi_request)
82
83         user_email = self.getUserEmail(wsgi_request)
84         
85         authorities = self.getAuthorities(wsgi_request)
86         
87         user_authority = self.getUserAuthority(wsgi_request)
88         
89         # getting the org from authority
90         for authority in authorities:
91             if authority['authority_hrn'] == user_authority:
92                 authority_name = authority['name']
93         
94         if method == 'POST' :
95         
96             if 'join' in wsgi_request.POST:
97                 post = {
98                     'user_hrn'          : user_hrn,
99                     'email'             : user_email,
100                     'project_name'      : wsgi_request.POST.get('project_name', ''),
101                     'authority_hrn'     : wsgi_request.POST.get('project_name', ''),
102                 }
103
104             else:
105                 post = {
106                     'user_hrn'          : user_hrn,
107                     'email'             : user_email,
108                     'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
109                     'project_name'      : wsgi_request.POST.get('project_name', ''),
110                     'purpose'           : wsgi_request.POST.get('purpose', ''),
111                 }
112
113                 if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
114                     errors.append('Organization is mandatory')
115     
116                 if (post['purpose'] is None or post['purpose'] == ''):
117                     errors.append('Project purpose is mandatory')
118
119                 if (re.search(r'^[A-Za-z0-9_]*$', post['project_name']) == None):
120                     errors.append('Project name may contain only letters, numbers, and underscore.')
121
122             # What kind of project name is valid?
123             if (post['project_name'] is None or post['project_name'] == ''):
124                 errors.append('Project name is mandatory')
125             
126             if not errors:
127                 logger.info("is_pi on auth_hrn = {}".format(user_authority))
128                 if is_pi(wsgi_request, user_hrn, user_authority):
129                     # PIs can directly create/join project in their own authority...
130                     if 'join' in wsgi_request.POST:
131                         authority_add_pis(wsgi_request, post['project_name'], user_hrn)
132                     else:
133                         hrn = post['authority_hrn'] + '.' + post['project_name']
134                         sfa_add_authority(wsgi_request, {'authority_hrn':hrn})
135                         authority_add_pis(wsgi_request, hrn, user_hrn)
136                     self.template_name = 'project-request-done-view.html'
137                 else:
138                     # Otherwise a wsgi_request is sent to the PI
139                     if 'join' in wsgi_request.POST:
140                         create_pending_join(wsgi_request, post)
141                     else:
142                         create_pending_project(wsgi_request, post)
143                     self.template_name = 'project-request-ack-view.html'
144
145         # retrieves the pending projects creation list
146         pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
147         # retrieves the pending join a project list
148         pending_join_projects = PendingJoin.objects.all().filter(user_hrn=user_hrn)
149
150         root_authority = user_authority.split('.', 1)[0]                  
151         env = {
152                'errors':        errors,
153                'username':      wsgi_request.user,
154                'theme':         self.theme,
155                'authorities':   authorities,
156                'authority_hrn': user_authority,
157                'root_authority_hrn': root_authority,
158                'pending_projects': pending_projects,
159                'pending_join_projects': pending_join_projects,
160         }
161         return render(wsgi_request, self.template, env)
162     
163         
164     
165         """
166         """
167         errors = []
168         slice_name =''
169         purpose=''
170         url=''
171         authority_hrn = None
172         authority_name = None
173         # Retrieve the list of authorities
174         authorities_query = Query.get('authority').select('name', 'authority_hrn')
175         authorities = execute_admin_query(wsgi_request, authorities_query)
176         if authorities is not None:
177             authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
178             authorities = sorted(authorities, key=lambda k: k['name'])
179
180         # Get user_email (XXX Would deserve to be simplified)
181         user_query  = Query().get('local:user').select('email','config')
182         user_details = execute_query(wsgi_request, user_query)
183         user_email = user_details[0].get('email')
184         # getting user_hrn
185         for user_detail in user_details:
186             user_config = json.loads(user_detail['config'])
187             user_authority = user_config.get('authority','N/A')              
188         # getting the org from authority        
189         for authority in authorities:
190             if authority['authority_hrn'] == user_authority:
191                 authority_name = authority['name']
192
193         # Handle the case when we use only hrn and not name
194         if authority_name is None:
195             authority_name = user_authority
196         #
197         account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
198         account_details = execute_query(wsgi_request, account_query)
199         #
200         platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
201         platform_details = execute_query(wsgi_request, platform_query)
202         
203         user_hrn = None
204         # getting user_hrn from local:account
205         for account_detail in account_details:
206             for platform_detail in platform_details:
207                 if platform_detail['platform_id'] == account_detail['platform_id']:
208                     # taking user_hrn only from myslice account
209                     # NOTE: we should later handle accounts filter_by auth_type= managed OR user
210                     if 'myslice' in platform_detail['platform']:
211                         account_config = json.loads(account_detail['config'])
212                         user_hrn = account_config.get('user_hrn','N/A')
213                         acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
214
215
216         # checking if pi or not
217         if acc_auth_cred == {} or acc_auth_cred == 'N/A':
218             pi = "is_not_pi"
219         else:
220             pi = "is_pi"
221
222
223         # Page rendering
224 #         page = Page(wsgi_request)
225 #         page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
226 #         page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
227 #         page.expose_js_metadata()
228
229         if method == 'POST':
230             # The form has been submitted
231
232             # get the domain url
233 #             current_site = Site.objects.get_current()
234 #             current_site = current_site.domain
235             
236             # getting the authority_hrn from the selected organization
237             for authority in authorities:
238                 if authority['name'] == wsgi_request.POST.get('org_name', ''):
239                     authority_hrn = authority['authority_hrn']
240
241             # Handle the case when we use only hrn and not name
242             if authority_hrn is None:
243                 authority_hrn = wsgi_request.POST.get('org_name', '')
244
245             slice_request = {
246                 'type'              : 'slice',
247                 'id'                : None,
248                 'user_hrn'          : user_hrn,
249                 'email'             : user_email,
250                 'timestamp'         : time.time(),
251                 'authority_hrn'     : authority_hrn,
252                 'organization'      : wsgi_request.POST.get('org_name', ''),
253                 'slice_name'        : wsgi_request.POST.get('slice_name', ''),
254                 'url'               : wsgi_request.POST.get('url', ''),
255                 'purpose'           : wsgi_request.POST.get('purpose', ''),
256                 'current_site'      : current_site
257             }
258             
259             # create slice_hrn based on authority_hrn and slice_name
260 #             slice_name = slice_request['slice_name']
261             req_slice_hrn = authority_hrn + '.' + slice_name
262             # comparing requested slice_hrn with the existing slice_hrn 
263             slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
264             slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
265             for _slice in slice_details_sfa:
266                 if _slice['slice_hrn'] == req_slice_hrn:
267                     errors.append('Slice already exists. Please use a different slice name.')
268             
269
270             # What kind of slice name is valid?
271             if (slice_name is None or slice_name == ''):
272                 errors.append('Slice name is mandatory')
273             
274             if (re.search(r'^[A-Za-z0-9_]*$', slice_name) == None):
275                 errors.append('Slice name may contain only letters, numbers, and underscore.')
276             
277             organization = slice_request['organization']    
278             if (organization is None or organization == ''):
279                 errors.append('Organization is mandatory')
280
281
282     
283             purpose = slice_request['purpose']
284             if (purpose is None or purpose == ''):
285                 errors.append('Experiment purpose is mandatory')
286
287             url = slice_request['url']
288
289             if not errors:
290                 if is_pi(wsgi_request, user_hrn, authority_hrn):
291                     # PIs can directly create slices in their own authority...
292                     create_slice(wsgi_request, slice_request)
293                     clear_user_creds(wsgi_request, user_email)
294                     self.template_name = 'slice-request-done-view.html'
295                 else:
296                     # Otherwise a wsgi_request is sent to the PI
297                     create_pending_slice(wsgi_request, slice_request, user_email)
298                     self.template_name = 'slice-request-ack-view.html'
299                 
300                 # log user activity
301                 activity.user.slice(wsgi_request)
302                 
303                 return render(wsgi_request, self.template, {'theme': self.theme}) # Redirect after POST
304         else:
305             slice_request = {}
306
307         template_env = {
308             'username': wsgi_request.user.email,
309             'errors': errors,
310             'slice_name': slice_name,
311             'purpose': purpose,
312             'email': user_email,
313             'user_hrn': user_hrn,
314             'url': url,
315             'pi': pi,
316             'authority_name': authority_name,        
317             'authority_hrn': user_authority,        
318             'cc_myself': True,
319             'authorities': authorities,
320             'theme': self.theme,
321             'section': "Slice request"
322         }
323         template_env.update(slice_request)
324         template_env.update(page.prelude_env())
325         return render(wsgi_request, self.template, template_env)