Revision dd5f8f4d
b/snf-astakos-app/astakos/im/auth_providers.py | ||
---|---|---|
42 | 42 |
from astakos.im import messages as astakos_messages |
43 | 43 |
|
44 | 44 |
import logging |
45 |
import urllib |
|
45 | 46 |
|
46 | 47 |
logger = logging.getLogger(__name__) |
47 | 48 |
|
... | ... | |
87 | 88 |
msg = 'AUTH_PROVIDER_%s' % msg |
88 | 89 |
return override_msg or getattr(astakos_messages, msg, msg) % params |
89 | 90 |
|
91 |
@property |
|
92 |
def add_url(self): |
|
93 |
return reverse(self.login_view) |
|
94 |
|
|
90 | 95 |
def __init__(self, user=None): |
91 | 96 |
self.user = user |
97 |
for tpl in ['login_prompt', 'login', 'signup_prompt']: |
|
98 |
tpl_name = '%s_%s' % (tpl, 'template') |
|
99 |
override = self.get_setting(tpl_name) |
|
100 |
if override: |
|
101 |
setattr(self, tpl_name, override) |
|
92 | 102 |
|
93 | 103 |
def __getattr__(self, key): |
94 | 104 |
if not key.startswith('get_'): |
... | ... | |
141 | 151 |
login_prompt = _('if you already have a username and password') |
142 | 152 |
signup_prompt = _('New to ~okeanos ?') |
143 | 153 |
signup_link_prompt = _('create an account now') |
144 |
|
|
145 |
|
|
146 |
@property |
|
147 |
def add_url(self): |
|
148 |
return reverse('password_change') |
|
154 |
login_view = 'password_change' |
|
149 | 155 |
|
150 | 156 |
one_per_user = True |
151 | 157 |
|
... | ... | |
171 | 177 |
primary_login_prompt = _('If you are a student/researcher/faculty you can' |
172 | 178 |
' login using your university-credentials in' |
173 | 179 |
' the following page') |
174 |
|
|
175 |
@property |
|
176 |
def add_url(self): |
|
177 |
return reverse('astakos.im.target.shibboleth.login') |
|
180 |
login_view = 'astakos.im.target.shibboleth.login' |
|
178 | 181 |
|
179 | 182 |
login_template = 'im/auth/shibboleth_login.html' |
180 |
login_prompt_template = 'im/auth/shibboleth_login_prompt.html'
|
|
183 |
login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html'
|
|
181 | 184 |
|
182 | 185 |
|
183 | 186 |
class TwitterAuthProvider(AuthProvider): |
... | ... | |
186 | 189 |
add_prompt = _('Allows you to login to your account using Twitter') |
187 | 190 |
details_tpl = _('Twitter screen name: %(info_screen_name)s') |
188 | 191 |
user_title = _('Twitter (%(info_screen_name)s)') |
189 |
|
|
190 |
@property |
|
191 |
def add_url(self): |
|
192 |
return reverse('astakos.im.target.twitter.login') |
|
192 |
login_view = 'astakos.im.target.twitter.login' |
|
193 | 193 |
|
194 | 194 |
login_template = 'im/auth/third_party_provider_generic_login.html' |
195 | 195 |
login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html' |
... | ... | |
201 | 201 |
add_prompt = _('Allows you to login to your account using Google') |
202 | 202 |
details_tpl = _('Google account: %(info_email)s') |
203 | 203 |
user_title = _('Google (%(info_email)s)') |
204 |
|
|
205 |
@property |
|
206 |
def add_url(self): |
|
207 |
return reverse('astakos.im.target.google.login') |
|
204 |
login_view = 'astakos.im.target.google.login' |
|
208 | 205 |
|
209 | 206 |
login_template = 'im/auth/third_party_provider_generic_login.html' |
210 | 207 |
login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html' |
... | ... | |
216 | 213 |
add_prompt = _('Allows you to login to your account using LinkedIn') |
217 | 214 |
user_title = _('LinkedIn (%(info_emailAddress)s)') |
218 | 215 |
details_tpl = _('LinkedIn account: %(info_emailAddress)s') |
219 |
|
|
220 |
@property |
|
221 |
def add_url(self): |
|
222 |
return reverse('astakos.im.target.linkedin.login') |
|
216 |
login_view = 'astakos.im.target.linkedin.login' |
|
223 | 217 |
|
224 | 218 |
login_template = 'im/auth/third_party_provider_generic_login.html' |
225 | 219 |
login_prompt_template = 'im/auth/third_party_provider_generic_login_prompt.html' |
b/snf-astakos-app/astakos/im/forms.py | ||
---|---|---|
468 | 468 |
|
469 | 469 |
class ExtendedPasswordResetForm(PasswordResetForm): |
470 | 470 |
""" |
471 |
Extends PasswordResetForm by overriding save method: |
|
472 |
passes a custom from_email in send_mail. |
|
471 |
Extends PasswordResetForm by overriding |
|
473 | 472 |
|
474 |
Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
|
|
475 |
accepts a from_email argument.
|
|
473 |
save method: to pass a custom from_email in send_mail.
|
|
474 |
clean_email: to handle local auth provider checks
|
|
476 | 475 |
""" |
477 | 476 |
def clean_email(self): |
478 | 477 |
email = super(ExtendedPasswordResetForm, self).clean_email() |
479 | 478 |
try: |
480 |
user = AstakosUser.objects.get(email__iexact=email) |
|
479 |
user = AstakosUser.objects.get_by_identifier(email) |
|
480 |
|
|
481 |
if not user.is_active: |
|
482 |
raise forms.ValidationError(_(astakos_messages.ACCOUNT_INACTIVE)) |
|
483 |
|
|
481 | 484 |
if not user.has_usable_password(): |
482 | 485 |
raise forms.ValidationError(_(astakos_messages.UNUSABLE_PASSWORD)) |
483 | 486 |
|
484 | 487 |
if not user.can_change_password(): |
485 |
raise forms.ValidationError(_('Password change for this account' |
|
486 |
' is not supported.')) |
|
487 |
|
|
488 |
raise forms.ValidationError(_(astakos_messages.AUTH_PROVIDER_CANNOT_CHANGE_PASSWORD)) |
|
488 | 489 |
except AstakosUser.DoesNotExist, e: |
489 | 490 |
raise forms.ValidationError(_(astakos_messages.EMAIL_UNKNOWN)) |
490 | 491 |
return email |
... | ... | |
619 | 620 |
# ) |
620 | 621 |
# desc = forms.CharField( |
621 | 622 |
# label= 'Description', |
622 |
# widget=forms.Textarea,
|
|
623 |
# widget=forms.Textarea, |
|
623 | 624 |
# help_text= "Please provide a short but descriptive abstract of your Project, so that anyone searching can quickly understand what this Project is about. " |
624 | 625 |
# ) |
625 | 626 |
# issue_date = forms.DateTimeField( |
... | ... | |
641 | 642 |
# required=True, min_value=1, |
642 | 643 |
# help_text="Here you specify the number of members this Project is going to have. This means that this number of people will be granted the resources you will specify in the next step. This can be '1' if you are the only one wanting to get resources. " |
643 | 644 |
# ) |
644 |
#
|
|
645 |
# |
|
645 | 646 |
# class Meta: |
646 | 647 |
# model = AstakosGroup |
647 |
#
|
|
648 |
# |
|
648 | 649 |
# def __init__(self, *args, **kwargs): |
649 | 650 |
# #update QueryDict |
650 | 651 |
# args = list(args) |
651 | 652 |
# qd = args.pop(0).copy() |
652 | 653 |
# members_unlimited = qd.pop('members_unlimited', False) |
653 | 654 |
# members_uplimit = qd.pop('members_uplimit', None) |
654 |
#
|
|
655 |
# |
|
655 | 656 |
# #substitue QueryDict |
656 | 657 |
# args.insert(0, qd) |
657 |
#
|
|
658 |
# |
|
658 | 659 |
# super(AstakosGroupCreationForm, self).__init__(*args, **kwargs) |
659 |
#
|
|
660 |
# |
|
660 | 661 |
# self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc', |
661 | 662 |
# 'issue_date', 'expiration_date', |
662 | 663 |
# 'moderation_enabled', 'max_participants'] |
... | ... | |
670 | 671 |
# map(add_fields, |
671 | 672 |
# ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit')) |
672 | 673 |
# ) |
673 |
#
|
|
674 |
# |
|
674 | 675 |
# def add_fields((k, v)): |
675 | 676 |
# self.fields[k] = forms.BooleanField( |
676 | 677 |
# required=False, |
... | ... | |
679 | 680 |
# map(add_fields, |
680 | 681 |
# ((k, v) for k,v in qd.iteritems() if k.startswith('is_selected_')) |
681 | 682 |
# ) |
682 |
#
|
|
683 |
# |
|
683 | 684 |
# def policies(self): |
684 | 685 |
# self.clean() |
685 | 686 |
# policies = [] |
686 | 687 |
# append = policies.append |
687 | 688 |
# for name, uplimit in self.cleaned_data.iteritems(): |
688 |
#
|
|
689 |
# |
|
689 | 690 |
# subs = name.split('_uplimit') |
690 | 691 |
# if len(subs) == 2: |
691 | 692 |
# prefix, suffix = subs |
692 | 693 |
# s, sep, r = prefix.partition(RESOURCE_SEPARATOR) |
693 | 694 |
# resource = Resource.objects.get(service__name=s, name=r) |
694 |
#
|
|
695 |
# |
|
695 | 696 |
# # keep only resource limits for selected resource groups |
696 | 697 |
# if self.cleaned_data.get( |
697 | 698 |
# 'is_selected_%s' % resource.group, False |
698 | 699 |
# ): |
699 | 700 |
# append(dict(service=s, resource=r, uplimit=uplimit)) |
700 | 701 |
# return policies |
701 |
#
|
|
702 |
# |
|
702 | 703 |
# class AstakosGroupCreationSummaryForm(forms.ModelForm): |
703 | 704 |
# kind = forms.ModelChoiceField( |
704 | 705 |
# queryset=GroupKind.objects.all(), |
... | ... | |
717 | 718 |
# max_participants = forms.IntegerField( |
718 | 719 |
# required=False, min_value=1 |
719 | 720 |
# ) |
720 |
#
|
|
721 |
# |
|
721 | 722 |
# class Meta: |
722 | 723 |
# model = AstakosGroup |
723 |
#
|
|
724 |
# |
|
724 | 725 |
# def __init__(self, *args, **kwargs): |
725 | 726 |
# #update QueryDict |
726 | 727 |
# args = list(args) |
727 | 728 |
# qd = args.pop(0).copy() |
728 | 729 |
# members_unlimited = qd.pop('members_unlimited', False) |
729 | 730 |
# members_uplimit = qd.pop('members_uplimit', None) |
730 |
#
|
|
731 |
# |
|
731 | 732 |
# #substitue QueryDict |
732 | 733 |
# args.insert(0, qd) |
733 |
#
|
|
734 |
# |
|
734 | 735 |
# super(AstakosGroupCreationSummaryForm, self).__init__(*args, **kwargs) |
735 | 736 |
# self.fields.keyOrder = ['kind', 'name', 'homepage', 'desc', |
736 | 737 |
# 'issue_date', 'expiration_date', |
... | ... | |
744 | 745 |
# map(add_fields, |
745 | 746 |
# ((k, v) for k,v in qd.iteritems() if k.endswith('_uplimit')) |
746 | 747 |
# ) |
747 |
#
|
|
748 |
# |
|
748 | 749 |
# def add_fields((k, v)): |
749 | 750 |
# self.fields[k] = forms.BooleanField( |
750 | 751 |
# required=False, |
... | ... | |
755 | 756 |
# ) |
756 | 757 |
# for f in self.fields.values(): |
757 | 758 |
# f.widget = forms.HiddenInput() |
758 |
#
|
|
759 |
# |
|
759 | 760 |
# def clean(self): |
760 | 761 |
# super(AstakosGroupCreationSummaryForm, self).clean() |
761 | 762 |
# self.cleaned_data['policies'] = [] |
... | ... | |
769 | 770 |
# prefix, suffix = subs |
770 | 771 |
# s, sep, r = prefix.partition(RESOURCE_SEPARATOR) |
771 | 772 |
# resource = Resource.objects.get(service__name=s, name=r) |
772 |
#
|
|
773 |
# |
|
773 | 774 |
# # keep only resource limits for selected resource groups |
774 | 775 |
# if self.cleaned_data.get( |
775 | 776 |
# 'is_selected_%s' % resource.group, False |
... | ... | |
778 | 779 |
# for name in tbd: |
779 | 780 |
# self.cleaned_data.pop(name, None) |
780 | 781 |
# return self.cleaned_data |
781 |
#
|
|
782 |
# |
|
782 | 783 |
# class AstakosGroupUpdateForm(forms.ModelForm): |
783 | 784 |
# class Meta: |
784 | 785 |
# model = AstakosGroup |
785 | 786 |
# fields = ( 'desc','homepage', 'moderation_enabled') |
786 |
#
|
|
787 |
#
|
|
787 |
# |
|
788 |
# |
|
788 | 789 |
# class AddGroupMembersForm(forms.Form): |
789 | 790 |
# q = forms.CharField( |
790 | 791 |
# max_length=800, widget=forms.Textarea, label=_('Add members'), |
791 | 792 |
# help_text=_(astakos_messages.ADD_GROUP_MEMBERS_Q_HELP), |
792 | 793 |
# required=True) |
793 |
#
|
|
794 |
# |
|
794 | 795 |
# def clean(self): |
795 | 796 |
# q = self.cleaned_data.get('q') or '' |
796 | 797 |
# users = q.split(',') |
... | ... | |
801 | 802 |
# raise forms.ValidationError(_(astakos_messages.UNKNOWN_USERS) % ','.join(unknown)) |
802 | 803 |
# self.valid_users = db_entries |
803 | 804 |
# return self.cleaned_data |
804 |
#
|
|
805 |
# |
|
805 | 806 |
# def get_valid_users(self): |
806 | 807 |
# """Should be called after form cleaning""" |
807 | 808 |
# try: |
808 | 809 |
# return self.valid_users |
809 | 810 |
# except: |
810 | 811 |
# return () |
811 |
#
|
|
812 |
#
|
|
812 |
# |
|
813 |
# |
|
813 | 814 |
# class AstakosGroupSearchForm(forms.Form): |
814 | 815 |
# q = forms.CharField(max_length=200, label='Search project') |
815 |
#
|
|
816 |
#
|
|
816 |
# |
|
817 |
# |
|
817 | 818 |
# class TimelineForm(forms.Form): |
818 | 819 |
# entity = forms.ModelChoiceField( |
819 | 820 |
# queryset=AstakosUser.objects.filter(is_active=True) |
... | ... | |
830 | 831 |
# ('charge_usage', 'Charge Usage'), |
831 | 832 |
# ('charge_traffic', 'Charge Traffic'), ) |
832 | 833 |
# ) |
833 |
#
|
|
834 |
# |
|
834 | 835 |
# def clean(self): |
835 | 836 |
# super(TimelineForm, self).clean() |
836 | 837 |
# d = self.cleaned_data |
... | ... | |
844 | 845 |
# if 'entity' in d: |
845 | 846 |
# d['entity'] = d['entity'].email |
846 | 847 |
# return d |
847 |
#
|
|
848 |
#
|
|
848 |
# |
|
849 |
# |
|
849 | 850 |
# class AstakosGroupSortForm(forms.Form): |
850 | 851 |
# sorting = forms.ChoiceField( |
851 | 852 |
# label='Sort by', |
... | ... | |
859 | 860 |
# ), |
860 | 861 |
# required=True |
861 | 862 |
# ) |
862 |
#
|
|
863 |
# |
|
863 | 864 |
# class MembersSortForm(forms.Form): |
864 | 865 |
# sorting = forms.ChoiceField( |
865 | 866 |
# label='Sort by', |
... | ... | |
869 | 870 |
# ), |
870 | 871 |
# required=True |
871 | 872 |
# ) |
872 |
#
|
|
873 |
# |
|
873 | 874 |
# class PickResourceForm(forms.Form): |
874 | 875 |
# resource = forms.ModelChoiceField( |
875 | 876 |
# queryset=Resource.objects.select_related().all() |
... | ... | |
920 | 921 |
homepage = forms.URLField( |
921 | 922 |
help_text="This should be a URL pointing at your project's site. e.g.: http://myproject.com ", |
922 | 923 |
widget=forms.TextInput(attrs={'placeholder': 'http://myproject.com'}), |
923 |
|
|
924 |
|
|
924 | 925 |
required=False |
925 | 926 |
) |
926 | 927 |
comments = forms.CharField(widget=forms.Textarea, required=False) |
927 |
|
|
928 |
|
|
928 | 929 |
class Meta: |
929 | 930 |
model = ProjectApplication |
930 | 931 |
exclude = ( |
... | ... | |
935 | 936 |
def __init__(self, *args, **kwargs): |
936 | 937 |
self.precursor_application = kwargs.get('instance') |
937 | 938 |
super(ProjectApplicationForm, self).__init__(*args, **kwargs) |
938 |
|
|
939 |
|
|
939 | 940 |
def clean(self): |
940 | 941 |
userid = self.data.get('user', None) |
941 | 942 |
self.user = None |
... | ... | |
948 | 949 |
raise forms.ValidationError(_(astakos_messages.NO_APPLICANT)) |
949 | 950 |
super(ProjectApplicationForm, self).clean() |
950 | 951 |
return self.cleaned_data |
951 |
|
|
952 |
|
|
952 | 953 |
@property |
953 | 954 |
def resource_policies(self): |
954 | 955 |
policies = [] |
... | ... | |
971 | 972 |
append(dict(service=s, resource=r, uplimit=uplimit)) |
972 | 973 |
else: |
973 | 974 |
append(dict(service=s, resource=r, uplimit=None)) |
974 |
|
|
975 |
|
|
975 | 976 |
return policies |
976 |
|
|
977 |
|
|
977 | 978 |
|
978 | 979 |
def save(self, commit=True): |
979 | 980 |
application = super(ProjectApplicationForm, self).save(commit=False) |
b/snf-astakos-app/astakos/im/target/__init__.py | ||
---|---|---|
1 |
# Copyright 2011-2012 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import json |
|
35 |
|
|
36 |
from django.contrib import messages |
|
37 |
from django.utils.translation import ugettext as _ |
|
38 |
from django.http import HttpResponseRedirect |
|
39 |
from django.core.urlresolvers import reverse |
|
40 |
|
|
41 |
from astakos.im.models import PendingThirdPartyUser |
|
42 |
from astakos.im.util import get_query |
|
43 |
from astakos.im import messages as astakos_messages |
|
44 |
from astakos.im import auth_providers |
|
45 |
from astakos.im.util import prepare_response, get_context |
|
46 |
from astakos.im.views import requires_anonymous, render_response |
|
47 |
|
|
48 |
|
|
49 |
def add_pending_auth_provider(request, third_party_token): |
|
50 |
|
|
51 |
if third_party_token: |
|
52 |
# use requests to assign the account he just authenticated with with |
|
53 |
# a third party provider account |
|
54 |
try: |
|
55 |
request.user.add_pending_auth_provider(third_party_token) |
|
56 |
messages.success(request, _(astakos_messages.AUTH_PROVIDER_ADDED)) |
|
57 |
except PendingThirdPartyUser.DoesNotExist: |
|
58 |
messages.error(request, _(astakos_messages.AUTH_PROVIDER_ADD_FAILED)) |
|
59 |
|
|
60 |
|
|
61 |
def get_pending_key(request): |
|
62 |
|
|
63 |
third_party_token = get_query(request).get('key', False) |
|
64 |
if not third_party_token: |
|
65 |
third_party_token = request.session.get('pending_key', None) |
|
66 |
if third_party_token: |
|
67 |
del request.session['pending_key'] |
|
68 |
return third_party_token |
|
69 |
|
|
70 |
|
|
71 |
def handle_third_party_signup(request, userid, provider_module, third_party_key, |
|
72 |
provider_info={}, |
|
73 |
pending_user_params={}, |
|
74 |
template="im/third_party_check_local.html", |
|
75 |
extra_context={}): |
|
76 |
|
|
77 |
# user wants to add another third party login method |
|
78 |
if third_party_key: |
|
79 |
messages.error(request, _(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
80 |
return HttpResponseRedirect(reverse('login') + "?key=%s" % third_party_key) |
|
81 |
|
|
82 |
provider = auth_providers.get_provider(provider_module) |
|
83 |
if not provider.is_available_for_create(): |
|
84 |
messages.error(request, |
|
85 |
_(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
86 |
return HttpResponseRedirect(reverse('login')) |
|
87 |
|
|
88 |
# eppn not stored in astakos models, create pending profile |
|
89 |
user, created = PendingThirdPartyUser.objects.get_or_create( |
|
90 |
third_party_identifier=userid, |
|
91 |
provider=provider_module, |
|
92 |
) |
|
93 |
# update pending user |
|
94 |
for param, value in pending_user_params.iteritems(): |
|
95 |
setattr(user, param, value) |
|
96 |
|
|
97 |
user.info = json.dumps(provider_info) |
|
98 |
user.generate_token() |
|
99 |
user.save() |
|
100 |
|
|
101 |
extra_context['provider'] = provider_module |
|
102 |
extra_context['provider_title'] = provider.get_title_display |
|
103 |
extra_context['token'] = user.token |
|
104 |
extra_context['signup_url'] = reverse('signup') + \ |
|
105 |
"?third_party_token=%s" % user.token |
|
106 |
extra_context['add_url'] = reverse('index') + \ |
|
107 |
"?key=%s#other-login-methods" % user.token |
|
108 |
extra_context['can_create'] = provider.is_available_for_create() |
|
109 |
extra_context['can_add'] = provider.is_available_for_add() |
|
110 |
|
|
111 |
|
|
112 |
return render_response( |
|
113 |
template, |
|
114 |
context_instance=get_context(request, extra_context) |
|
115 |
) |
|
116 |
|
b/snf-astakos-app/astakos/im/target/google.py | ||
---|---|---|
45 | 45 |
|
46 | 46 |
from urlparse import urlunsplit, urlsplit |
47 | 47 |
|
48 |
from astakos.im.util import prepare_response, get_context |
|
48 |
from astakos.im.util import prepare_response, get_context, login_url
|
|
49 | 49 |
from astakos.im.views import requires_anonymous, render_response, \ |
50 | 50 |
requires_auth_provider |
51 | 51 |
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL |
... | ... | |
54 | 54 |
from astakos.im.activation_backends import get_backend, SimpleBackend |
55 | 55 |
from astakos.im import settings |
56 | 56 |
from astakos.im import auth_providers |
57 |
from astakos.im.target import add_pending_auth_provider, get_pending_key, \ |
|
58 |
handle_third_party_signup |
|
57 | 59 |
|
58 | 60 |
import logging |
59 | 61 |
import time |
... | ... | |
97 | 99 |
if force_login: |
98 | 100 |
params['approval_prompt'] = 'force' |
99 | 101 |
|
102 |
if request.GET.get('key', None): |
|
103 |
request.session['pending_key'] = request.GET.get('key') |
|
104 |
|
|
100 | 105 |
url = "%s?%s" % (authenticate_url, urllib.urlencode(params)) |
101 | 106 |
return HttpResponseRedirect(url) |
102 | 107 |
|
... | ... | |
143 | 148 |
provider_info = access_token_data |
144 | 149 |
affiliation = 'Google.com' |
145 | 150 |
|
151 |
third_party_key = get_pending_key(request) |
|
152 |
|
|
146 | 153 |
# an existing user accessed the view |
147 | 154 |
if request.user.is_authenticated(): |
148 | 155 |
if request.user.has_auth_provider('google', identifier=userid): |
... | ... | |
172 | 179 |
# authenticate user |
173 | 180 |
response = prepare_response(request, |
174 | 181 |
user, |
182 |
userid, |
|
175 | 183 |
request.GET.get('next'), |
176 | 184 |
'renew' in request.GET) |
177 | 185 |
messages.success(request, _(astakos_messages.LOGIN_SUCCESS)) |
186 |
add_pending_auth_provider(request, third_party_key) |
|
178 | 187 |
response.set_cookie('astakos_last_login_method', 'google') |
179 | 188 |
return response |
180 | 189 |
else: |
181 | 190 |
message = user.get_inactive_message() |
182 | 191 |
messages.error(request, message) |
183 |
return HttpResponseRedirect(reverse('login'))
|
|
192 |
return HttpResponseRedirect(login_url(request))
|
|
184 | 193 |
|
185 | 194 |
except AstakosUser.DoesNotExist, e: |
186 |
provider = auth_providers.get_provider('google') |
|
187 |
if not provider.is_available_for_create(): |
|
188 |
messages.error(request, |
|
189 |
_(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
190 |
return HttpResponseRedirect(reverse('login')) |
|
191 |
|
|
192 |
# eppn not stored in astakos models, create pending profile |
|
193 |
user, created = PendingThirdPartyUser.objects.get_or_create( |
|
194 |
third_party_identifier=userid, |
|
195 |
provider='google', |
|
196 |
) |
|
197 |
# update pending user |
|
198 |
user.affiliation = affiliation |
|
199 |
user.info = json.dumps(provider_info) |
|
200 |
user.generate_token() |
|
201 |
user.save() |
|
202 |
|
|
203 |
extra_context['provider'] = 'google' |
|
204 |
extra_context['provider_title'] = provider.get_title_display |
|
205 |
extra_context['token'] = user.token |
|
206 |
extra_context['signup_url'] = reverse('signup') + \ |
|
207 |
"?third_party_token=%s" % user.token |
|
208 |
extra_context['add_url'] = reverse('index') + \ |
|
209 |
"?key=%s#other-login-methods" % user.token |
|
210 |
extra_context['can_create'] = provider.is_available_for_create() |
|
211 |
extra_context['can_add'] = provider.is_available_for_add() |
|
212 |
|
|
213 |
|
|
214 |
return render_response( |
|
215 |
template, |
|
216 |
context_instance=get_context(request, extra_context) |
|
217 |
) |
|
218 |
|
|
195 |
user_info = {'affiliation': affiliation} |
|
196 |
return handle_third_party_signup(request, userid, 'google', |
|
197 |
third_party_key, |
|
198 |
provider_info, |
|
199 |
user_info, |
|
200 |
template, |
|
201 |
extra_context) |
|
219 | 202 |
|
b/snf-astakos-app/astakos/im/target/linkedin.py | ||
---|---|---|
45 | 45 |
|
46 | 46 |
from urlparse import urlunsplit, urlsplit |
47 | 47 |
|
48 |
from astakos.im.util import prepare_response, get_context |
|
48 |
from astakos.im.util import prepare_response, get_context, login_url
|
|
49 | 49 |
from astakos.im.views import requires_anonymous, render_response, \ |
50 | 50 |
requires_auth_provider |
51 | 51 |
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL |
... | ... | |
54 | 54 |
from astakos.im.activation_backends import get_backend, SimpleBackend |
55 | 55 |
from astakos.im import settings |
56 | 56 |
from astakos.im import auth_providers |
57 |
from astakos.im.target import add_pending_auth_provider, get_pending_key, \ |
|
58 |
handle_third_party_signup |
|
57 | 59 |
|
58 | 60 |
import astakos.im.messages as astakos_messages |
59 | 61 |
|
... | ... | |
85 | 87 |
|
86 | 88 |
url = request_token.get('xoauth_request_auth_url') + "?oauth_token=%s" % request_token.get('oauth_token') |
87 | 89 |
|
90 |
if request.GET.get('key', None): |
|
91 |
request.session['pending_key'] = request.GET.get('key') |
|
92 |
|
|
88 | 93 |
return HttpResponseRedirect(url) |
89 | 94 |
|
90 | 95 |
|
... | ... | |
116 | 121 |
messages.error(request, 'Invalid linkedin token response') |
117 | 122 |
return HttpResponseRedirect(reverse('edit_profile')) |
118 | 123 |
access_token = dict(cgi.parse_qsl(content)) |
119 |
print "ACCESS", access_token |
|
120 | 124 |
|
121 | 125 |
token = oauth.Token(access_token['oauth_token'], |
122 | 126 |
access_token['oauth_token_secret']) |
123 | 127 |
client = oauth.Client(consumer, token) |
124 | 128 |
resp, content = client.request("http://api.linkedin.com/v1/people/~:(id,first-name,last-name,industry,email-address)?format=json", "GET") |
125 | 129 |
if resp['status'] != '200': |
126 |
print resp, content |
|
127 | 130 |
try: |
128 | 131 |
del request.session['request_token'] |
129 | 132 |
except: |
... | ... | |
136 | 139 |
username = profile_data.get('emailAddress', None) |
137 | 140 |
realname = profile_data.get('firstName', '') + ' ' + profile_data.get('lastName', '') |
138 | 141 |
provider_info = profile_data |
139 |
affiliation = 'linkedin.com' |
|
142 |
affiliation = 'LinkedIn.com' |
|
143 |
|
|
144 |
third_party_key = get_pending_key(request) |
|
140 | 145 |
|
141 | 146 |
# an existing user accessed the view |
142 | 147 |
if request.user.is_authenticated(): |
... | ... | |
170 | 175 |
request.GET.get('next'), |
171 | 176 |
'renew' in request.GET) |
172 | 177 |
messages.success(request, _(astakos_messages.LOGIN_SUCCESS)) |
178 |
add_pending_auth_provider(request, third_party_key) |
|
173 | 179 |
response.set_cookie('astakos_last_login_method', 'linkedin') |
174 | 180 |
return response |
175 | 181 |
else: |
176 | 182 |
message = user.get_inactive_message() |
177 | 183 |
messages.error(request, message) |
178 |
return HttpResponseRedirect(reverse('login'))
|
|
184 |
return HttpResponseRedirect(login_url(request))
|
|
179 | 185 |
|
180 | 186 |
except AstakosUser.DoesNotExist, e: |
181 |
provider = auth_providers.get_provider('linkedin') |
|
182 |
if not provider.is_available_for_create(): |
|
183 |
messages.error(request, |
|
184 |
_(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
185 |
return HttpResponseRedirect(reverse('login')) |
|
186 |
|
|
187 |
# eppn not stored in astakos models, create pending profile |
|
188 |
user, created = PendingThirdPartyUser.objects.get_or_create( |
|
189 |
third_party_identifier=userid, |
|
190 |
provider='linkedin', |
|
191 |
) |
|
192 |
# update pending user |
|
193 |
user.realname = realname |
|
194 |
user.affiliation = affiliation |
|
195 |
user.info = json.dumps(provider_info) |
|
196 |
user.generate_token() |
|
197 |
user.save() |
|
198 |
|
|
199 |
extra_context['provider'] = 'linkedin' |
|
200 |
extra_context['provider_title'] = provider.get_title_display |
|
201 |
extra_context['token'] = user.token |
|
202 |
extra_context['signup_url'] = reverse('signup') + \ |
|
203 |
"?third_party_token=%s" % user.token |
|
204 |
extra_context['add_url'] = reverse('index') + \ |
|
205 |
"?key=%s#other-login-methods" % user.token |
|
206 |
extra_context['can_create'] = provider.is_available_for_create() |
|
207 |
extra_context['can_add'] = provider.is_available_for_add() |
|
208 |
|
|
209 |
|
|
210 |
return render_response( |
|
211 |
template, |
|
212 |
context_instance=get_context(request, extra_context) |
|
213 |
) |
|
214 |
|
|
215 |
|
|
187 |
user_info = {'affiliation': affiliation, 'realname': realname} |
|
188 |
return handle_third_party_signup(request, userid, 'linkedin', |
|
189 |
third_party_key, |
|
190 |
provider_info, |
|
191 |
user_info, |
|
192 |
template, |
|
193 |
extra_context) |
|
216 | 194 |
|
b/snf-astakos-app/astakos/im/target/redirect.py | ||
---|---|---|
138 | 138 |
response['Location'] = url |
139 | 139 |
response.status_code = 302 |
140 | 140 |
return response |
141 |
|
b/snf-astakos-app/astakos/im/target/shibboleth.py | ||
---|---|---|
45 | 45 |
|
46 | 46 |
from urlparse import urlunsplit, urlsplit |
47 | 47 |
|
48 |
from astakos.im.util import prepare_response, get_context |
|
48 |
from astakos.im.util import prepare_response, get_context, login_url
|
|
49 | 49 |
from astakos.im.views import ( |
50 | 50 |
requires_anonymous, render_response, requires_auth_provider) |
51 | 51 |
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL |
... | ... | |
54 | 54 |
from astakos.im.activation_backends import get_backend, SimpleBackend |
55 | 55 |
from astakos.im import auth_providers |
56 | 56 |
from astakos.im import settings |
57 |
from astakos.im.target import add_pending_auth_provider, get_pending_key, \ |
|
58 |
handle_third_party_signup |
|
57 | 59 |
|
58 | 60 |
import astakos.im.messages as astakos_messages |
59 |
|
|
60 | 61 |
import logging |
61 | 62 |
|
62 | 63 |
logger = logging.getLogger(__name__) |
63 | 64 |
|
65 |
|
|
64 | 66 |
class Tokens: |
65 | 67 |
# these are mapped by the Shibboleth SP software |
66 | 68 |
SHIB_EPPN = "HTTP_EPPN" # eduPersonPrincipalName |
... | ... | |
72 | 74 |
SHIB_SESSION_ID = "HTTP_SHIB_SESSION_ID" |
73 | 75 |
SHIB_MAIL = "HTTP_SHIB_MAIL" |
74 | 76 |
|
77 |
|
|
75 | 78 |
@requires_auth_provider('shibboleth', login=True) |
76 | 79 |
@require_http_methods(["GET", "POST"]) |
77 | 80 |
def login( |
... | ... | |
82 | 85 |
extra_context = extra_context or {} |
83 | 86 |
|
84 | 87 |
tokens = request.META |
88 |
third_party_key = get_pending_key(request) |
|
85 | 89 |
|
86 | 90 |
try: |
87 | 91 |
eppn = tokens.get(Tokens.SHIB_EPPN) |
... | ... | |
101 | 105 |
raise KeyError(_(astakos_messages.SHIBBOLETH_MISSING_NAME)) |
102 | 106 |
else: |
103 | 107 |
realname = '' |
108 |
|
|
104 | 109 |
except KeyError, e: |
105 | 110 |
# invalid shibboleth headers, redirect to login, display message |
106 | 111 |
messages.error(request, e.message) |
107 |
return HttpResponseRedirect(reverse('login'))
|
|
112 |
return HttpResponseRedirect(login_url(request))
|
|
108 | 113 |
|
109 | 114 |
affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '') |
110 | 115 |
email = tokens.get(Tokens.SHIB_MAIL, '') |
111 | 116 |
provider_info = {'eppn': eppn, 'email': email, 'name': realname} |
117 |
userid = eppn |
|
112 | 118 |
|
113 | 119 |
# an existing user accessed the view |
114 | 120 |
if request.user.is_authenticated(): |
121 |
|
|
115 | 122 |
if request.user.has_auth_provider('shibboleth', identifier=eppn): |
116 | 123 |
return HttpResponseRedirect(reverse('edit_profile')) |
117 | 124 |
|
... | ... | |
136 | 143 |
identifier=eppn |
137 | 144 |
) |
138 | 145 |
if user.is_active: |
146 |
|
|
139 | 147 |
# authenticate user |
140 | 148 |
response = prepare_response(request, |
141 | 149 |
user, |
142 | 150 |
request.GET.get('next'), |
143 | 151 |
'renew' in request.GET) |
144 | 152 |
messages.success(request, _(astakos_messages.LOGIN_SUCCESS)) |
153 |
add_pending_auth_provider(request, third_party_key) |
|
145 | 154 |
response.set_cookie('astakos_last_login_method', 'local') |
146 | 155 |
return response |
147 | 156 |
else: |
148 | 157 |
message = user.get_inactive_message() |
149 | 158 |
messages.error(request, message) |
150 |
return HttpResponseRedirect(reverse('login'))
|
|
159 |
return HttpResponseRedirect(login_url(request))
|
|
151 | 160 |
|
152 | 161 |
except AstakosUser.DoesNotExist, e: |
153 |
provider = auth_providers.get_provider('shibboleth') |
|
154 |
if not provider.is_available_for_create(): |
|
155 |
messages.error(request, |
|
156 |
_(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
157 |
return HttpResponseRedirect(reverse('login')) |
|
158 |
|
|
159 |
# eppn not stored in astakos models, create pending profile |
|
160 |
user, created = PendingThirdPartyUser.objects.get_or_create( |
|
161 |
third_party_identifier=eppn, |
|
162 |
provider='shibboleth' |
|
163 |
) |
|
164 |
# update pending user |
|
165 |
user.realname = realname |
|
166 |
user.affiliation = affiliation |
|
167 |
user.email = email |
|
168 |
user.info = json.dumps(provider_info) |
|
169 |
user.generate_token() |
|
170 |
user.save() |
|
171 |
|
|
172 |
extra_context['provider'] = 'shibboleth' |
|
173 |
extra_context['provider_title'] = provider.get_title_display |
|
174 |
extra_context['token'] = user.token |
|
175 |
extra_context['signup_url'] = reverse('signup') + \ |
|
176 |
"?third_party_token=%s" % user.token |
|
177 |
extra_context['add_url'] = reverse('index') + \ |
|
178 |
"?key=%s#other-login-methods" % user.token |
|
179 |
extra_context['can_create'] = provider.is_available_for_create() |
|
180 |
extra_context['can_add'] = provider.is_available_for_add() |
|
181 |
|
|
182 |
|
|
183 |
return render_response( |
|
184 |
template, |
|
185 |
context_instance=get_context(request, extra_context) |
|
186 |
) |
|
162 |
user_info = {'affiliation': affiliation, 'realname': realname} |
|
163 |
return handle_third_party_signup(request, userid, 'shibboleth', |
|
164 |
third_party_key, |
|
165 |
provider_info, |
|
166 |
user_info, |
|
167 |
template, |
|
168 |
extra_context) |
|
187 | 169 |
|
b/snf-astakos-app/astakos/im/target/twitter.py | ||
---|---|---|
45 | 45 |
|
46 | 46 |
from urlparse import urlunsplit, urlsplit |
47 | 47 |
|
48 |
from astakos.im.util import prepare_response, get_context |
|
48 |
from astakos.im.util import prepare_response, get_context, login_url
|
|
49 | 49 |
from astakos.im.views import requires_anonymous, render_response, \ |
50 | 50 |
requires_auth_provider, required_auth_methods_assigned |
51 | 51 |
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION, BASEURL |
... | ... | |
54 | 54 |
from astakos.im.activation_backends import get_backend, SimpleBackend |
55 | 55 |
from astakos.im import settings |
56 | 56 |
from astakos.im import auth_providers |
57 |
from astakos.im.target import add_pending_auth_provider, get_pending_key, \ |
|
58 |
handle_third_party_signup |
|
57 | 59 |
|
58 | 60 |
import astakos.im.messages as astakos_messages |
59 | 61 |
|
... | ... | |
89 | 91 |
if force_login: |
90 | 92 |
params['force_login'] = 1 |
91 | 93 |
|
94 |
if request.GET.get('key', None): |
|
95 |
request.session['pending_key'] = request.GET.get('key') |
|
96 |
|
|
97 |
|
|
92 | 98 |
url = "%s?%s" % (authenticate_url, urllib.urlencode(params)) |
93 | 99 |
|
94 | 100 |
return HttpResponseRedirect(url) |
... | ... | |
128 | 134 |
provider_info = {'screen_name': username} |
129 | 135 |
affiliation = 'Twitter.com' |
130 | 136 |
|
137 |
third_party_key = get_pending_key(request) |
|
138 |
|
|
131 | 139 |
# an existing user accessed the view |
132 | 140 |
if request.user.is_authenticated(): |
133 | 141 |
if request.user.has_auth_provider('twitter', identifier=userid): |
... | ... | |
160 | 168 |
request.GET.get('next'), |
161 | 169 |
'renew' in request.GET) |
162 | 170 |
messages.success(request, _(astakos_messages.LOGIN_SUCCESS)) |
171 |
add_pending_auth_provider(request, third_party_key) |
|
163 | 172 |
response.set_cookie('astakos_last_login_method', 'twitter') |
164 | 173 |
return response |
165 | 174 |
else: |
166 | 175 |
message = user.get_inactive_message() |
167 | 176 |
messages.error(request, message) |
168 |
return HttpResponseRedirect(reverse('login'))
|
|
177 |
return HttpResponseRedirect(login_url(request))
|
|
169 | 178 |
|
170 | 179 |
except AstakosUser.DoesNotExist, e: |
171 |
provider = auth_providers.get_provider('twitter') |
|
172 |
if not provider.is_available_for_create() and not provider.is_available_for_add(): |
|
173 |
messages.error(request, |
|
174 |
_(astakos_messages.AUTH_PROVIDER_INVALID_LOGIN)) |
|
175 |
return HttpResponseRedirect(reverse('login')) |
|
176 |
|
|
177 |
# eppn not stored in astakos models, create pending profile |
|
178 |
user, created = PendingThirdPartyUser.objects.get_or_create( |
|
179 |
third_party_identifier=userid, |
|
180 |
provider='twitter', |
|
181 |
) |
|
182 |
# update pending user |
|
183 |
user.affiliation = affiliation |
|
184 |
user.info = json.dumps(provider_info) |
|
185 |
user.generate_token() |
|
186 |
user.save() |
|
187 |
|
|
188 |
extra_context['provider'] = 'twitter' |
|
189 |
extra_context['provider_title'] = provider.get_title_display |
|
190 |
extra_context['token'] = user.token |
|
191 |
extra_context['signup_url'] = reverse('signup') + \ |
|
192 |
"?third_party_token=%s" % user.token |
|
193 |
extra_context['add_url'] = reverse('index') + \ |
|
194 |
"?key=%s#other-login-methods" % user.token |
|
195 |
extra_context['can_create'] = provider.is_available_for_create() |
|
196 |
extra_context['can_add'] = provider.is_available_for_add() |
|
197 |
|
|
198 |
|
|
199 |
return render_response( |
|
200 |
template, |
|
201 |
context_instance=get_context(request, extra_context) |
|
202 |
) |
|
180 |
user_info = {'affiliation': affiliation} |
|
181 |
return handle_third_party_signup(request, userid, 'twitter', |
|
182 |
third_party_key, |
|
183 |
provider_info, |
|
184 |
user_info, |
|
185 |
template, |
|
186 |
extra_context) |
|
203 | 187 |
|
b/snf-astakos-app/astakos/im/templates/im/auth/shibboleth_login.html | ||
---|---|---|
1 |
{% load astakos_tags %} |
|
1 | 2 |
<p> |
2 | 3 |
{{ master_auth_provider.get_primary_login_prompt_display }} |
3 | 4 |
</p> |
4 | 5 |
<br /> |
5 |
<a class="submit" href="/im/login/shibboleth">ACADEMIC LOGIN</a> |
|
6 |
<a class="submit" href="{% provider_login_url master_auth_provider %}">ACADEMIC LOGIN</a> |
/dev/null | ||
---|---|---|
1 |
<br /> |
|
2 |
{{ provider.get_login_prompt }} |
|
3 |
<a href="/im/login/shibboleth?{% ifnotequal next "" %}&next={{ next|urlencode }}{% endifnotequal %}{% ifnotequal code ""%}{% if next != "" %}&{% else %}?{% endif %}code={{ code }}{% endifnotequal %}" |
|
4 |
alt="{{ provider.get_title_display }}">{{ provider.get_title_display }}</a> |
b/snf-astakos-app/astakos/im/templates/im/auth/third_party_provider_generic_login.html | ||
---|---|---|
1 |
<h2><a href="{{ provider.add_url }}">{{ provider.get_primary_login_prompt_display|safe }} {{ provider.get_title_display }}</a></h2> |
|
1 |
{% load astakos_tags %} |
|
2 |
<h2><a href="{% provider_login_url provider %}"> |
|
3 |
{{ provider.get_primary_login_prompt_display|safe }} {{ provider.get_title_display }} |
|
4 |
</a></h2> |
b/snf-astakos-app/astakos/im/templates/im/auth/third_party_provider_generic_login_prompt.html | ||
---|---|---|
1 |
<Br />{{ provider.get_login_prompt_display|safe }} |
|
2 |
<a href="{{ provider.add_url }}?{% ifnotequal next "" %}&next={{ next|urlencode }}{% endifnotequal %}{% ifnotequal code ""%}{% if next != "" %}&{% else %}?{% endif %}code={{ code }}{% endifnotequal %}" |
|
3 |
alt="{{ provider.get_title_display }}">{{ provider.get_title_display }}</a> |
|
1 |
{% load astakos_tags %} |
|
2 |
<br />{{ provider.get_login_prompt_display|safe }} |
|
3 |
<a href="{% provider_login_url provider %}" alt="{{ provider.get_title_display }}">{{ provider.get_title_display }}</a> |
/dev/null | ||
---|---|---|
1 |
<h2><a href="/im/login/{{ provider.add_url }}">{{ provider.get_login_prompt_display }}</a></h2> |
/dev/null | ||
---|---|---|
1 |
<br />{{ provider.get_login_prompt_display }} |
|
2 |
<a href="/im/login/twitter?{% ifnotequal next "" %}&next={{ next|urlencode }}{% endifnotequal %}{% ifnotequal code ""%}{% if next != "" %}&{% else %}?{% endif %}code={{ code }}{% endifnotequal %}" alt="{{ provider.get_title_display }}">{{ provider.get_title_display }}</a> |
b/snf-astakos-app/astakos/im/templatetags/astakos_tags.py | ||
---|---|---|
1 |
# Copyright 2011 GRNET S.A. All rights reserved. |
|
2 |
# |
|
3 |
# Redistribution and use in source and binary forms, with or |
|
4 |
# without modification, are permitted provided that the following |
|
5 |
# conditions are met: |
|
6 |
# |
|
7 |
# 1. Redistributions of source code must retain the above |
|
8 |
# copyright notice, this list of conditions and the following |
|
9 |
# disclaimer. |
|
10 |
# |
|
11 |
# 2. Redistributions in binary form must reproduce the above |
|
12 |
# copyright notice, this list of conditions and the following |
|
13 |
# disclaimer in the documentation and/or other materials |
|
14 |
# provided with the distribution. |
|
15 |
# |
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
27 |
# POSSIBILITY OF SUCH DAMAGE. |
|
28 |
# |
|
29 |
# The views and conclusions contained in the software and |
|
30 |
# documentation are those of the authors and should not be |
|
31 |
# interpreted as representing official policies, either expressed |
|
32 |
# or implied, of GRNET S.A. |
|
33 |
|
|
34 |
import urllib |
|
35 |
|
|
36 |
from inspect import getargspec |
|
37 |
|
|
1 | 38 |
from django import template |
2 | 39 |
from django.core.urlresolvers import resolve |
3 | 40 |
from django.conf import settings |
41 |
from django.template import TemplateSyntaxError, Variable |
|
4 | 42 |
|
5 | 43 |
register = template.Library() |
6 | 44 |
|
... | ... | |
16 | 54 |
}) |
17 | 55 |
|
18 | 56 |
|
57 |
# helper tag decorator |
|
58 |
# https://github.com/djblets/djblets/blob/master/djblets/util/decorators.py#L96 |
|
59 |
def basictag(takes_context=False): |
|
60 |
""" |
|
61 |
A decorator similar to Django's @register.simple_tag that optionally |
|
62 |
takes a context parameter. This condenses many tag implementations down |
|
63 |
to a few lines of code. |
|
64 |
|
|
65 |
Example: |
|
66 |
@register.tag |
|
67 |
@basictag(takes_context=True) |
|
68 |
def printuser(context): |
|
69 |
return context['user'] |
|
70 |
""" |
|
71 |
class BasicTagNode(template.Node): |
|
72 |
def __init__(self, take_context, tag_name, tag_func, args): |
|
73 |
self.takes_context = takes_context |
|
74 |
self.tag_name = tag_name |
|
75 |
self.tag_func = tag_func |
|
76 |
self.args = args |
|
77 |
|
|
78 |
def render(self, context): |
|
79 |
args = [Variable(var).resolve(context) for var in self.args] |
|
80 |
|
|
81 |
if self.takes_context: |
|
82 |
return self.tag_func(context, *args) |
|
83 |
else: |
|
84 |
return self.tag_func(*args) |
|
85 |
|
|
86 |
def basictag_func(tag_func): |
|
87 |
def _setup_tag(parser, token): |
|
88 |
bits = token.split_contents() |
|
89 |
tag_name = bits[0] |
|
90 |
del(bits[0]) |
|
91 |
|
|
92 |
params, xx, xxx, defaults = getargspec(tag_func) |
|
93 |
max_args = len(params) |
|
94 |
|
|
95 |
if takes_context: |
|
96 |
if params[0] == 'context': |
|
97 |
max_args -= 1 # Ignore context |
|
98 |
else: |
|
99 |
raise TemplateSyntaxError, \ |
|
100 |
"Any tag function decorated with takes_context=True " \ |
|
101 |
"must have a first argument of 'context'" |
|
102 |
|
|
103 |
min_args = max_args - len(defaults or []) |
|
104 |
|
|
105 |
if not min_args <= len(bits) <= max_args: |
|
106 |
if min_args == max_args: |
|
107 |
raise TemplateSyntaxError, \ |
|
108 |
"%r tag takes %d arguments." % (tag_name, min_args) |
|
109 |
else: |
|
110 |
raise TemplateSyntaxError, \ |
|
111 |
"%r tag takes %d to %d arguments, got %d." % \ |
|
112 |
(tag_name, min_args, max_args, len(bits)) |
|
113 |
|
|
114 |
return BasicTagNode(takes_context, tag_name, tag_func, bits) |
|
115 |
|
|
116 |
_setup_tag.__name__ = tag_func.__name__ |
|
117 |
_setup_tag.__doc__ = tag_func.__doc__ |
|
118 |
_setup_tag.__dict__.update(tag_func.__dict__) |
|
119 |
return _setup_tag |
|
120 |
|
|
121 |
return basictag_func |
|
122 |
|
|
123 |
|
|
19 | 124 |
@register.tag(name='display_messages') |
20 | 125 |
def display_messages(parser, token): |
21 | 126 |
return MessagesNode() |
... | ... | |
67 | 172 |
|
68 | 173 |
|
69 | 174 |
@register.simple_tag |
70 |
def olga(v): |
|
71 |
return v+'a' |
|
72 |
|
|
73 |
@register.simple_tag |
|
74 | 175 |
def get_grant_value(rname, form): |
75 | 176 |
grants = form.instance.grants |
76 | 177 |
service_name, resource_name = rname.split('.',1) |
... | ... | |
78 | 179 |
return form.instance.projectresourcegrant_set.get(resource__name=resource_name, |
79 | 180 |
resource__service__name=service_name).member_capacity |
80 | 181 |
except: |
81 |
return '' |
|
182 |
return '' |
|
183 |
|
|
184 |
@register.tag(name="provider_login_url") |
|
185 |
@basictag(takes_context=True) |
|
186 |
def provider_login_url(context, provider): |
|
187 |
request = context['request'].REQUEST |
|
188 |
next = request.get('next', None) |
|
189 |
code = request.get('code', None) |
|
190 |
key = request.get('key', None) |
|
191 |
|
|
192 |
attrs = {} |
|
193 |
if next: |
|
194 |
attrs['next'] = next |
|
195 |
if code: |
|
196 |
attrs['code'] = code |
|
197 |
if key: |
|
198 |
attrs['key'] = key |
|
199 |
|
|
200 |
url = provider.add_url |
|
201 |
|
|
202 |
joinchar = "?" |
|
203 |
if "?" in url: |
|
204 |
joinchar = "&" |
|
205 |
|
|
206 |
return "%s%s%s" % (provider.add_url, joinchar, urllib.urlencode(attrs)) |
|
207 |
|
Also available in: Unified diff