Skip to content

Rewrite using Django#4

Draft
marc0777 wants to merge 5 commits into
mainfrom
rewrite/django
Draft

Rewrite using Django#4
marc0777 wants to merge 5 commits into
mainfrom
rewrite/django

Conversation

@marc0777
Copy link
Copy Markdown
Member

No description provided.

marc0777 and others added 5 commits March 19, 2026 00:16
Remove the entire pnogo_api/ package (Flask app, raw SQL DB layer,
S3 helpers, auth decorator, and static assets) in preparation for
the Django rewrite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch to Django 5.1, DRF, django-cors-headers, django-storages,
whitenoise, and markupsafe. Drop Flask, flask-cors, itsdangerous,
and werkzeug. Pin version to 2.0.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New Django project with:
- Cndr and Picture models (same db_table names for compat)
- DRF serializers and views for all CRUD + image serving endpoints
- Token-based auth supporting X-API-Key header, Authorization header,
  and legacy ?key= query param via service-account Users
- Image processing service layer (resize, stretch, bitmap)
- MinIO/S3 storage service
- Django Admin for Pictures and Cndrs
- Data migration to transfer old Flask auth table keys to Django
  User + Token records

New API at /api/pictures/, /api/cndr/, /api/version/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Map all old Flask-style routes (/getall, /info, /kill, /get, etc.)
to new Django views with transparent parameter adaptation. Legacy
endpoints preserve old response shapes (e.g. 'name' field instead
of 'cndr', plain text responses for mutations).

Self-contained in legacy.py + legacy_urls.py for easy removal
once clients are updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Dockerfile CMD now runs pnogo.wsgi:application via granian
- Add collectstatic step to Docker build
- Add MinIO service to docker-compose for local dev
- Add staticfiles/ to .gitignore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread pnogo/legacy.py
updated = Picture.objects.filter(pk=pk).update(description=desc)
if not updated:
return Response(status=404)
return HttpResponse(f"done! set desc of {pk} to: {desc}")

Check warning

Code scanning / CodeQL

Reflected server-side cross-site scripting Medium

Cross-site scripting vulnerability due to a
user-provided value
.

Copilot Autofix

AI about 2 months ago

In general, to fix reflected server-side XSS you must not inject raw user input into HTML responses. Instead, escape or otherwise sanitize the user-controlled data before including it in any string that may be interpreted as HTML by the browser.

For this specific case in pnogo/legacy.py, the problematic part is interpolating desc directly into the HttpResponse. The safest minimal change is to HTML-escape desc before interpolation. The file already imports escape from markupsafe, a standard escaping utility compatible with many Python web contexts, so we can reuse that. We will update the return line in LegacyDescView.get to use escape(desc) instead of desc. This preserves functionality (the client still sees the description text echoed back) while preventing any injected HTML/JavaScript from being interpreted by the browser.

Concretely:

  • In LegacyDescView.get, change the final line from:
    • return HttpResponse(f"done! set desc of {pk} to: {desc}")
  • To:
    • return HttpResponse(f"done! set desc of {pk} to: {escape(desc)}")

No new imports are required, since escape is already imported at the top of the file.


Suggested changeset 1
pnogo/legacy.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pnogo/legacy.py b/pnogo/legacy.py
--- a/pnogo/legacy.py
+++ b/pnogo/legacy.py
@@ -101,7 +101,7 @@
         updated = Picture.objects.filter(pk=pk).update(description=desc)
         if not updated:
             return Response(status=404)
-        return HttpResponse(f"done! set desc of {pk} to: {desc}")
+        return HttpResponse(f"done! set desc of {pk} to: {escape(desc)}")
 
 
 # --- /kill, /killpnogo ---
EOF
@@ -101,7 +101,7 @@
updated = Picture.objects.filter(pk=pk).update(description=desc)
if not updated:
return Response(status=404)
return HttpResponse(f"done! set desc of {pk} to: {desc}")
return HttpResponse(f"done! set desc of {pk} to: {escape(desc)}")


# --- /kill, /killpnogo ---
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants