Skip to content

Commit 8b581f4

Browse files
authored
Merge pull request #98 from mapbox/validate-add-source-token
Report an error quickly if the token username doesn't match the username
2 parents 63a08db + 2f5e62a commit 8b581f4

14 files changed

+89
-36
lines changed

mapbox_tilesets/scripts/cli.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import click
66
import cligj
7+
import base64
78
from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
89

910
import mapbox_tilesets
@@ -535,6 +536,27 @@ def _upload_source(
535536
if replace:
536537
method = "put"
537538

539+
# This does the decoding by hand instead of using pyjwt because
540+
# pyjwt rejects tokens that don't pad the base64 with = signs.
541+
token_parts = mapbox_token.split(".")
542+
if len(token_parts) < 2:
543+
raise errors.TilesetsError(
544+
f"Token {mapbox_token} does not contain a payload component"
545+
)
546+
else:
547+
while len(token_parts[1]) % 4 != 0:
548+
token_parts[1] = token_parts[1] + "="
549+
body = json.loads(base64.b64decode(token_parts[1]))
550+
if "u" in body:
551+
if username != body["u"]:
552+
raise errors.TilesetsError(
553+
f"Token username {body['u']} does not match username {username}"
554+
)
555+
else:
556+
raise errors.TilesetsError(
557+
f"Token {mapbox_token} does not contain a username"
558+
)
559+
538560
with tempfile.TemporaryFile() as file:
539561
for feature in features:
540562
if not no_validation:

tests/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
@pytest.fixture(scope="function")
88
def token_environ(monkeypatch):
9-
monkeypatch.setenv("MAPBOX_ACCESS_TOKEN", "fake-token")
9+
# '{"u":"test-user"}' in base64
10+
monkeypatch.setenv("MAPBOX_ACCESS_TOKEN", "pk.eyJ1IjoidGVzdC11c2VyIn0K")
1011
monkeypatch.setenv("MapboxAccessToken", "test-token")
1112

1213

tests/test_cli_create.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def test_cli_create_success(mock_request_post, MockResponse):
5050
)
5151
assert result.exit_code == 0
5252
mock_request_post.assert_called_with(
53-
"https://api.mapbox.com/tilesets/v1/test.id?access_token=fake-token",
53+
"https://api.mapbox.com/tilesets/v1/test.id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K",
5454
json={
5555
"name": "test name",
5656
"description": "",
@@ -108,7 +108,7 @@ def test_cli_create_success_description(mock_request_post, MockResponse):
108108
assert result.exit_code == 0
109109

110110
mock_request_post.assert_called_with(
111-
"https://api.mapbox.com/tilesets/v1/test.id?access_token=fake-token",
111+
"https://api.mapbox.com/tilesets/v1/test.id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K",
112112
json={
113113
"name": "test name",
114114
"description": "test description",

tests/test_cli_delete.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_cli_delete(mock_request_delete):
2828
mock_request_delete.return_value = MockResponse("", status_code=200)
2929
result = runner.invoke(delete, ["test.id"], input="test.id")
3030
mock_request_delete.assert_called_with(
31-
"https://api.mapbox.com/tilesets/v1/test.id?access_token=fake-token"
31+
"https://api.mapbox.com/tilesets/v1/test.id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
3232
)
3333
assert result.exit_code == 0
3434
assert (
@@ -62,7 +62,7 @@ def test_cli_delete_force(mock_request_delete):
6262
mock_request_delete.return_value = MockResponse("", status_code=204)
6363
result = runner.invoke(delete, ["test.id", "--force"])
6464
mock_request_delete.assert_called_with(
65-
"https://api.mapbox.com/tilesets/v1/test.id?access_token=fake-token"
65+
"https://api.mapbox.com/tilesets/v1/test.id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
6666
)
6767
assert result.exit_code == 0
6868
assert result.output == "Tileset deleted.\n"
@@ -79,7 +79,7 @@ def test_cli_delete_fail(mock_request_delete):
7979
)
8080
result = runner.invoke(delete, ["test.id", "--force"])
8181
mock_request_delete.assert_called_with(
82-
"https://api.mapbox.com/tilesets/v1/test.id?access_token=fake-token"
82+
"https://api.mapbox.com/tilesets/v1/test.id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
8383
)
8484
assert result.exit_code == 1
8585
assert isinstance(result.exception, TilesetsError)

tests/test_cli_jobs.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_cli_job(mock_request_get, MockResponse):
1717
mock_request_get.return_value = MockResponse(message)
1818
result = runner.invoke(jobs, ["test.id"])
1919
mock_request_get.assert_called_with(
20-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=fake-token&limit=100"
20+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100"
2121
)
2222
assert result.exit_code == 0
2323
assert json.loads(result.output) == message
@@ -34,7 +34,7 @@ def test_cli_job_error(mock_request_get, MockResponse):
3434
mock_request_get.return_value = MockResponse(message, status_code=404)
3535
result = runner.invoke(jobs, ["test.id"])
3636
mock_request_get.assert_called_with(
37-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=fake-token&limit=100"
37+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100"
3838
)
3939
assert result.exit_code == 0
4040
assert json.loads(result.output) == message
@@ -51,7 +51,7 @@ def test_cli_jobs_and_stage(mock_request_get, MockResponse):
5151
mock_request_get.return_value = MockResponse(message)
5252
result = runner.invoke(jobs, ["test.id", "--stage", "success"])
5353
mock_request_get.assert_called_with(
54-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=fake-token&limit=100&stage=success"
54+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&stage=success"
5555
)
5656
assert result.exit_code == 0
5757
assert json.loads(result.output) == message
@@ -68,7 +68,7 @@ def test_cli_jobs_limit(mock_request_get, MockResponse):
6868
mock_request_get.return_value = MockResponse(message)
6969
result = runner.invoke(jobs, ["test.id", "--limit", "10"])
7070
mock_request_get.assert_called_with(
71-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=fake-token&limit=10"
71+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=10"
7272
)
7373
assert result.exit_code == 0
7474

@@ -93,7 +93,7 @@ def test_cli_jobs_stage_and_limit(mock_request_get, MockResponse):
9393
mock_request_get.return_value = MockResponse(message)
9494
result = runner.invoke(jobs, ["test.id", "--stage", "success", "--limit", "10"])
9595
mock_request_get.assert_called_with(
96-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=fake-token&limit=10&stage=success"
96+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=10&stage=success"
9797
)
9898
assert result.exit_code == 0
9999
assert json.loads(result.output) == message
@@ -110,7 +110,7 @@ def test_cli_single_job(mock_request_get, MockResponse):
110110
mock_request_get.return_value = MockResponse(message)
111111
result = runner.invoke(job, ["test.id", "job_id"])
112112
mock_request_get.assert_called_with(
113-
"https://api.mapbox.com/tilesets/v1/test.id/jobs/job_id?access_token=fake-token"
113+
"https://api.mapbox.com/tilesets/v1/test.id/jobs/job_id?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
114114
)
115115
assert result.exit_code == 0
116116
assert json.loads(result.output) == message

tests/test_cli_list.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_cli_list(mock_request_get, MockResponse):
2121
mock_request_get.return_value = MockResponse(message)
2222
result = runner.invoke(list, ["test"])
2323
mock_request_get.assert_called_with(
24-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100"
24+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100"
2525
)
2626
assert result.exit_code == 0
2727
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -40,7 +40,7 @@ def test_cli_list_verbose(mock_request_get, MockResponse):
4040
mock_request_get.return_value = MockResponse(message)
4141
result = runner.invoke(list, ["test", "--verbose"])
4242
mock_request_get.assert_called_with(
43-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100"
43+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100"
4444
)
4545
assert result.exit_code == 0
4646

@@ -59,7 +59,7 @@ def test_cli_list_bad_token(mock_request_get, MockResponse):
5959
mock_request_get.return_value = MockResponse(message, status_code=404)
6060
result = runner.invoke(list, ["test"])
6161
mock_request_get.assert_called_with(
62-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100"
62+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100"
6363
)
6464
assert result.exit_code == 1
6565
assert result.exception
@@ -78,7 +78,7 @@ def test_cli_list_type_vector(mock_request_get, MockResponse):
7878
mock_request_get.return_value = MockResponse(message)
7979
result = runner.invoke(list, ["test", "--type", "vector"])
8080
mock_request_get.assert_called_with(
81-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&type=vector"
81+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&type=vector"
8282
)
8383
assert result.exit_code == 0
8484
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -97,7 +97,7 @@ def test_cli_list_type_raster(mock_request_get, MockResponse):
9797
mock_request_get.return_value = MockResponse(message)
9898
result = runner.invoke(list, ["test", "--type", "raster"])
9999
mock_request_get.assert_called_with(
100-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&type=raster"
100+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&type=raster"
101101
)
102102
assert result.exit_code == 0
103103
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -116,7 +116,7 @@ def test_cli_list_visibility_public(mock_request_get, MockResponse):
116116
mock_request_get.return_value = MockResponse(message)
117117
result = runner.invoke(list, ["test", "--visibility", "public"])
118118
mock_request_get.assert_called_with(
119-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&visibility=public"
119+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&visibility=public"
120120
)
121121
assert result.exit_code == 0
122122
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -135,7 +135,7 @@ def test_cli_list_visibility_private(mock_request_get, MockResponse):
135135
mock_request_get.return_value = MockResponse(message)
136136
result = runner.invoke(list, ["test", "--visibility", "private"])
137137
mock_request_get.assert_called_with(
138-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&visibility=private"
138+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&visibility=private"
139139
)
140140
assert result.exit_code == 0
141141
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -154,7 +154,7 @@ def test_cli_list_sortby_created(mock_request_get, MockResponse):
154154
mock_request_get.return_value = MockResponse(message)
155155
result = runner.invoke(list, ["test", "--sortby", "created"])
156156
mock_request_get.assert_called_with(
157-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&sortby=created"
157+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&sortby=created"
158158
)
159159
assert result.exit_code == 0
160160
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -173,7 +173,7 @@ def test_cli_list_sortby_modified(mock_request_get, MockResponse):
173173
mock_request_get.return_value = MockResponse(message)
174174
result = runner.invoke(list, ["test", "--sortby", "modified"])
175175
mock_request_get.assert_called_with(
176-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=100&sortby=modified"
176+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=100&sortby=modified"
177177
)
178178
assert result.exit_code == 0
179179
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -192,7 +192,7 @@ def test_cli_list_limit_10(mock_request_get, MockResponse):
192192
mock_request_get.return_value = MockResponse(message)
193193
result = runner.invoke(list, ["test", "--limit", "10"])
194194
mock_request_get.assert_called_with(
195-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=10"
195+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=10"
196196
)
197197
assert result.exit_code == 0
198198
assert result.output == """test.tileset-1\ntest.tileset-2\n"""
@@ -233,7 +233,7 @@ def test_cli_list_options(mock_request_get, MockResponse):
233233
],
234234
)
235235
mock_request_get.assert_called_with(
236-
"https://api.mapbox.com/tilesets/v1/test?access_token=fake-token&limit=10&type=vector&visibility=private&sortby=created"
236+
"https://api.mapbox.com/tilesets/v1/test?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&limit=10&type=vector&visibility=private&sortby=created"
237237
)
238238
assert result.exit_code == 0
239239
assert result.output == """test.tileset-1\ntest.tileset-2\n"""

tests/test_cli_publish.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_cli_publish(mock_request_post):
2929
mock_request_post.return_value = MockResponse({"message": "mock message"}, 200)
3030
result = runner.invoke(publish, ["test.id"])
3131
mock_request_post.assert_called_with(
32-
"https://api.mapbox.com/tilesets/v1/test.id/publish?access_token=fake-token"
32+
"https://api.mapbox.com/tilesets/v1/test.id/publish?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
3333
)
3434
assert result.exit_code == 0
3535
assert (

tests/test_cli_sources.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,35 @@ def side_effect(fields):
4949
)
5050

5151

52+
@pytest.mark.usefixtures("token_environ")
53+
@mock.patch("mapbox_tilesets.scripts.cli.MultipartEncoder")
54+
@mock.patch("mapbox_tilesets.scripts.cli.MultipartEncoderMonitor")
55+
@mock.patch("requests.Session.post")
56+
def test_cli_add_source_wrong_username(
57+
mock_request_post,
58+
mock_multipart_encoder_monitor,
59+
mock_multipart_encoder,
60+
MockResponse,
61+
MockMultipartEncoding,
62+
):
63+
if "MAPBOX_ACCESS_TOKEN" in os.environ:
64+
del os.environ["MAPBOX_ACCESS_TOKEN"]
65+
66+
# This is the base64 encoding of '{"u":"wrong-user"}', not a real token
67+
os.environ["MapboxAccessToken"] = "pk.eyJ1Ijoid3JvbmctdXNlciJ9Cg.xxx"
68+
69+
runner = CliRunner()
70+
validated_result = runner.invoke(
71+
add_source, ["test-user-wrong", "hello-world", "tests/fixtures/valid.ldgeojson"]
72+
)
73+
assert validated_result.exit_code == 1
74+
75+
assert (
76+
str(validated_result.exception)
77+
== "Token username wrong-user does not match username test-user-wrong"
78+
)
79+
80+
5281
def test_cli_add_source_no_token():
5382
if "MAPBOX_ACCESS_TOKEN" in os.environ:
5483
del os.environ["MAPBOX_ACCESS_TOKEN"]

tests/test_cli_status.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def test_cli_status(mock_request_get, MockResponse):
1717
mock_request_get.return_value = MockResponse(message)
1818
result = runner.invoke(status, ["test.id"])
1919
mock_request_get.assert_called_with(
20-
"https://api.mapbox.com/tilesets/v1/test.id/jobs?limit=1&access_token=fake-token"
20+
"https://api.mapbox.com/tilesets/v1/test.id/jobs?limit=1&access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
2121
)
2222
assert result.exit_code == 0
2323
expected_status = {

tests/test_cli_tilejson.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_cli_tilejson(mock_request_get, MockResponse):
4949
mock_request_get.return_value = MockResponse(message)
5050
result = runner.invoke(tilejson, ["test.id"])
5151
mock_request_get.assert_called_with(
52-
"https://api.mapbox.com/v4/test.id.json?access_token=fake-token"
52+
"https://api.mapbox.com/v4/test.id.json?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
5353
)
5454
assert result.exit_code == 0
5555

@@ -63,7 +63,7 @@ def test_cli_tilejson_composite(mock_request_get, MockResponse):
6363
mock_request_get.return_value = MockResponse("")
6464
result = runner.invoke(tilejson, ["test.id,test.another"])
6565
mock_request_get.assert_called_with(
66-
"https://api.mapbox.com/v4/test.id,test.another.json?access_token=fake-token"
66+
"https://api.mapbox.com/v4/test.id,test.another.json?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
6767
)
6868
assert result.exit_code == 0
6969

@@ -77,7 +77,7 @@ def test_cli_tilejson_secure(mock_request_get, MockResponse):
7777
mock_request_get.return_value = MockResponse("")
7878
result = runner.invoke(tilejson, ["test.id", "--secure"])
7979
mock_request_get.assert_called_with(
80-
"https://api.mapbox.com/v4/test.id.json?access_token=fake-token&secure"
80+
"https://api.mapbox.com/v4/test.id.json?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K&secure"
8181
)
8282
assert result.exit_code == 0
8383

@@ -91,7 +91,7 @@ def test_cli_tilejson_error(mock_request_get, MockResponse):
9191
mock_request_get.return_value = MockResponse({"message": "uh oh"}, 422)
9292
result = runner.invoke(tilejson, ["test.id,test.another"])
9393
mock_request_get.assert_called_with(
94-
"https://api.mapbox.com/v4/test.id,test.another.json?access_token=fake-token"
94+
"https://api.mapbox.com/v4/test.id,test.another.json?access_token=pk.eyJ1IjoidGVzdC11c2VyIn0K"
9595
)
9696
assert result.exit_code == 1
9797
assert isinstance(result.exception, TilesetsError)

0 commit comments

Comments
 (0)