Skip to content

Commit 6f47153

Browse files
committed
docs(backend): basic api example
1 parent a4b8d01 commit 6f47153

File tree

4 files changed

+307
-0
lines changed

4 files changed

+307
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
> [!CAUTION]
3+
> This script provides a simple way to interact with the MapSwipe backend endpoint.\
4+
> Future updates may introduce breaking changes.
5+
6+
7+
Copy `sample.env` as `.env` and change the required variables
8+
9+
Run the example script using uv
10+
```
11+
uv run run.py
12+
```
13+
> NOTE: To install uv https://docs.astral.sh/uv/getting-started/installation/
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
# /// script
2+
# dependencies = [
3+
# "httpx",
4+
# "python-dotenv",
5+
# ]
6+
# ///
7+
8+
# NOTE: Please read ./README.md
9+
10+
import httpx
11+
import logging
12+
from dotenv import dotenv_values
13+
14+
logger = logging.getLogger(__name__)
15+
config = dotenv_values(".env")
16+
17+
18+
# Define the GraphQL query
19+
class Query:
20+
21+
ME = """
22+
query MyQuery {
23+
me {
24+
id
25+
displayName
26+
}
27+
}
28+
"""
29+
30+
PUBLIC_PROJECTS = """
31+
query MyQuery($filters: ProjectFilter = {}) {
32+
publicProjects(filters: $filters) {
33+
totalCount
34+
results {
35+
id
36+
firebaseId
37+
name
38+
39+
exportAggregatedResults {
40+
id
41+
file {
42+
url
43+
}
44+
}
45+
exportUsers {
46+
id
47+
file {
48+
url
49+
}
50+
}
51+
exportTasks {
52+
id
53+
file {
54+
url
55+
}
56+
}
57+
exportResults {
58+
id
59+
file {
60+
url
61+
}
62+
}
63+
exportModerateToHighAgreementYesMaybeGeometries {
64+
id
65+
file {
66+
url
67+
}
68+
}
69+
exportHotTaskingManagerGeometries {
70+
id
71+
file {
72+
url
73+
}
74+
}
75+
exportHistory {
76+
id
77+
file {
78+
url
79+
}
80+
}
81+
exportGroups {
82+
id
83+
file {
84+
url
85+
}
86+
}
87+
exportAreaOfInterest {
88+
id
89+
file {
90+
url
91+
}
92+
}
93+
exportAggregatedResultsWithGeometry {
94+
id
95+
file {
96+
url
97+
}
98+
}
99+
100+
}
101+
}
102+
}
103+
"""
104+
105+
PROJECTS = """
106+
query MyQuery {
107+
projects {
108+
totalCount
109+
results {
110+
id
111+
firebaseId
112+
name
113+
114+
exportAggregatedResults {
115+
id
116+
file {
117+
url
118+
}
119+
}
120+
exportUsers {
121+
id
122+
file {
123+
url
124+
}
125+
}
126+
exportTasks {
127+
id
128+
file {
129+
url
130+
}
131+
}
132+
exportResults {
133+
id
134+
file {
135+
url
136+
}
137+
}
138+
exportModerateToHighAgreementYesMaybeGeometries {
139+
id
140+
file {
141+
url
142+
}
143+
}
144+
exportHotTaskingManagerGeometries {
145+
id
146+
file {
147+
url
148+
}
149+
}
150+
exportHistory {
151+
id
152+
file {
153+
url
154+
}
155+
}
156+
exportGroups {
157+
id
158+
file {
159+
url
160+
}
161+
}
162+
exportAreaOfInterest {
163+
id
164+
file {
165+
url
166+
}
167+
}
168+
exportAggregatedResultsWithGeometry {
169+
id
170+
file {
171+
url
172+
}
173+
}
174+
175+
}
176+
}
177+
}
178+
"""
179+
180+
class MapswipeApi:
181+
# Set the base URL
182+
BASE_URL = config["BACKEND_URL"]
183+
CSRFTOKEN_KEY = config["CSRFTOKEN_KEY"]
184+
MANAGER_URL = config["MANAGER_URL"]
185+
186+
ENABLE_AUTHENTICATION = config.get("ENABLE_AUTHENTICATION", "false").lower() == "true"
187+
FB_AUTH_URL = config.get("FB_AUTH_URL")
188+
189+
# Your web-app login credential
190+
FB_USERNAME = config.get("FB_USERNAME")
191+
FB_PASSWORD = config.get("FB_PASSWORD")
192+
193+
def __enter__(self):
194+
self.client = httpx.Client(base_url=self.BASE_URL, timeout=10.0)
195+
196+
# For CSRF
197+
health_resp = self.client.get("/health-check/")
198+
health_resp.raise_for_status()
199+
200+
if self.ENABLE_AUTHENTICATION:
201+
self.login_with_firebaes()
202+
203+
csrf_token = self.client.cookies.get(self.CSRFTOKEN_KEY)
204+
self.headers = {
205+
"content-type": "application/json",
206+
# Required for CSRF verification
207+
"x-csrftoken": csrf_token,
208+
"origin": self.MANAGER_URL,
209+
}
210+
return self
211+
212+
def __exit__(self, exc_type, exc_value, traceback):
213+
self.client.close()
214+
return False # If True, suppresses exceptions
215+
216+
def login_with_firebaes(self):
217+
logger.info("Logging using firebase auth")
218+
resp = httpx.post(
219+
self.FB_AUTH_URL,
220+
headers={
221+
"origin": self.MANAGER_URL,
222+
},
223+
json={
224+
"returnSecureToken": True,
225+
"email": self.FB_USERNAME,
226+
"password": self.FB_PASSWORD,
227+
"clientType": "CLIENT_TYPE_WEB",
228+
},
229+
)
230+
resp.raise_for_status()
231+
232+
idToken = resp.json()["idToken"]
233+
234+
resp = self.client.post(
235+
"/firebase-auth/",
236+
json={
237+
"token": idToken,
238+
},
239+
)
240+
resp.raise_for_status()
241+
242+
def graphql_request(self, query, variables = None):
243+
graphql_resp = self.client.post(
244+
"/graphql/",
245+
headers=self.headers,
246+
json={
247+
"query": query,
248+
"variables": variables,
249+
},
250+
)
251+
252+
graphql_resp.raise_for_status()
253+
254+
return graphql_resp.json()
255+
256+
257+
with MapswipeApi() as api:
258+
print('Public endpoints')
259+
260+
print(
261+
api.graphql_request(
262+
Query.PUBLIC_PROJECTS,
263+
variables={
264+
"filters": {
265+
"status": {
266+
"exact": "FINISHED",
267+
}
268+
}
269+
},
270+
)
271+
)
272+
273+
print('Private endpoints')
274+
print(api.graphql_request(Query.ME))
275+
276+
print(api.graphql_request(Query.PROJECTS))
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
BACKEND_URL=https://backend-2.mapswipe.dev.togglecorp.com
2+
CSRFTOKEN_KEY=MAPSWIPE-ALPHA-2-CSRFTOKEN
3+
MANAGER_URL=https://manager-2.mapswipe.dev.togglecorp.com
4+
5+
ENABLE_AUTHENTICATION=false
6+
7+
# XXX: For the key, go to the managers dashboard login page, open th network tab, after login you can see the key in the network tab
8+
FB_AUTH_URL=https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
9+
10+
# Your web-app login credential
11+
FB_USERNAME=me@example.com
12+
FB_PASSWORD=my-very-good-password
13+
14+
## Production
15+
# BACKEND_URL=https://backend.mapswipe.org
16+
# CSRFTOKEN_KEY=MAPSWIPE-PROD-CSRFTOKEN
17+
# MANAGER_URL=https://managers.mapswipe.org

0 commit comments

Comments
 (0)