From f7fe47742a101f4a2bbe6350868ac49b355f5803 Mon Sep 17 00:00:00 2001 From: Mats Blomdahl Date: Thu, 26 Oct 2017 12:56:13 +0200 Subject: [PATCH 1/2] Bump version, add changelog entry --- README.rst | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 36bf83b7..372e2050 100644 --- a/README.rst +++ b/README.rst @@ -183,6 +183,13 @@ DB Models Changelog ========= +v. 0.4.5 +-------- + +* Bug fixes (`#75 `_, + `#76 `_) + + v. 0.4.4 -------- diff --git a/package-lock.json b/package-lock.json index 098de9c5..3749a77c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "xl_auth", - "version": "0.4.4", + "version": "0.4.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3a44a511..a020ccda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xl_auth", - "version": "0.4.4", + "version": "0.4.5", "author": "National Library of Sweden", "license": "Apache-2.0", "description": "OAuth2 authorization for LibrisXL, replacing BibDB counterpart", From ba886ae5e72c8c4be9cca16895d545d193ba5e2f Mon Sep 17 00:00:00 2001 From: Mats Blomdahl Date: Thu, 26 Oct 2017 16:47:36 +0200 Subject: [PATCH 2/2] Fix bug #75 and add database migration --- migrations/script.py.mako | 10 +++--- ...make_user_password_friends_non_nullable.py | 34 +++++++++++++++++++ tests/models/test_user.py | 6 ++-- xl_auth/user/models.py | 12 ++++--- 4 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 migrations/versions/c9e1cd58c4a7_make_user_password_friends_non_nullable.py diff --git a/migrations/script.py.mako b/migrations/script.py.mako index 2c015630..48e3e70a 100755 --- a/migrations/script.py.mako +++ b/migrations/script.py.mako @@ -1,15 +1,17 @@ -"""${message} +"""${message}. Revision ID: ${up_revision} Revises: ${down_revision | comma,n} Create Date: ${create_date} """ -from alembic import op + +from __future__ import absolute_import, division, print_function, unicode_literals + import sqlalchemy as sa +from alembic import op ${imports if imports else ""} - -# revision identifiers, used by Alembic. +# Revision identifiers, used by Alembic. revision = ${repr(up_revision)} down_revision = ${repr(down_revision)} branch_labels = ${repr(branch_labels)} diff --git a/migrations/versions/c9e1cd58c4a7_make_user_password_friends_non_nullable.py b/migrations/versions/c9e1cd58c4a7_make_user_password_friends_non_nullable.py new file mode 100644 index 00000000..d690aaf0 --- /dev/null +++ b/migrations/versions/c9e1cd58c4a7_make_user_password_friends_non_nullable.py @@ -0,0 +1,34 @@ +"""Make user password and friends non-nullable. + +Revision ID: c9e1cd58c4a7 +Revises: bc2c31758e2a +Create Date: 2017-10-26 16:19:22.453941 + +""" + +from __future__ import absolute_import, division, print_function, unicode_literals + +import sqlalchemy as sa +from alembic import op + +# Revision identifiers, used by Alembic. +revision = 'c9e1cd58c4a7' +down_revision = 'bc2c31758e2a' +branch_labels = None +depends_on = None + + +def upgrade(): + """Make columns 'active', 'is_admin' and 'password' non-nullable.""" + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.alter_column('active', existing_type=sa.BOOLEAN(), nullable=False) + batch_op.alter_column('is_admin', existing_type=sa.BOOLEAN(), nullable=False) + batch_op.alter_column('password', existing_type=sa.BLOB(), nullable=False) + + +def downgrade(): + """Make things nullable again.""" + with op.batch_alter_table('users', schema=None) as batch_op: + batch_op.alter_column('password', existing_type=sa.BLOB(), nullable=True) + batch_op.alter_column('is_admin', existing_type=sa.BOOLEAN(), nullable=True) + batch_op.alter_column('active', existing_type=sa.BOOLEAN(), nullable=True) diff --git a/tests/models/test_user.py b/tests/models/test_user.py index f9b3677d..47204568 100644 --- a/tests/models/test_user.py +++ b/tests/models/test_user.py @@ -33,11 +33,11 @@ def test_created_at_defaults_to_datetime(): @pytest.mark.usefixtures('db') -def test_password_is_nullable(): - """Test null password.""" +def test_password_defaults_to_a_random_one(): + """Test empty password field is assigned some random password, instead of being set to tull.""" user = User(email='foo@bar.com', full_name='Mr. Foo Bar') user.save() - assert user.password is None + assert user.password is not None @pytest.mark.usefixtures('db') diff --git a/xl_auth/user/models.py b/xl_auth/user/models.py index 3971aa63..d6da7c32 100644 --- a/xl_auth/user/models.py +++ b/xl_auth/user/models.py @@ -5,6 +5,8 @@ import datetime as dt import hashlib +from binascii import hexlify +from os import urandom from flask_login import UserMixin @@ -35,12 +37,12 @@ class User(UserMixin, SurrogatePK, Model): __tablename__ = 'users' email = Column(db.String(255), unique=True, nullable=False) full_name = Column(db.String(255), unique=False, nullable=False) - password = Column(db.Binary(128), nullable=True) - active = Column(db.Boolean(), default=False) - is_admin = Column(db.Boolean(), default=False) + password = Column(db.Binary(128), nullable=False) + active = Column(db.Boolean(), default=False, nullable=False) + is_admin = Column(db.Boolean(), default=False, nullable=False) permissions = relationship('Permission', back_populates='user') roles = relationship('Role', back_populates='user') - created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow) + created_at = Column(db.DateTime, default=dt.datetime.utcnow, nullable=False) def __init__(self, email, full_name, password=None, **kwargs): """Create instance.""" @@ -48,7 +50,7 @@ def __init__(self, email, full_name, password=None, **kwargs): if password: self.set_password(password) else: - self.password = None + self.set_password(hexlify(urandom(16))) def set_password(self, password): """Set password."""