1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-04-28 03:10:45 +00:00

add password_session app

This commit is contained in:
lian 2015-07-22 15:03:33 +08:00
parent ebf1d7f8d0
commit f1b352e9ac
10 changed files with 128 additions and 0 deletions

View File

@ -29,6 +29,8 @@ from seahub.utils.ip import get_remote_ip
from seahub.settings import USER_PASSWORD_MIN_LENGTH, \
USER_STRONG_PASSWORD_REQUIRED, USER_PASSWORD_STRENGTH_LEVEL
from seahub.password_session import update_session_auth_hash
# Get an instance of a logger
logger = logging.getLogger(__name__)
@ -352,6 +354,7 @@ def password_change(request, template_name='registration/password_change_form.ht
form = password_change_form(user=request.user, data=request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, request.user)
return HttpResponseRedirect(post_change_redirect)
else:
form = password_change_form(user=request.user)

View File

@ -0,0 +1,3 @@
VERSION = '0.3.3'
from .handlers import update_session_auth_hash

View File

@ -0,0 +1,31 @@
from django.conf import settings
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
from hashlib import md5
PASSWORD_HASH_KEY = getattr(settings, 'PASSWORD_SESSION_PASSWORD_HASH_KEY', 'password_session_password_hash_key')
def get_password_hash(user):
"""Returns a string of crypted password hash"""
password = user.password or ''
return md5(
md5(password.encode()).hexdigest().encode() + settings.SECRET_KEY.encode()
).hexdigest()
def update_session_auth_hash(request, user):
"""
Updates a session hash to prevent logging out `user` from a current session.
If `request.user` is defined through ``AuthenticationMiddleware``
then make sure that `user` the same as `request.user`.
"""
if not hasattr(request, 'user') or request.user == user:
request.session[PASSWORD_HASH_KEY] = get_password_hash(user)
@receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
"""Saves password hash in session"""
update_session_auth_hash(request, user)

View File

@ -0,0 +1,11 @@
from django.contrib.auth import logout
from .handlers import get_password_hash, PASSWORD_HASH_KEY
class CheckPasswordHash(object):
"""Logout user if value of hash key in session is not equal to current password hash"""
def process_view(self, request, *args, **kwargs):
if getattr(request.user, 'is_authenticated') and request.user.is_authenticated():
if request.session.get(PASSWORD_HASH_KEY) != get_password_hash(request.user):
logout(request)

View File

@ -0,0 +1 @@
# This file needs for tests

View File

@ -0,0 +1 @@
from .tests import *

View File

@ -0,0 +1,16 @@
try:
from django.conf.urls import url, patterns, include
except ImportError: # for Django 1.3 compatibility
from django.conf.urls.defaults import url, patterns, include
from django.contrib import admin
from .test_views import change_password_view
admin.autodiscover()
urlpatterns = patterns(
'',
url(r'^password/change/', change_password_view),
url(r'^admin/', include(admin.site.urls)),
)

View File

@ -0,0 +1,13 @@
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from password_session import update_session_auth_hash
@login_required(login_url='/admin/')
def change_password_view(request):
user = request.user
user.set_password(request.POST.get('password'))
user.save()
update_session_auth_hash(request, user)
return HttpResponse("Hello, %s! Your password has been changed!" % user.username)

View File

@ -0,0 +1,47 @@
from django.test import TestCase, Client
try:
from django.contrib.auth import get_user_model
except ImportError: # for Django 1.3 compatibility
from django.contrib.auth.models import User as OldUser
get_user_model = lambda: OldUser
User = get_user_model()
class PasswordSessionTest(TestCase):
def setUp(self):
self.password = 'qwe123'
self.user = User.objects.create_user(email='albert@tugushev.ru', username='albert', password=self.password)
self.user.is_superuser = True
self.user.is_staff = True
self.user.save()
def tearDown(self):
self.user.delete()
def test_invalidate_session_after_change_password(self):
# Test clients
client1 = Client()
client2 = Client()
# Auth client1 through django.test.client.login
self.assertTrue(client1.login(username=self.user.username, password=self.password))
# Auth client2 through admin view
response = client2.post('/admin/', follow=True, data={'username': self.user.username,
'password': self.password,
'this_is_the_login_form': 1,
'next': '/admin/'},)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, 'this_is_the_login_form')
# Change password for client1
response = client1.post('/password/change/', data={'password': '123qwe'})
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Hello')
# client2 should be logged out
response = client2.get('/admin/')
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'this_is_the_login_form')

View File

@ -117,6 +117,7 @@ MIDDLEWARE_CLASSES = (
'seahub.auth.middleware.AuthenticationMiddleware',
'seahub.base.middleware.BaseMiddleware',
'seahub.base.middleware.InfobarMiddleware',
'seahub.password_session.middleware.CheckPasswordHash'
)
SITE_ROOT_URLCONF = 'seahub.urls'
@ -205,6 +206,7 @@ INSTALLED_APPS = (
'seahub.share',
'seahub.help',
'seahub.thumbnail',
'seahub.password_session',
)