From be7ac2043b4276412ba57e05568d1a9c037d25ae Mon Sep 17 00:00:00 2001 From: Klaas van Schelven Date: Mon, 8 Sep 2025 14:50:23 +0200 Subject: [PATCH] Implement /api/0/ endpoint Fix #97 --- bugsink/urls.py | 4 ++-- files/views.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/bugsink/urls.py b/bugsink/urls.py index 560272b..ae5c8cf 100644 --- a/bugsink/urls.py +++ b/bugsink/urls.py @@ -11,7 +11,7 @@ from teams.views import debug_email as debug_teams_email from bugsink.app_settings import get_settings from users.views import signup, confirm_email, resend_confirmation, request_reset_password, reset_password, preferences from ingest.views import download_envelope -from files.views import chunk_upload, artifact_bundle_assemble, api_catch_all +from files.views import chunk_upload, artifact_bundle_assemble, api_root, api_catch_all from bugsink.decorators import login_exempt from .views import home, trigger_error, favicon, settings_view, silence_email_system_warning, counts, health_check_ready @@ -50,7 +50,7 @@ urlpatterns = [ path("api/0/organizations//artifactbundle/assemble/", artifact_bundle_assemble, name="artifact_bundle_assemble"), - path('api/', include('ingest.urls')), + path('api/0/', api_root, name='api_root'), path('api/', api_catch_all, name='api_catch_all'), diff --git a/files/views.py b/files/views.py index 3b2e5eb..c29b6df 100644 --- a/files/views.py +++ b/files/views.py @@ -207,6 +207,9 @@ def download_file(request, checksum): return response +# Note: the below 2 views are not strictly "files" API views, but since the idea of "API Compatibility beyond ingest" +# is basically files-only (and the views below are about API compatibility), they live here. + @csrf_exempt def api_catch_all(request, subpath): # This is a catch-all for unimplemented API endpoints. It logs the request details and raises a 404 (if @@ -249,3 +252,25 @@ def api_catch_all(request, subpath): logger.info("\n".join(lines)) raise Http404("Unimplemented API endpoint: /api/" + subpath) + + +@csrf_exempt +@requires_auth_token +def api_root(request): + # the results of this endpoint mimick what Sentry does for the GET on the /api/0/ path; we simply did a request on + # their endpoint and hardcoded the result below. + + # This endpoint has some use in that sentry-cli uses it to check for token validity in the `login` flow (see #97) + + # Bugsink currently only has Bugsink-wide tokens (superuser tokens) which best map to "org" tokens. Sentry's + # org-tokens "currently have a limited set of scopes", in particular they _only_ support 'org:ci' which maps to + # "Source Map Upload, Release Creation", which is exactly what we allow too. + + # Returning the below for valid tokens makes sentry-cli say "Valid org token", which is great. And our failure for + # "@requires_auth_token" makes it say "Invalid token" which is also great. + return JsonResponse({ + "version": "0", + "auth": { + "scopes": ["org:ci"]}, + "user": None, + })