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):
688 authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
689 #authorities_query = Query.get('authority').select('authority_hrn')
690 authorities = execute_query(request, authorities_query)
692 if request.method == 'POST':
693 #get_email = PendingUser.objects.get(email)
694 reg_fname = request.POST.get('firstname', '')
695 reg_lname = request.POST.get('lastname', '')
696 reg_aff = request.POST.get('affiliation','')
697 reg_auth = request.POST.get('authority_hrn', '')
698 reg_email = request.POST.get('email','').lower()
700 #POST value validation
701 if (re.search(r'^[\w+\s.@+-]+$', reg_fname)==None):
702 errors.append('First Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
703 #return HttpResponse("Only Letters, Numbers, - and _ allowd in First Name")
704 #return render(request, 'register_4m_f4f.html')
705 if (re.search(r'^[\w+\s.@+-]+$', reg_lname) == None):
706 errors.append('Last Name may contain only letters, numbers, spaces and @/./+/-/_ characters.')
707 #return HttpResponse("Only Letters, Numbers, - and _ is allowed in Last name")
708 #return render(request, 'register_4m_f4f.html')
709 if (re.search(r'^[\w+\s.@+-]+$', reg_aff) == None):
710 errors.append('Affiliation may contain only letters, numbers, spaces and @/./+/-/_ characters.')
711 #return HttpResponse("Only Letters, Numbers and _ is allowed in Affiliation")
712 #return render(request, 'register_4m_f4f.html')
713 # XXX validate authority hrn !!
714 if PendingUser.objects.filter(email__iexact=reg_email):
715 errors.append('Email already registered.Please provide a new email address.')
716 #return HttpResponse("Email Already exists")
717 #return render(request, 'register_4m_f4f.html')
718 if 'generate' in request.POST['question']:
720 #from M2Crypto import Rand, RSA, BIO
724 def blank_callback():
725 "Replace the default dashes"
729 Rand.rand_seed (os.urandom (KEY_LENGTH))
731 key = RSA.gen_key (KEY_LENGTH, 65537, blank_callback)
732 # Create memory buffers
733 pri_mem = BIO.MemoryBuffer()
734 pub_mem = BIO.MemoryBuffer()
735 # Save keys to buffers
736 key.save_key_bio(pri_mem, None)
737 key.save_pub_key_bio(pub_mem)
739 public_key = pub_mem.getvalue()
740 private_key = pri_mem.getvalue()
742 keypair = '{"user_public_key":"'+ public_key + '", "user_private_key":"'+ private_key + '"}'
743 keypair = re.sub("\r", "", keypair)
744 keypair = re.sub("\n", "\\n", keypair)
745 #keypair = keypair.rstrip('\r\n')
746 keypair = ''.join(keypair.split())
747 #return HttpResponse(keypair)
749 up_file = request.FILES['user_public_key']
750 file_content = up_file.read()
751 file_name = up_file.name
752 file_extension = os.path.splitext(file_name)[1]
753 allowed_extension = ['.pub','.txt']
754 if file_extension in allowed_extension and re.search(r'ssh-rsa',file_content):
755 keypair = '{"user_public_key":"'+ file_content +'"}'
756 keypair = re.sub("\r", "", keypair)
757 keypair = re.sub("\n", "\\n",keypair)
758 keypair = ''.join(keypair.split())
760 errors.append('Please upload a valid RSA public key [.txt or .pub].')
762 #b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
763 # email=reg_email, password=request.POST['password'], keypair=keypair)
766 b = PendingUser(first_name=reg_fname, last_name=reg_lname, affiliation=reg_aff,
767 authority_hrn=reg_auth,
768 email=reg_email, password=request.POST['password'], keypair=keypair)
770 return render(request, 'user_register_complete.html')
772 return render(request, 'register_4m_f4f.html',{
773 'topmenu_items': topmenu_items('Register', request),
775 'firstname': request.POST.get('firstname', ''),
776 'lastname': request.POST.get('lastname', ''),
777 'affiliation': request.POST.get('affiliation', ''),
778 'authority_hrn': request.POST.get('authority_hrn', ''),
779 'email': request.POST.get('email', ''),
780 'password': request.POST.get('password', ''),
781 'authorities': authorities
785 # view for contact form
786 def contact(request):
787 if request.method == 'POST': # If the form has been submitted...
788 form = ContactForm(request.POST) # A form bound to the POST data
789 if form.is_valid(): # All validation rules pass
790 # Process the data in form.cleaned_data
791 first_name = form.cleaned_data['first_name']
792 last_name = form.cleaned_data['last_name']
793 affiliation = form.cleaned_data['affiliation']
794 subject = form.cleaned_data['subject']
795 message = form.cleaned_data['message']
796 email = form.cleaned_data['email'] # email of the sender
797 cc_myself = form.cleaned_data['cc_myself']
799 recipients = ['yasin.upmc@gmail.com']
801 recipients.append(email)
803 from django.core.mail import send_mail
804 send_mail("Onelab user submitted a query ", [first_name,last_name,affiliation,subject,message], email, recipients)
805 return render(request,'contact_sent.html') # Redirect after POST
807 form = ContactForm() # An unbound form
809 return render(request, 'contact.html', {
811 'topmenu_items': topmenu_items('Contact Us', request),
812 'username': the_user (request)
817 def slice_request(request):
818 if request.method == 'POST': # If the form has been submitted...
819 form = SliceRequestForm(request.POST) # A form bound to the POST data
820 if form.is_valid(): # All validation rules pass
821 # Process the data in form.cleaned_data
822 slice_name = form.cleaned_data['slice_name']
823 number_of_nodes = form.cleaned_data['number_of_nodes']
824 type_of_nodes = form.cleaned_data['type_of_nodes']
825 purpose = form.cleaned_data['purpose']
826 email = form.cleaned_data['email'] # email of the sender
827 cc_myself = form.cleaned_data['cc_myself']
829 recipients = ['yasin.upmc@gmail.com','jordan.auge@lip6.fr']
831 recipients.append(email)
833 from django.core.mail import send_mail
834 send_mail("Onelab New Slice request form submitted", [slice_name,number_of_nodes,type_of_nodes,purpose], email, recipients)
835 return render(request,'slicereq_recvd.html') # Redirect after POST
837 form = SliceRequestForm() # An unbound form
840 # template_env['form'] = form
841 # template_env['topmenu_items'] = topmenu_items('Request a slice', request)
842 # template_env['unfold1_main'] = render(request, 'slice_request_.html', {
845 # from django.shortcuts import render_to_response
846 # from django.template import RequestContext
847 # return render_to_response ('view-unfold1.html',template_env,
848 # context_instance=RequestContext(request))
850 return render(request, 'slice_request.html', {
852 'topmenu_items': topmenu_items('Request a slice', request),
853 'username': the_user (request)
857 class PresViewView(TemplateView):
858 template_name = "view-unfold1.html"
860 def get_context_data(self, **kwargs):
862 page = Page(self.request)
864 pres_view = PresView(page = page)
866 context = super(PresViewView, self).get_context_data(**kwargs)
868 #context['ALL_STATIC'] = "all_static"
869 context['unfold1_main'] = pres_view.render(self.request)
871 # XXX This is repeated in all pages
872 # more general variables expected in the template
873 context['title'] = 'Test view that combines various plugins'
874 # the menu items on the top
875 context['topmenu_items'] = topmenu_items('PresView', self.request)
876 # so we can sho who is logged
877 context['username'] = the_user(self.request)
879 prelude_env = page.prelude_env()
880 context.update(prelude_env)
884 def json_me(config_file,type):
886 for ligne in config_file:
887 if not ligne.startswith('#'):
888 args = ligne.split(';')
889 json_answer += str('{ "name": "' + args[0] + '" ,"id":"' + args[1] + '" ,"descriptif":"' + args[2]+'"')
891 json_answer += str(',"contraints":')
893 json_answer += str('""')
895 json_answer += str(args[3])
896 json_answer += str('},')
897 return json_answer[:-1]
900 DIR = '/var/myslice/'
901 STATIC = '%s/config_method_static' % DIR
902 DYNAMIC = '%s/config_method_dynamic' % DIR
903 ANIMATION = '%s/config_method_animation' % DIR
905 def pres_view_methods(request, type):
909 elif type =="static":
910 config = open(STATIC, "r")
911 json_answer = str('{ "options": [')
912 json_answer += str(json_me(config,"static"))
913 json_answer += str('] }')
915 elif type =="dynamic":
916 config = open(DYNAMIC, "r")
917 json_answer = str('{ "options": [')
918 json_answer += str(json_me(config,"dynamic"))
919 json_answer += str('] }')
921 elif type =="animation":
922 config = open(ANIMATION, "r")
923 json_answer = str('{ "options": [')
924 json_answer += str(json_me(config,"animation"))
925 json_answer += str('] }')
928 config = open(STATIC, "r")
929 json_answer = str('{ "static": [')
930 json_answer += str(json_me(config,"static"))
931 json_answer += str('],')
932 json_answer += str('"dynamic": [')
934 config = open(DYNAMIC, "r")
935 json_answer += str(json_me(config,"dynamic"))
936 json_answer += str('],')
937 json_answer += str('"animation": [')
939 config = open(ANIMATION, "r")
940 json_answer += str(json_me(config,"animation"))
941 json_answer += str('] }')
945 return HttpResponse (json_answer, mimetype="application/json")
947 def pres_view_animation(request, constraints, id):
949 # sites crees depuis 2008
950 # static.py?contraints=']date_created':1262325600&id='name_id"'
952 # method = request.getvalue('method') #ex : GetSites
953 #constraints = "']date_created':1262325600"
959 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
960 # constraints = {}#request.getvalue('constraints') // nul = {}
961 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
963 config_file = open(ANIMATION, "r")
964 for ligne in config_file:
965 if not ligne.startswith('#'):
966 ligne = ligne.split('\n')
967 first = ligne[0].split(';')
968 if (str(first[1]) == str(id)):
972 #Les print_method, print_option sont definis par le client (js)
973 #Les animations acceptent que les connexions anonymous
974 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
975 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
978 #Creation d'un objet event
982 "print_options": event.print_options,
983 "print_method": event.print_method,
984 "message": event.data
989 json_answer = json.dumps(cmd)
990 return HttpResponse (json_answer, mimetype="application/json")
992 def pres_view_static(request, constraints, id):
993 #constraints = "']date_created':1262325600"
996 # method = 'GetSites'#request.getvalue('method') #ex : GetSites
997 # constraints = {}#request.getvalue('constraints') // nul = {}
998 # response_field = "'site_id','name','date_created'"#request.getvalue('response_field')
1000 config_file = open(STATIC, "r")
1001 for ligne in config_file:
1002 if not ligne.startswith('#'):
1003 ligne = ligne.split('\n')
1004 first = ligne[0].split(';')
1005 if (str(first[1]) == str(id)):
1009 #Les print_method, print_option sont definis par le client (js)
1010 #Les animations acceptent que les connexions anonymous
1011 # args = "postmsg;animation;;;anonymous;https://www.planet-lab.eu/PLCAPI/;"
1012 args = ";;"+str(save[8])+";"+str(save[9])+";anonymous;"+str(save[5])+";"+str(save[6])+";{"+str(constraints)+"};"+str(save[7])+";"
1015 #Creation d'un objet event
1019 "print_options": event.print_options,
1020 "print_method": event.print_method,
1021 "message": event.data
1026 json_answer = json.dumps(cmd)
1027 return HttpResponse (json_answer, mimetype="application/json")
1029 class ValidatePendingView(TemplateView):
1030 template_name = "validate_pending.html"
1032 def get_context_data(self, **kwargs):
1033 # We might have slices on different registries with different user accounts
1034 # 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
1035 # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
1037 #messages.info(self.request, 'You have logged in')
1038 page = Page(self.request)
1040 ctx_my_authorities = {}
1041 ctx_delegation_authorities = {}
1044 # The user need to be logged in
1045 if the_user(self.request):
1046 # Who can a PI validate:
1047 # His own authorities + those he has credentials for.
1048 # In MySlice we need to look at credentials also.
1051 # XXX This will have to be asynchroneous. Need to implement barriers,
1052 # for now it will be sufficient to have it working statically
1054 # get user_id to later on query accounts
1055 # XXX Having real query plan on local tables would simplify all this
1056 # XXX $user_email is still not available for local tables
1057 #user_query = Query().get('local:user').filter_by('email', '==', '$user_email').select('user_id')
1058 user_query = Query().get('local:user').filter_by('email', '==', the_user(self.request)).select('user_id')
1059 user, = execute_query(self.request, user_query)
1060 user_id = user['user_id']
1062 # Query manifold to learn about available SFA platforms for more information
1063 # In general we will at least have the portal
1064 # For now we are considering all registries
1065 all_authorities = []
1067 sfa_platforms_query = Query().get('local:platform').filter_by('gateway_type', '==', 'sfa').select('platform_id', 'platform', 'auth_type')
1068 sfa_platforms = execute_query(self.request, sfa_platforms_query)
1069 for sfa_platform in sfa_platforms:
1070 print "SFA PLATFORM > ", sfa_platform['platform']
1071 if not 'auth_type' in sfa_platform:
1073 auth = sfa_platform['auth_type']
1074 if not auth in all_authorities:
1075 all_authorities.append(auth)
1076 platform_ids.append(sfa_platform['platform_id'])
1078 # We can check on which the user has authoritity credentials = PI rights
1079 credential_authorities = set()
1080 credential_authorities_expired = set()
1082 # User account on these registries
1083 user_accounts_query = Query.get('local:account').filter_by('user_id', '==', user_id).filter_by('platform_id', 'included', platform_ids).select('config')
1084 user_accounts = execute_query(self.request, user_accounts_query)
1086 #print user_accounts
1088 for user_account in user_accounts:
1089 config = json.loads(user_account['config'])
1091 if 'authority_credentials' in config:
1092 for authority_hrn, credential in config['authority_credentials'].items():
1093 #if credential is not expired:
1094 credential_authorities.add(authority_hrn)
1096 # credential_authorities_expired.add(authority_hrn)
1097 if 'delegated_authority_credentials' in config:
1098 for authority_hrn, credential in config['delegated_authority_credentials'].items():
1099 #if credential is not expired:
1100 credential_authorities.add(authority_hrn)
1102 # credential_authorities_expired.add(authority_hrn)
1104 print 'credential_authorities =', credential_authorities
1105 print 'credential_authorities_expired =', credential_authorities_expired
1107 # ** Where am I a PI **
1108 # For this we need to ask SFA (of all authorities) = PI function
1109 pi_authorities_query = Query.get('user').filter_by('user_hrn', '==', '$user_hrn').select('pi_authorities')
1110 pi_authorities_tmp = execute_query(self.request, pi_authorities_query)
1111 pi_authorities = set()
1112 for pa in pi_authorities_tmp:
1113 pi_authorities |= set(pa['pi_authorities'])
1115 print "pi_authorities =", pi_authorities
1117 # My authorities + I have a credential
1118 pi_credential_authorities = pi_authorities & credential_authorities
1119 pi_no_credential_authorities = pi_authorities - credential_authorities - credential_authorities_expired
1120 pi_expired_credential_authorities = pi_authorities & credential_authorities_expired
1121 # Authorities I've been delegated PI rights
1122 pi_delegation_credential_authorities = credential_authorities - pi_authorities
1123 pi_delegation_expired_authorities = credential_authorities_expired - pi_authorities
1125 print "pi_credential_authorities =", pi_credential_authorities
1126 print "pi_no_credential_authorities =", pi_no_credential_authorities
1127 print "pi_expired_credential_authorities =", pi_expired_credential_authorities
1128 print "pi_delegation_credential_authorities = ", pi_delegation_credential_authorities
1129 print "pi_delegation_expired_authorities = ", pi_delegation_expired_authorities
1131 # Summary intermediary
1132 pi_my_authorities = pi_credential_authorities | pi_no_credential_authorities | pi_expired_credential_authorities
1133 pi_delegation_authorities = pi_delegation_credential_authorities | pi_delegation_expired_authorities
1136 print "pi_my_authorities = ", pi_my_authorities
1137 print "pi_delegation_authorities = ", pi_delegation_authorities
1140 queried_pending_authorities = pi_my_authorities | pi_delegation_authorities
1142 print "queried_pending_authorities = ", queried_pending_authorities
1144 # Pending requests + authorities
1145 #pending_users = PendingUser.objects.filter(authority_hrn__in = queried_pending_authorities).all()
1146 #pending_slices = PendingSlice.objects.filter(authority_hrn__in = queried_pending_authorities).all()
1147 pending_users = PendingUser.objects.all()
1148 pending_slices = PendingSlice.objects.all()
1150 # Dispatch requests and build the proper structure for the template:
1152 print "pending users =", pending_users
1153 print "pending slices =", pending_slices
1155 for user in pending_users:
1156 auth_hrn = user.authority_hrn
1159 request['type'] = 'user'
1160 request['id'] = 'TODO' # XXX in DB ?
1161 request['timestamp'] = 'TODO' # XXX in DB ?
1162 request['details'] = "%s %s <%s>" % (user.first_name, user.last_name, user.email)
1164 if auth_hrn in pi_my_authorities:
1165 dest = ctx_my_authorities
1167 # define the css class
1168 if auth_hrn in pi_credential_authorities:
1169 request['allowed'] = 'allowed'
1170 elif auth_hrn in pi_expired_credential_authorities:
1171 request['allowed'] = 'expired'
1172 else: # pi_no_credential_authorities
1173 request['allowed'] = 'denied'
1175 elif auth_hrn in pi_delegation_authorities:
1176 dest = ctx_delegation_authorities
1178 if auth_hrn in pi_delegation_credential_authorities:
1179 request['allowed'] = 'allowed'
1180 else: # pi_delegation_expired_authorities
1181 request['allowed'] = 'expired'
1186 if not auth_hrn in dest:
1188 print "auth_hrn [%s] was added %r" % (auth_hrn, request)
1189 dest[auth_hrn].append(request)
1191 for slice in pending_slices:
1192 auth_hrn = slice.authority_hrn
1194 auth_hrn = "ple.upmc" # XXX HARDCODED
1197 request['type'] = 'slice'
1198 request['id'] = 'TODO' # XXX in DB ?
1199 request['timestamp'] = 'TODO' # XXX in DB ?
1200 request['details'] = "Number of nodes: %d -- Type of nodes: %s<br/>%s" % ('TODO', 'TODO', 'TODO') # XXX
1201 if auth_hrn in pi_my_authorities:
1202 dest = ctx_my_authorities
1204 # define the css class
1205 if auth_hrn in pi_credential_authorities:
1206 request['allowed'] = 'allowed'
1207 elif auth_hrn in pi_expired_credential_authorities:
1208 request['allowed'] = 'expired'
1209 else: # pi_no_credential_authorities
1210 request['allowed'] = 'denied'
1212 elif auth_hrn in pi_delegation_authorities:
1213 dest = ctx_delegation_authorities
1215 if auth_hrn in pi_delegation_credential_authorities:
1216 request['allowed'] = 'allowed'
1217 else: # pi_delegation_expired_authorities
1218 request['allowed'] = 'expired'
1220 if not auth_hrn in dest:
1222 dest[auth_hrn].append(request)
1224 context = super(ValidatePendingView, self).get_context_data(**kwargs)
1225 context['my_authorities'] = ctx_my_authorities
1226 context['delegation_authorities'] = ctx_delegation_authorities
1228 # XXX This is repeated in all pages
1229 # more general variables expected in the template
1230 context['title'] = 'Test view that combines various plugins'
1231 # the menu items on the top
1232 context['topmenu_items'] = topmenu_items('Dashboard', self.request)
1233 # so we can sho who is logged
1234 context['username'] = the_user(self.request)
1236 # XXX We need to prepare the page for queries
1237 #context.update(page.prelude_env())