slice and project name should be lowercase, added checks in js and python
[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             project_name = wsgi_request.POST.get('project_name', '')
97             if not project_name or len(project_name) == 0 :
98                 errors.append('Project name can\'t be empty')
99
100             # accept only lowercase names
101             project_name = project_name.lower()
102
103             if 'join' in wsgi_request.POST:
104                 post = {
105                     'user_hrn'          : user_hrn,
106                     'email'             : user_email,
107                     'project_name'      : project_name,
108                     'authority_hrn'     : project_name,
109                 }
110
111             else:
112                 post = {
113                     'user_hrn'          : user_hrn,
114                     'email'             : user_email,
115                     'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
116                     'project_name'      : project_name,
117                     'purpose'           : wsgi_request.POST.get('purpose', ''),
118                 }
119
120                 # for new projects max project_name length is 10
121                 if (len(post['project_name']) >10):
122                     errors.append('Project name can be maximum 10 characters long')
123
124                 #if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
125                 #    errors.append('Organization is mandatory')
126     
127                 if post['purpose'] is None or post['purpose'] == '':
128                     errors.append('Project purpose is mandatory')
129
130                 if re.search(r'^[A-Za-z0-9_]*$', post['project_name']) is None:
131                     errors.append('Project name may contain only letters, numbers, and underscore.')
132
133             # What kind of project name is valid?
134             if post['project_name'] is None or post['project_name'] == '':
135                 errors.append('Project name is mandatory')   
136             
137             if not errors:
138                 logger.info("is_pi on auth_hrn = {}".format(user_authority))
139                 if is_pi(wsgi_request, user_hrn, user_authority):
140                     # PIs can directly create/join project in their own authority...
141                     if 'join' in wsgi_request.POST:
142                         authority_add_pis(wsgi_request, post['project_name'], user_hrn)
143                     else:
144                         hrn = post['authority_hrn'] + '.' + post['project_name']
145                         sfa_add_authority(wsgi_request, {'authority_hrn':hrn})
146                         authority_add_pis(wsgi_request, hrn, user_hrn)
147                     self.template_name = 'project-request-done-view.html'
148                 else:
149                     # Otherwise a wsgi_request is sent to the PI
150                     if 'join' in wsgi_request.POST:
151                         create_pending_join(wsgi_request, post)
152                     else:
153                         create_pending_project(wsgi_request, post)
154                     self.template_name = 'project-request-ack-view.html'
155
156         # retrieves the pending projects creation list
157         pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
158         # retrieves the pending join a project list
159         pending_join_projects = PendingJoin.objects.all().filter(user_hrn=user_hrn)
160
161         root_authority = user_authority.split('.', 1)[0]                  
162         env = {
163                'errors':        errors,
164                'username':      wsgi_request.user,
165                'theme':         self.theme,
166                'authorities':   authorities,
167                'authority_hrn': user_authority,
168                'root_authority_hrn': root_authority,
169                'pending_projects': pending_projects,
170                'pending_join_projects': pending_join_projects,
171         }
172         return render(wsgi_request, self.template, env)