M21: add optional organisation identity
This commit is contained in:
@@ -66,9 +66,7 @@ def test_return_registered_audit_event_exposes_before_after_and_link(ops_client)
|
||||
)
|
||||
|
||||
key = "test-audit-before-after-001"
|
||||
events = ops_client.get(
|
||||
"/api/v1/audit", params={"action": "return_registered"}
|
||||
).json()
|
||||
events = ops_client.get("/api/v1/audit", params={"action": "return_registered"}).json()
|
||||
event = next(e for e in events if e["metadata"]["idempotency_key"] == key)
|
||||
assert event["before"] == {"status": "active"}
|
||||
assert event["after"]["status"] == "returned"
|
||||
|
||||
@@ -4,6 +4,48 @@ def test_unauthenticated_dashboard_is_rejected(client):
|
||||
assert response.json()["error"]["code"] == "401"
|
||||
|
||||
|
||||
def test_oidc_status_is_disabled_without_configuration(client):
|
||||
assert client.get("/api/v1/auth/oidc/status").json() == {
|
||||
"enabled": False,
|
||||
"provider_name": None,
|
||||
}
|
||||
assert client.get("/api/v1/auth/oidc/login").status_code == 404
|
||||
|
||||
|
||||
def test_oidc_callback_auto_provisions_and_logs_in(client, monkeypatch):
|
||||
import app.api.routers.auth as auth_router
|
||||
|
||||
class FakeClient:
|
||||
async def authorize_access_token(self, _request):
|
||||
return {
|
||||
"userinfo": {
|
||||
"sub": "external-subject-1",
|
||||
"email": "oidc.user@example.test",
|
||||
"email_verified": True,
|
||||
"name": "OIDC User",
|
||||
}
|
||||
}
|
||||
|
||||
class FakeOAuth:
|
||||
def create_client(self, _name):
|
||||
return FakeClient()
|
||||
|
||||
monkeypatch.setattr(auth_router.settings, "oidc_enabled", True)
|
||||
monkeypatch.setattr(auth_router.settings, "oidc_issuer_url", "https://id.example.test")
|
||||
monkeypatch.setattr(auth_router.settings, "oidc_client_id", "client")
|
||||
monkeypatch.setattr(auth_router.settings, "oidc_client_secret", "secret")
|
||||
monkeypatch.setattr(auth_router.settings, "oidc_allowed_email_domains", "example.test")
|
||||
monkeypatch.setattr(auth_router, "oauth", FakeOAuth())
|
||||
|
||||
response = client.get("/api/v1/auth/oidc/callback", follow_redirects=False)
|
||||
assert response.status_code == 307
|
||||
assert response.headers["location"].endswith("/dashboard")
|
||||
session = client.get("/api/v1/auth/session")
|
||||
assert session.status_code == 200
|
||||
assert session.json()["display_name"] == "OIDC User"
|
||||
assert session.json()["role"] == "rental_employee"
|
||||
|
||||
|
||||
def test_demo_login_grants_access(ops_client):
|
||||
response = ops_client.get("/api/v1/dashboard")
|
||||
assert response.status_code == 200
|
||||
@@ -83,9 +125,7 @@ def test_logout_rejects_a_cookie_even_if_the_browser_retains_it(ops_client):
|
||||
ops_client.cookies.clear()
|
||||
|
||||
# A fresh login in the same second receives a distinct signed token and remains valid.
|
||||
fresh_login = ops_client.post(
|
||||
"/api/v1/demo/login", json={"role": "operations_manager"}
|
||||
)
|
||||
fresh_login = ops_client.post("/api/v1/demo/login", json={"role": "operations_manager"})
|
||||
assert fresh_login.status_code == 200
|
||||
assert ops_client.get("/api/v1/auth/session").status_code == 200
|
||||
|
||||
|
||||
@@ -65,9 +65,7 @@ def test_attention_vehicles_respects_limit(client):
|
||||
|
||||
|
||||
def test_vehicle_details_known_ref(client):
|
||||
response = client.get(
|
||||
"/api/v1/integrations/mcp/vehicles/MO-016", headers=_headers()
|
||||
)
|
||||
response = client.get("/api/v1/integrations/mcp/vehicles/MO-016", headers=_headers())
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["public_ref"] == "MO-016"
|
||||
@@ -75,9 +73,7 @@ def test_vehicle_details_known_ref(client):
|
||||
|
||||
|
||||
def test_vehicle_details_unknown_ref_is_404(client):
|
||||
response = client.get(
|
||||
"/api/v1/integrations/mcp/vehicles/MO-999", headers=_headers()
|
||||
)
|
||||
response = client.get("/api/v1/integrations/mcp/vehicles/MO-999", headers=_headers())
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
|
||||
@@ -56,9 +56,7 @@ def test_seed_demo_scenarios_present():
|
||||
assert duplicate_issue is not None
|
||||
assert duplicate_issue.rule_type == "possible_duplicate_customer"
|
||||
|
||||
failed_run = db.scalar(
|
||||
select(OutboxEvent).where(OutboxEvent.delivery_status == "failed")
|
||||
)
|
||||
failed_run = db.scalar(select(OutboxEvent).where(OutboxEvent.delivery_status == "failed"))
|
||||
assert failed_run is not None
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -36,9 +36,7 @@ def _facts(**overrides) -> VehicleStatusFacts:
|
||||
|
||||
|
||||
def test_available_with_active_rental_recommends_rented():
|
||||
result = evaluate_vehicle_status(
|
||||
_vehicle("available"), _facts(active_booking_refs=["BK-0001"])
|
||||
)
|
||||
result = evaluate_vehicle_status(_vehicle("available"), _facts(active_booking_refs=["BK-0001"]))
|
||||
assert result.recommended_status == "rented"
|
||||
assert result.recommendation_code == RECOMMENDATION_CODE_ACTIVE_RENTAL
|
||||
assert result.safe_to_apply is True
|
||||
@@ -83,9 +81,7 @@ def test_rented_with_no_active_booking_recommends_available():
|
||||
|
||||
|
||||
def test_service_threshold_reached_recommends_maintenance():
|
||||
result = evaluate_vehicle_status(
|
||||
_vehicle("available"), _facts(service_threshold_reached=True)
|
||||
)
|
||||
result = evaluate_vehicle_status(_vehicle("available"), _facts(service_threshold_reached=True))
|
||||
assert result.recommended_status == "maintenance"
|
||||
assert result.recommendation_code == RECOMMENDATION_CODE_SERVICE_THRESHOLD
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ def test_retry_failed_run_moves_to_pending_and_audits(ops_client):
|
||||
|
||||
|
||||
def test_retry_requires_operations_manager(employee_client):
|
||||
response = employee_client.post(
|
||||
"/api/v1/workflows/00000000-0000-4000-8000-000000000020/retry"
|
||||
)
|
||||
response = employee_client.post("/api/v1/workflows/00000000-0000-4000-8000-000000000020/retry")
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user