Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
856882d
Migrate to schemathesis and add rest fuzz tests
ahmedxgouda Dec 31, 2025
95fa30b
Apply cspell
ahmedxgouda Dec 31, 2025
ab17c1a
Update Fuzz Dockerfile context
ahmedxgouda Dec 31, 2025
ee2db6a
Update rest auth for fuzz
ahmedxgouda Jan 1, 2026
53680ff
Optimize Project Health Stats query and split rest and graphql tests
ahmedxgouda Jan 1, 2026
ad9f80f
Split rest and graphql tests workflows
ahmedxgouda Jan 1, 2026
f499fe3
Update ci/cd
ahmedxgouda Jan 1, 2026
bf36420
Apply rabbit suggestions
ahmedxgouda Jan 1, 2026
9a2469d
Update ci/cd
ahmedxgouda Jan 1, 2026
62cf309
Apply rabbit's suggestions
ahmedxgouda Jan 1, 2026
90229b3
Increase number of examples
ahmedxgouda Jan 1, 2026
32e8cf0
Apply rabbit's suggestions
ahmedxgouda Jan 1, 2026
55f9c93
Apply pre-commit checks
ahmedxgouda Jan 1, 2026
72f1455
Merge branch 'feature/e2e-backend' into e2e/migrate-to-schemathesis
ahmedxgouda Jan 2, 2026
76317b6
Merge branch 'feature/e2e-backend' into e2e/migrate-to-schemathesis
ahmedxgouda Jan 3, 2026
15a5338
Update CI/CD
ahmedxgouda Jan 3, 2026
8e94807
Update makefile
ahmedxgouda Jan 3, 2026
e7c2a83
Update CI/CD
ahmedxgouda Jan 3, 2026
9bfc020
Update CI/CD
ahmedxgouda Jan 3, 2026
35a7953
Update ci/cd
ahmedxgouda Jan 3, 2026
b5dff77
Update ci/cd
ahmedxgouda Jan 3, 2026
09c6df6
Update CI/CD
ahmedxgouda Jan 3, 2026
7f8dce6
Update settings.base.py and ci/cd
ahmedxgouda Jan 3, 2026
45745d2
Update configuration and ci/cd
ahmedxgouda Jan 3, 2026
4cdc0ec
Update alphabitical order in env files
ahmedxgouda Jan 3, 2026
2cb8575
Fix negative indexing
ahmedxgouda Jan 3, 2026
d8f48e4
Add EscapeNullCharactersMiddleware
ahmedxgouda Jan 5, 2026
b2889f5
Update middleware, schemathesis config and add HTTP BadRequest status…
ahmedxgouda Jan 5, 2026
b04a1bb
Update rest api schema
ahmedxgouda Jan 5, 2026
7f8472f
Update tests
ahmedxgouda Jan 6, 2026
7a58f68
Merge branch 'feature/e2e-backend' into e2e/migrate-to-schemathesis
ahmedxgouda Jan 6, 2026
888d69c
Optimize recentIssues
ahmedxgouda Jan 6, 2026
049a62e
Add optimiazations and fixes
ahmedxgouda Jan 6, 2026
37d6ef9
Update tests, ci/cd and apply rabbit suggestions
ahmedxgouda Jan 6, 2026
b926648
Optimize N+1 queries
ahmedxgouda Jan 6, 2026
65ab732
Update tests
ahmedxgouda Jan 6, 2026
04212fc
Update rest schema and add a name for Fuzz Tests job in CI/CD
ahmedxgouda Jan 6, 2026
2f3e878
Fix negative indexing
ahmedxgouda Jan 6, 2026
0e86350
Update project health metrics filters and pagination
ahmedxgouda Jan 6, 2026
b1dd271
Update mentorship app, ci/cd, and entrypoint
ahmedxgouda Jan 6, 2026
7e6a053
Add trigram index to project
ahmedxgouda Jan 7, 2026
8cbcdf2
Update nest.dump
ahmedxgouda Jan 7, 2026
b5a1cae
Update entrypoint
ahmedxgouda Jan 7, 2026
30a2d91
Apply checks
ahmedxgouda Jan 7, 2026
dec17df
Add
ahmedxgouda Jan 7, 2026
24dbe5b
Add optimizations
ahmedxgouda Jan 7, 2026
d497542
Update tests
ahmedxgouda Jan 7, 2026
0019c04
Update CI/CD
ahmedxgouda Jan 7, 2026
5e107aa
Add fixes
ahmedxgouda Jan 7, 2026
b09badb
Apply rabbit's suggestion
ahmedxgouda Jan 8, 2026
d2b477b
Refactor docker files
ahmedxgouda Jan 8, 2026
8788ef1
Apply cspell
ahmedxgouda Jan 8, 2026
a8af00d
Refactor limits
ahmedxgouda Jan 8, 2026
0908be1
Update milestone enum and rest api endpoints
ahmedxgouda Jan 8, 2026
ad8b748
Apply middleware suggestions
ahmedxgouda Jan 8, 2026
9df950a
Migrate to strawberry_django.field
ahmedxgouda Jan 8, 2026
42114d3
Update REDIS_AUTH_ENABLED default value
ahmedxgouda Jan 8, 2026
446e362
Update queries to use strawberry_django.field
ahmedxgouda Jan 8, 2026
1182cc3
Apply rabbit suggestions
ahmedxgouda Jan 8, 2026
1fc8d64
Update tests and appply rabbit suggestion
ahmedxgouda Jan 8, 2026
76e0360
Fix pagination.limit
ahmedxgouda Jan 8, 2026
607fc50
Add optimizations and fixes
ahmedxgouda Jan 9, 2026
5d516a8
Update code
ahmedxgouda Jan 9, 2026
bc1c8ef
Add optimizations
ahmedxgouda Jan 10, 2026
076d6c9
Add optimizations
ahmedxgouda Jan 10, 2026
40a68cb
Add optimizations
ahmedxgouda Jan 10, 2026
34c5e41
Add fixes
ahmedxgouda Jan 11, 2026
8b3c80b
Add milestone index migration
ahmedxgouda Jan 11, 2026
8e7aa32
Update nest.dump
ahmedxgouda Jan 11, 2026
7ebf238
Add optimizations and fixes
ahmedxgouda Jan 12, 2026
1a2080e
Update snapshot query
ahmedxgouda Jan 12, 2026
b240fc9
Update backend tests
ahmedxgouda Jan 12, 2026
92e5a48
Update project model
ahmedxgouda Jan 12, 2026
e8304e1
Apply rabbit suggestion
ahmedxgouda Jan 12, 2026
349b72d
Merge branch 'feature/e2e-backend' into e2e/migrate-to-schemathesis
ahmedxgouda Jan 13, 2026
1b0d920
Apply rabbit suggestions
ahmedxgouda Jan 14, 2026
2b1551f
Apply rabbit suggestion and update tests
ahmedxgouda Jan 14, 2026
5d9bf41
Update code
arkid15r Jan 16, 2026
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
123 changes: 19 additions & 104 deletions .github/workflows/run-ci-cd.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Run CI/CD
name: Run CI/CD

on:
merge_group:
Expand Down Expand Up @@ -263,13 +263,11 @@ jobs:
- 5432:5432
cache:
image: redis:8.0.5-alpine3.21
env:
REDIS_PASSWORD: nest-cache-e2e-password
options: >-
--health-cmd="redis-cli -a $$REDIS_PASSWORD ping"
--health-cmd="redis-cli ping"
--health-interval=5s
--health-timeout=5s
--health-retries=5
--health-timeout=5s
ports:
- 6379:6379
steps:
Expand All @@ -291,6 +289,8 @@ jobs:
--env-file backend/.env.e2e.example \
--network host \
-e DJANGO_DB_HOST=localhost \
-e DJANGO_REDIS_AUTH_ENABLED=False \
-e DJANGO_REDIS_HOST=localhost \
-p 9000:9000 \
owasp/nest:test-backend-latest \
sh -c '
Expand Down Expand Up @@ -381,109 +381,24 @@ jobs:
echo "release_version=$(date '+%y.%-m.%-d')-${GITHUB_SHA::7}" >> $GITHUB_OUTPUT
fi

run-fuzz-tests:
name: Run fuzz tests
run-graphql-fuzz-tests:
name: Run GraphQL fuzz tests
needs:
- scan-code
- scan-ci-dependencies
runs-on: ubuntu-latest
timeout-minutes: 15
services:
db:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: nest_db_fuzz
POSTGRES_PASSWORD: nest_user_fuzz_password
POSTGRES_USER: nest_user_fuzz
options: >-
--health-cmd="pg_isready -U nest_user_fuzz -d nest_db_fuzz -h localhost -p 5432"
--health-interval=5s
--health-timeout=5s
--health-retries=5
ports:
- 5432:5432
cache:
image: redis:8.0.5-alpine3.21
env:
REDIS_PASSWORD: nest-fuzz-cache-password
options: >-
--health-cmd="redis-cli -a $$REDIS_PASSWORD ping"
--health-interval=5s
--health-timeout=5s
--health-retries=5
ports:
- 6379:6379
steps:
- name: Check out repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8

- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f

- name: Setup Backend environment
uses: ./.github/workflows/setup-backend-environment
with:
db_username: nest_user_fuzz
db_name: nest_db_fuzz

- name: Run backend with fuzz environment variables
run: |
docker run -d --rm --name fuzz-nest-backend \
--env-file backend/.env.fuzz.example \
--network host \
-e DJANGO_DB_HOST=localhost \
-p 9500:9500 \
owasp/nest:test-backend-latest \
sh -c '
python manage.py migrate &&
gunicorn wsgi:application --bind 0.0.0.0:9500
'

- name: Waiting for the backend to be ready
run: |
timeout 5m bash -c '
until wget --spider http://localhost:9500/a; do
echo "Waiting for backend..."
sleep 5
done
'
echo "Backend is up!"

- name: Load Postgres data
env:
PGPASSWORD: nest_user_fuzz_password
run: |
pg_restore -h localhost -U nest_user_fuzz -d nest_db_fuzz < backend/data/nest.dump
uses: ./.github/workflows/run-fuzz-tests.yaml
with:
test-file: graphql_test.py

- name: Build Fuzz-testing image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
cache-from: |
type=gha
type=registry,ref=owasp/nest:test-fuzz-backend-cache
cache-to: |
type=gha,compression=zstd
context: docker/backend
file: docker/backend/Dockerfile.fuzz
load: true
platforms: linux/amd64
tags: owasp/nest:test-fuzz-backend-latest

- name: Run backend fuzz tests
run: |
mkdir -p ${{ github.workspace }}/fuzzing_results &&
chmod -R 777 ${{ github.workspace }}/fuzzing_results &&
docker run -e BASE_URL=http://localhost:9500 --network host \
-v ${{ github.workspace }}/fuzzing_results:/home/owasp/fuzzing_results \
owasp/nest:test-fuzz-backend-latest

- name: Upload fuzzing results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
if: always()
with:
name: fuzzing-results
path: fuzzing_results/
retention-days: 30
run-rest-fuzz-tests:
name: Run REST fuzz tests
needs:
- scan-code
- scan-ci-dependencies
uses: ./.github/workflows/run-fuzz-tests.yaml
with:
test-file: rest_test.py
rest-url: http://localhost:9500/api/v0

build-staging-images:
name: Build Staging Images
Expand Down
118 changes: 118 additions & 0 deletions .github/workflows/run-fuzz-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: Run fuzz tests

on:
workflow_call:
inputs:
test-file:
description: 'The test file to run fuzz tests on'
required: true
type: string
rest-url:
description: 'The REST API URL to test against'
required: false
type: string
default: 'http://localhost:9500/api/v0'

jobs:
run-fuzz-tests:
name: Run Fuzz Tests
runs-on: ubuntu-latest
timeout-minutes: 20
services:
db:
image: pgvector/pgvector:pg16
env:
POSTGRES_DB: nest_db_fuzz
POSTGRES_PASSWORD: nest_user_fuzz_password
POSTGRES_USER: nest_user_fuzz
options: >-
--health-cmd="pg_isready -U nest_user_fuzz -d nest_db_fuzz -h localhost -p 5432"
--health-interval=5s
--health-retries=5
--health-timeout=5s
ports:
- 5432:5432
cache:
image: redis:8.0.5-alpine3.21
options: >-
--health-cmd="redis-cli ping"
--health-interval=5s
--health-retries=5
--health-timeout=5s
ports:
- 6379:6379
steps:
- name: Check out repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8

- name: Set up Docker buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f

- name: Setup Backend environment
uses: ./.github/workflows/setup-backend-environment
with:
db_username: nest_user_fuzz
db_name: nest_db_fuzz

- name: Run backend with fuzz environment variables
run: |
docker run -d --rm --name fuzz-nest-backend \
--env-file backend/.env.fuzz.example \
--network host \
-e DJANGO_DB_HOST=localhost \
-e DJANGO_REDIS_AUTH_ENABLED=False \
-e DJANGO_REDIS_HOST=localhost \
-p 9500:9500 \
owasp/nest:test-backend-latest \
sh -c '
python manage.py migrate &&
gunicorn wsgi:application --bind 0.0.0.0:9500
'

- name: Waiting for the backend to be ready
run: |
timeout 5m bash -c '
until wget --spider http://localhost:9500/a; do
echo "Waiting for backend..."
sleep 5
done
'
echo "Backend is up!"

- name: Load Postgres data
env:
PGPASSWORD: nest_user_fuzz_password
run: |
set -euo pipefail
if ! pg_restore -h localhost -U nest_user_fuzz -d nest_db_fuzz < backend/data/nest.dump; then
echo "Data loading failed"
exit 1
fi
echo "Data loading completed."

- name: Build Fuzz-testing image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
cache-from: |
type=gha
type=registry,ref=owasp/nest:test-fuzz-backend-cache
cache-to: |
type=gha,compression=zstd
context: backend
file: docker/backend/Dockerfile.fuzz
load: true
platforms: linux/amd64
tags: owasp/nest:test-fuzz-backend-latest

Comment on lines 93 to 106
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find fuzz-related files and directories

echo "=== Searching for Dockerfile in fuzz directories ==="
fd -t f "Dockerfile" | grep -i fuzz

echo -e "\n=== Searching for entrypoint.sh in fuzz directories ==="
fd -t f "entrypoint.sh" | grep -i fuzz

echo -e "\n=== Searching for test_rest.py or similar fuzz test files ==="
fd -t f "test_rest.py" 

echo -e "\n=== Checking all fuzz directories ==="
fd -t d "fuzz"

echo -e "\n=== Listing contents of backend directory ==="
ls -la backend/ 2>/dev/null || echo "backend/ not found"

echo -e "\n=== Listing contents of docker directory ==="
ls -la docker/ 2>/dev/null || echo "docker/ not found"

echo -e "\n=== Repository root structure ==="
ls -la | grep -E "^d"

Repository: OWASP/Nest

Length of output: 2685


Critical: Docker build file path must be relative to context.

When context is set to a directory, the file path must be relative to that context. Currently:

  • context: docker/backend/fuzz
  • file: docker/backend/fuzz/Dockerfile

This causes Docker to look for docker/backend/fuzz/docker/backend/fuzz/Dockerfile, which doesn't exist.

Fix by making the file path relative to the context directory:

Proposed fix
       - name: Build Fuzz-testing image
         uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
         with:
           cache-from: |
             type=gha
             type=registry,ref=owasp/nest:test-fuzz-backend-cache
           cache-to: |
             type=gha,compression=zstd
           context: docker/backend/fuzz
-          file: docker/backend/fuzz/Dockerfile
+          file: Dockerfile
           load: true
           platforms: linux/amd64
           tags: owasp/nest:test-fuzz-backend-latest
🤖 Prompt for AI Agents
In @.github/workflows/run-fuzz-tests.yaml around lines 88 - 101, The GitHub
Actions step "Build Fuzz-testing image" sets context: docker/backend/fuzz but
uses an absolute file path; change the file field to be relative to the context
(e.g., file: Dockerfile or file: ./Dockerfile) so the docker/build-push-action
(uses: docker/build-push-action@2634353...) can find the Dockerfile within the
specified context; ensure platforms, tags, cache-* settings remain unchanged.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure it works after file location refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the Dockerfile location and directory structure

echo "=== Checking if Dockerfile exists at docker/backend/fuzz/Dockerfile ==="
if [ -f "docker/backend/fuzz/Dockerfile" ]; then
    echo "✅ Found: docker/backend/fuzz/Dockerfile"
    echo ""
    echo "=== First 10 lines of the Dockerfile ==="
    head -n 10 docker/backend/fuzz/Dockerfile
else
    echo "❌ Not found: docker/backend/fuzz/Dockerfile"
fi

echo ""
echo "=== Directory structure of docker/backend/fuzz ==="
ls -la docker/backend/fuzz/

echo ""
echo "=== Verifying entrypoint.sh location ==="
if [ -f "docker/backend/fuzz/entrypoint.sh" ]; then
    echo "✅ Found: docker/backend/fuzz/entrypoint.sh"
else
    echo "❌ Not found: docker/backend/fuzz/entrypoint.sh"
fi

echo ""
echo "=== Checking test files directory ==="
if [ -d "docker/backend/fuzz/tests" ]; then
    echo "✅ Found: docker/backend/fuzz/tests/"
    ls -la docker/backend/fuzz/tests/
else
    echo "❌ Not found: docker/backend/fuzz/tests/"
fi

Length of output: 1213


@arkid15r, I've verified the file structure after the refactoring and can confirm everything is in place correctly:

Verified file locations:

  • docker/backend/fuzz/Dockerfile exists
  • docker/backend/fuzz/entrypoint.sh exists
  • docker/backend/fuzz/tests/test_graphql.py exists
  • docker/backend/fuzz/tests/test_rest.py exists

The CodeRabbit fix is correct and necessary. With the current configuration:

  • context: docker/backend/fuzz
  • file: docker/backend/fuzz/Dockerfile

Docker will look for docker/backend/fuzz/docker/backend/fuzz/Dockerfile, which doesn't exist.

Apply the fix:

context: docker/backend/fuzz
file: Dockerfile  # ✅ relative to context

This matches the pattern used in your docker-compose/fuzz/compose.yaml where the build context is ../../docker/backend/fuzz with dockerfile: Dockerfile.


🧠 Learnings used
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1139
File: docker-compose/fuzz.yaml:70-83
Timestamp: 2025-12-26T06:57:30.908Z
Learning: In the fuzz testing environment (docker-compose/fuzz.yaml), the data-loader and graphql services are orchestrated in separate phases via the Makefile's test-fuzz target, not run simultaneously. The data is loaded to completion first, then the graphql fuzzer is started separately against the populated database. The docker-compose dependencies reflect runtime health checks rather than orchestration order.

- name: Run fuzz tests
env:
TEST_FILE: ${{ inputs.test-file }}
REST_URL: ${{ inputs.rest-url }}
run: |
docker run \
--network host \
-e BASE_URL=http://localhost:9500 \
-e CI=true \
-e REST_URL="$REST_URL" \
-e TEST_FILE="$TEST_FILE" \
owasp/nest:test-fuzz-backend-latest
1 change: 1 addition & 0 deletions backend/.env.e2e.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DJANGO_DB_PASSWORD=nest_user_e2e_password
DJANGO_DB_PORT=5432
DJANGO_OPEN_AI_SECRET_KEY=None
DJANGO_PUBLIC_IP_ADDRESS="127.0.0.1"
DJANGO_REDIS_AUTH_ENABLED=True
DJANGO_REDIS_HOST=cache
DJANGO_REDIS_PASSWORD=nest-cache-e2e-password
DJANGO_RELEASE_VERSION=None
Expand Down
1 change: 1 addition & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DJANGO_DB_USER=None
DJANGO_ELEVENLABS_API_KEY=None
DJANGO_OPEN_AI_SECRET_KEY=None
DJANGO_PUBLIC_IP_ADDRESS="127.0.0.1"
DJANGO_REDIS_AUTH_ENABLED=True
DJANGO_REDIS_HOST=None
DJANGO_REDIS_PASSWORD=None
DJANGO_RELEASE_VERSION=None
Expand Down
1 change: 1 addition & 0 deletions backend/.env.fuzz.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ DJANGO_DB_PASSWORD=nest_user_fuzz_password
DJANGO_DB_PORT=5432
DJANGO_OPEN_AI_SECRET_KEY=None
DJANGO_PUBLIC_IP_ADDRESS="127.0.0.1"
DJANGO_REDIS_AUTH_ENABLED=True
DJANGO_REDIS_HOST=cache
DJANGO_REDIS_PASSWORD=nest-fuzz-cache-password
DJANGO_RELEASE_VERSION=None
Expand Down
7 changes: 7 additions & 0 deletions backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ migrate:
migrations:
@CMD="python manage.py makemigrations" $(MAKE) exec-backend-command

migrations-empty:
@CMD="python manage.py makemigrations --empty $(APP_NAME)" $(MAKE) exec-backend-command

purge-data:
@CMD="python manage.py purge_data" $(MAKE) exec-backend-command

Expand Down Expand Up @@ -188,6 +191,10 @@ test-fuzz:
@docker volume rm -f nest-fuzz_fuzz-db-data >/dev/null 2>&1 || true
@COMPOSE_BAKE=true DOCKER_BUILDKIT=1 \
docker compose --project-name nest-fuzz -f docker-compose/fuzz/compose.yaml up --build --remove-orphans --abort-on-container-exit db cache backend data-loader
@echo "Running REST API fuzz tests..."
@COMPOSE_BAKE=true DOCKER_BUILDKIT=1 \
docker compose --project-name nest-fuzz -f docker-compose/fuzz/compose.yaml up --build --remove-orphans --abort-on-container-exit db backend rest
@echo "Running GraphQL fuzz tests..."
@COMPOSE_BAKE=true DOCKER_BUILDKIT=1 \
docker compose --project-name nest-fuzz -f docker-compose/fuzz/compose.yaml up --build --remove-orphans --abort-on-container-exit db cache backend graphql

Expand Down
11 changes: 11 additions & 0 deletions backend/apps/api/rest/v0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from django.conf import settings
from ninja import NinjaAPI, Swagger
from ninja.errors import ValidationError
from ninja.pagination import RouterPaginated
from ninja.throttling import AuthRateThrottle

Expand Down Expand Up @@ -103,6 +104,16 @@
api = NinjaAPI(**{**api_settings, **api_settings_customization})


@api.exception_handler(ValidationError)
def validation_exception_handler(request, exc):
"""Handle validation exceptions."""
return api.create_response(
request,
{"message": "Invalid request", "errors": exc.errors},
status=400,
)


@api.get("/", include_in_schema=False)
def api_root(request):
"""Handle API root endpoint requests."""
Expand Down
3 changes: 2 additions & 1 deletion backend/apps/api/rest/v0/chapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ninja.responses import Response

from apps.api.decorators.cache import cache_response
from apps.api.rest.v0.common import Leader, LocationFilter
from apps.api.rest.v0.common import Leader, LocationFilter, ValidationErrorSchema
from apps.owasp.models.chapter import Chapter as ChapterModel

router = RouterPaginated(tags=["Chapters"])
Expand Down Expand Up @@ -100,6 +100,7 @@ def list_chapters(
description="Retrieve chapter details.",
operation_id="get_chapter",
response={
HTTPStatus.BAD_REQUEST: ValidationErrorSchema,
HTTPStatus.NOT_FOUND: ChapterError,
HTTPStatus.OK: ChapterDetail,
},
Expand Down
2 changes: 2 additions & 0 deletions backend/apps/api/rest/v0/committee.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from ninja.responses import Response

from apps.api.decorators.cache import cache_response
from apps.api.rest.v0.common import ValidationErrorSchema
from apps.owasp.models.committee import Committee as CommitteeModel

router = RouterPaginated(tags=["Committees"])
Expand Down Expand Up @@ -70,6 +71,7 @@ def list_committees(
description="Retrieve committee details.",
operation_id="get_committee",
response={
HTTPStatus.BAD_REQUEST: ValidationErrorSchema,
HTTPStatus.NOT_FOUND: CommitteeError,
HTTPStatus.OK: CommitteeDetail,
},
Expand Down
7 changes: 7 additions & 0 deletions backend/apps/api/rest/v0/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ class Leader(Schema):
name: str


class ValidationErrorSchema(Schema):
"""Schema for validation error."""

message: str
errors: list[dict] | dict | None = None


class LocationFilter(FilterSchema):
"""Filter for Location."""

Expand Down
Loading
Loading