Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ instance
pnogo_api.egg-info
venv
__pycache__
staticfiles
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ FROM python:3.10-slim-bookworm
COPY --from=builder --chown=app:app /app /app

ENV PATH="/app/.venv/bin:$PATH"
ENV DJANGO_SETTINGS_MODULE=pnogo.settings

WORKDIR /app

EXPOSE 8000
RUN python manage.py collectstatic --noinput 2>/dev/null || true

CMD ["granian", "--interface", "wsgi", "--workers", "2", "--host", "0.0.0.0", "--port", "8080", "pnogo_api.run:app"]
EXPOSE 8080

CMD ["granian", "--interface", "wsgi", "--workers", "2", "--host", "0.0.0.0", "--port", "8080", "pnogo.wsgi:application"]
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,18 @@ services:
volumes:
- postgres_data:/var/lib/postgresql/data

minio:
image: minio/minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data

volumes:
postgres_data:
minio_data:
20 changes: 20 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env python
import os
import sys


def main():
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pnogo.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == "__main__":
main()
Empty file added pnogo/__init__.py
Empty file.
17 changes: 17 additions & 0 deletions pnogo/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.contrib import admin

from .models import Cndr, Picture


@admin.register(Picture)
class PictureAdmin(admin.ModelAdmin):
list_display = ("id", "file", "description", "cndr", "points", "sent", "daily_date")
list_filter = ("cndr", "daily_date")
search_fields = ("file", "description")
raw_id_fields = ("cndr",)


@admin.register(Cndr)
class CndrAdmin(admin.ModelAdmin):
list_display = ("id", "name")
search_fields = ("name",)
33 changes: 33 additions & 0 deletions pnogo/authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed


class TokenQueryParamAuthentication(TokenAuthentication):
"""
DRF TokenAuthentication extended to also accept:
- X-API-Key header
- ?key= query param (legacy)

Falls back to the standard Authorization: Token <key> header.
"""

def authenticate(self, request):
# Try X-API-Key header or ?key= query param first
key = request.META.get("HTTP_X_API_KEY") or request.query_params.get("key")
if key:
return self.authenticate_credentials(key)

# Fall back to standard "Authorization: Token <key>" header
return super().authenticate(request)

def authenticate_credentials(self, key):
try:
token = Token.objects.select_related("user").get(key=key)
except Token.DoesNotExist:
raise AuthenticationFailed("Invalid API key.")

if not token.user.is_active:
raise AuthenticationFailed("User inactive.")

return (token.user, token)
Loading
Loading