Revision 5ce3ce4f snf-astakos-app/astakos/im/views.py

b/snf-astakos-app/astakos/im/views.py
53 53
from django.utils.http import urlencode
54 54
from django.utils.translation import ugettext as _
55 55
from django.views.generic.create_update import (create_object, delete_object,
56
    get_model_and_form_class
57
)
56
                                                get_model_and_form_class
57
                                                )
58 58
from django.views.generic.list_detail import object_list, object_detail
59 59

  
60
from astakos.im.models import (AstakosUser, ApprovalTerms, AstakosGroup, Resource,
60
from astakos.im.models import (
61
    AstakosUser, ApprovalTerms, AstakosGroup, Resource,
61 62
    EmailChange, GroupKind, Membership)
62 63
from astakos.im.activation_backends import get_backend, SimpleBackend
63 64
from astakos.im.util import get_context, prepare_response, set_cookie, get_query
64
from astakos.im.forms import (LoginForm, InvitationForm, ProfileForm, FeedbackForm,
65
from astakos.im.forms import (
66
    LoginForm, InvitationForm, ProfileForm, FeedbackForm,
65 67
    SignApprovalTermsForm, ExtendedPasswordChangeForm, EmailChangeForm,
66 68
    AstakosGroupCreationForm, AstakosGroupSearchForm
67 69
)
68 70
from astakos.im.functions import (send_feedback, SendMailError,
69
    invite as invite_func, logout as auth_logout, activate as activate_func,
70
    switch_account_to_shibboleth, send_admin_notification, SendNotificationError
71
)
72
from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
71
                                  invite as invite_func, logout as auth_logout, activate as activate_func,
72
                                  switch_account_to_shibboleth, send_admin_notification, SendNotificationError
73
                                  )
74
from astakos.im.settings import (
75
    COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
73 76
    LOGGING_LEVEL
74 77
)
75 78
from astakos.im.tasks import request_billing
76 79

  
77 80
logger = logging.getLogger(__name__)
78 81

  
82

  
79 83
def render_response(template, tab=None, status=200, reset_cookie=False, context_instance=None, **kwargs):
80 84
    """
81 85
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
......
85 89
    if tab is None:
86 90
        tab = template.partition('_')[0].partition('.html')[0]
87 91
    kwargs.setdefault('tab', tab)
88
    html = loader.render_to_string(template, kwargs, context_instance=context_instance)
92
    html = loader.render_to_string(
93
        template, kwargs, context_instance=context_instance)
89 94
    response = HttpResponse(html, status=status)
90 95
    if reset_cookie:
91 96
        set_cookie(response, context_instance['request'].user)
......
106 111
        return func(request, *args)
107 112
    return wrapper
108 113

  
114

  
109 115
def signed_terms_required(func):
110 116
    """
111 117
    Decorator checkes whether the request.user is Anonymous and in that case
......
115 121
    def wrapper(request, *args, **kwargs):
116 122
        if request.user.is_authenticated() and not request.user.signed_terms:
117 123
            params = urlencode({'next': request.build_absolute_uri(),
118
                              'show_form':''})
124
                                'show_form': ''})
119 125
            terms_uri = reverse('latest_terms') + '?' + params
120 126
            return HttpResponseRedirect(terms_uri)
121 127
        return func(request, *args, **kwargs)
122 128
    return wrapper
123 129

  
130

  
124 131
@signed_terms_required
125 132
def index(request, login_template_name='im/login.html', extra_context=None):
126 133
    """
......
148 155
    if request.user.is_authenticated():
149 156
        return HttpResponseRedirect(reverse('edit_profile'))
150 157
    return render_response(template_name,
151
                           login_form = LoginForm(request=request),
152
                           context_instance = get_context(request, extra_context))
158
                           login_form=LoginForm(request=request),
159
                           context_instance=get_context(request, extra_context))
160

  
153 161

  
154 162
@login_required
155 163
@signed_terms_required
......
190 198
    status = None
191 199
    message = None
192 200
    form = InvitationForm()
193
    
201

  
194 202
    inviter = request.user
195 203
    if request.method == 'POST':
196 204
        form = InvitationForm(request.POST)
......
219 227
    sent = [{'email': inv.username,
220 228
             'realname': inv.realname,
221 229
             'is_consumed': inv.is_consumed}
222
             for inv in request.user.invitations_sent.all()]
230
            for inv in request.user.invitations_sent.all()]
223 231
    kwargs = {'inviter': inviter,
224
              'sent':sent}
232
              'sent': sent}
225 233
    context = get_context(request, extra_context, **kwargs)
226 234
    return render_response(template_name,
227
                           invitation_form = form,
228
                           context_instance = context)
235
                           invitation_form=form,
236
                           context_instance=context)
237

  
229 238

  
230 239
@login_required
231 240
@signed_terms_required
......
282 291
            request.user.is_verified = True
283 292
            request.user.save()
284 293
    return render_response(template_name,
285
                           reset_cookie = reset_cookie,
286
                           profile_form = form,
287
                           context_instance = get_context(request,
288
                                                          extra_context))
294
                           reset_cookie=reset_cookie,
295
                           profile_form=form,
296
                           context_instance=get_context(request,
297
                                                        extra_context))
298

  
289 299

  
290 300
def signup(request, template_name='im/signup.html', on_success='im/signup_complete.html', extra_context=None, backend=None):
291 301
    """
......
298 308
    if present, otherwise to the ``astakos.im.activation_backends.InvitationBackend``
299 309
    if settings.ASTAKOS_INVITATIONS_ENABLED is True or ``astakos.im.activation_backends.SimpleBackend`` if not
300 310
    (see activation_backends);
301
    
311

  
302 312
    Upon successful user creation, if ``next`` url parameter is present the user is redirected there
303 313
    otherwise renders the same page with a success message.
304
    
314

  
305 315
    On unsuccessful creation, renders ``template_name`` with an error message.
306
    
316

  
307 317
    **Arguments**
308
    
318

  
309 319
    ``template_name``
310 320
        A custom template to render. This is optional;
311 321
        if not specified, this will default to ``im/signup.html``.
......
318 328
        An dictionary of variables to add to the template context.
319 329

  
320 330
    **Template:**
321
    
331

  
322 332
    im/signup.html or ``template_name`` keyword argument.
323
    im/signup_complete.html or ``on_success`` keyword argument. 
333
    im/signup_complete.html or ``on_success`` keyword argument.
324 334
    """
325 335
    if request.user.is_authenticated():
326 336
        return HttpResponseRedirect(reverse('edit_profile'))
327
    
337

  
328 338
    provider = get_query(request).get('provider', 'local')
329 339
    try:
330 340
        if not backend:
......
345 355
                    additional_email = form.cleaned_data['additional_email']
346 356
                    if additional_email != user.email:
347 357
                        user.additionalmail_set.create(email=additional_email)
348
                        msg = 'Additional email: %s saved for user %s.' % (additional_email, user.email)
358
                        msg = 'Additional email: %s saved for user %s.' % (
359
                            additional_email, user.email)
349 360
                        logger.log(LOGGING_LEVEL, msg)
350 361
                if user and user.is_active:
351 362
                    next = request.POST.get('next', '')
......
361 372
                messages.error(request, message)
362 373
                logger.exception(e)
363 374
    return render_response(template_name,
364
                           signup_form = form,
365
                           provider = provider,
375
                           signup_form=form,
376
                           provider=provider,
366 377
                           context_instance=get_context(request, extra_context))
367 378

  
379

  
368 380
@login_required
369 381
@signed_terms_required
370 382
def feedback(request, template_name='im/feedback.html', email_template_name='im/feedback_mail.txt', extra_context=None):
......
412 424
                message = _('Feedback successfully sent')
413 425
                messages.success(request, message)
414 426
    return render_response(template_name,
415
                           feedback_form = form,
416
                           context_instance = get_context(request, extra_context))
427
                           feedback_form=form,
428
                           context_instance=get_context(request, extra_context))
429

  
417 430

  
418 431
@signed_terms_required
419 432
def logout(request, template='registration/logged_out.html', extra_context=None):
......
441 454
    response.write(loader.render_to_string(template, context_instance=context))
442 455
    return response
443 456

  
457

  
444 458
@transaction.commit_manually
445 459
def activate(request, greeting_email_template_name='im/welcome_email.txt', helpdesk_email_template_name='im/helpdesk_notification.txt'):
446 460
    """
......
456 470
        user = AstakosUser.objects.get(auth_token=token)
457 471
    except AstakosUser.DoesNotExist:
458 472
        return HttpResponseBadRequest(_('No such user'))
459
    
473

  
460 474
    if user.is_active:
461 475
        message = _('Account already active.')
462 476
        messages.error(request, message)
463 477
        return index(request)
464
        
478

  
465 479
    try:
466 480
        local_user = AstakosUser.objects.get(
467
            ~Q(id = user.id),
481
            ~Q(id=user.id),
468 482
            email=user.email,
469 483
            is_active=True
470 484
        )
......
512 526
            transaction.rollback()
513 527
            return index(request)
514 528

  
529

  
515 530
def approval_terms(request, term_id=None, template_name='im/approval_terms.html', extra_context=None):
516 531
    term = None
517 532
    terms = None
......
538 553
        form = SignApprovalTermsForm(request.POST, instance=request.user)
539 554
        if not form.is_valid():
540 555
            return render_response(template_name,
541
                           terms = terms,
542
                           approval_terms_form = form,
543
                           context_instance = get_context(request, extra_context))
556
                                   terms=terms,
557
                                   approval_terms_form=form,
558
                                   context_instance=get_context(request, extra_context))
544 559
        user = form.save()
545 560
        return HttpResponseRedirect(next)
546 561
    else:
......
548 563
        if request.user.is_authenticated() and not request.user.signed_terms:
549 564
            form = SignApprovalTermsForm(instance=request.user)
550 565
        return render_response(template_name,
551
                               terms = terms,
552
                               approval_terms_form = form,
553
                               context_instance = get_context(request, extra_context))
566
                               terms=terms,
567
                               approval_terms_form=form,
568
                               context_instance=get_context(request, extra_context))
569

  
554 570

  
555 571
@signed_terms_required
556 572
def change_password(request):
557 573
    return password_change(request,
558
                            post_change_redirect=reverse('edit_profile'),
559
                            password_change_form=ExtendedPasswordChangeForm)
574
                           post_change_redirect=reverse('edit_profile'),
575
                           password_change_form=ExtendedPasswordChangeForm)
576

  
560 577

  
561 578
@signed_terms_required
562 579
@login_required
......
579 596
        except ValueError, e:
580 597
            messages.error(request, e)
581 598
        return render_response(confirm_template_name,
582
                               modified_user = user if 'user' in locals() else None,
583
                               context_instance = get_context(request,
584
                                                              extra_context))
585
    
599
                               modified_user=user if 'user' in locals(
600
                               ) else None,
601
                               context_instance=get_context(request,
602
                                                            extra_context))
603

  
586 604
    if not request.user.is_authenticated():
587 605
        path = quote(request.get_full_path())
588 606
        url = request.build_absolute_uri(reverse('index'))
......
604 622
            messages.success(request, msg)
605 623
            transaction.commit()
606 624
    return render_response(form_template_name,
607
                           form = form,
608
                           context_instance = get_context(request,
609
                                                          extra_context))
625
                           form=form,
626
                           context_instance=get_context(request,
627
                                                        extra_context))
628

  
610 629

  
611 630
@signed_terms_required
612 631
@login_required
613 632
def group_add(request, kind_name='default'):
614 633
    try:
615
        kind = GroupKind.objects.get(name = kind_name)
634
        kind = GroupKind.objects.get(name=kind_name)
616 635
    except:
617 636
        return HttpResponseBadRequest(_('No such group kind'))
618
    
619
    template_loader=loader
620
    post_save_redirect='/im/group/%(id)s/'
621
    context_processors=None
637

  
638
    template_loader = loader
639
    post_save_redirect = '/im/group/%(id)s/'
640
    context_processors = None
622 641
    model, form_class = get_model_and_form_class(
623 642
        model=None,
624 643
        form_class=AstakosGroupCreationForm
625 644
    )
626
    resources = dict( (str(r.id), r) for r in Resource.objects.select_related().all() )
645
    resources = dict(
646
        (str(r.id), r) for r in Resource.objects.select_related().all())
627 647
    policies = []
628 648
    if request.method == 'POST':
629 649
        form = form_class(request.POST, request.FILES, resources=resources)
630 650
        if form.is_valid():
631 651
            new_object = form.save()
632
            
652

  
633 653
            # save owner
634 654
            new_object.owners = [request.user]
635
            
655

  
636 656
            # save quota policies
637 657
            for (rid, limit) in form.resources():
638 658
                try:
......
643 663
                    continue
644 664
                else:
645 665
                    new_object.astakosgroupquota_set.create(
646
                        resource = r,
647
                        limit = limit
666
                        resource=r,
667
                        limit=limit
648 668
                    )
649 669
                policies.append('%s %d' % (r, limit))
650 670
            msg = _("The %(verbose_name)s was created successfully.") %\
651
                                    {"verbose_name": model._meta.verbose_name}
671
                {"verbose_name": model._meta.verbose_name}
652 672
            messages.success(request, msg, fail_silently=True)
653
            
673

  
654 674
            # send notification
655 675
            try:
656 676
                send_admin_notification(
657 677
                    template_name='im/group_creation_notification.txt',
658 678
                    dictionary={
659
                        'group':new_object,
660
                        'owner':request.user,
661
                        'policies':policies,
679
                        'group': new_object,
680
                        'owner': request.user,
681
                        'policies': policies,
662 682
                    },
663 683
                    subject='%s alpha2 testing group creation notification' % SITENAME
664 684
                )
......
668 688
    else:
669 689
        now = datetime.now()
670 690
        data = {
671
            'kind':kind
691
            'kind': kind
672 692
        }
673 693
        form = form_class(data, resources=resources)
674 694

  
......
683 703
    }, context_processors)
684 704
    return HttpResponse(t.render(c))
685 705

  
706

  
686 707
@signed_terms_required
687 708
@login_required
688 709
def group_list(request):
689 710
    list = request.user.astakos_groups.select_related().all()
690 711
    return object_list(request, queryset=list,
691
                extra_context=dict(
692
                    is_search=False
693
                )
694
    )
712
                       extra_context=dict(
713
                       is_search=False
714
                       )
715
                       )
716

  
695 717

  
696 718
@signed_terms_required
697 719
@login_required
......
701 723
    except AstakosGroup.DoesNotExist:
702 724
        return HttpResponseBadRequest(_('Invalid group.'))
703 725
    return object_detail(request,
704
         AstakosGroup.objects.all(),
705
         object_id=group_id,
706
         extra_context = {'quota':group.quota}
707
    )
726
                         AstakosGroup.objects.all(),
727
                         object_id=group_id,
728
                         extra_context={'quota': group.quota}
729
                         )
730

  
708 731

  
709 732
@signed_terms_required
710 733
@login_required
711 734
def group_approval_request(request, group_id):
712 735
    return HttpResponse()
713 736

  
737

  
714 738
@signed_terms_required
715 739
@login_required
716 740
def group_search(request, extra_context=None, **kwargs):
......
720 744
        form = AstakosGroupSearchForm(get_query(request))
721 745
        if form.is_valid():
722 746
            q = form.cleaned_data['q'].strip()
723
            queryset = AstakosGroup.objects.select_related().filter(name__contains=q)
747
            queryset = AstakosGroup.objects.select_related(
748
            ).filter(name__contains=q)
724 749
            return object_list(
725 750
                request,
726 751
                queryset,
......
732 757
            )
733 758
    return render_response(
734 759
        template='im/astakosgroup_list.html',
735
        form = form,
760
        form=form,
736 761
        context_instance=get_context(request, extra_context),
737 762
        is_search=False
738
        )
763
    )
764

  
739 765

  
740 766
@signed_terms_required
741 767
@login_required
742 768
def group_join(request, group_id):
743 769
    m = Membership(group_id=group_id,
744
        person=request.user,
745
        date_requested=datetime.now()
746
    )
770
                   person=request.user,
771
                   date_requested=datetime.now()
772
                   )
747 773
    try:
748 774
        m.save()
749 775
        post_save_redirect = reverse(
......
757 783
        messages.error(request, msg)
758 784
        return group_search(request)
759 785

  
786

  
760 787
@signed_terms_required
761 788
@login_required
762 789
def group_leave(request, group_id):
......
772 799
    return delete_object(
773 800
        request,
774 801
        model=Membership,
775
        object_id = m.id,
802
        object_id=m.id,
776 803
        template_name='im/astakosgroup_list.html',
777
        post_delete_redirect = reverse(
804
        post_delete_redirect=reverse(
778 805
            'group_detail',
779 806
            kwargs=dict(group_id=group_id)
780 807
        )
781 808
    )
782 809

  
810

  
783 811
def handle_membership():
784 812
    def decorator(func):
785 813
        @wraps(func)
......
804 832
        return wrapper
805 833
    return decorator
806 834

  
835

  
807 836
@signed_terms_required
808 837
@login_required
809 838
@handle_membership()
......
817 846
        logger.exception(e)
818 847
        msg = _('Something went wrong during %s\'s approval.' % realname)
819 848
        messages.error(request, msg)
820
    
849

  
850

  
821 851
@signed_terms_required
822 852
@login_required
823 853
@handle_membership()
......
832 862
        msg = _('Something went wrong during %s\'s disapproval.' % realname)
833 863
        messages.error(request, msg)
834 864

  
865

  
835 866
@signed_terms_required
836 867
@login_required
837 868
def resource_list(request):
......
840 871
        context_instance=get_context(request),
841 872
        quota=request.user.quota
842 873
    )
843
    
874

  
875

  
844 876
def group_create_list(request):
845 877
    return render_response(
846 878
        template='im/astakosgroup_create_list.html',
847 879
        context_instance=get_context(request),
848 880
    )
849 881

  
882

  
850 883
@signed_terms_required
851 884
@login_required
852 885
def billing(request):
......
855 888
    start = datetime(today.year, today.month, 1).strftime("%s")
856 889
    end = datetime(today.year, today.month, month_last_day).strftime("%s")
857 890
    r = request_billing.apply(args=(request.user.email,
858
        int(start) * 1000,
859
        int(end) * 1000)
860
    )
891
                                    int(start) * 1000,
892
                                    int(end) * 1000)
893
                              )
861 894
    data = None
862 895
    try:
863 896
        status, data = r.result
......
868 901
    return render_response(
869 902
        template='im/billing.html',
870 903
        context_instance=get_context(request),
871
        data = data
872
    )
904
        data=data
905
    )

Also available in: Unified diff