forked from OurHike/OurHike
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_routers_closures.py
More file actions
141 lines (107 loc) · 4.36 KB
/
Copy pathtest_routers_closures.py
File metadata and controls
141 lines (107 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
"""Tests for the `/closures` router.
See ../../features/MAP_OPTIONS.md's closures/reroutes section. Closures
mirror Report a Problem's create-vs-verify permission split (any
authenticated user can report one; only a maintainer/club_admin can modify
its real-world status). `moderation_status` is a real gap MAP_OPTIONS.md
never specifies - it has no moderation-state field at all, only the
closure's physical `status` (open/closed/reroute_available) - added here so
public queries have something to filter unverified closures out on, the same
way Report's `status`/`visibility` split already works.
"""
import uuid
from datetime import datetime, timedelta, timezone
import jwt
from app.config import settings
from app.models.closure import Closure, ModerationStatus
from app.models.profile import Profile, Role
TEST_SECRET = settings.supabase_jwt_secret
def _make_token(user_id: str) -> str:
payload = {"sub": user_id, "exp": datetime.now(timezone.utc) + timedelta(hours=1)}
return jwt.encode(payload, TEST_SECRET, algorithm="HS256")
def _auth_headers(user_id: str) -> dict[str, str]:
return {"Authorization": f"Bearer {_make_token(user_id)}"}
_VALID_PAYLOAD = {
"reason_type": "storm_damage",
"note": "Large blowdown blocking the trail after the storm.",
"start_mile_marker": 1408.6,
"end_mile_marker": 1411.0,
}
def test_create_closure_requires_authentication(client):
response = client.post("/closures", json=_VALID_PAYLOAD)
assert response.status_code == 401
def test_create_closure_always_starts_at_moderation_status_submitted(client):
user_id = str(uuid.uuid4())
# A client trying to self-verify should have no effect - moderation_status
# isn't even a field ReportCreate-equivalent accepts.
payload = dict(_VALID_PAYLOAD, moderation_status="verified")
response = client.post("/closures", json=payload, headers=_auth_headers(user_id))
assert response.status_code == 201
assert response.json()["moderation_status"] == "submitted"
def test_public_list_closures_excludes_moderation_status_submitted(client, db_session):
reporter = Profile(id=str(uuid.uuid4()), role=Role.hiker)
db_session.add(reporter)
db_session.commit()
verified = Closure(
reported_by=reporter.id,
reason_type="storm_damage",
start_mile_marker=100.0,
end_mile_marker=102.0,
moderation_status=ModerationStatus.verified,
)
submitted = Closure(
reported_by=reporter.id,
reason_type="flooding",
start_mile_marker=200.0,
end_mile_marker=201.0,
moderation_status=ModerationStatus.submitted,
)
db_session.add_all([verified, submitted])
db_session.commit()
response = client.get("/closures")
assert response.status_code == 200
ids = [c["id"] for c in response.json()]
assert verified.id in ids
assert submitted.id not in ids
def test_list_closures_requires_no_authentication(client):
response = client.get("/closures")
assert response.status_code == 200
def test_update_closure_status_rejected_for_a_plain_hiker_role_with_403(client, db_session):
reporter = Profile(id=str(uuid.uuid4()), role=Role.hiker)
db_session.add(reporter)
db_session.commit()
closure = Closure(
reported_by=reporter.id,
reason_type="storm_damage",
start_mile_marker=1.0,
end_mile_marker=2.0,
)
db_session.add(closure)
db_session.commit()
hiker_id = str(uuid.uuid4())
response = client.patch(
f"/closures/{closure.id}",
json={"status": "closed"},
headers=_auth_headers(hiker_id),
)
assert response.status_code == 403
def test_update_closure_status_allowed_for_maintainer_role(client, db_session):
reporter = Profile(id=str(uuid.uuid4()), role=Role.hiker)
maintainer_id = str(uuid.uuid4())
maintainer = Profile(id=maintainer_id, role=Role.maintainer)
db_session.add_all([reporter, maintainer])
db_session.commit()
closure = Closure(
reported_by=reporter.id,
reason_type="storm_damage",
start_mile_marker=1.0,
end_mile_marker=2.0,
)
db_session.add(closure)
db_session.commit()
response = client.patch(
f"/closures/{closure.id}",
json={"status": "closed"},
headers=_auth_headers(maintainer_id),
)
assert response.status_code == 200
assert response.json()["status"] == "closed"