P3 auth cors and distance fixes
This commit is contained in:
@@ -91,21 +91,21 @@ def get_base_speed(age: int) -> float:
|
|||||||
# Скорость смещения потерявшегося ребёнка (не скорость ходьбы)
|
# Скорость смещения потерявшегося ребёнка (не скорость ходьбы)
|
||||||
# ПСО ЭКСТРЕМУМ: 94% найдены в пределах 3 км
|
# ПСО ЭКСТРЕМУМ: 94% найдены в пределах 3 км
|
||||||
if age <= 2:
|
if age <= 2:
|
||||||
return 0.3
|
return 1.0
|
||||||
elif age <= 5:
|
elif age <= 5:
|
||||||
return 0.7
|
|
||||||
elif age <= 8:
|
|
||||||
return 1.2
|
|
||||||
elif age <= 12:
|
|
||||||
return 1.5
|
|
||||||
elif age <= 15:
|
|
||||||
return 2.0
|
return 2.0
|
||||||
|
elif age <= 8:
|
||||||
|
return 3.0
|
||||||
|
elif age <= 12:
|
||||||
|
return 4.0
|
||||||
|
elif age <= 15:
|
||||||
|
return 5.0
|
||||||
elif age <= 17:
|
elif age <= 17:
|
||||||
return 2.5
|
return 5.5
|
||||||
elif age <= 64:
|
elif age <= 64:
|
||||||
return 2.5
|
return 5.0
|
||||||
else: # 65+
|
else: # 65+
|
||||||
return 1.5
|
return 3.0
|
||||||
|
|
||||||
|
|
||||||
def get_terrain_coefficient(terrain: str) -> float:
|
def get_terrain_coefficient(terrain: str) -> float:
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from types import SimpleNamespace
|
||||||
|
import importlib
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from fastapi.testclient import TestClient
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
if str(REPO_ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(REPO_ROOT))
|
||||||
|
|
||||||
|
|
||||||
|
def make_user(role: str):
|
||||||
|
return SimpleNamespace(
|
||||||
|
id='test-user',
|
||||||
|
username='tester',
|
||||||
|
email='tester@example.com',
|
||||||
|
full_name='Test User',
|
||||||
|
role=role,
|
||||||
|
is_active=True,
|
||||||
|
last_login=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_admin_dashboard_requires_admin_role():
|
||||||
|
from backend.main import app
|
||||||
|
from backend.routers import auth
|
||||||
|
|
||||||
|
app.dependency_overrides[auth.get_current_user] = lambda: make_user('operator')
|
||||||
|
try:
|
||||||
|
client = TestClient(app)
|
||||||
|
response = client.get('/api/v1/admin/dashboard')
|
||||||
|
assert response.status_code == 403
|
||||||
|
finally:
|
||||||
|
app.dependency_overrides.clear()
|
||||||
|
|
||||||
|
|
||||||
|
def test_admin_dashboard_allows_admin_role():
|
||||||
|
from backend.main import app
|
||||||
|
from backend.routers import auth
|
||||||
|
|
||||||
|
app.dependency_overrides[auth.get_current_user] = lambda: make_user('admin')
|
||||||
|
try:
|
||||||
|
client = TestClient(app)
|
||||||
|
response = client.get('/api/v1/admin/dashboard')
|
||||||
|
assert response.status_code == 200
|
||||||
|
payload = response.json()
|
||||||
|
assert 'total_cases' in payload
|
||||||
|
finally:
|
||||||
|
app.dependency_overrides.clear()
|
||||||
|
|
||||||
|
|
||||||
|
def test_cases_endpoint_allows_field_role():
|
||||||
|
from backend.main import app
|
||||||
|
from backend.routers import auth
|
||||||
|
|
||||||
|
app.dependency_overrides[auth.get_current_user] = lambda: make_user('field')
|
||||||
|
try:
|
||||||
|
client = TestClient(app)
|
||||||
|
response = client.get('/api/v1/cases')
|
||||||
|
assert response.status_code == 200
|
||||||
|
payload = response.json()
|
||||||
|
assert 'items' in payload
|
||||||
|
finally:
|
||||||
|
app.dependency_overrides.clear()
|
||||||
|
|
||||||
|
|
||||||
|
def test_cors_uses_allowlist_from_environment(monkeypatch):
|
||||||
|
monkeypatch.setenv('CORS_ORIGINS', 'https://ui.example.com,https://admin.example.com')
|
||||||
|
monkeypatch.setenv('CORS_ALLOW_CREDENTIALS', 'true')
|
||||||
|
|
||||||
|
import backend.main as main
|
||||||
|
importlib.reload(main)
|
||||||
|
client = TestClient(main.app)
|
||||||
|
|
||||||
|
response = client.options(
|
||||||
|
'/api/v1/cases',
|
||||||
|
headers={
|
||||||
|
'Origin': 'https://ui.example.com',
|
||||||
|
'Access-Control-Request-Method': 'GET',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code in (200, 204)
|
||||||
|
assert response.headers['access-control-allow-origin'] == 'https://ui.example.com'
|
||||||
|
assert response.headers['access-control-allow-credentials'] == 'true'
|
||||||
|
|
||||||
|
|
||||||
|
def test_cors_rejects_unlisted_origin(monkeypatch):
|
||||||
|
monkeypatch.setenv('CORS_ORIGINS', 'https://ui.example.com')
|
||||||
|
monkeypatch.setenv('CORS_ALLOW_CREDENTIALS', 'true')
|
||||||
|
|
||||||
|
import backend.main as main
|
||||||
|
importlib.reload(main)
|
||||||
|
client = TestClient(main.app)
|
||||||
|
|
||||||
|
response = client.options(
|
||||||
|
'/api/v1/cases',
|
||||||
|
headers={
|
||||||
|
'Origin': 'https://evil.example.com',
|
||||||
|
'Access-Control-Request-Method': 'GET',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code in (200, 400)
|
||||||
|
assert response.headers.get('access-control-allow-origin') is None
|
||||||
@@ -91,21 +91,21 @@ def get_base_speed(age: int) -> float:
|
|||||||
# Скорость смещения потерявшегося ребёнка (не скорость ходьбы)
|
# Скорость смещения потерявшегося ребёнка (не скорость ходьбы)
|
||||||
# ПСО ЭКСТРЕМУМ: 94% найдены в пределах 3 км
|
# ПСО ЭКСТРЕМУМ: 94% найдены в пределах 3 км
|
||||||
if age <= 2:
|
if age <= 2:
|
||||||
return 0.3
|
return 1.0
|
||||||
elif age <= 5:
|
elif age <= 5:
|
||||||
return 0.7
|
|
||||||
elif age <= 8:
|
|
||||||
return 1.2
|
|
||||||
elif age <= 12:
|
|
||||||
return 1.5
|
|
||||||
elif age <= 15:
|
|
||||||
return 2.0
|
return 2.0
|
||||||
|
elif age <= 8:
|
||||||
|
return 3.0
|
||||||
|
elif age <= 12:
|
||||||
|
return 4.0
|
||||||
|
elif age <= 15:
|
||||||
|
return 5.0
|
||||||
elif age <= 17:
|
elif age <= 17:
|
||||||
return 2.5
|
return 5.5
|
||||||
elif age <= 64:
|
elif age <= 64:
|
||||||
return 2.5
|
return 5.0
|
||||||
else: # 65+
|
else: # 65+
|
||||||
return 1.5
|
return 3.0
|
||||||
|
|
||||||
|
|
||||||
def get_terrain_coefficient(terrain: str) -> float:
|
def get_terrain_coefficient(terrain: str) -> float:
|
||||||
|
|||||||
Reference in New Issue
Block a user