Commit 7b996d13 authored by Sofia Papagiannaki's avatar Sofia Papagiannaki
Browse files

Flush other user sessions during password/token change

Refs: #3007
parent 27052cdb
......@@ -89,9 +89,8 @@ class LocalUserCreationForm(UserCreationForm):
"""
Changes the order of fields, and removes the username field.
"""
request = kwargs.get('request', None)
request = kwargs.pop('request', None)
if request:
kwargs.pop('request')
self.ip = request.META.get('REMOTE_ADDR',
request.META.get('HTTP_X_REAL_IP', None))
......@@ -150,7 +149,6 @@ class LocalUserCreationForm(UserCreationForm):
save behavior is complete.
"""
user = super(LocalUserCreationForm, self).save(commit=False)
user.renew_token()
if commit:
user.save()
logger._log(LOGGING_LEVEL, 'Created user %s' % user.email, [])
......@@ -240,7 +238,6 @@ class ThirdPartyUserCreationForm(forms.ModelForm):
def save(self, commit=True):
user = super(ThirdPartyUserCreationForm, self).save(commit=False)
user.set_unusable_password()
user.renew_token()
user.provider = get_query(self.request).get('provider')
if commit:
user.save()
......@@ -385,6 +382,7 @@ class ProfileForm(forms.ModelForm):
fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires')
def __init__(self, *args, **kwargs):
self.session_key = kwargs.pop('session_key', None)
super(ProfileForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
ro_fields = ('email', 'auth_token', 'auth_token_expires')
......@@ -396,7 +394,10 @@ class ProfileForm(forms.ModelForm):
user = super(ProfileForm, self).save(commit=False)
user.is_verified = True
if self.cleaned_data.get('renew'):
user.renew_token()
user.renew_token(
flush_sessions=True,
current_key=self.session_key
)
if commit:
user.save()
return user
......@@ -523,11 +524,17 @@ class ExtendedPasswordChangeForm(PasswordChangeForm):
help_text='Unsetting this may result in security risk.')
def __init__(self, user, *args, **kwargs):
self.session_key = kwargs.pop('session_key', None)
super(ExtendedPasswordChangeForm, self).__init__(user, *args, **kwargs)
def save(self, commit=True):
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
self.user.renew_token()
try:
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
self.user.renew_token()
self.user.flush_sessions(current_key=self.session_key)
except AttributeError:
# if user model does has not such methods
pass
return super(ExtendedPasswordChangeForm, self).save(commit=commit)
class ExtendedSetPasswordForm(SetPasswordForm):
......@@ -536,15 +543,23 @@ class ExtendedSetPasswordForm(SetPasswordForm):
to optionally renew also the token.
"""
if not NEWPASSWD_INVALIDATE_TOKEN:
renew = forms.BooleanField(label='Renew token', required=False,
initial=True,
help_text='Unsetting this may result in security risk.')
renew = forms.BooleanField(
label='Renew token',
required=False,
initial=True,
help_text='Unsetting this may result in security risk.'
)
def __init__(self, user, *args, **kwargs):
super(ExtendedSetPasswordForm, self).__init__(user, *args, **kwargs)
def save(self, commit=True):
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
if isinstance(self.user, AstakosUser):
try:
self.user = AstakosUser.objects.get(id=self.user.id)
if NEWPASSWD_INVALIDATE_TOKEN or self.cleaned_data.get('renew'):
self.user.renew_token()
self.user.flush_sessions()
except BaseException, e:
logger.exception(e)
pass
return super(ExtendedSetPasswordForm, self).save(commit=commit)
......@@ -40,7 +40,11 @@ from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
from django.template import Context, loader
from django.contrib.auth import login as auth_login, logout as auth_logout
from django.contrib.auth import (
login as auth_login,
logout as auth_logout,
SESSION_KEY
)
from django.http import HttpRequest
from urllib import quote
......@@ -49,12 +53,14 @@ from smtplib import SMTPException
from datetime import datetime
from functools import wraps
from astakos.im.settings import DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL, \
SITENAME, BASEURL, DEFAULT_ADMIN_EMAIL, LOGGING_LEVEL, \
VERIFICATION_EMAIL_SUBJECT, ADMIN_NOTIFICATION_EMAIL_SUBJECT, \
HELPDESK_NOTIFICATION_EMAIL_SUBJECT, INVITATION_EMAIL_SUBJECT, \
from astakos.im.settings import (
DEFAULT_CONTACT_EMAIL, DEFAULT_FROM_EMAIL,
SITENAME, BASEURL, DEFAULT_ADMIN_EMAIL, LOGGING_LEVEL,
VERIFICATION_EMAIL_SUBJECT, ADMIN_NOTIFICATION_EMAIL_SUBJECT,
HELPDESK_NOTIFICATION_EMAIL_SUBJECT, INVITATION_EMAIL_SUBJECT,
GREETING_EMAIL_SUBJECT, FEEDBACK_EMAIL_SUBJECT, EMAIL_CHANGE_EMAIL_SUBJECT
from astakos.im.models import Invitation, AstakosUser
)
from astakos.im.models import Invitation, AstakosUser, SessionCatalog
logger = logging.getLogger(__name__)
......@@ -75,7 +81,12 @@ def logged(func, msg):
return r
return with_logging
login = logged(auth_login, '%s logged in.')
def login(request, user):
auth_login(request, user)
SessionCatalog(session_key=request.session.session_key, user=user).save()
login = logged(login, '%s logged in.')
logout = logged(auth_logout, '%s logged out.')
def send_verification(user, template_name='im/activation_email.txt'):
......
......@@ -99,7 +99,6 @@ class Command(BaseCommand):
email=email, affiliation=affiliation,
provider='local')
user.set_password(password)
user.renew_token()
if options['active']:
user.is_active = True
......
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'SessionCatalog'
db.create_table('im_sessioncatalog', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('session_key', self.gf('django.db.models.fields.CharField')(max_length=40)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='sessions', null=True, to=orm['im.AstakosUser'])),
))
db.send_create_signal('im', ['SessionCatalog'])
def backwards(self, orm):
# Deleting model 'SessionCatalog'
db.delete_table('im_sessioncatalog')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'im.additionalmail': {
'Meta': {'object_name': 'AdditionalMail'},
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['im.AstakosUser']"})
},
'im.approvalterms': {
'Meta': {'object_name': 'ApprovalTerms'},
'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 27, 16, 51, 48, 446565)', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location': ('django.db.models.fields.CharField', [], {'max_length': '255'})
},
'im.astakosuser': {
'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'AstakosUser', '_ormbases': ['auth.User']},
'activation_sent': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'date_signed_terms': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'email_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'has_credits': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'has_signed_terms': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'invitations': ('django.db.models.fields.IntegerField', [], {'default': '100'}),
'is_verified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {}),
'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'})
},
'im.emailchange': {
'Meta': {'object_name': 'EmailChange'},
'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'new_email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
'requested_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 11, 27, 16, 51, 48, 448299)'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emailchange_user'", 'unique': 'True', 'to': "orm['im.AstakosUser']"})
},
'im.invitation': {
'Meta': {'object_name': 'Invitation'},
'code': ('django.db.models.fields.BigIntegerField', [], {'db_index': 'True'}),
'consumed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'inviter': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'invitations_sent'", 'null': 'True', 'to': "orm['im.AstakosUser']"}),
'is_consumed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'realname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
},
'im.pendingthirdpartyuser': {
'Meta': {'unique_together': "(('provider', 'third_party_identifier'),)", 'object_name': 'PendingThirdPartyUser'},
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'third_party_identifier': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'im.service': {
'Meta': {'object_name': 'Service'},
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'icon': ('django.db.models.fields.FilePathField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
'url': ('django.db.models.fields.FilePathField', [], {'max_length': '100'})
},
'im.sessioncatalog': {
'Meta': {'object_name': 'SessionCatalog'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'sessions'", 'null': 'True', 'to': "orm['im.AstakosUser']"})
}
}
complete_apps = ['im']
......@@ -49,13 +49,16 @@ from django.core.exceptions import ValidationError
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.db import transaction
from django.db.models.signals import post_save, post_syncdb
from django.db.models.signals import post_save, pre_save, post_syncdb
from django.db.models import Q
from django.conf import settings
from django.utils.importlib import import_module
from astakos.im.settings import DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL, \
AUTH_TOKEN_DURATION, BILLING_FIELDS, QUEUE_CONNECTION, SITENAME, \
from astakos.im.settings import (
DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL,
AUTH_TOKEN_DURATION, BILLING_FIELDS, QUEUE_CONNECTION, SITENAME,
EMAILCHANGE_ACTIVATION_DAYS, LOGGING_LEVEL
)
QUEUE_CLIENT_ID = 3 # Astakos.
......@@ -165,20 +168,37 @@ class AstakosUser(User):
except Group.DoesNotExist, e:
logger.exception(e)
def renew_token(self):
def renew_token(self, flush_sessions=False, current_key=None):
md5 = hashlib.md5()
md5.update(settings.SECRET_KEY)
md5.update(self.username)
md5.update(self.realname.encode('ascii', 'ignore'))
md5.update(asctime())
self.auth_token = b64encode(md5.digest())
self.auth_token_created = datetime.now()
self.auth_token_expires = self.auth_token_created + \
timedelta(hours=AUTH_TOKEN_DURATION)
if flush_sessions:
self.flush_sessions(current_key)
msg = 'Token renewed for %s' % self.email
logger._log(LOGGING_LEVEL, msg, [])
def flush_sessions(self, current_key=None):
q = self.sessions
if current_key:
q = q.exclude(session_key=current_key)
keys = q.values_list('session_key', flat=True)
if keys:
msg = 'Flushing sessions: %s' % ','.join(keys)
logger._log(LOGGING_LEVEL, msg, [])
engine = import_module(settings.SESSION_ENGINE)
for k in keys:
s = engine.SessionStore(k)
s.flush()
# q.all().delete()
def __unicode__(self):
return self.username
......@@ -355,12 +375,6 @@ class Service(models.Model):
auth_token_created = models.DateTimeField('Token creation date', null=True)
auth_token_expires = models.DateTimeField('Token expiration date', null=True)
def save(self, **kwargs):
if not self.id:
self.renew_token()
self.full_clean()
super(Service, self).save(**kwargs)
def renew_token(self):
md5 = hashlib.md5()
md5.update(settings.SECRET_KEY)
......@@ -372,6 +386,8 @@ class Service(models.Model):
self.auth_token_created = datetime.now()
self.auth_token_expires = self.auth_token_created + \
timedelta(hours=AUTH_TOKEN_DURATION)
msg = 'Token renewed for %s' % self.name
logger._log(LOGGING_LEVEL, msg, [])
class AdditionalMail(models.Model):
"""
......@@ -419,13 +435,16 @@ class PendingThirdPartyUser(models.Model):
self.username = username
super(PendingThirdPartyUser, self).save(**kwargs)
class SessionCatalog(models.Model):
session_key = models.CharField(_('session key'), max_length=40)
user = models.ForeignKey(AstakosUser, related_name='sessions', null=True)
def create_astakos_user(u):
try:
AstakosUser.objects.get(user_ptr=u.pk)
except AstakosUser.DoesNotExist:
extended_user = AstakosUser(user_ptr_id=u.pk)
extended_user.__dict__.update(u.__dict__)
extended_user.renew_token()
extended_user.save()
except:
pass
......@@ -443,4 +462,14 @@ def superuser_post_save(sender, instance, **kwargs):
if instance.is_superuser:
create_astakos_user(instance)
post_save.connect(superuser_post_save, sender=User)
\ No newline at end of file
def astakosuser_post_save(sender, instance, **kwargs):
pass
post_save.connect(superuser_post_save, sender=User)
def renew_token(sender, instance, **kwargs):
if not instance.id:
instance.renew_token()
pre_save.connect(renew_token, sender=AstakosUser)
pre_save.connect(renew_token, sender=Service)
\ No newline at end of file
......@@ -31,7 +31,7 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from django.http import HttpResponseBadRequest
from django.http import HttpResponseBadRequest, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.auth import authenticate
......@@ -40,11 +40,12 @@ from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from astakos.im.util import prepare_response, get_query
from astakos.im.views import requires_anonymous
from astakos.im.views import requires_anonymous, signed_terms_required
from astakos.im.models import AstakosUser, PendingThirdPartyUser
from astakos.im.forms import LoginForm
from astakos.im.forms import LoginForm, ExtendedPasswordChangeForm
from astakos.im.settings import RATELIMIT_RETRIES_ALLOWED
from astakos.im.settings import ENABLE_LOCAL_ACCOUNT_MIGRATION
......@@ -123,4 +124,26 @@ def login(request, on_failure='im/login.html'):
request,
_('Account successfully switched to %(provider)s' % user.__dict__)
)
return prepare_response(request, user, next)
\ No newline at end of file
return prepare_response(request, user, next)
@require_http_methods(["GET", "POST"])
@signed_terms_required
@login_required
def password_change(request, template_name='registration/password_change_form.html',
post_change_redirect=None, password_change_form=ExtendedPasswordChangeForm):
if post_change_redirect is None:
post_change_redirect = reverse('django.contrib.auth.views.password_change_done')
if request.method == "POST":
form = password_change_form(
user=request.user,
data=request.POST,
session_key=request.session.session_key
)
if form.is_valid():
form.save()
return HttpResponseRedirect(post_change_redirect)
else:
form = password_change_form(user=request.user)
return render_to_response(template_name, {
'form': form,
}, context_instance=RequestContext(request))
\ No newline at end of file
......@@ -96,7 +96,10 @@ def login(request):
return response
renew = request.GET.get('renew', None)
if renew == '':
request.user.renew_token()
request.user.renew_token(
flush_sessions=True,
current_key=request.session.session_key
)
try:
request.user.save()
except ValidationError, e:
......
{% extends "im/account_base.html" %}
{% block body %}
<form action="{% url django.contrib.auth.views.password_change %}" method="post"
<form action="{% url astakos.im.target.local.password_change %}" method="post"
class="withlabels">{% csrf_token %}
{% include "im/form_render.html" %}
......
......@@ -49,7 +49,6 @@ urlpatterns = patterns('astakos.im.views',
url(r'^activate/?$', 'activate'),
url(r'^approval_terms/?$', 'approval_terms', {}, name='latest_terms'),
url(r'^approval_terms/(?P<term_id>\d+)/?$', 'approval_terms'),
url(r'^password/?$', 'change_password', {}, name='password_change'),
url(r'^send/activation/(?P<user_id>\d+)/?$', 'send_activation', {}, name='send_activation')
)
......@@ -66,7 +65,12 @@ urlpatterns += patterns('astakos.im.target',
if 'local' in IM_MODULES:
urlpatterns += patterns('astakos.im.target',
url(r'^local/?$', 'local.login')
url(r'^local/?$', 'local.login'),
url(r'^password_change/?$', 'local.password_change', {
'post_change_redirect':'profile',
'password_change_form':ExtendedPasswordChangeForm
},
name='password_change')
)
urlpatterns += patterns('django.contrib.auth.views',
url(r'^local/password_reset/?$', 'password_reset',
......@@ -75,9 +79,7 @@ if 'local' in IM_MODULES:
url(r'^local/password_reset_done/?$', 'password_reset_done'),
url(r'^local/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/?$',
'password_reset_confirm', {'set_password_form':ExtendedSetPasswordForm}),
url(r'^local/password/reset/complete/?$', 'password_reset_complete'),
url(r'^password_change/?$', 'password_change', {'post_change_redirect':'profile',
'password_change_form':ExtendedPasswordChangeForm})
url(r'^local/password/reset/complete/?$', 'password_reset_complete')
)
if INVITATIONS_ENABLED:
......
......@@ -156,7 +156,10 @@ def prepare_response(request, user, next='', renew=False):
renew = renew or (not user.auth_token)
renew = renew or (user.auth_token_expires and user.auth_token_expires < datetime.datetime.now())
if renew:
user.renew_token()
user.renew_token(
flush_sessions=True,
current_key=request.session.session_key
)
try:
user.save()
except ValidationError, e:
......
......@@ -263,15 +263,25 @@ def edit_profile(request, template_name='im/profile.html', extra_context=None):
* LOGIN_URL: login uri
"""
extra_context = extra_context or {}
form = ProfileForm(instance=request.user)
form = ProfileForm(
instance=request.user,
session_key=request.session.session_key
)
extra_context['next'] = request.GET.get('next')
if request.method == 'POST':
form = ProfileForm(request.POST, instance=request.user)
form = ProfileForm(
request.POST,
instance=request.user,
session_key=request.session.session_key
)
if form.is_valid():
try:
prev_token = request.user.auth_token
user = form.save()
form = ProfileForm(instance=user)
form = ProfileForm(
instance=user,
session_key=request.session.session_key
)
next = restrict_next(
request.POST.get('next'),
domain=COOKIE_DOMAIN
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment