X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=portal%2Fviews.py;h=980265ca8800713c4dcabc95a9479e74f23ad796;hb=d68dcefd28c832608cdb359a07a8b871cbe612ae;hp=2dc5324733238710a82ff3db4776fc65a8576343;hpb=ca6870f59241a93d85a159d48890ac7ec408a1ea;p=myslice.git diff --git a/portal/views.py b/portal/views.py index 2dc53247..980265ca 100644 --- a/portal/views.py +++ b/portal/views.py @@ -39,10 +39,13 @@ from portal.forms import UserRegisterForm, SliceRequestForm, Cont from portal.util import RegistrationView, ActivationView from portal.models import PendingUser, PendingSlice from manifold.core.query import Query +from manifold.manifoldapi import execute_query from unfold.page import Page from myslice.viewutils import topmenu_items, the_user from django.http import HttpResponseRedirect, HttpResponse -import os.path, re + +from M2Crypto import Rand, RSA, BIO +import os, re class DashboardView(TemplateView): template_name = "dashboard.html" @@ -59,9 +62,12 @@ class DashboardView(TemplateView): #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn') slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn') auth_query = Query().get('network').select('network_hrn') + print "AUTH QUERY =====================", auth_query + print "filter", auth_query.filters page.enqueue_query(slice_query) page.enqueue_query(auth_query) + page.expose_js_metadata() page.expose_queries() slicelist = SimpleList( @@ -470,7 +476,12 @@ class UserValidateView(ActivationView): # View for my_account form def my_account(request): - return render(request, 'my_account.html') + return render(request, 'my_account.html', { + #'form': form, + 'topmenu_items': topmenu_items('My Account', request), + 'username': the_user (request) + }) + #my_acc form value processing def acc_process(request): @@ -488,7 +499,7 @@ def acc_process(request): #approach borrowed from register view #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email, password, site) #conventional approach - #b = PendingUser(first_name=edited_first_name, edited_last_name=last_name) + #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name) #b.save() # select and update [will be used throughout this view] @@ -509,8 +520,8 @@ def acc_process(request): get_user.save() return HttpResponse('Success: Password Changed!!') elif 'generate' in request.POST: - import os - from M2Crypto import Rand, RSA, BIO + #import os + #from M2Crypto import Rand, RSA, BIO KEY_LENGTH = 2048 @@ -534,9 +545,10 @@ def acc_process(request): private_key = pri_mem.getvalue() # Saving to DB keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}' - #keypair = re.sub("\r", "", keypair) - #keypair = re.sub("\n", "\\n", keypair) - keypair = keypair.rstrip('\r\n') + keypair = re.sub("\r", "", keypair) + keypair = re.sub("\n", "\\n", keypair) + #keypair = keypair.rstrip('\r\n') + keypair = ''.join(keypair.split()) get_user.keypair = keypair get_user.save() return HttpResponse('Success: New Keypair Generated! %s' % keypair) @@ -547,22 +559,100 @@ def acc_process(request): file_name = up_file.name file_extension = os.path.splitext(file_name)[1] allowed_extension = ['.pub','.txt'] - if file_extension in allowed_extension: + if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content): file_content = '{"user_public_key":"'+ file_content +'"}' file_content = re.sub("\r", "", file_content) file_content = re.sub("\n", "\\n",file_content) + file_content = ''.join(file_content.split()) get_user.keypair = file_content get_user.save() return HttpResponse('Success: Publickey uploaded! Old records overwritten') else: - return HttpResponse('Please upload a valid public key.') + return HttpResponse('Please upload a valid RSA public key [.txt or .pub].') else: message = 'You submitted an empty form.' return HttpResponse(message) def register_4m_f4f(request): - return render(request, 'register_4m_f4f.html') + #return render(request, 'register_4m_f4f.html') + +#def reg_4m_f4f_process(request): + if 'submit' in request.POST: + #get_email = PendingUser.objects.get(email) + reg_fname = request.POST['firstname'] + reg_lname = request.POST['lastname'] + reg_aff = request.POST['affiliation'] + reg_email = request.POST['email'].lower() + + #POST value validation + if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None): + messages.error(request, 'First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.') + #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name") + return render(request, 'register_4m_f4f.html') + if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None): + messages.error(request, 'Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.') + #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name") + return render(request, 'register_4m_f4f.html') + if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None): + messages.error(request, 'Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.') + #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation") + return render(request, 'register_4m_f4f.html') + if PendingUser.objects.filter(email__iexact=reg_email): + messages.error(request, 'Email already registered.Please provide a new email address.') + #return HttpResponse("Email Already exists") + return render(request, 'register_4m_f4f.html') + if 'generate' in request.POST['question']: + #import os + #from M2Crypto import Rand, RSA, BIO + + KEY_LENGTH = 2048 + + def blank_callback(): + "Replace the default dashes" + return + + # Random seed + Rand.rand_seed (os.urandom (KEY_LENGTH)) + # Generate key pair + key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback) + # Create memory buffers + pri_mem = BIO.MemoryBuffer() + pub_mem = BIO.MemoryBuffer() + # Save keys to buffers + key.save_key_bio(pri_mem, None) + key.save_pub_key_bio(pub_mem) + # Get keys + public_key = pub_mem.getvalue() + private_key = pri_mem.getvalue() + # Saving to DB + keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}' + keypair = re.sub("\r", "", keypair) + keypair = re.sub("\n", "\\n", keypair) + #keypair = keypair.rstrip('\r\n') + keypair = ''.join(keypair.split()) + #return HttpResponse(keypair) + else: + up_file = request.FILES['user_public_key'] + file_content = up_file.read() + file_name = up_file.name + file_extension = os.path.splitext(file_name)[1] + allowed_extension = ['.pub','.txt'] + if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content): + keypair = '{"user_public_key":"'+ file_content +'"}' + keypair = re.sub("\r", "", keypair) + keypair = re.sub("\n", "\\n",keypair) + keypair = ''.join(keypair.split()) + else: + return HttpResponse('Please upload a valid RSA public key [.txt or .pub].') + + b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff, + email=reg_email, password=request.POST['password'], keypair=keypair) + b.save() + + return render(request, 'user_register_complete.html') + return render(request, 'register_4m_f4f.html') + # view for contact form def contact(request): @@ -587,9 +677,12 @@ def contact(request): return render(request,'contact_sent.html') # Redirect after POST else: form = ContactForm() # An unbound form - + return render(request, 'contact.html', { 'form': form, + 'topmenu_items': topmenu_items('Contact Us', request), + 'username': the_user (request) + }) @@ -804,3 +897,217 @@ def pres_view_static(request, constraints, id): json_answer = json.dumps(cmd) return HttpResponse (json_answer, mimetype="application/json") + +class ValidatePendingView(TemplateView): + template_name = "validate_pending.html" + + def get_context_data(self, **kwargs): + # We might have slices on different registries with different user accounts + # We note that this portal could be specific to a given registry, to which we register users, but i'm not sure that simplifies things + # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn + + #messages.info(self.request, 'You have logged in') + page = Page(self.request) + + ctx_my_authorities = {} + ctx_delegation_authorities = {} + + + # The user need to be logged in + if the_user(self.request): + # Who can a PI validate: + # His own authorities + those he has credentials for. + # In MySlice we need to look at credentials also. + + + # XXX This will have to be asynchroneous. Need to implement barriers, + # for now it will be sufficient to have it working statically + + # get user_id to later on query accounts + # XXX Having real query plan on local tables would simplify all this + # XXX $user_email is still not available for local tables + #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id') + user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id') + user, = execute_query(self.request, user_query) + user_id = user['user_id'] + + # Query manifold to learn about available SFA platforms for more information + # In general we will at least have the portal + # For now we are considering all registries + all_authorities = [] + platform_ids = [] + sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type') + sfa_platforms = execute_query(self.request, sfa_platforms_query) + for sfa_platform in sfa_platforms: + print "SFA PLATFORM > ", sfa_platform['platform'] + if not 'auth_type' in sfa_platform: + continue + auth = sfa_platform['auth_type'] + if not auth in all_authorities: + all_authorities.append(auth) + platform_ids.append(sfa_platform['platform_id']) + + # We can check on which the user has authoritity credentials = PI rights + credential_authorities = set() + credential_authorities_expired = set() + + # User account on these registries + user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config') + user_accounts = execute_query(self.request, user_accounts_query) + #print "=" * 80 + #print user_accounts + #print "=" * 80 + for user_account in user_accounts: + config = json.loads(user_account['config']) + creds = [] + if 'authority_credentials' in config: + for authority_hrn, credential in config['authority_credentials'].items(): + #if credential is not expired: + credential_authorities.add(authority_hrn) + #else + # credential_authorities_expired.add(authority_hrn) + if 'delegated_authority_credentials' in config: + for authority_hrn, credential in config['delegated_authority_credentials'].items(): + #if credential is not expired: + credential_authorities.add(authority_hrn) + #else + # credential_authorities_expired.add(authority_hrn) + + print 'credential_authorities =', credential_authorities + print 'credential_authorities_expired =', credential_authorities_expired + + # ** Where am I a PI ** + # For this we need to ask SFA (of all authorities) = PI function + pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities') + pi_authorities_tmp = execute_query(self.request, pi_authorities_query) + pi_authorities = set() + for pa in pi_authorities_tmp: + pi_authorities |= set(pa['pi_authorities']) + + print "pi_authorities =", pi_authorities + + # My authorities + I have a credential + pi_credential_authorities = pi_authorities & credential_authorities + pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired + pi_expired_credential_authorities = pi_authorities & credential_authorities_expired + # Authorities I've been delegated PI rights + pi_delegation_credential_authorities = credential_authorities - pi_authorities + pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities + + print "pi_credential_authorities =", pi_credential_authorities + print "pi_no_credential_authorities =", pi_no_credential_authorities + print "pi_expired_credential_authorities =", pi_expired_credential_authorities + print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities + print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities + + # Summary intermediary + pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities + pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities + + print "--" + print "pi_my_authorities = ", pi_my_authorities + print "pi_delegation_authorities = ", pi_delegation_authorities + + # Summary all + queried_pending_authorities = pi_my_authorities | pi_delegation_authorities + print "----" + print "queried_pending_authorities = ", queried_pending_authorities + + # Pending requests + authorities + #pending_users = PendingUser.objects.filter(authority_hrn__in = queried_pending_authorities).all() + #pending_slices = PendingSlice.objects.filter(authority_hrn__in = queried_pending_authorities).all() + pending_users = PendingUser.objects.all() + pending_slices = PendingSlice.objects.all() + + # Dispatch requests and build the proper structure for the template: + + print "pending users =", pending_users + print "pending slices =", pending_slices + + for user in pending_users: + auth_hrn = user.authority_hrn + if not auth_hrn: + auth_hrn = "ple.upmc" # XXX HARDCODED + + request = {} + request['type'] = 'user' + request['id'] = 'TODO' # XXX in DB ? + request['timestamp'] = 'TODO' # XXX in DB ? + request['details'] = "%s %s <%s>" % (user.first_name, user.last_name, user.email) + + if auth_hrn in pi_my_authorities: + dest = ctx_my_authorities + + # define the css class + if auth_hrn in pi_credential_authorities: + request['allowed'] = 'allowed' + elif auth_hrn in pi_expired_credential_authorities: + request['allowed'] = 'expired' + else: # pi_no_credential_authorities + request['allowed'] = 'denied' + + elif auth_hrn in pi_delegation_authorities: + dest = ctx_delegation_authorities + + if auth_hrn in pi_delegation_credential_authorities: + request['allowed'] = 'allowed' + else: # pi_delegation_expired_authorities + request['allowed'] = 'expired' + + else: + continue + + if not auth_hrn in dest: + dest[auth_hrn] = [] + print "auth_hrn [%s] was added %r" % (auth_hrn, request) + dest[auth_hrn].append(request) + + for slice in pending_slices: + auth_hrn = slice.authority_hrn + if not auth_hrn: + auth_hrn = "ple.upmc" # XXX HARDCODED + + request = {} + request['type'] = 'slice' + request['id'] = 'TODO' # XXX in DB ? + request['timestamp'] = 'TODO' # XXX in DB ? + request['details'] = "Number of nodes: %d -- Type of nodes: %s
%s" % ('TODO', 'TODO', 'TODO') # XXX + if auth_hrn in pi_my_authorities: + dest = ctx_my_authorities + + # define the css class + if auth_hrn in pi_credential_authorities: + request['allowed'] = 'allowed' + elif auth_hrn in pi_expired_credential_authorities: + request['allowed'] = 'expired' + else: # pi_no_credential_authorities + request['allowed'] = 'denied' + + elif auth_hrn in pi_delegation_authorities: + dest = ctx_delegation_authorities + + if auth_hrn in pi_delegation_credential_authorities: + request['allowed'] = 'allowed' + else: # pi_delegation_expired_authorities + request['allowed'] = 'expired' + + if not auth_hrn in dest: + dest[auth_hrn] = [] + dest[auth_hrn].append(request) + + context = super(ValidatePendingView, self).get_context_data(**kwargs) + context['my_authorities'] = ctx_my_authorities + context['delegation_authorities'] = ctx_delegation_authorities + + # XXX This is repeated in all pages + # more general variables expected in the template + context['title'] = 'Test view that combines various plugins' + # the menu items on the top + context['topmenu_items'] = topmenu_items('Dashboard', self.request) + # so we can sho who is logged + context['username'] = the_user(self.request) + + # XXX We need to prepare the page for queries + #context.update(page.prelude_env()) + + return context