From d16769aefa2cc27433fc2a9eb17968bb895b8844 Mon Sep 17 00:00:00 2001 From: tmeissner Date: Sun, 28 Oct 2018 23:27:13 +0100 Subject: [PATCH] Chapter 8: Password hashing with Werkzeug (8a) --- app/models.py | 13 +++++++++++++ tests/test_user_model.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/test_user_model.py diff --git a/app/models.py b/app/models.py index 5c885d6..063c42b 100644 --- a/app/models.py +++ b/app/models.py @@ -1,3 +1,4 @@ +from werkzeug.security import generate_password_hash, check_password_hash from . import db @@ -16,6 +17,18 @@ class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), unique=True, index=True) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) + password_hash = db.Column(db.String(128)) + + @property + def password(self): + raise AttributeError('Password is not a readable attribute') + + @password.setter + def password(self, password): + self.password_hash = generate_password_hash(password) + + def verify_password(self, password): + return check_password_hash(self.password_hash, password) def __repr__(self): return '' % self.username diff --git a/tests/test_user_model.py b/tests/test_user_model.py new file mode 100644 index 0000000..b705a3b --- /dev/null +++ b/tests/test_user_model.py @@ -0,0 +1,35 @@ +import unittest +from app import create_app, db +from app.models import User + + +class UserModelTestCase(unittest.TestCase): + def setUp(self): + self.app = create_app('testing') + self.app_context = self.app.app_context() + self.app_context.push() + db.create_all() + + def tearDown(self): + db.session.remove() + db.drop_all() + self.app_context.pop() + + def test_password_setter(self): + u = User(password='cat') + self.assertTrue(u.password_hash is not None) + + def test_no_password_getter(self): + u = User(password='cat') + with self.assertRaises(AttributeError): + u.password + + def test_password_verification(self): + u = User(password='cat') + self.assertTrue(u.verify_password('cat')) + self.assertFalse(u.verify_password('dog')) + + def test_password_salts_are_random(self): + u = User(password='cat') + u2 = User(password='cat') + self.assertTrue(u.password_hash != u2.password_hash)