1 # -*- coding: utf-8 -*-
3 # portal/views.py: views for the portal application
4 # This file is part of the Manifold project.
7 # Jordan Augé <jordan.auge@lip6.fr>
8 # Mohammed Yasin Rahman <mohammed-yasin.rahman@lip6.fr>
9 # Copyright 2013, UPMC Sorbonne Universités / LIP6
11 # This program is free software; you can redistribute it and/or modify it under
12 # the terms of the GNU General Public License as published by the Free Software
13 # Foundation; either version 3, or (at your option) any later version.
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20 # You should have received a copy of the GNU General Public License along with
21 # this program; see the file COPYING. If not, write to the Free Software
22 # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 from django.conf import settings
25 from django.contrib.sites.models import Site, RequestSite
26 from django.contrib import messages
27 from django.views.generic import View
28 from django.views.generic.base import TemplateView
29 from django.shortcuts import render
31 from plugins.lists.simplelist import SimpleList
32 from plugins.hazelnut import Hazelnut
33 from plugins.pres_view import PresView
34 from portal.event import Event
37 from portal import signals
38 from portal.forms import SliceRequestForm, ContactForm
39 from portal.util import RegistrationView, ActivationView
40 from portal.models import PendingUser, PendingSlice
41 from manifold.core.query import Query
42 from manifold.manifoldapi import execute_query
43 from unfold.page import Page
44 from myslice.viewutils import topmenu_items, the_user
45 from django.http import HttpResponseRedirect, HttpResponse
47 from M2Crypto import Rand, RSA, BIO
50 class DashboardView(TemplateView):
51 template_name = "dashboard.html"
53 def get_context_data(self, **kwargs):
54 # We might have slices on different registries with different user accounts
55 # 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
56 # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
58 #messages.info(self.request, 'You have logged in')
59 page = Page(self.request)
62 #slice_query = Query().get('slice').filter_by('user.user_hrn', 'contains', user_hrn).select('slice_hrn')
63 slice_query = Query().get('user').filter_by('user_hrn', '==', '$user_hrn').select('user_hrn', 'slice.slice_hrn')
64 auth_query = Query().get('network').select('network_hrn')
65 print "AUTH QUERY =====================", auth_query
66 print "filter", auth_query.filters
67 page.enqueue_query(slice_query)
68 page.enqueue_query(auth_query)
70 page.expose_js_metadata()
73 slicelist = SimpleList(
76 key = 'slice.slice_hrn',
80 authlist = SimpleList(
87 context = super(DashboardView, self).get_context_data(**kwargs)
88 context['person'] = self.request.user
89 context['networks'] = authlist.render(self.request)
90 context['slices'] = slicelist.render(self.request)
92 # XXX This is repeated in all pages
93 # more general variables expected in the template
94 context['title'] = 'Test view that combines various plugins'
95 # the menu items on the top
96 context['topmenu_items'] = topmenu_items('Dashboard', self.request)
97 # so we can sho who is logged
98 context['username'] = the_user(self.request)
100 context.update(page.prelude_env())
104 # DEPRECATED #class UserRegisterView(RegistrationView):
106 # DEPRECATED # A registration backend which follows a simple workflow:
108 # DEPRECATED # 1. User signs up, inactive account is created.
110 # DEPRECATED # 2. Email is sent to user with activation link.
112 # DEPRECATED # 3. User clicks activation link, account is now active.
114 # DEPRECATED # Using this backend requires that
116 # DEPRECATED # * ``registration`` be listed in the ``INSTALLED_APPS`` setting
117 # DEPRECATED # (since this backend makes use of models defined in this
118 # DEPRECATED # application).
120 # DEPRECATED # * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying
121 # DEPRECATED # (as an integer) the number of days from registration during
122 # DEPRECATED # which a user may activate their account (after that period
123 # DEPRECATED # expires, activation will be disallowed).
125 # DEPRECATED # * The creation of the templates
126 # DEPRECATED # ``registration/activation_email_subject.txt`` and
127 # DEPRECATED # ``registration/activation_email.txt``, which will be used for
128 # DEPRECATED # the activation email. See the notes for this backends
129 # DEPRECATED # ``register`` method for details regarding these templates.
131 # DEPRECATED # Additionally, registration can be temporarily closed by adding the
132 # DEPRECATED # setting ``REGISTRATION_OPEN`` and setting it to
133 # DEPRECATED # ``False``. Omitting this setting, or setting it to ``True``, will
134 # DEPRECATED # be interpreted as meaning that registration is currently open and
135 # DEPRECATED # permitt ed.
137 # DEPRECATED # Internally, this is accomplished via storing an activation key in
138 # DEPRECATED # an instance of ``registration.models.RegistrationProfile``. See
139 # DEPRECATED # that model and its custom manager for full documentation of its
140 # DEPRECATED # fields and supported operations.
143 # DEPRECATED ## DEPRECATED # form_class = UserRegisterForm
145 # DEPRECATED # def register(self, request, **cleaned_data):
147 # DEPRECATED # Given a username, email address and password, register a new
148 # DEPRECATED # user account, which will initially be inactive.
150 # DEPRECATED # Along with the new ``User`` object, a new
151 # DEPRECATED # ``registration.models.RegistrationProfile`` will be created,
152 # DEPRECATED # tied to that ``User``, containing the activation key which
153 # DEPRECATED # will be used for this account.
155 # DEPRECATED # An email will be sent to the supplied email address; this
156 # DEPRECATED # email should contain an activation link. The email will be
157 # DEPRECATED # rendered using two templates. See the documentation for
158 # DEPRECATED # ``RegistrationProfile.send_activation_email()`` for
159 # DEPRECATED # information about these templates and the contexts provided to
162 # DEPRECATED # After the ``User`` and ``RegistrationProfile`` are created and
163 # DEPRECATED # the activation email is sent, the signal
164 # DEPRECATED # ``registration.signals.user_registered`` will be sent, with
165 # DEPRECATED # the new ``User`` as the keyword argument ``user`` and the
166 # DEPRECATED # class of this backend as the sender.
169 # DEPRECATED # first_name = cleaned_data['first_name']
170 # DEPRECATED # last_name = cleaned_data['last_name']
171 # DEPRECATED # affiliation= cleaned_data['affiliation']
172 # DEPRECATED # email = cleaned_data['email']
173 # DEPRECATED # password = cleaned_data['password1']
175 # DEPRECATED # #password2 = cleaned_data['password2']
176 # DEPRECATED # keypair = cleaned_data['keypair']
178 # DEPRECATED # #if Site._meta.installed:
179 # DEPRECATED # # site = Site.objects.get_current()
180 # DEPRECATED # #else:
181 # DEPRECATED # # site = RequestSite(request)
182 # DEPRECATED # site = None
184 # DEPRECATED # new_user = PendingUser.objects.create_inactive_user(first_name, last_name, email, password, site)
185 # DEPRECATED # signals.user_registered.send(sender=self.__class__,
186 # DEPRECATED # user=new_user,
187 # DEPRECATED # request=request)
188 # DEPRECATED # return new_user
190 # DEPRECATED # def get_context_data(self, **kwargs):
191 # DEPRECATED # context = super(UserRegisterView, self).get_context_data(**kwargs)
192 # DEPRECATED # context['topmenu_items'] = topmenu_items('Register', self.request)
193 # DEPRECATED # context['username'] = the_user (self.request)
194 # DEPRECATED # return context
196 # DEPRECATED # def registration_allowed(self, request):
198 # DEPRECATED # Indicate whether account registration is currently permitted,
199 # DEPRECATED # based on the value of the setting ``REGISTRATION_OPEN``. This
200 # DEPRECATED # is determined as follows:
202 # DEPRECATED # * If ``REGISTRATION_OPEN`` is not specified in settings, or is
203 # DEPRECATED # set to ``True``, registration is permitted.
205 # DEPRECATED # * If ``REGISTRATION_OPEN`` is both specified and set to
206 # DEPRECATED # ``False``, registration is not permitted.
209 # DEPRECATED # return getattr(settings, 'REGISTRATION_OPEN', True)
211 # DEPRECATED # def get_success_url(self, request, user):
213 # DEPRECATED # Return the name of the URL to redirect to after successful
214 # DEPRECATED # user registration.
217 # DEPRECATED # return ('user_register_complete', (), {})
220 # DEPRECATED #class UserValidateView(ActivationView):
221 # DEPRECATED # def activate(self, request, activation_key):
223 # DEPRECATED # Given an an activation key, look up and activate the user
224 # DEPRECATED # account corresponding to that key (if possible).
226 # DEPRECATED # After successful activation, the signal
227 # DEPRECATED # ``registration.signals.user_activated`` will be sent, with the
228 # DEPRECATED # newly activated ``User`` as the keyword argument ``user`` and
229 # DEPRECATED # the class of this backend as the sender.
232 # DEPRECATED # activated_user = RegistrationProfile.objects.activate_user(activation_key)
233 # DEPRECATED # if activated_user:
234 # DEPRECATED # signals.user_activated.send(sender=self.__class__,
235 # DEPRECATED # user=activated_user,
236 # DEPRECATED # request=request)
237 # DEPRECATED # return activated_user
239 # DEPRECATED # def get_success_url(self, request, user):
240 # DEPRECATED # return ('registration_activation_complete', (), {})
243 # DEPRECATED #from portal.portalpage import PortalPage
244 # DEPRECATED #from plugins.wizard import Wizard
245 # DEPRECATED #from plugins.form import CreateForm
246 # DEPRECATED #from plugins.raw.raw import Raw # XXX
248 # DEPRECATED #from myslice.viewutils import the_user
250 # DEPRECATED #from django.template.loader import render_to_string
251 # DEPRECATED #from django.template import RequestContext
252 # DEPRECATED #from django.views import generic
254 # DEPRECATED #from django.contrib.formtools.wizard.views import NamedUrlSessionWizardView
255 # DEPRECATED ##from django.core.files.storage import FileSystemStorage
256 # DEPRECATED #from django.core.files.storage import default_storage
258 # DEPRECATED ##class MerlinWizard(NamedUrlSessionWizardView):
263 # DEPRECATED ## @classonlymethod
264 # DEPRECATED ## def as_view(cls, *args, **kwargs):
265 # DEPRECATED ## kwargs.update({
266 # DEPRECATED ## 'form_list': [
267 # DEPRECATED ## NameForm,
268 # DEPRECATED ## QuestForm,
269 # DEPRECATED ## ColorForm,
271 # DEPRECATED ## 'url_name': 'merlin_wizard'
273 # DEPRECATED ## return super(MerlinWizard, cls).as_view(*args, **kwargs)
275 # DEPRECATED #class UserRegisterWizardView(NamedUrlSessionWizardView):
276 # DEPRECATED ##class UserRegisterWizardView(LoginRequiredMixin, NamedUrlSessionWizardView):
277 # DEPRECATED # # Notice that I specify a file storage instance. If you don't specify this,
278 # DEPRECATED # # and you need to support FileField or ImageField in your forms, you'll get
279 # DEPRECATED # # errors from Django. This is something else I think could be handled by
280 # DEPRECATED # # the views better. Seems to me that it should just use whatever the
281 # DEPRECATED # # default/specified storage is for the rest of your project/application.
282 # DEPRECATED # file_storage = default_storage # FileSystemStorage()
283 # DEPRECATED # template_name = "register_user_wizard.html"
285 # DEPRECATED # def done(self, form_list, **kwargs):
286 # DEPRECATED # step1_form = form_list[0]
287 # DEPRECATED # step2_form = form_list[1]
289 # DEPRECATED # productext = self.create_product(product_form)
290 # DEPRECATED # shippings = self.create_shippings(productext, shipping_forms)
291 # DEPRECATED # images = self.create_images(productext, image_forms)
293 # DEPRECATED # if all([productext, shippings, images]):
294 # DEPRECATED # del self.request.session["wizard_product_wizard_view"]
296 # DEPRECATED # messages.success(self.request,
297 # DEPRECATED # _("Your product has been created."))
298 # DEPRECATED # return HttpResponseRedirect(self.get_success_url(productext))
300 # DEPRECATED # messages.error(self.request, _("Something went wrong creating your "
301 # DEPRECATED # "product. Please try again or contact support."))
302 # DEPRECATED # return HttpResponseRedirect(reverse("register_wizard"))
304 # DEPRECATED # #def get_form_kwargs(self, step):
305 # DEPRECATED # # if step == "product":
306 # DEPRECATED # # return {"user": self.request.user}
307 # DEPRECATED # # return {}
309 # DEPRECATED ## The portal should hook the slice and user creation pages
311 # DEPRECATED #def register_user(request):
313 # DEPRECATED # if request.method == 'POST':
314 # DEPRECATED # form = UserRegisterForm(request.POST) # Nous reprenons les données
315 # DEPRECATED # if form.is_valid():
316 # DEPRECATED # first_name = form.cleaned_data['first_name']
317 # DEPRECATED # last_name = form.cleaned_data['last_name']
318 # DEPRECATED # email = form.cleaned_data['email']
319 # DEPRECATED # password = form.cleaned_data['password']
320 # DEPRECATED # password2 = form.cleaned_data['password2']
321 # DEPRECATED # keypair = form.cleaned_data['keypair']
322 # DEPRECATED # ## Ici nous pouvons traiter les données du formulaire
323 # DEPRECATED # #sujet = form.cleaned_data['sujet']
324 # DEPRECATED # #message = form.cleaned_data['message']
325 # DEPRECATED # #envoyeur = form.cleaned_data['envoyeur']
326 # DEPRECATED # #renvoi = form.cleaned_data['renvoi']
327 # DEPRECATED # ## Nous pourrions ici envoyer l'e-mail grâce aux données que nous venons de récupérer
328 # DEPRECATED # #envoi = True
330 # DEPRECATED # form = UserRegisterForm()
331 # DEPRECATED # return render(request, 'register_user.html', locals())
333 # DEPRECATED #def index(request):
335 # DEPRECATED # WIZARD_TITLE = 'User registration'
336 # DEPRECATED # STEP1_TITLE = 'Enter your details'
337 # DEPRECATED # STEP2_TITLE = 'Select your institution'
338 # DEPRECATED # STEP3_TITLE = 'Authentication'
339 # DEPRECATED # STEP4_TITLE = 'Request a slice (optional)'
340 # DEPRECATED # STEP5_TITLE = 'Waiting for validation'
341 # DEPRECATED # STEP6_TITLE = 'Account validated'
343 # DEPRECATED # STEP0 = render_to_string('account_validated.html', context_instance=RequestContext(request))
344 # DEPRECATED # STEP2_HTML = """
345 # DEPRECATED # coucou
347 # DEPRECATED # STEP4 = """
350 # DEPRECATED # STEP5 = render_to_string('account_validated.html', context_instance=RequestContext(request))
352 # DEPRECATED # p = PortalPage(request)
354 # DEPRECATED # # This is redundant with the Wizard title
355 # DEPRECATED # p << "<h3>User registration</h3>"
357 # DEPRECATED # sons = []
358 # DEPRECATED # start_step = 1
360 # DEPRECATED # # STEP 1
361 # DEPRECATED # # If the user already exists (is logged), let's display a summary of his account details
362 # DEPRECATED # # Otherwise propose a form to fill in
363 # DEPRECATED # if the_user(request):
364 # DEPRECATED # # Fill a disabled form with user info
365 # DEPRECATED # # Please logout to register another user
366 # DEPRECATED # sons.append(Raw(page=p, title=STEP1_TITLE, togglable=False, html=STEP0))
367 # DEPRECATED # start_step += 1
369 # DEPRECATED # # We could pass a list of fields also, instead of retrieving them from metadata
370 # DEPRECATED # # Otherwise we need some heuristics to display nice forms
371 # DEPRECATED # # XXX Could we log the user in after the form is validated ?
372 # DEPRECATED # # XXX Explain the password is for XXX
373 # DEPRECATED # field_list = [{
374 # DEPRECATED # 'name' : 'First name',
375 # DEPRECATED # 'field' : 'firstname',
376 # DEPRECATED # 'type' : 'text',
377 # DEPRECATED # 'validate_rx' : '^[a-zA-Z -]+$',
378 # DEPRECATED # 'validate_err': 'Your first name must be comprised of letters only',
379 # DEPRECATED # 'description' : 'Enter your first name',
381 # DEPRECATED # 'name' : 'Last name',
382 # DEPRECATED # 'field' : 'lastname',
383 # DEPRECATED # 'type' : 'text',
384 # DEPRECATED # 'validate_rx' : '^[a-zA-Z -]+$',
385 # DEPRECATED # 'validate_err': 'Your last name must be comprised of letters only',
386 # DEPRECATED # 'description' : 'Enter your last name',
388 # DEPRECATED # 'name' : 'Email',
389 # DEPRECATED # 'field' : 'email',
390 # DEPRECATED # 'type' : 'text',
391 # DEPRECATED # 'description' : 'Enter your email address',
393 # DEPRECATED # 'name' : 'Password',
394 # DEPRECATED # 'field' : 'password',
395 # DEPRECATED # 'type' : 'password',
396 # DEPRECATED # 'description' : 'Enter your password',
398 # DEPRECATED # 'name' : 'Confirm password',
399 # DEPRECATED # 'field' : 'password2',
400 # DEPRECATED # 'type' : 'password',
401 # DEPRECATED # 'description' : 'Enter your password again',
403 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP1_TITLE, togglable = False, object = 'local:user', fields = field_list))
405 # DEPRECATED # # STEP 2
406 # DEPRECATED # # If the user already exists (is logged), let's display a summary of its institution
407 # DEPRECATED # # Otherwise propose a form to fill in (we should base our selection on the email)
408 # DEPRECATED # if the_user(request):
409 # DEPRECATED # # Fill a disabled form with institution
410 # DEPRECATED # # Please logout to register another user
411 # DEPRECATED # sons.append(Raw(page=p, title=STEP2_TITLE, togglable=False, html="User created"))
412 # DEPRECATED # start_step += 1
414 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP2_TITLE, togglable = False, object = 'slice')) #institution'))
416 # DEPRECATED # # STEP3
417 # DEPRECATED # # Please should your prefered authentication method
418 # DEPRECATED # # This step should allow the user to either choose the user or managed mode in MySlice
419 # DEPRECATED # sons.append(Raw(page = p, title = STEP3_TITLE, togglable = False, html = STEP2_HTML))
421 # DEPRECATED # # Step 4: Request a slice (optional)
422 # DEPRECATED # sons.append(CreateForm(page = p, title = STEP4_TITLE, togglable = False, object = 'slice'))
424 # DEPRECATED # # Step 5: Your request is waiting for validation
425 # DEPRECATED # # Periodic refresh
426 # DEPRECATED # sons.append(Raw(page = p, title = STEP5_TITLE, togglable = False, html = STEP4))
428 # DEPRECATED # # Step 6: Account validation = welcome for newly validated users
429 # DEPRECATED # # . delegation
430 # DEPRECATED # # . platforms
431 # DEPRECATED # # . slice
432 # DEPRECATED # # . pointers
433 # DEPRECATED # sons.append(Raw(page = p, title = STEP6_TITLE, togglable = False, html = STEP5))
435 # DEPRECATED # wizard = Wizard(
436 # DEPRECATED # page = p,
437 # DEPRECATED # title = WIZARD_TITLE,
438 # DEPRECATED # togglable = False,
439 # DEPRECATED # sons = sons,
440 # DEPRECATED # start_step = start_step,
443 # DEPRECATED # p << wizard.render(request) # in portal page if possible
445 # DEPRECATED # return p.render()
448 # DEPRECATED ## view for my_account
449 # DEPRECATED # class MyAccountView(TemplateView):
450 # DEPRECATED # template_name = "my_account.html"
452 # DEPRECATED # def from_process(self, request, **cleaned_data):
453 # DEPRECATED # #if request.method == 'POST':
454 # DEPRECATED # # if request.POST['submit_name']:
455 # DEPRECATED # if 'fname' in request.POST:
456 # DEPRECATED # messsag= "Got Name"
457 # DEPRECATED # #return render(request, 'portal/my_account.html')
458 # DEPRECATED # #response = HttpResponse("Here's the text of the Web page.")
459 # DEPRECATED # return HttpResponse(message)
461 # DEPRECATED # def get_context_data(self, **kwargs):
462 # DEPRECATED # page = Page(self.request)
463 # DEPRECATED # context = super(MyAccountView, self).get_context_data(**kwargs)
464 # DEPRECATED # context['person'] = self.request.user
465 # DEPRECATED # # XXX This is repeated in all pages
466 # DEPRECATED # # more general variables expected in the template
467 # DEPRECATED # context['title'] = 'User Profile Page'
468 # DEPRECATED # # the menu items on the top
469 # DEPRECATED # context['topmenu_items'] = topmenu_items('my_account', self.request)
470 # DEPRECATED # # so we can sho who is logged
471 # DEPRECATED # context['username'] = the_user(self.request)
472 # DEPRECATED # context.update(page.prelude_env())
473 # DEPRECATED # return context
477 # View for my_account form
478 def my_account(request):
479 return render(request, 'my_account.html', {
481 'topmenu_items': topmenu_items('My Account', request),
482 'username': the_user (request)
486 class PlatformsView(TemplateView):
487 template_name = "platforms.html"
489 def get_context_data(self, **kwargs):
490 page = Page(self.request)
492 network_query = Query().get('local:platform').filter_by('disabled', '==', '0').select('platform','platform_longname','gateway_type')
493 page.enqueue_query(network_query)
495 page.expose_js_metadata()
496 page.expose_queries()
497 networklist = Hazelnut(
500 domid = 'checkboxes',
501 # this is the query at the core of the slice list
502 query = network_query,
503 query_all = network_query,
505 datatables_options = {
506 # for now we turn off sorting on the checkboxes columns this way
507 # this of course should be automatic in hazelnut
508 'aoColumns' : [None, None, None, None, {'bSortable': False}],
509 'iDisplayLength' : 25,
510 'bLengthChange' : True,
514 # networklist = SimpleList(
518 # query = network_query,
521 context = super(PlatformsView, self).get_context_data(**kwargs)
522 context['person'] = self.request.user
523 context['networks'] = networklist.render(self.request)
525 # XXX This is repeated in all pages
526 # more general variables expected in the template
527 context['title'] = 'Platforms connected to MySlice'
528 # the menu items on the top
529 context['topmenu_items'] = topmenu_items('Platforms', self.request)
530 # so we can sho who is logged
531 context['username'] = the_user(self.request)
533 context.update(page.prelude_env())
537 # View for 1 platform and its details
538 class PlatformView(TemplateView):
539 template_name = "platform.html"
541 def get_context_data(self, **kwargs):
542 page = Page(self.request)
544 for key, value in kwargs.iteritems():
545 print "%s = %s" % (key, value)
546 if key == "platformname":
549 network_query = Query().get('local:platform').filter_by('platform', '==', platformname).select('platform','platform_longname','gateway_type')
550 page.enqueue_query(network_query)
552 page.expose_js_metadata()
553 page.expose_queries()
554 networklist = Hazelnut(
557 domid = 'checkboxes',
558 # this is the query at the core of the slice list
559 query = network_query,
560 query_all = network_query,
562 datatables_options = {
563 # for now we turn off sorting on the checkboxes columns this way
564 # this of course should be automatic in hazelnut
565 'aoColumns' : [None, None, None, None, {'bSortable': False}],
566 'iDisplayLength' : 25,
567 'bLengthChange' : True,
571 # networklist = SimpleList(
575 # query = network_query,
578 context = super(PlatformView, self).get_context_data(**kwargs)
579 context['person'] = self.request.user
580 context['networks'] = networklist.render(self.request)
582 # XXX This is repeated in all pages
583 # more general variables expected in the template
584 context['title'] = 'Platforms connected to MySlice'
585 # the menu items on the top
586 # context['topmenu_items'] = topmenu_items('Platforms', self.request)
587 # so we can sho who is logged
588 context['username'] = the_user(self.request)
590 context.update(page.prelude_env())
594 #my_acc form value processing
595 def acc_process(request):
596 # getting the user_id from the session [now hardcoded]
597 get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
598 if 'submit_name' in request.POST:
599 edited_first_name = request.POST['fname']
600 edited_last_name = request.POST['lname']
601 #email = 'test_email@gmail.com'
602 #password = 'test_pp'
603 #message = 'F_Name: %s L_name: %s dummy_pp: %s' % (first_name, last_name, password)
606 # insert into DB [needed for registration page]
607 #approach borrowed from register view
608 #new_user = PendingUser.objects.create_inactive_user(edited_first_name, edited_last_name, email, password, site)
609 #conventional approach
610 #b = PendingUser(first_name=edited_first_name, last_name=edited_last_name)
613 # select and update [will be used throughout this view]
614 # select the logged in user [for the moment hard coded]
615 #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
616 # update first and last name
617 get_user.first_name = edited_first_name
618 get_user.last_name = edited_last_name
621 return HttpResponse('Success: Name Updated!!')
622 elif 'submit_pass' in request.POST:
623 edited_password = request.POST['password']
624 # select the logged in user [for the moment hard coded]
625 #get_user = PendingUser.objects.get(id='1') # here we will get the id/email from session e.g., person.email
627 get_user.password = edited_password
629 return HttpResponse('Success: Password Changed!!')
630 elif 'generate' in request.POST:
632 #from M2Crypto import Rand, RSA, BIO
636 def blank_callback():
637 "Replace the default dashes"
641 Rand.rand_seed (os.urandom (KEY_LENGTH))
643 key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
644 # Create memory buffers
645 pri_mem = BIO.MemoryBuffer()
646 pub_mem = BIO.MemoryBuffer()
647 # Save keys to buffers
648 key.save_key_bio(pri_mem, None)
649 key.save_pub_key_bio(pub_mem)
652 public_key = pub_mem.getvalue()
653 private_key = pri_mem.getvalue()
655 keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
656 keypair = re.sub("\r", "", keypair)
657 keypair = re.sub("\n", "\\n", keypair)
658 #keypair = keypair.rstrip('\r\n')
659 keypair = ''.join(keypair.split())
660 get_user.keypair = keypair
662 return HttpResponse('Success: New Keypair Generated! %s' % keypair)
664 elif 'upload_key' in request.POST:
665 up_file = request.FILES['pubkey']
666 file_content = up_file.read()
667 file_name = up_file.name
668 file_extension = os.path.splitext(file_name)[1]
669 allowed_extension = ['.pub','.txt']
670 if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
671 file_content = '{"user_public_key":"'+ file_content +'"}'
672 file_content = re.sub("\r", "", file_content)
673 file_content = re.sub("\n", "\\n",file_content)
674 file_content = ''.join(file_content.split())
675 get_user.keypair = file_content
677 return HttpResponse('Success: Publickey uploaded! Old records overwritten')
679 return HttpResponse('Please upload a valid RSA public key [.txt or .pub].')
682 message = 'You submitted an empty form.'
683 return HttpResponse(message)
685 def register_4m_f4f(request):
687 if request.method == 'POST':
688 #get_email = PendingUser.objects.get(email)
689 reg_fname = request.POST.get('firstname', '')
690 reg_lname = request.POST.get('lastname', '')
691 reg_aff = request.POST.get('affiliation','')
692 reg_email = request.POST.get('email','').lower()
694 #POST value validation
695 if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
696 errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
697 #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
698 #return render(request, 'register_4m_f4f.html')
699 if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
700 errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
701 #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
702 #return render(request, 'register_4m_f4f.html')
703 if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
704 errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
705 #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
706 #return render(request, 'register_4m_f4f.html')
707 if PendingUser.objects.filter(email__iexact=reg_email):
708 errors.append('Email already registered.Please provide a new email address.')
709 #return HttpResponse("Email Already exists")
710 #return render(request, 'register_4m_f4f.html')
711 if 'generate' in request.POST['question']:
713 #from M2Crypto import Rand, RSA, BIO
717 def blank_callback():
718 "Replace the default dashes"
722 Rand.rand_seed (os.urandom (KEY_LENGTH))
724 key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
725 # Create memory buffers
726 pri_mem = BIO.MemoryBuffer()
727 pub_mem = BIO.MemoryBuffer()
728 # Save keys to buffers
729 key.save_key_bio(pri_mem, None)
730 key.save_pub_key_bio(pub_mem)
732 public_key = pub_mem.getvalue()
733 private_key = pri_mem.getvalue()
735 keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
736 keypair = re.sub("\r", "", keypair)
737 keypair = re.sub("\n", "\\n", keypair)
738 #keypair = keypair.rstrip('\r\n')
739 keypair = ''.join(keypair.split())
740 #return HttpResponse(keypair)
742 up_file = request.FILES['user_public_key']
743 file_content = up_file.read()
744 file_name = up_file.name
745 file_extension = os.path.splitext(file_name)[1]
746 allowed_extension = ['.pub','.txt']
747 if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
748 keypair = '{"user_public_key":"'+ file_content +'"}'
749 keypair = re.sub("\r", "", keypair)
750 keypair = re.sub("\n", "\\n",keypair)
751 keypair = ''.join(keypair.split())
753 errors.append('Please upload a valid RSA public key [.txt or .pub].')
755 #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
756 # email=reg_email, password=request.POST['password'], keypair=keypair)
759 b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
760 email=reg_email, password=request.POST['password'], keypair=keypair)
762 return render(request, 'user_register_complete.html')
764 return render(request, 'register_4m_f4f.html',{
765 'topmenu_items': topmenu_items('Register', request),
767 'firstname': request.POST.get('firstname', ''),
768 'lastname': request.POST.get('lastname', ''),
769 'affiliation': request.POST.get('affiliation', ''),
770 'email': request.POST.get('email', ''),
771 'password': request.POST.get('password', ''),
775 # view for contact form
776 def contact(request):
777 if request.method == 'POST': # If the form has been submitted...
778 form = ContactForm(request.POST) # A form bound to the POST data
779 if form.is_valid(): # All validation rules pass
780 # Process the data in form.cleaned_data
781 first_name = form.cleaned_data['first_name']
782 last_name = form.cleaned_data['last_name']
783 affiliation = form.cleaned_data['affiliation']
784 subject = form.cleaned_data['subject']
785 message = form.cleaned_data['message']
786 email = form.cleaned_data['email'] # email of the sender
787 cc_myself = form.cleaned_data['cc_myself']
789 recipients = ['yasin.upmc@gmail.com']
791 recipients.append(email)
793 from django.core.mail import send_mail
794 send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
795 return render(request,'contact_sent.html') # Redirect after POST
797 form = ContactForm() # An unbound form
799 return render(request, 'contact.html', {
801 'topmenu_items': topmenu_items('Contact Us', request),
802 'username': the_user (request)
807 def slice_request(request):
808 if request.method == 'POST': # If the form has been submitted...
809 form = SliceRequestForm(request.POST) # A form bound to the POST data
810 if form.is_valid(): # All validation rules pass
811 # Process the data in form.cleaned_data
812 slice_name = form.cleaned_data['slice_name']
813 number_of_nodes = form.cleaned_data['number_of_nodes']
814 type_of_nodes = form.cleaned_data['type_of_nodes']
815 purpose = form.cleaned_data['purpose']
816 email = form.cleaned_data['email'] # email of the sender
817 cc_myself = form.cleaned_data['cc_myself']
819 recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
821 recipients.append(email)
823 from django.core.mail import send_mail
824 send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
825 return render(request,'slicereq_recvd.html') # Redirect after POST
827 form = SliceRequestForm() # An unbound form
830 # template_env['form'] = form
831 # template_env['topmenu_items'] = topmenu_items('Request a slice', request)
832 # template_env['unfold1_main'] = render(request, 'slice_request_.html', {
835 # from django.shortcuts import render_to_response
836 # from django.template import RequestContext
837 # return render_to_response ('view-unfold1.html',template_env,
838 # context_instance=RequestContext(request))
840 return render(request, 'slice_request.html', {
842 'topmenu_items': topmenu_items('Request a slice', request),
843 'username': the_user (request)
847 class PresViewView(TemplateView):
848 template_name = "view-unfold1.html"
850 def get_context_data(self, **kwargs):
852 page = Page(self.request)
854 pres_view = PresView(page = page)
856 context = super(PresViewView, self).get_context_data(**kwargs)
858 #context['ALL_STATIC'] = "all_static"
859 context['unfold1_main'] = pres_view.render(self.request)
861 # XXX This is repeated in all pages
862 # more general variables expected in the template
863 context['title'] = 'Test view that combines various plugins'
864 # the menu items on the top
865 context['topmenu_items'] = topmenu_items('PresView', self.request)
866 # so we can sho who is logged
867 context['username'] = the_user(self.request)
869 prelude_env = page.prelude_env()
870 context.update(prelude_env)
874 def json_me(config_file,type):
876 for ligne in config_file:
877 if not ligne.startswith('#'):
878 args = ligne.split(';')
879 json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1] + '" ,"descriptif":"' + args[2]+'"')
881 json_answer += str(',"contraints":')
883 json_answer += str('""')
885 json_answer += str(args[3])
886 json_answer += str('},')
887 return json_answer[:-1]
890 DIR = '/var/myslice/'
891 STATIC = '%s/config_method_static' % DIR
892 DYNAMIC = '%s/config_method_dynamic' % DIR
893 ANIMATION = '%s/config_method_animation' % DIR
895 def pres_view_methods(request, type):
899 elif type =="static":
900 config = open(STATIC, "r")
901 json_answer = str('{ "options": [')
902 json_answer += str(json_me(config,"static"))
903 json_answer += str('] }')
905 elif type =="dynamic":
906 config = open(DYNAMIC, "r")
907 json_answer = str('{ "options": [')
908 json_answer += str(json_me(config,"dynamic"))
909 json_answer += str('] }')
911 elif type =="animation":
912 config = open(ANIMATION, "r")
913 json_answer = str('{ "options": [')
914 json_answer += str(json_me(config,"animation"))
915 json_answer += str('] }')
918 config = open(STATIC, "r")
919 json_answer = str('{ "static": [')
920 json_answer += str(json_me(config,"static"))
921 json_answer += str('],')
922 json_answer += str('"dynamic": [')
924 config = open(DYNAMIC, "r")
925 json_answer += str(json_me(config,"dynamic"))
926 json_answer += str('],')
927 json_answer += str('"animation": [')
929 config = open(ANIMATION, "r")
930 json_answer += str(json_me(config,"animation"))
931 json_answer += str('] }')
935 return HttpResponse (json_answer, mimetype="application/json")
937 def pres_view_animation(request, constraints, id):
939 # sites crees depuis 2008
940 # static.py?contraints=']date_created':1262325600&id='name_id"'
942 # method = request.getvalue('method') #ex : GetSites
943 #constraints = "']date_created':1262325600"
949 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
950 # constraints = {}#request.getvalue('constraints') // nul = {}
951 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
953 config_file = open(ANIMATION, "r")
954 for ligne in config_file:
955 if not ligne.startswith('#'):
956 ligne = ligne.split('\n')
957 first = ligne[0].split(';')
958 if (str(first[1]) == str(id)):
962 #Les print_method, print_option sont definis par le client (js)
963 #Les animations acceptent que les connexions anonymous
964 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
965 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
968 #Creation d'un objet event
972 "print_options": event.print_options,
973 "print_method": event.print_method,
974 "message": event.data
979 json_answer = json.dumps(cmd)
980 return HttpResponse (json_answer, mimetype="application/json")
982 def pres_view_static(request, constraints, id):
983 #constraints = "']date_created':1262325600"
986 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
987 # constraints = {}#request.getvalue('constraints') // nul = {}
988 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
990 config_file = open(STATIC, "r")
991 for ligne in config_file:
992 if not ligne.startswith('#'):
993 ligne = ligne.split('\n')
994 first = ligne[0].split(';')
995 if (str(first[1]) == str(id)):
999 #Les print_method, print_option sont definis par le client (js)
1000 #Les animations acceptent que les connexions anonymous
1001 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
1002 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
1005 #Creation d'un objet event
1009 "print_options": event.print_options,
1010 "print_method": event.print_method,
1011 "message": event.data
1016 json_answer = json.dumps(cmd)
1017 return HttpResponse (json_answer, mimetype="application/json")
1019 class ValidatePendingView(TemplateView):
1020 template_name = "validate_pending.html"
1022 def get_context_data(self, **kwargs):
1023 # We might have slices on different registries with different user accounts
1024 # 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
1025 # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
1027 #messages.info(self.request, 'You have logged in')
1028 page = Page(self.request)
1030 ctx_my_authorities = {}
1031 ctx_delegation_authorities = {}
1034 # The user need to be logged in
1035 if the_user(self.request):
1036 # Who can a PI validate:
1037 # His own authorities + those he has credentials for.
1038 # In MySlice we need to look at credentials also.
1041 # XXX This will have to be asynchroneous. Need to implement barriers,
1042 # for now it will be sufficient to have it working statically
1044 # get user_id to later on query accounts
1045 # XXX Having real query plan on local tables would simplify all this
1046 # XXX $user_email is still not available for local tables
1047 #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
1048 user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
1049 user, = execute_query(self.request, user_query)
1050 user_id = user['user_id']
1052 # Query manifold to learn about available SFA platforms for more information
1053 # In general we will at least have the portal
1054 # For now we are considering all registries
1055 all_authorities = []
1057 sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
1058 sfa_platforms = execute_query(self.request, sfa_platforms_query)
1059 for sfa_platform in sfa_platforms:
1060 print "SFA PLATFORM > ", sfa_platform['platform']
1061 if not 'auth_type' in sfa_platform:
1063 auth = sfa_platform['auth_type']
1064 if not auth in all_authorities:
1065 all_authorities.append(auth)
1066 platform_ids.append(sfa_platform['platform_id'])
1068 # We can check on which the user has authoritity credentials = PI rights
1069 credential_authorities = set()
1070 credential_authorities_expired = set()
1072 # User account on these registries
1073 user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
1074 user_accounts = execute_query(self.request, user_accounts_query)
1076 #print user_accounts
1078 for user_account in user_accounts:
1079 config = json.loads(user_account['config'])
1081 if 'authority_credentials' in config:
1082 for authority_hrn, credential in config['authority_credentials'].items():
1083 #if credential is not expired:
1084 credential_authorities.add(authority_hrn)
1086 # credential_authorities_expired.add(authority_hrn)
1087 if 'delegated_authority_credentials' in config:
1088 for authority_hrn, credential in config['delegated_authority_credentials'].items():
1089 #if credential is not expired:
1090 credential_authorities.add(authority_hrn)
1092 # credential_authorities_expired.add(authority_hrn)
1094 print 'credential_authorities =', credential_authorities
1095 print 'credential_authorities_expired =', credential_authorities_expired
1097 # ** Where am I a PI **
1098 # For this we need to ask SFA (of all authorities) = PI function
1099 pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
1100 pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
1101 pi_authorities = set()
1102 for pa in pi_authorities_tmp:
1103 pi_authorities |= set(pa['pi_authorities'])
1105 print "pi_authorities =", pi_authorities
1107 # My authorities + I have a credential
1108 pi_credential_authorities = pi_authorities & credential_authorities
1109 pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
1110 pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
1111 # Authorities I've been delegated PI rights
1112 pi_delegation_credential_authorities = credential_authorities - pi_authorities
1113 pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
1115 print "pi_credential_authorities =", pi_credential_authorities
1116 print "pi_no_credential_authorities =", pi_no_credential_authorities
1117 print "pi_expired_credential_authorities =", pi_expired_credential_authorities
1118 print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
1119 print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
1121 # Summary intermediary
1122 pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
1123 pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
1126 print "pi_my_authorities = ", pi_my_authorities
1127 print "pi_delegation_authorities = ", pi_delegation_authorities
1130 queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
1132 print "queried_pending_authorities = ", queried_pending_authorities
1134 # Pending requests + authorities
1135 #pending_users = PendingUser.objects.filter(authority_hrn__in = queried_pending_authorities).all()
1136 #pending_slices = PendingSlice.objects.filter(authority_hrn__in = queried_pending_authorities).all()
1137 pending_users = PendingUser.objects.all()
1138 pending_slices = PendingSlice.objects.all()
1140 # Dispatch requests and build the proper structure for the template:
1142 print "pending users =", pending_users
1143 print "pending slices =", pending_slices
1145 for user in pending_users:
1146 auth_hrn = user.authority_hrn
1148 auth_hrn = "ple.upmc" # XXX HARDCODED
1151 request['type'] = 'user'
1152 request['id'] = 'TODO' # XXX in DB ?
1153 request['timestamp'] = 'TODO' # XXX in DB ?
1154 request['details'] = "%s %s <%s>" % (user.first_name, user.last_name, user.email)
1156 if auth_hrn in pi_my_authorities:
1157 dest = ctx_my_authorities
1159 # define the css class
1160 if auth_hrn in pi_credential_authorities:
1161 request['allowed'] = 'allowed'
1162 elif auth_hrn in pi_expired_credential_authorities:
1163 request['allowed'] = 'expired'
1164 else: # pi_no_credential_authorities
1165 request['allowed'] = 'denied'
1167 elif auth_hrn in pi_delegation_authorities:
1168 dest = ctx_delegation_authorities
1170 if auth_hrn in pi_delegation_credential_authorities:
1171 request['allowed'] = 'allowed'
1172 else: # pi_delegation_expired_authorities
1173 request['allowed'] = 'expired'
1178 if not auth_hrn in dest:
1180 print "auth_hrn [%s] was added %r" % (auth_hrn, request)
1181 dest[auth_hrn].append(request)
1183 for slice in pending_slices:
1184 auth_hrn = slice.authority_hrn
1186 auth_hrn = "ple.upmc" # XXX HARDCODED
1189 request['type'] = 'slice'
1190 request['id'] = 'TODO' # XXX in DB ?
1191 request['timestamp'] = 'TODO' # XXX in DB ?
1192 request['details'] = "Number of nodes: %d -- Type of nodes: %s<br/>%s" % ('TODO', 'TODO', 'TODO') # XXX
1193 if auth_hrn in pi_my_authorities:
1194 dest = ctx_my_authorities
1196 # define the css class
1197 if auth_hrn in pi_credential_authorities:
1198 request['allowed'] = 'allowed'
1199 elif auth_hrn in pi_expired_credential_authorities:
1200 request['allowed'] = 'expired'
1201 else: # pi_no_credential_authorities
1202 request['allowed'] = 'denied'
1204 elif auth_hrn in pi_delegation_authorities:
1205 dest = ctx_delegation_authorities
1207 if auth_hrn in pi_delegation_credential_authorities:
1208 request['allowed'] = 'allowed'
1209 else: # pi_delegation_expired_authorities
1210 request['allowed'] = 'expired'
1212 if not auth_hrn in dest:
1214 dest[auth_hrn].append(request)
1216 context = super(ValidatePendingView, self).get_context_data(**kwargs)
1217 context['my_authorities'] = ctx_my_authorities
1218 context['delegation_authorities'] = ctx_delegation_authorities
1220 # XXX This is repeated in all pages
1221 # more general variables expected in the template
1222 context['title'] = 'Test view that combines various plugins'
1223 # the menu items on the top
1224 context['topmenu_items'] = topmenu_items('Dashboard', self.request)
1225 # so we can sho who is logged
1226 context['username'] = the_user(self.request)
1228 # XXX We need to prepare the page for queries
1229 #context.update(page.prelude_env())