Revision 4e30244e
b/snf-astakos-app/astakos/im/activation_backends.py | ||
---|---|---|
47 | 47 |
from astakos.im.forms import * |
48 | 48 |
from astakos.im.util import get_invitation |
49 | 49 |
from astakos.im.functions import send_verification, send_admin_notification, activate |
50 |
from astakos.im.settings import INVITATIONS_ENABLED, DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, MODERATION_ENABLED, SITENAME, BASEURL, DEFAULT_ADMIN_EMAIL, RE_USER_EMAIL_PATTERNS
|
|
50 |
from astakos.im.settings import INVITATIONS_ENABLED, DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, MODERATION_ENABLED, SITENAME, DEFAULT_ADMIN_EMAIL, RE_USER_EMAIL_PATTERNS |
|
51 | 51 |
|
52 | 52 |
import socket |
53 | 53 |
import logging |
... | ... | |
100 | 100 |
or invitation username is reserved. |
101 | 101 |
""" |
102 | 102 |
self.request = request |
103 |
self.invitation = get_invitation(request) |
|
104 | 103 |
super(InvitationsBackend, self).__init__() |
105 | 104 |
|
106 |
def get_signup_form(self, provider='local'): |
|
105 |
def get_signup_form(self, provider='local', instance=None):
|
|
107 | 106 |
""" |
108 | 107 |
Returns the form class name |
109 | 108 |
""" |
110 |
invitation = self.invitation |
|
111 |
initial_data = self.get_signup_initial_data(provider) |
|
112 |
prefix = 'Invited' if invitation else '' |
|
113 |
main = provider.capitalize() |
|
114 |
suffix = 'UserCreationForm' |
|
115 |
formclass = '%s%s%s' % (prefix, main, suffix) |
|
116 |
ip = self.request.META.get('REMOTE_ADDR', |
|
117 |
self.request.META.get('HTTP_X_REAL_IP', None)) |
|
118 |
return globals()[formclass](initial_data, ip=ip) |
|
109 |
try: |
|
110 |
self.invitation = get_invitation(self.request) |
|
111 |
except (Invitation, ValueError), e: |
|
112 |
self.invitation = None |
|
113 |
else: |
|
114 |
invitation = self.invitation |
|
115 |
initial_data = self.get_signup_initial_data(provider) |
|
116 |
prefix = 'Invited' if invitation else '' |
|
117 |
main = provider.capitalize() |
|
118 |
suffix = 'UserCreationForm' |
|
119 |
formclass = '%s%s%s' % (prefix, main, suffix) |
|
120 |
ip = self.request.META.get('REMOTE_ADDR', |
|
121 |
self.request.META.get('HTTP_X_REAL_IP', None)) |
|
122 |
return globals()[formclass](initial_data, instance=instance, ip=ip) |
|
119 | 123 |
|
120 | 124 |
def get_signup_initial_data(self, provider): |
121 | 125 |
""" |
... | ... | |
134 | 138 |
initial_data = {'email':invitation.username, |
135 | 139 |
'inviter':invitation.inviter.realname, |
136 | 140 |
'first_name':u.first_name, |
137 |
'last_name':u.last_name} |
|
141 |
'last_name':u.last_name, |
|
142 |
'provider':provider} |
|
138 | 143 |
else: |
139 | 144 |
if provider == request.POST.get('provider', ''): |
140 | 145 |
initial_data = request.POST |
... | ... | |
191 | 196 |
self.request = request |
192 | 197 |
super(SimpleBackend, self).__init__() |
193 | 198 |
|
194 |
def get_signup_form(self, provider='local'): |
|
199 |
def get_signup_form(self, provider='local', instance=None):
|
|
195 | 200 |
""" |
196 | 201 |
Returns the form class name |
197 | 202 |
""" |
... | ... | |
205 | 210 |
initial_data = request.POST |
206 | 211 |
ip = self.request.META.get('REMOTE_ADDR', |
207 | 212 |
self.request.META.get('HTTP_X_REAL_IP', None)) |
208 |
return globals()[formclass](initial_data, ip=ip) |
|
213 |
return globals()[formclass](initial_data, instance=instance, ip=ip)
|
|
209 | 214 |
|
210 | 215 |
def _is_preaccepted(self, user): |
211 | 216 |
if super(SimpleBackend, self)._is_preaccepted(user): |
b/snf-astakos-app/astakos/im/forms.py | ||
---|---|---|
45 | 45 |
from django.utils.safestring import mark_safe |
46 | 46 |
|
47 | 47 |
from astakos.im.models import AstakosUser, Invitation |
48 |
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED
|
|
48 |
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED |
|
49 | 49 |
from astakos.im.widgets import DummyWidget, RecaptchaWidget, ApprovalTermsWidget |
50 | 50 |
|
51 | 51 |
# since Django 1.4 use django.core.urlresolvers.reverse_lazy instead |
... | ... | |
160 | 160 |
super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs) |
161 | 161 |
|
162 | 162 |
#set readonly form fields |
163 |
self.fields['inviter'].widget.attrs['readonly'] = True |
|
164 |
self.fields['email'].widget.attrs['readonly'] = True |
|
165 |
self.fields['username'].widget.attrs['readonly'] = True |
|
163 |
ro = ('inviter', 'email', 'username',) |
|
164 |
for f in ro: |
|
165 |
self.fields[f].widget.attrs['readonly'] = True |
|
166 |
|
|
166 | 167 |
|
167 | 168 |
def save(self, commit=True): |
168 | 169 |
user = super(InvitedLocalUserCreationForm, self).save(commit=False) |
... | ... | |
230 | 231 |
logger.info('Created user %s', user) |
231 | 232 |
return user |
232 | 233 |
|
234 |
#class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm): |
|
235 |
# def __init__(self, *args, **kwargs): |
|
236 |
# super(InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs) |
|
237 |
# #set readonly form fields |
|
238 |
# self.fields['email'].widget.attrs['readonly'] = True |
|
239 |
|
|
233 | 240 |
class InvitedThirdPartyUserCreationForm(ThirdPartyUserCreationForm): |
241 |
""" |
|
242 |
Extends the LocalUserCreationForm: adds an inviter readonly field. |
|
243 |
""" |
|
244 |
inviter = forms.CharField(widget=forms.TextInput(), label=_('Inviter Real Name')) |
|
245 |
|
|
234 | 246 |
def __init__(self, *args, **kwargs): |
247 |
""" |
|
248 |
Changes the order of fields, and removes the username field. |
|
249 |
""" |
|
235 | 250 |
super(InvitedThirdPartyUserCreationForm, self).__init__(*args, **kwargs) |
251 |
|
|
236 | 252 |
#set readonly form fields |
237 |
self.fields['email'].widget.attrs['readonly'] = True |
|
253 |
ro = ('inviter', 'email',) |
|
254 |
for f in ro: |
|
255 |
self.fields[f].widget.attrs['readonly'] = True |
|
256 |
|
|
257 |
def save(self, commit=True): |
|
258 |
user = super(InvitedThirdPartyUserCreationForm, self).save(commit=False) |
|
259 |
level = user.invitation.inviter.level + 1 |
|
260 |
user.level = level |
|
261 |
user.invitations = INVITATIONS_PER_LEVEL.get(level, 0) |
|
262 |
user.email_verified = True |
|
263 |
if commit: |
|
264 |
user.save() |
|
265 |
return user |
|
238 | 266 |
|
239 | 267 |
class ShibbolethUserCreationForm(ThirdPartyUserCreationForm): |
240 | 268 |
def clean_email(self): |
... | ... | |
250 | 278 |
raise forms.ValidationError(_("This email is already associated with another shibboleth account.")) |
251 | 279 |
except AstakosUser.DoesNotExist: |
252 | 280 |
return email |
281 |
|
|
282 |
class InvitedShibbolethUserCreationForm(InvitedThirdPartyUserCreationForm): |
|
283 |
pass |
|
253 | 284 |
|
254 | 285 |
class LoginForm(AuthenticationForm): |
255 | 286 |
username = forms.EmailField(label=_("Email")) |
... | ... | |
326 | 357 |
'url': url, |
327 | 358 |
'site_name': SITENAME, |
328 | 359 |
'user': user, |
329 |
'baseurl': BASEURL,
|
|
360 |
'baseurl': request.build_absolute_uri(),
|
|
330 | 361 |
'support': DEFAULT_CONTACT_EMAIL |
331 | 362 |
} |
332 | 363 |
from_email = DEFAULT_FROM_EMAIL |
b/snf-astakos-app/astakos/im/functions.py | ||
---|---|---|
100 | 100 |
Raises SendInvitationError |
101 | 101 |
""" |
102 | 102 |
subject = _('Invitation to %s alpha2 testing' % SITENAME) |
103 |
url = '%s?code=%d' % (urljoin(BASEURL, reverse('astakos.im.views.signup')), invitation.code)
|
|
103 |
url = '%s?code=%d' % (urljoin(BASEURL, reverse('astakos.im.views.index')), invitation.code)
|
|
104 | 104 |
message = render_to_string('im/invitation.txt', { |
105 | 105 |
'invitation': invitation, |
106 | 106 |
'url': url, |
b/snf-astakos-app/astakos/im/management/commands/modifyuser.py | ||
---|---|---|
81 | 81 |
dest='inactive', |
82 | 82 |
default=False, |
83 | 83 |
help="Change user's state to inactive"), |
84 |
make_option('--group', |
|
85 |
dest='group', |
|
86 |
help="Extend user groups"), |
|
84 |
make_option('--add-group', |
|
85 |
dest='add-group', |
|
86 |
help="Add user group"), |
|
87 |
make_option('--delete-group', |
|
88 |
dest='delete-group', |
|
89 |
help="Delete user group"), |
|
87 | 90 |
) |
88 | 91 |
|
89 | 92 |
def handle(self, *args, **options): |
... | ... | |
108 | 111 |
if invitations is not None: |
109 | 112 |
user.invitations = int(invitations) |
110 | 113 |
|
111 |
groupname = options.get('group') |
|
114 |
groupname = options.get('add-group')
|
|
112 | 115 |
if groupname is not None: |
113 | 116 |
try: |
114 | 117 |
group = Group.objects.get(name=groupname) |
... | ... | |
116 | 119 |
except Group.DoesNotExist, e: |
117 | 120 |
raise CommandError("Group named %s does not exist." % groupname) |
118 | 121 |
|
122 |
groupname = options.get('delete-group') |
|
123 |
if groupname is not None: |
|
124 |
try: |
|
125 |
group = Group.objects.get(name=groupname) |
|
126 |
user.groups.remove(group) |
|
127 |
except Group.DoesNotExist, e: |
|
128 |
raise CommandError("Group named %s does not exist." % groupname) |
|
129 |
|
|
119 | 130 |
level = options.get('level') |
120 | 131 |
if level is not None: |
121 | 132 |
user.level = int(level) |
b/snf-astakos-app/astakos/im/target/shibboleth.py | ||
---|---|---|
39 | 39 |
from astakos.im.util import get_or_create_user, prepare_response, get_context, get_invitation |
40 | 40 |
from astakos.im.views import requires_anonymous, render_response |
41 | 41 |
from astakos.im.settings import DEFAULT_USER_LEVEL |
42 |
from astakos.im.models import AstakosUser |
|
43 |
from astakos.im.forms import ShibbolethUserCreationForm, LoginForm |
|
42 |
from astakos.im.models import AstakosUser, Invitation |
|
43 |
from astakos.im.forms import LoginForm |
|
44 |
from astakos.im.activation_backends import get_backend, SimpleBackend |
|
44 | 45 |
|
45 | 46 |
class Tokens: |
46 | 47 |
# these are mapped by the Shibboleth SP software |
... | ... | |
54 | 55 |
|
55 | 56 |
@requires_anonymous |
56 | 57 |
def login(request, backend=None, on_login_template='im/login.html', on_creation_template='im/signup.html', extra_context={}): |
57 |
#tokens = request.META
|
|
58 |
# |
|
59 |
#try:
|
|
60 |
# eppn = tokens[Tokens.SHIB_EPPN]
|
|
61 |
#except KeyError:
|
|
62 |
# return HttpResponseBadRequest("Missing unique token in request")
|
|
63 |
# |
|
64 |
#if Tokens.SHIB_DISPLAYNAME in tokens:
|
|
65 |
# realname = tokens[Tokens.SHIB_DISPLAYNAME]
|
|
66 |
#elif Tokens.SHIB_CN in tokens:
|
|
67 |
# realname = tokens[Tokens.SHIB_CN]
|
|
68 |
#elif Tokens.SHIB_NAME in tokens and Tokens.SHIB_SURNAME in tokens:
|
|
69 |
# realname = tokens[Tokens.SHIB_NAME] + ' ' + tokens[Tokens.SHIB_SURNAME]
|
|
70 |
#else:
|
|
71 |
# return HttpResponseBadRequest("Missing user name in request")
|
|
72 |
# |
|
73 |
#affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '')
|
|
58 |
tokens = request.META |
|
59 |
|
|
60 |
try: |
|
61 |
eppn = tokens[Tokens.SHIB_EPPN] |
|
62 |
except KeyError: |
|
63 |
return HttpResponseBadRequest("Missing unique token in request") |
|
64 |
|
|
65 |
if Tokens.SHIB_DISPLAYNAME in tokens: |
|
66 |
realname = tokens[Tokens.SHIB_DISPLAYNAME] |
|
67 |
elif Tokens.SHIB_CN in tokens: |
|
68 |
realname = tokens[Tokens.SHIB_CN] |
|
69 |
elif Tokens.SHIB_NAME in tokens and Tokens.SHIB_SURNAME in tokens: |
|
70 |
realname = tokens[Tokens.SHIB_NAME] + ' ' + tokens[Tokens.SHIB_SURNAME] |
|
71 |
else: |
|
72 |
return HttpResponseBadRequest("Missing user name in request") |
|
73 |
|
|
74 |
affiliation = tokens.get(Tokens.SHIB_EP_AFFILIATION, '') |
|
74 | 75 |
|
75 |
eppn, realname, affiliation = 'spapagian', 'Sofia Papagiannaki', 'grnet' |
|
76 | 76 |
try: |
77 | 77 |
user = AstakosUser.objects.get(provider='shibboleth', third_party_identifier=eppn) |
78 | 78 |
if user.is_active: |
... | ... | |
88 | 88 |
context_instance=RequestContext(request)) |
89 | 89 |
except AstakosUser.DoesNotExist, e: |
90 | 90 |
user = AstakosUser(third_party_identifier=eppn, realname=realname, |
91 |
affiliation=affiliation, |
|
92 |
provider='shibboleth') |
|
91 |
affiliation=affiliation, provider='shibboleth') |
|
92 |
try: |
|
93 |
if not backend: |
|
94 |
backend = get_backend(request) |
|
95 |
form = backend.get_signup_form(provider='shibboleth', instance=user) |
|
96 |
except (Invitation.DoesNotExist, ValueError), e: |
|
97 |
form = SimpleBackend(request).get_signup_form(provider='shibboleth', instance=user) |
|
98 |
messages.add_message(request, messages.ERROR, e) |
|
99 |
form.data.update({'third_party_identifier':eppn, 'realname':realname, |
|
100 |
'affiliation':affiliation}) |
|
93 | 101 |
return render_response(on_creation_template, |
94 |
signup_form = ShibbolethUserCreationForm(instance=user), |
|
95 |
provider = 'shibboleth', |
|
102 |
signup_form = form, |
|
96 | 103 |
context_instance=get_context(request, extra_context)) |
b/snf-astakos-app/astakos/im/templates/im/login_base.html | ||
---|---|---|
41 | 41 |
{% for o in im_modules %} |
42 | 42 |
<div> |
43 | 43 |
{% if o != 'local' %} |
44 |
LOGIN using
|
|
45 |
<a href="/im/login/{{ o }}{% ifnotequal next "" %}?next={{ next|urlencode }}{% endifnotequal %}"
|
|
44 |
LOGIN using |
|
45 |
<a href="/im/login/{{ o }}{% ifnotequal next "" %}&next={{ next|urlencode }}{% endifnotequal %}{% ifnotequal code ""%}{% if next != "" %}&{% else %}?{% endif %}code={{ code }}{% endifnotequal %}"
|
|
46 | 46 |
alt="{{ o|title }}">{{ o }}</a> |
47 | 47 |
{% endif %} |
48 | 48 |
</div> |
... | ... | |
56 | 56 |
{% endfor %} |
57 | 57 |
<div class="bottom"> |
58 | 58 |
{% block body.login.signup %} |
59 |
new to okeanos ? <a href="{% url astakos.im.views.signup %}">CREATE ACCOUNT</a> |
|
59 |
new to okeanos ? <a href="{% url astakos.im.views.signup %}{% ifnotequal code "" %}?code={{ code|urlencode }}{% endifnotequal %}">CREATE ACCOUNT</a>
|
|
60 | 60 |
{% endblock %} |
61 | 61 |
</div> |
62 | 62 |
</div> |
b/snf-astakos-app/astakos/im/util.py | ||
---|---|---|
113 | 113 |
if not code: |
114 | 114 |
return |
115 | 115 |
invitation = Invitation.objects.get(code = code) |
116 |
print '>>>', invitation |
|
117 | 116 |
if invitation.is_consumed: |
118 | 117 |
raise ValueError(_('Invitation is used')) |
119 | 118 |
try: |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
54 | 54 |
from django.contrib.auth.views import password_change |
55 | 55 |
|
56 | 56 |
from astakos.im.models import AstakosUser, Invitation, ApprovalTerms |
57 |
from astakos.im.activation_backends import get_backend |
|
57 |
from astakos.im.activation_backends import get_backend, SimpleBackend
|
|
58 | 58 |
from astakos.im.util import get_context, prepare_response, set_cookie, has_signed_terms |
59 | 59 |
from astakos.im.forms import * |
60 | 60 |
from astakos.im.functions import send_greeting, send_feedback, SendMailError |
61 |
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, BASEURL, LOGOUT_NEXT
|
|
61 |
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, COOKIE_NAME, COOKIE_DOMAIN, IM_MODULES, SITENAME, LOGOUT_NEXT |
|
62 | 62 |
from astakos.im.functions import invite as invite_func |
63 | 63 |
|
64 | 64 |
logger = logging.getLogger(__name__) |
... | ... | |
310 | 310 |
""" |
311 | 311 |
if request.user.is_authenticated(): |
312 | 312 |
return HttpResponseRedirect(reverse('astakos.im.views.index')) |
313 |
|
|
314 |
query_dict = request.__getattribute__(request.method) |
|
315 |
provider = query_dict.get('provider', 'local') |
|
313 | 316 |
try: |
314 |
form = LocalUserCreationForm() |
|
315 | 317 |
if not backend: |
316 | 318 |
backend = get_backend(request) |
317 |
query_dict = request.__getattribute__(request.method) |
|
318 |
provider = query_dict.get('provider', 'local') |
|
319 | 319 |
form = backend.get_signup_form(provider) |
320 | 320 |
except (Invitation.DoesNotExist, ValueError), e: |
321 |
messages.add_message(request, messages.ERROR, e) |
|
322 |
except ValueError, e: |
|
321 |
form = SimpleBackend(request).get_signup_form(provider) |
|
323 | 322 |
messages.add_message(request, messages.ERROR, e) |
324 | 323 |
if request.method == 'POST': |
325 | 324 |
if form.is_valid(): |
Also available in: Unified diff