Files
MyPOS/tests/test_tenancy_isolation.py
T
2026-05-06 14:19:07 -04:00

82 lines
2.8 KiB
Python

"""
tests/test_tenancy_isolation.py
Verifies that tenant data isolation rules are enforced —
one tenant's data must never be accessible from another tenant's session.
"""
import pytest
from app.extensions import db, bcrypt as _bcrypt
from app.models.platform import Tenant, Plan
from app.models.salon import User, Customer, Location
def _create_tenant_with_user(app, slug, email, customer_name):
with app.app_context():
plan = Plan.query.first()
tenant = Tenant(
slug=slug,
name=slug,
owner_email=email,
plan_id=plan.id,
status="active",
)
db.session.add(tenant)
db.session.flush()
loc = Location(
tenant_id=tenant.id, name="Main", is_primary=True, is_active=True
)
db.session.add(loc)
user = User(
tenant_id=tenant.id,
email=email,
password_hash=_bcrypt.generate_password_hash("IsolationPass1").decode("utf-8"),
role="tenant_admin",
is_active=True,
)
db.session.add(user)
db.session.flush()
customer = Customer(
tenant_id=tenant.id,
name=customer_name,
phone=f"555-{tenant.id:04d}",
)
db.session.add(customer)
db.session.commit()
return tenant.id, customer.id
class TestTenancyIsolation:
def test_customer_belongs_to_own_tenant(self, tenant_app):
"""Querying customers filtered by tenant_id returns only that tenant's data."""
t1_id, c1_id = _create_tenant_with_user(
tenant_app, "iso-tenant-1", "owner1@iso.com", "Alice"
)
t2_id, c2_id = _create_tenant_with_user(
tenant_app, "iso-tenant-2", "owner2@iso.com", "Bob"
)
with tenant_app.app_context():
t1_customers = Customer.query.filter_by(tenant_id=t1_id).all()
t2_customers = Customer.query.filter_by(tenant_id=t2_id).all()
t1_ids = {c.id for c in t1_customers}
t2_ids = {c.id for c in t2_customers}
assert c1_id in t1_ids
assert c2_id not in t1_ids
assert c2_id in t2_ids
assert c1_id not in t2_ids
def test_no_cross_tenant_customer_names(self, tenant_app):
"""Alice should not appear in tenant 2's query results."""
with tenant_app.app_context():
t1 = Tenant.query.filter_by(slug="iso-tenant-1").first()
t2 = Tenant.query.filter_by(slug="iso-tenant-2").first()
if t1 and t2:
t1_names = {c.name for c in Customer.query.filter_by(tenant_id=t1.id).all()}
t2_names = {c.name for c in Customer.query.filter_by(tenant_id=t2.id).all()}
assert "Alice" not in t2_names
assert "Bob" not in t1_names