- Add Role model and user_roles association table (many-to-many) - Add password_hash column to User model (nullable, for future bcrypt) - Keep is_admin boolean for backward compatibility - Add is_admin_effective property: true if legacy is_admin OR 'admin' role - Update auth dependency (get_current_admin_user) to use is_admin_effective - Update bootstrap login to auto-create 'admin' role and assign on login - Update Google OAuth login to use is_admin_effective for token creation - Add migrate_roles.py: idempotent migration script to backfill roles - Add unit tests for Role, User, association table, and is_admin_effective
88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
"""Tests for app.user_models — User, Role, and UserRole relationships."""
|
|
|
|
import pytest
|
|
|
|
from app.user_models import User, Role, user_roles
|
|
|
|
|
|
class TestRoleModel:
|
|
"""Verify Role model definition."""
|
|
|
|
def test_role_table_name(self):
|
|
assert Role.__tablename__ == "roles"
|
|
|
|
def test_role_has_name_column(self):
|
|
col = Role.__table__.columns["name"]
|
|
assert col.type.__visit_name__ == "VARCHAR"
|
|
|
|
def test_role_name_is_unique(self):
|
|
col = Role.__table__.columns["name"]
|
|
assert col.unique is True
|
|
|
|
def test_role_name_not_nullable(self):
|
|
col = Role.__table__.columns["name"]
|
|
assert col.nullable is False
|
|
|
|
|
|
class TestUserModel:
|
|
"""Verify User model still works with new role fields."""
|
|
|
|
def test_user_table_name(self):
|
|
assert User.__tablename__ == "users"
|
|
|
|
def test_user_has_is_admin_column(self):
|
|
col = User.__table__.columns["is_admin"]
|
|
assert col.default.arg is False
|
|
|
|
def test_user_has_password_hash_column(self):
|
|
col = User.__table__.columns["password_hash"]
|
|
assert col.nullable is True
|
|
|
|
def test_user_roles_relationship(self):
|
|
assert hasattr(User, "roles")
|
|
|
|
|
|
class TestUserRoleAssociation:
|
|
"""Verify the user_roles association table."""
|
|
|
|
def test_user_roles_table_name(self):
|
|
assert user_roles.name == "user_roles"
|
|
|
|
def test_user_roles_has_user_id(self):
|
|
assert "user_id" in user_roles.columns
|
|
|
|
def test_user_roles_has_role_id(self):
|
|
assert "role_id" in user_roles.columns
|
|
|
|
def test_user_roles_composite_primary_key(self):
|
|
pk = [col for col in user_roles.columns if col.primary_key]
|
|
assert len(pk) == 2
|
|
|
|
|
|
class TestIsAdminEffective:
|
|
"""Test the is_admin_effective property."""
|
|
|
|
def test_legacy_is_admin_true(self):
|
|
user = User(email="a@test.com", display_name="A", is_admin=True)
|
|
assert user.is_admin_effective is True
|
|
|
|
def test_legacy_is_admin_false_no_roles(self):
|
|
user = User(email="b@test.com", display_name="B", is_admin=False)
|
|
assert user.is_admin_effective is False
|
|
|
|
def test_role_based_admin(self):
|
|
user = User(email="c@test.com", display_name="C", is_admin=False)
|
|
role = Role(name="admin")
|
|
user.roles.append(role)
|
|
assert user.is_admin_effective is True
|
|
|
|
def test_non_admin_role_does_not_grant_admin(self):
|
|
user = User(email="d@test.com", display_name="D", is_admin=False)
|
|
role = Role(name="editor")
|
|
user.roles.append(role)
|
|
assert user.is_admin_effective is False
|
|
|
|
def test_legacy_is_admin_true_overrides_empty_roles(self):
|
|
user = User(email="e@test.com", display_name="E", is_admin=True)
|
|
assert user.is_admin_effective is True
|