Files
site/WESP_REL/tests/test_lab_access_control.py
2026-07-17 12:57:18 +03:00

138 lines
5.3 KiB
Python

"""Доступ к модулю Lab — per-user lab_access и server-side guards."""
from __future__ import annotations
import unittest
from app import create_app, db
from app.models import Recipe, WebUser
from app.models.base import default_uuid
from app.services.setup_state import mark_setup_complete
from tests.helpers.zootech_test_helpers import ZootechTestConfig
from werkzeug.security import generate_password_hash
class LabAccessControlTests(unittest.TestCase):
def setUp(self) -> None:
self.app = create_app(ZootechTestConfig)
self.client = self.app.test_client()
self.ctx = self.app.app_context()
self.ctx.push()
db.create_all()
mark_setup_complete(self.app)
recipe = Recipe(id=default_uuid(), name="Lab access test", heads_per_trip=10, mixing_time=5)
db.session.add(recipe)
db.session.add(
WebUser(
login="zootech-test-admin",
password_hash=generate_password_hash("zootech-test-secret"),
is_superuser=True,
)
)
db.session.add(
WebUser(
login="zootech-no-lab",
password_hash=generate_password_hash("zootech-no-lab-secret"),
is_superuser=False,
lab_access=False,
)
)
db.session.add(
WebUser(
login="zootech-with-lab",
password_hash=generate_password_hash("zootech-with-lab-secret"),
is_superuser=False,
lab_access=True,
)
)
db.session.commit()
self.recipe_id = recipe.id
def tearDown(self) -> None:
db.session.remove()
db.drop_all()
self.ctx.pop()
def _login(self, login: str, password: str) -> None:
r = self.client.post("/api/auth/login", json={"login": login, "password": password})
self.assertEqual(r.status_code, 200, r.get_data(as_text=True))
def test_auth_check_can_lab_for_superuser(self) -> None:
self._login("zootech-test-admin", "zootech-test-secret")
body = self.client.get("/api/auth/check").get_json()
self.assertTrue(body.get("can_lab"))
def test_auth_check_can_lab_disabled_for_zootech(self) -> None:
self._login("zootech-no-lab", "zootech-no-lab-secret")
body = self.client.get("/api/auth/check").get_json()
self.assertFalse(body.get("can_lab"))
def test_auth_check_can_lab_enabled_for_zootech(self) -> None:
self._login("zootech-with-lab", "zootech-with-lab-secret")
body = self.client.get("/api/auth/check").get_json()
self.assertTrue(body.get("can_lab"))
def test_lab_page_redirect_without_access(self) -> None:
self._login("zootech-no-lab", "zootech-no-lab-secret")
r = self.client.get("/lab", follow_redirects=False)
self.assertEqual(r.status_code, 302)
self.assertIn("/recipes", r.headers.get("Location", ""))
def test_lab_page_ok_with_access(self) -> None:
self._login("zootech-with-lab", "zootech-with-lab-secret")
r = self.client.get("/lab")
self.assertEqual(r.status_code, 200)
def test_lab_api_forbidden_without_access(self) -> None:
self._login("zootech-no-lab", "zootech-no-lab-secret")
r = self.client.get("/api/lab/recipes")
self.assertEqual(r.status_code, 403, r.get_data(as_text=True))
def test_lab_api_ok_with_access(self) -> None:
self._login("zootech-with-lab", "zootech-with-lab-secret")
r = self.client.get("/api/lab/recipes")
self.assertEqual(r.status_code, 200, r.get_data(as_text=True))
def test_components_nutrients_hidden_without_lab_access(self) -> None:
self._login("zootech-no-lab", "zootech-no-lab-secret")
create = self.client.post(
"/api/components",
json={
"name": "Сено",
"type": "Грубые корма",
"dry_matter": 88,
"price": 10,
"nutrients": {"Сырая зола": 50},
},
)
self.assertEqual(create.status_code, 403, create.get_data(as_text=True))
create_ok = self.client.post(
"/api/components",
json={"name": "Сено", "type": "Грубые корма", "dry_matter": 88, "price": 10},
)
self.assertEqual(create_ok.status_code, 201, create_ok.get_data(as_text=True))
comp_id = create_ok.get_json()["id"]
get_one = self.client.get(f"/api/components/{comp_id}").get_json()
self.assertEqual(get_one.get("nutrients"), {})
def test_admin_can_toggle_lab_access(self) -> None:
self._login("zootech-test-admin", "zootech-test-secret")
user = db.session.query(WebUser).filter_by(login="zootech-no-lab").one()
patch = self.client.patch(
f"/api/admin/users/{user.id}",
json={"lab_access": True},
)
self.assertEqual(patch.status_code, 200, patch.get_data(as_text=True))
db.session.refresh(user)
self.assertTrue(user.lab_access)
self.client.post("/api/auth/logout")
self._login("zootech-no-lab", "zootech-no-lab-secret")
r = self.client.get("/api/lab/recipes")
self.assertEqual(r.status_code, 200, r.get_data(as_text=True))
if __name__ == "__main__":
unittest.main()