Revision bf0c6de5
b/snf-astakos-app/astakos/im/forms.py | ||
---|---|---|
89 | 89 |
""" |
90 | 90 |
Changes the order of fields, and removes the username field. |
91 | 91 |
""" |
92 |
request = kwargs.get('request', None)
|
|
92 |
request = kwargs.pop('request', None)
|
|
93 | 93 |
if request: |
94 |
kwargs.pop('request') |
|
95 | 94 |
self.ip = request.META.get('REMOTE_ADDR', |
96 | 95 |
request.META.get('HTTP_X_REAL_IP', None)) |
97 | 96 |
|
... | ... | |
150 | 149 |
save behavior is complete. |
151 | 150 |
""" |
152 | 151 |
user = super(LocalUserCreationForm, self).save(commit=False) |
153 |
user.renew_token() |
|
154 | 152 |
if commit: |
155 | 153 |
user.save() |
156 | 154 |
logger._log(LOGGING_LEVEL, 'Created user %s' % user.email, []) |
... | ... | |
240 | 238 |
def save(self, commit=True): |
241 | 239 |
user = super(ThirdPartyUserCreationForm, self).save(commit=False) |
242 | 240 |
user.set_unusable_password() |
243 |
user.renew_token() |
|
244 | 241 |
user.provider = get_query(self.request).get('provider') |
245 | 242 |
if commit: |
246 | 243 |
user.save() |
... | ... | |
385 | 382 |
fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires') |
386 | 383 |
|
387 | 384 |
def __init__(self, *args, **kwargs): |
385 |
self.session_key = kwargs.pop('session_key', None) |
|
388 | 386 |
super(ProfileForm, self).__init__(*args, **kwargs) |
389 | 387 |
instance = getattr(self, 'instance', None) |
390 | 388 |
ro_fields = ('email', 'auth_token', 'auth_token_expires') |
... | ... | |
396 | 394 |
user = super(ProfileForm, self).save(commit=False) |
397 | 395 |
user.is_verified = True |
398 | 396 |
if self.cleaned_data.get('renew'): |
399 |
user.renew_token() |
|
397 |
user.renew_token( |
|
398 |
flush_sessions=True, |
|
399 |
current_key=self.session_key |
|
400 |
) |
|
400 | 401 |
if commit: |
401 | 402 |
user.save() |
402 | 403 |
return user |
... | ... | |
523 | 524 |
help_text='Unsetting this may result in security risk.') |
524 | 525 |
|
525 | 526 |
def __init__(self, user, *args, **kwargs): |
527 |
self.session_key = kwargs.pop('session_key', None) |
|
526 | 528 |
super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs) |
527 | 529 |
|
528 | 530 |
def save(self, commit=True): |
529 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
530 |
self.user.renew_token() |
|
531 |
try: |
|
532 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
533 |
self.user.renew_token() |
|
534 |
self.user.flush_sessions(current_key=self.session_key) |
|
535 |
except AttributeError: |
|
536 |
# if user model does has not such methods |
|
537 |
pass |
|
531 | 538 |
return super(ExtendedPasswordChangeForm, self).save(commit=commit) |
532 | 539 |
|
533 | 540 |
class ExtendedSetPasswordForm(SetPasswordForm): |
... | ... | |
536 | 543 |
to optionally renew also the token. |
537 | 544 |
""" |
538 | 545 |
if not NEWPASSWD_INVALIDATE_TOKEN: |
539 |
renew = forms.BooleanField(label='Renew token', required=False, |
|
540 |
initial=True, |
|
541 |
help_text='Unsetting this may result in security risk.') |
|
546 |
renew = forms.BooleanField( |
|
547 |
label='Renew token', |
|
548 |
required=False, |
|
549 |
initial=True, |
|
550 |
help_text='Unsetting this may result in security risk.' |
|
551 |
) |
|
542 | 552 |
|
543 | 553 |
def __init__(self, user, *args, **kwargs): |
544 | 554 |
super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs) |
545 | 555 |
|
546 | 556 |
def save(self, commit=True): |
547 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
548 |
if isinstance(self.user, AstakosUser): |
|
557 |
try: |
|
558 |
self.user = AstakosUser.objects.get(id=self.user.id) |
|
559 |
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'): |
|
549 | 560 |
self.user.renew_token() |
561 |
self.user.flush_sessions() |
|
562 |
except BaseException, e: |
|
563 |
logger.exception(e) |
|
564 |
pass |
|
550 | 565 |
return super(ExtendedSetPasswordForm, self).save(commit=commit) |
b/snf-astakos-app/astakos/im/functions.py | ||
---|---|---|
40 | 40 |
from django.core.urlresolvers import reverse |
41 | 41 |
from django.core.exceptions import ValidationError |
42 | 42 |
from django.template import Context, loader |
43 |
from django.contrib.auth import login as auth_login, logout as auth_logout |
|
43 |
from django.contrib.auth import ( |
|
44 |
login as auth_login, |
|
45 |
logout as auth_logout, |
|
46 |
SESSION_KEY |
|
47 |
) |
|
44 | 48 |
from django.http import HttpRequest |
45 | 49 |
|
46 | 50 |
from urllib import quote |
... | ... | |
49 | 53 |
from datetime import datetime |
50 | 54 |
from functools import wraps |
51 | 55 |
|
52 |
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, \ |
|
53 |
SITENAME, BASEURL, DEFAULT_ADMIN_EMAIL, LOGGING_LEVEL, \ |
|
54 |
VERIFICATION_EMAIL_SUBJECT, ADMIN_NOTIFICATION_EMAIL_SUBJECT, \ |
|
55 |
HELPDESK_NOTIFICATION_EMAIL_SUBJECT, INVITATION_EMAIL_SUBJECT, \ |
|
56 |
from astakos.im.settings import ( |
|
57 |
DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, |
|
58 |
SITENAME, BASEURL, DEFAULT_ADMIN_EMAIL, LOGGING_LEVEL, |
|
59 |
VERIFICATION_EMAIL_SUBJECT, ADMIN_NOTIFICATION_EMAIL_SUBJECT, |
|
60 |
HELPDESK_NOTIFICATION_EMAIL_SUBJECT, INVITATION_EMAIL_SUBJECT, |
|
56 | 61 |
GREETING_EMAIL_SUBJECT, FEEDBACK_EMAIL_SUBJECT, EMAIL_CHANGE_EMAIL_SUBJECT |
57 |
from astakos.im.models import Invitation, AstakosUser |
|
62 |
) |
|
63 |
from astakos.im.models import Invitation, AstakosUser, SessionCatalog |
|
58 | 64 |
|
59 | 65 |
logger = logging.getLogger(__name__) |
60 | 66 |
|
... | ... | |
75 | 81 |
return r |
76 | 82 |
return with_logging |
77 | 83 |
|
78 |
login = logged(auth_login, '%s logged in.') |
|
84 |
|
|
85 |
def login(request, user): |
|
86 |
auth_login(request, user) |
|
87 |
SessionCatalog(session_key=request.session.session_key, user=user).save() |
|
88 |
|
|
89 |
login = logged(login, '%s logged in.') |
|
79 | 90 |
logout = logged(auth_logout, '%s logged out.') |
80 | 91 |
|
81 | 92 |
def send_verification(user, template_name='im/activation_email.txt'): |
b/snf-astakos-app/astakos/im/management/commands/user-add.py | ||
---|---|---|
99 | 99 |
email=email, affiliation=affiliation, |
100 | 100 |
provider='local') |
101 | 101 |
user.set_password(password) |
102 |
user.renew_token() |
|
103 | 102 |
|
104 | 103 |
if options['active']: |
105 | 104 |
user.is_active = True |
b/snf-astakos-app/astakos/im/migrations/0016_auto__add_sessioncatalog.py | ||
---|---|---|
1 |
# encoding: utf-8 |
|
2 |
import datetime |
|
3 |
from south.db import db |
|
4 |
from south.v2 import SchemaMigration |
|
5 |
from django.db import models |
|
6 |
|
|
7 |
class Migration(SchemaMigration): |
|
8 |
|
|
9 |
def forwards(self, orm): |
|
10 |
|
|
11 |
# Adding model 'SessionCatalog' |
|
12 |
db.create_table('im_sessioncatalog', ( |
|
13 |
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
|
14 |
('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)), |
|
15 |
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='sessions', null=True, to=orm['im.AstakosUser'])), |
|
16 |
)) |
|
17 |
db.send_create_signal('im', ['SessionCatalog']) |
|
18 |
|
|
19 |
|
|
20 |
def backwards(self, orm): |
|
21 |
|
|
22 |
# Deleting model 'SessionCatalog' |
|
23 |
db.delete_table('im_sessioncatalog') |
|
24 |
|
|
25 |
|
|
26 |
models = { |
|
27 |
'auth.group': { |
|
28 |
'Meta': {'object_name': 'Group'}, |
|
29 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
30 |
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), |
|
31 |
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) |
|
32 |
}, |
|
33 |
'auth.permission': { |
|
34 |
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, |
|
35 |
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
36 |
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), |
|
37 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
38 |
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) |
|
39 |
}, |
|
40 |
'auth.user': { |
|
41 |
'Meta': {'object_name': 'User'}, |
|
42 |
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
|
43 |
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), |
|
44 |
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
45 |
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), |
|
46 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
47 |
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), |
|
48 |
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
49 |
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
50 |
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), |
|
51 |
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
52 |
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), |
|
53 |
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), |
|
54 |
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
|
55 |
}, |
|
56 |
'contenttypes.contenttype': { |
|
57 |
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, |
|
58 |
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
59 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
60 |
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), |
|
61 |
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) |
|
62 |
}, |
|
63 |
'im.additionalmail': { |
|
64 |
'Meta': {'object_name': 'AdditionalMail'}, |
|
65 |
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), |
|
66 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
67 |
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"}) |
|
68 |
}, |
|
69 |
'im.approvalterms': { |
|
70 |
'Meta': {'object_name': 'ApprovalTerms'}, |
|
71 |
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 27, 16, 51, 48, 446565)', 'db_index': 'True'}), |
|
72 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
73 |
'location': ('django.db.models.fields.CharField', [], {'max_length': '255'}) |
|
74 |
}, |
|
75 |
'im.astakosuser': { |
|
76 |
'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'AstakosUser', '_ormbases': ['auth.User']}, |
|
77 |
'activation_sent': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
|
78 |
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
|
79 |
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), |
|
80 |
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), |
|
81 |
'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), |
|
82 |
'date_signed_terms': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
|
83 |
'email_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
84 |
'has_credits': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
85 |
'has_signed_terms': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
86 |
'invitations': ('django.db.models.fields.IntegerField', [], {'default': '100'}), |
|
87 |
'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
88 |
'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}), |
|
89 |
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
|
90 |
'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
|
91 |
'updated': ('django.db.models.fields.DateTimeField', [], {}), |
|
92 |
'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}) |
|
93 |
}, |
|
94 |
'im.emailchange': { |
|
95 |
'Meta': {'object_name': 'EmailChange'}, |
|
96 |
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}), |
|
97 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
98 |
'new_email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), |
|
99 |
'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 27, 16, 51, 48, 448299)'}), |
|
100 |
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchange_user'", 'unique': 'True', 'to': "orm['im.AstakosUser']"}) |
|
101 |
}, |
|
102 |
'im.invitation': { |
|
103 |
'Meta': {'object_name': 'Invitation'}, |
|
104 |
'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}), |
|
105 |
'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), |
|
106 |
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), |
|
107 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
108 |
'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.AstakosUser']"}), |
|
109 |
'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), |
|
110 |
'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}), |
|
111 |
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) |
|
112 |
}, |
|
113 |
'im.pendingthirdpartyuser': { |
|
114 |
'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'PendingThirdPartyUser'}, |
|
115 |
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
|
116 |
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), |
|
117 |
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
118 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
119 |
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), |
|
120 |
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), |
|
121 |
'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), |
|
122 |
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) |
|
123 |
}, |
|
124 |
'im.service': { |
|
125 |
'Meta': {'object_name': 'Service'}, |
|
126 |
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}), |
|
127 |
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), |
|
128 |
'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), |
|
129 |
'icon': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}), |
|
130 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
131 |
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), |
|
132 |
'url': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}) |
|
133 |
}, |
|
134 |
'im.sessioncatalog': { |
|
135 |
'Meta': {'object_name': 'SessionCatalog'}, |
|
136 |
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
|
137 |
'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), |
|
138 |
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'to': "orm['im.AstakosUser']"}) |
|
139 |
} |
|
140 |
} |
|
141 |
|
|
142 |
complete_apps = ['im'] |
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
49 | 49 |
from django.template.loader import render_to_string |
50 | 50 |
from django.core.mail import send_mail |
51 | 51 |
from django.db import transaction |
52 |
from django.db.models.signals import post_save, post_syncdb |
|
52 |
from django.db.models.signals import post_save, pre_save, post_syncdb
|
|
53 | 53 |
from django.db.models import Q |
54 | 54 |
from django.conf import settings |
55 |
from django.utils.importlib import import_module |
|
55 | 56 |
|
56 |
from astakos.im.settings import DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL, \ |
|
57 |
AUTH_TOKEN_DURATION, BILLING_FIELDS, QUEUE_CONNECTION, SITENAME, \ |
|
57 |
from astakos.im.settings import ( |
|
58 |
DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL, |
|
59 |
AUTH_TOKEN_DURATION, BILLING_FIELDS, QUEUE_CONNECTION, SITENAME, |
|
58 | 60 |
EMAILCHANGE_ACTIVATION_DAYS, LOGGING_LEVEL |
61 |
) |
|
59 | 62 |
|
60 | 63 |
QUEUE_CLIENT_ID = 3 # Astakos. |
61 | 64 |
|
... | ... | |
165 | 168 |
except Group.DoesNotExist, e: |
166 | 169 |
logger.exception(e) |
167 | 170 |
|
168 |
def renew_token(self): |
|
171 |
def renew_token(self, flush_sessions=False, current_key=None):
|
|
169 | 172 |
md5 = hashlib.md5() |
170 | 173 |
md5.update(settings.SECRET_KEY) |
171 | 174 |
md5.update(self.username) |
172 | 175 |
md5.update(self.realname.encode('ascii', 'ignore')) |
173 | 176 |
md5.update(asctime()) |
174 |
|
|
177 |
|
|
175 | 178 |
self.auth_token = b64encode(md5.digest()) |
176 | 179 |
self.auth_token_created = datetime.now() |
177 | 180 |
self.auth_token_expires = self.auth_token_created + \ |
178 | 181 |
timedelta(hours=AUTH_TOKEN_DURATION) |
182 |
if flush_sessions: |
|
183 |
self.flush_sessions(current_key) |
|
179 | 184 |
msg = 'Token renewed for %s' % self.email |
180 | 185 |
logger._log(LOGGING_LEVEL, msg, []) |
181 | 186 |
|
187 |
def flush_sessions(self, current_key=None): |
|
188 |
q = self.sessions |
|
189 |
if current_key: |
|
190 |
q = q.exclude(session_key=current_key) |
|
191 |
|
|
192 |
keys = q.values_list('session_key', flat=True) |
|
193 |
if keys: |
|
194 |
msg = 'Flushing sessions: %s' % ','.join(keys) |
|
195 |
logger._log(LOGGING_LEVEL, msg, []) |
|
196 |
engine = import_module(settings.SESSION_ENGINE) |
|
197 |
for k in keys: |
|
198 |
s = engine.SessionStore(k) |
|
199 |
s.flush() |
|
200 |
# q.all().delete() |
|
201 |
|
|
182 | 202 |
def __unicode__(self): |
183 | 203 |
return self.username |
184 | 204 |
|
... | ... | |
355 | 375 |
auth_token_created = models.DateTimeField('Token creation date', null=True) |
356 | 376 |
auth_token_expires = models.DateTimeField('Token expiration date', null=True) |
357 | 377 |
|
358 |
def save(self, **kwargs): |
|
359 |
if not self.id: |
|
360 |
self.renew_token() |
|
361 |
self.full_clean() |
|
362 |
super(Service, self).save(**kwargs) |
|
363 |
|
|
364 | 378 |
def renew_token(self): |
365 | 379 |
md5 = hashlib.md5() |
366 | 380 |
md5.update(settings.SECRET_KEY) |
... | ... | |
372 | 386 |
self.auth_token_created = datetime.now() |
373 | 387 |
self.auth_token_expires = self.auth_token_created + \ |
374 | 388 |
timedelta(hours=AUTH_TOKEN_DURATION) |
389 |
msg = 'Token renewed for %s' % self.name |
|
390 |
logger._log(LOGGING_LEVEL, msg, []) |
|
375 | 391 |
|
376 | 392 |
class AdditionalMail(models.Model): |
377 | 393 |
""" |
... | ... | |
419 | 435 |
self.username = username |
420 | 436 |
super(PendingThirdPartyUser, self).save(**kwargs) |
421 | 437 |
|
438 |
class SessionCatalog(models.Model): |
|
439 |
session_key = models.CharField(_('session key'), max_length=40) |
|
440 |
user = models.ForeignKey(AstakosUser, related_name='sessions', null=True) |
|
441 |
|
|
422 | 442 |
def create_astakos_user(u): |
423 | 443 |
try: |
424 | 444 |
AstakosUser.objects.get(user_ptr=u.pk) |
425 | 445 |
except AstakosUser.DoesNotExist: |
426 | 446 |
extended_user = AstakosUser(user_ptr_id=u.pk) |
427 | 447 |
extended_user.__dict__.update(u.__dict__) |
428 |
extended_user.renew_token() |
|
429 | 448 |
extended_user.save() |
430 | 449 |
except: |
431 | 450 |
pass |
... | ... | |
443 | 462 |
if instance.is_superuser: |
444 | 463 |
create_astakos_user(instance) |
445 | 464 |
|
446 |
post_save.connect(superuser_post_save, sender=User) |
|
465 |
def astakosuser_post_save(sender, instance, **kwargs): |
|
466 |
pass |
|
467 |
|
|
468 |
post_save.connect(superuser_post_save, sender=User) |
|
469 |
|
|
470 |
def renew_token(sender, instance, **kwargs): |
|
471 |
if not instance.id: |
|
472 |
instance.renew_token() |
|
473 |
|
|
474 |
pre_save.connect(renew_token, sender=AstakosUser) |
|
475 |
pre_save.connect(renew_token, sender=Service) |
b/snf-astakos-app/astakos/im/target/local.py | ||
---|---|---|
31 | 31 |
# interpreted as representing official policies, either expressed |
32 | 32 |
# or implied, of GRNET S.A. |
33 | 33 |
|
34 |
from django.http import HttpResponseBadRequest |
|
34 |
from django.http import HttpResponseBadRequest, HttpResponseRedirect
|
|
35 | 35 |
from django.shortcuts import render_to_response |
36 | 36 |
from django.template import RequestContext |
37 | 37 |
from django.contrib.auth import authenticate |
... | ... | |
40 | 40 |
from django.views.decorators.csrf import csrf_exempt |
41 | 41 |
from django.views.decorators.http import require_http_methods |
42 | 42 |
from django.core.urlresolvers import reverse |
43 |
from django.contrib.auth.decorators import login_required |
|
43 | 44 |
|
44 | 45 |
from astakos.im.util import prepare_response, get_query |
45 |
from astakos.im.views import requires_anonymous |
|
46 |
from astakos.im.views import requires_anonymous, signed_terms_required
|
|
46 | 47 |
from astakos.im.models import AstakosUser, PendingThirdPartyUser |
47 |
from astakos.im.forms import LoginForm |
|
48 |
from astakos.im.forms import LoginForm, ExtendedPasswordChangeForm
|
|
48 | 49 |
from astakos.im.settings import RATELIMIT_RETRIES_ALLOWED |
49 | 50 |
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION |
50 | 51 |
|
... | ... | |
123 | 124 |
request, |
124 | 125 |
_('Account successfully switched to %(provider)s' % user.__dict__) |
125 | 126 |
) |
126 |
return prepare_response(request, user, next) |
|
127 |
return prepare_response(request, user, next) |
|
128 |
|
|
129 |
@require_http_methods(["GET", "POST"]) |
|
130 |
@signed_terms_required |
|
131 |
@login_required |
|
132 |
def password_change(request, template_name='registration/password_change_form.html', |
|
133 |
post_change_redirect=None, password_change_form=ExtendedPasswordChangeForm): |
|
134 |
if post_change_redirect is None: |
|
135 |
post_change_redirect = reverse('django.contrib.auth.views.password_change_done') |
|
136 |
if request.method == "POST": |
|
137 |
form = password_change_form( |
|
138 |
user=request.user, |
|
139 |
data=request.POST, |
|
140 |
session_key=request.session.session_key |
|
141 |
) |
|
142 |
if form.is_valid(): |
|
143 |
form.save() |
|
144 |
return HttpResponseRedirect(post_change_redirect) |
|
145 |
else: |
|
146 |
form = password_change_form(user=request.user) |
|
147 |
return render_to_response(template_name, { |
|
148 |
'form': form, |
|
149 |
}, context_instance=RequestContext(request)) |
b/snf-astakos-app/astakos/im/target/redirect.py | ||
---|---|---|
96 | 96 |
return response |
97 | 97 |
renew = request.GET.get('renew', None) |
98 | 98 |
if renew == '': |
99 |
request.user.renew_token() |
|
99 |
request.user.renew_token( |
|
100 |
flush_sessions=True, |
|
101 |
current_key=request.session.session_key |
|
102 |
) |
|
100 | 103 |
try: |
101 | 104 |
request.user.save() |
102 | 105 |
except ValidationError, e: |
b/snf-astakos-app/astakos/im/templates/registration/password_change_form.html | ||
---|---|---|
1 | 1 |
{% extends "im/account_base.html" %} |
2 | 2 |
|
3 | 3 |
{% block body %} |
4 |
<form action="{% url django.contrib.auth.views.password_change %}" method="post"
|
|
4 |
<form action="{% url astakos.im.target.local.password_change %}" method="post"
|
|
5 | 5 |
class="withlabels">{% csrf_token %} |
6 | 6 |
|
7 | 7 |
{% include "im/form_render.html" %} |
b/snf-astakos-app/astakos/im/urls.py | ||
---|---|---|
49 | 49 |
url(r'^activate/?$', 'activate'), |
50 | 50 |
url(r'^approval_terms/?$', 'approval_terms', {}, name='latest_terms'), |
51 | 51 |
url(r'^approval_terms/(?P<term_id>\d+)/?$', 'approval_terms'), |
52 |
url(r'^password/?$', 'change_password', {}, name='password_change'), |
|
53 | 52 |
url(r'^send/activation/(?P<user_id>\d+)/?$', 'send_activation', {}, name='send_activation') |
54 | 53 |
) |
55 | 54 |
|
... | ... | |
66 | 65 |
|
67 | 66 |
if 'local' in IM_MODULES: |
68 | 67 |
urlpatterns += patterns('astakos.im.target', |
69 |
url(r'^local/?$', 'local.login') |
|
68 |
url(r'^local/?$', 'local.login'), |
|
69 |
url(r'^password_change/?$', 'local.password_change', { |
|
70 |
'post_change_redirect':'profile', |
|
71 |
'password_change_form':ExtendedPasswordChangeForm |
|
72 |
}, |
|
73 |
name='password_change') |
|
70 | 74 |
) |
71 | 75 |
urlpatterns += patterns('django.contrib.auth.views', |
72 | 76 |
url(r'^local/password_reset/?$', 'password_reset', |
... | ... | |
75 | 79 |
url(r'^local/password_reset_done/?$', 'password_reset_done'), |
76 | 80 |
url(r'^local/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/?$', |
77 | 81 |
'password_reset_confirm', {'set_password_form':ExtendedSetPasswordForm}), |
78 |
url(r'^local/password/reset/complete/?$', 'password_reset_complete'), |
|
79 |
url(r'^password_change/?$', 'password_change', {'post_change_redirect':'profile', |
|
80 |
'password_change_form':ExtendedPasswordChangeForm}) |
|
82 |
url(r'^local/password/reset/complete/?$', 'password_reset_complete') |
|
81 | 83 |
) |
82 | 84 |
|
83 | 85 |
if INVITATIONS_ENABLED: |
b/snf-astakos-app/astakos/im/util.py | ||
---|---|---|
156 | 156 |
renew = renew or (not user.auth_token) |
157 | 157 |
renew = renew or (user.auth_token_expires and user.auth_token_expires < datetime.datetime.now()) |
158 | 158 |
if renew: |
159 |
user.renew_token() |
|
159 |
user.renew_token( |
|
160 |
flush_sessions=True, |
|
161 |
current_key=request.session.session_key |
|
162 |
) |
|
160 | 163 |
try: |
161 | 164 |
user.save() |
162 | 165 |
except ValidationError, e: |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
263 | 263 |
* LOGIN_URL: login uri |
264 | 264 |
""" |
265 | 265 |
extra_context = extra_context or {} |
266 |
form = ProfileForm(instance=request.user) |
|
266 |
form = ProfileForm( |
|
267 |
instance=request.user, |
|
268 |
session_key=request.session.session_key |
|
269 |
) |
|
267 | 270 |
extra_context['next'] = request.GET.get('next') |
268 | 271 |
if request.method == 'POST': |
269 |
form = ProfileForm(request.POST, instance=request.user) |
|
272 |
form = ProfileForm( |
|
273 |
request.POST, |
|
274 |
instance=request.user, |
|
275 |
session_key=request.session.session_key |
|
276 |
) |
|
270 | 277 |
if form.is_valid(): |
271 | 278 |
try: |
272 | 279 |
prev_token = request.user.auth_token |
273 | 280 |
user = form.save() |
274 |
form = ProfileForm(instance=user) |
|
281 |
form = ProfileForm( |
|
282 |
instance=user, |
|
283 |
session_key=request.session.session_key |
|
284 |
) |
|
275 | 285 |
next = restrict_next( |
276 | 286 |
request.POST.get('next'), |
277 | 287 |
domain=COOKIE_DOMAIN |
Also available in: Unified diff