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