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