password management for amo Users

This commit is contained in:
Jeff Balogh 2010-01-12 17:22:26 -08:00 коммит произвёл Dave Dash
Родитель 817e5b42b2
Коммит ae8f7349de
4 изменённых файлов: 104 добавлений и 39 удалений

Просмотреть файл

@ -1,4 +1,7 @@
from datetime import datetime
import hashlib
import random
import string
from django.db import models
from django.contrib.auth.models import User
@ -7,6 +10,20 @@ import amo
from translations.fields import TranslatedField
def get_hexdigest(algorithm, salt, raw_password):
return hashlib.new(algorithm, salt + raw_password).hexdigest()
def rand_string(length):
return ''.join(random.choice(string.letters) for i in xrange(length))
def create_password(algorithm, raw_password):
salt = get_hexdigest(algorithm, rand_string(12), rand_string(12))[:64]
hsh = get_hexdigest(algorithm, salt, raw_password)
return '$'.join([algorithm, salt, hsh])
class UserProfile(amo.ModelBase):
nickname = models.CharField(max_length=255, unique=True, default='')
@ -69,3 +86,18 @@ class UserProfile(amo.ModelBase):
self.resetcode_expires = datetime.now()
super(UserProfile, self).save(force_insert, force_update)
def check_password(self, raw_password):
if '$' not in self.password:
valid = (get_hexdigest('md5', '', raw_password) == self.password)
if valid:
# Upgrade an old password.
self.set_password(raw_password)
self.save()
return valid
algo, salt, hsh = self.password.split('$')
return hsh == get_hexdigest(algo, salt, raw_password)
def set_password(self, raw_password, algorithm='sha512'):
self.password = create_password(algorithm, raw_password)

Просмотреть файл

@ -1,39 +0,0 @@
from nose.tools import eq_
from .helpers import user_link
from .models import UserProfile
def test_user_link():
u = UserProfile(firstname='John', lastname='Connor', pk=1)
eq_(user_link(u), """<a href="/users/1">John Connor</a>""")
def test_display_name_nickname():
u = UserProfile(nickname='Terminator', pk=1)
eq_(u.display_name, 'Terminator')
def test_welcome_name():
u1 = UserProfile(lastname='Connor', pk=1)
u2 = UserProfile(firstname='Sarah', nickname='sc', lastname='Connor', pk=1)
u3 = UserProfile(nickname='sc', lastname='Connor', pk=1)
u4 = UserProfile(pk=1)
eq_(u1.welcome_name, 'Connor')
eq_(u2.welcome_name, 'Sarah')
eq_(u3.welcome_name, 'sc')
eq_(u4.welcome_name, '')
def test_resetcode_expires():
"""
For some reasone resetcode is required, and we default it to
'0000-00-00 00:00' in mysql, but that doesn't fly in Django since it's an
invalid date. If Django reads this from the db, it interprets this as
resetcode_expires as None
"""
u = UserProfile(lastname='Connor', pk=2, resetcode_expires=None,
email='j.connor@sky.net')
u.save()
assert(u.resetcode_expires)

Просмотреть файл

@ -0,0 +1,9 @@
from nose.tools import eq_
from users.helpers import user_link
from users.models import UserProfile
def test_user_link():
u = UserProfile(firstname='John', lastname='Connor', pk=1)
eq_(user_link(u), """<a href="/users/1">John Connor</a>""")

Просмотреть файл

@ -0,0 +1,63 @@
import hashlib
from django import test
from nose.tools import eq_
from users.models import UserProfile, get_hexdigest
def test_display_name_nickname():
u = UserProfile(nickname='Terminator', pk=1)
eq_(u.display_name, 'Terminator')
def test_welcome_name():
u1 = UserProfile(lastname='Connor', pk=1)
u2 = UserProfile(firstname='Sarah', nickname='sc', lastname='Connor', pk=1)
u3 = UserProfile(nickname='sc', lastname='Connor', pk=1)
u4 = UserProfile(pk=1)
eq_(u1.welcome_name, 'Connor')
eq_(u2.welcome_name, 'Sarah')
eq_(u3.welcome_name, 'sc')
eq_(u4.welcome_name, '')
def test_resetcode_expires():
"""
For some reasone resetcode is required, and we default it to
'0000-00-00 00:00' in mysql, but that doesn't fly in Django since it's an
invalid date. If Django reads this from the db, it interprets this as
resetcode_expires as None
"""
u = UserProfile(lastname='Connor', pk=2, resetcode_expires=None,
email='j.connor@sky.net')
u.save()
assert u.resetcode_expires
class TestPasswords(test.TestCase):
def test_invalid_old_password(self):
u = UserProfile(password='sekrit')
assert u.check_password('sekrit') is False
def test_invalid_new_password(self):
u = UserProfile()
u.set_password('sekrit')
assert u.check_password('wrong') is False
def test_valid_old_password(self):
hsh = hashlib.md5('sekrit').hexdigest()
u = UserProfile(password=hsh)
assert u.check_password('sekrit') is True
# Make sure we updated the old password.
algo, salt, hsh = u.password.split('$')
eq_(algo, 'sha512')
eq_(hsh, get_hexdigest(algo, salt, 'sekrit'))
def test_valid_new_password(self):
u = UserProfile()
u.set_password('sekrit')
assert u.check_password('sekrit') is True