diff --git a/bats_ai/api.py b/bats_ai/api.py deleted file mode 100644 index 9b1cc1ca..00000000 --- a/bats_ai/api.py +++ /dev/null @@ -1,50 +0,0 @@ -import logging - -from ninja import NinjaAPI -from oauth2_provider.models import AccessToken - -from bats_ai.core.views import ( - ConfigurationRouter, - ExportAnnotationRouter, - GRTSCellsRouter, - GuanoMetadataRouter, - ProcessingTaskRouter, - RecordingAnnotationRouter, - RecordingRouter, - RecordingTagRouter, - SpeciesRouter, - VettingRouter, -) -from bats_ai.core.views.nabat import NABatConfigurationRouter, NABatRecordingRouter - -logger = logging.getLogger(__name__) - - -def global_auth(request): - if request.user.is_anonymous: - token = request.headers.get('Authorization', '').replace('Bearer ', '') - if len(token) > 0: - try: - access_token = AccessToken.objects.get(token=token) - except AccessToken.DoesNotExist: - access_token = None - if access_token and access_token.user: - if not access_token.user.is_anonymous: - request.user = access_token.user - return not request.user.is_anonymous - - -api = NinjaAPI(auth=global_auth) - -api.add_router('/recording/', RecordingRouter) -api.add_router('/species/', SpeciesRouter) -api.add_router('/grts/', GRTSCellsRouter) -api.add_router('/guano/', GuanoMetadataRouter) -api.add_router('/recording-annotation/', RecordingAnnotationRouter) -api.add_router('/export-annotation/', ExportAnnotationRouter) -api.add_router('/configuration/', ConfigurationRouter) -api.add_router('/processing-task/', ProcessingTaskRouter) -api.add_router('/recording-tag/', RecordingTagRouter) -api.add_router('/nabat/recording/', NABatRecordingRouter) -api.add_router('/nabat/configuration/', NABatConfigurationRouter) -api.add_router('/vetting/', VettingRouter) diff --git a/bats_ai/core/api.py b/bats_ai/core/api.py new file mode 100644 index 00000000..c8940e48 --- /dev/null +++ b/bats_ai/core/api.py @@ -0,0 +1,21 @@ +from ninja import NinjaAPI +from resonant_utils.ninja import HttpOAuth2 + +from bats_ai.core import views +from bats_ai.core.views import nabat + +api = NinjaAPI(auth=HttpOAuth2()) + +api.add_router('/recording/', views.RecordingRouter) +api.add_router('/species/', views.SpeciesRouter) +api.add_router('/grts/', views.GRTSCellsRouter) +api.add_router('/guano/', views.GuanoMetadataRouter) +api.add_router('/recording-annotation/', views.RecordingAnnotationRouter) +api.add_router('/export-annotation/', views.ExportAnnotationRouter) +api.add_router('/configuration/', views.ConfigurationRouter) +api.add_router('/processing-task/', views.ProcessingTaskRouter) +api.add_router('/recording-tag/', views.RecordingTagRouter) +api.add_router('/vetting/', views.VettingRouter) + +api.add_router('/nabat/recording/', nabat.NABatRecordingRouter) +api.add_router('/nabat/configuration/', nabat.NABatConfigurationRouter) diff --git a/bats_ai/core/tests/conftest.py b/bats_ai/core/tests/conftest.py index 7bdf30bf..28dc235c 100644 --- a/bats_ai/core/tests/conftest.py +++ b/bats_ai/core/tests/conftest.py @@ -2,7 +2,7 @@ from ninja.testing import TestClient import pytest -from bats_ai.api import api +from bats_ai.core.api import api @pytest.fixture diff --git a/bats_ai/core/views/configuration.py b/bats_ai/core/views/configuration.py index d3034a0d..9520240b 100644 --- a/bats_ai/core/views/configuration.py +++ b/bats_ai/core/views/configuration.py @@ -42,14 +42,14 @@ def get_configuration(request): default_spectrogram_background_color=config.default_spectrogram_background_color, non_admin_upload_enabled=config.non_admin_upload_enabled, mark_annotations_completed_enabled=config.mark_annotations_completed_enabled, - is_admin=request.user.is_authenticated and request.user.is_superuser, + is_admin=request.user.is_superuser, ) # Endpoint to update the configuration (admin only) @router.patch('/') def update_configuration(request, payload: ConfigurationSchema): - if not request.user.is_authenticated or not request.user.is_superuser: + if not request.user.is_superuser: return JsonResponse({'error': 'Permission denied'}, status=403) config = Configuration.objects.first() if not config: @@ -62,17 +62,13 @@ def update_configuration(request, payload: ConfigurationSchema): @router.get('/is_admin/') def check_is_admin(request): - if request.user.is_authenticated: - return {'is_admin': request.user.is_superuser} - return {'is_admin': False} + return {'is_admin': request.user.is_superuser} @router.get('/me') def get_current_user(request): - if request.user.is_authenticated: - return { - 'email': request.user.email, - 'name': request.user.username, - 'id': request.user.id, - } - return {'email': '', 'name': ''} + return { + 'email': request.user.email, + 'name': request.user.username, + 'id': request.user.id, + } diff --git a/bats_ai/core/views/nabat/nabat_configuration.py b/bats_ai/core/views/nabat/nabat_configuration.py index 17535f1d..d06415e5 100644 --- a/bats_ai/core/views/nabat/nabat_configuration.py +++ b/bats_ai/core/views/nabat/nabat_configuration.py @@ -25,7 +25,7 @@ @router.post('/update-species') def update_species_list(request: HttpRequest): - if not request.user.is_authenticated or not request.user.is_superuser: + if not request.user.is_superuser: return JsonResponse({'error': 'Permission denied'}, status=403) existing_task = ProcessingTask.objects.filter( metadata__type=ProcessingTaskType.UPDATING_SPECIES.value, @@ -81,7 +81,7 @@ class RecordingListItemSchema(Schema): @router.get('/recordings', response=list[RecordingListItemSchema]) @paginate def list_recordings(request: HttpRequest, filters: Query[RecordingFilterSchema]): - if not request.user.is_authenticated or not request.user.is_superuser: + if not request.user.is_superuser: return JsonResponse({'error': 'Permission denied'}, status=403) recordings = NABatRecording.objects.annotate( @@ -154,7 +154,7 @@ class AnnotationSchema(Schema): def recording_annotations( request: HttpRequest, recording_id: int, filters: Query[AnnotationFilterSchema] ): - if not request.user.is_authenticated or not request.user.is_superuser: + if not request.user.is_superuser: return JsonResponse({'error': 'Permission denied'}, status=403) try: @@ -188,7 +188,7 @@ def recording_annotations( @router.get('/stats') def get_stats(request: HttpRequest): - if not request.user.is_authenticated or not request.user.is_superuser: + if not request.user.is_superuser: return JsonResponse({'error': 'Permission denied'}, status=403) total_recordings = NABatRecording.objects.count() diff --git a/bats_ai/core/views/nabat/nabat_recording.py b/bats_ai/core/views/nabat/nabat_recording.py index 61384e1d..2ce8c8d6 100644 --- a/bats_ai/core/views/nabat/nabat_recording.py +++ b/bats_ai/core/views/nabat/nabat_recording.py @@ -96,9 +96,8 @@ def get_email_if_authorized( `recording_id` is retrieved. """ # Superuser shortcut - if request.user and request.user.is_authenticated: - if request.user.is_superuser: - return request.user.email or 'superuser@nabat.org' + if request.user and request.user.is_superuser: + return request.user.email or 'superuser@nabat.org' # Decode JWT token try: payload = decode_jwt(api_token) @@ -412,7 +411,7 @@ def get_nabat_recording_annotation( fileAnnotations = NABatRecordingAnnotation.objects.filter(nabat_recording=nabat_recording_id) - if request.user.is_authenticated and request.user.is_superuser: + if request.user.is_superuser: # If the user is a superuser, return all annotations pass elif user_email: diff --git a/bats_ai/urls.py b/bats_ai/urls.py index 00183486..c1d155cd 100644 --- a/bats_ai/urls.py +++ b/bats_ai/urls.py @@ -2,7 +2,7 @@ from django.contrib import admin from django.urls import include, path -from .api import api +from bats_ai.core.api import api urlpatterns = [ path('accounts/', include('allauth.urls')), diff --git a/pyproject.toml b/pyproject.toml index 861e87a3..49c76ab3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ dependencies = [ "django-extensions", "django-oauth-toolkit", "django-resonant-settings[allauth,celery]", - "django-resonant-utils[allauth,s3_storage]", + "django-resonant-utils[allauth,ninja,s3-storage]", "django-s3-file-field[s3]", "django-storages[s3]", "django-stubs-ext", diff --git a/uv.lock b/uv.lock index 366c1cd0..bc5db7db 100644 --- a/uv.lock +++ b/uv.lock @@ -213,7 +213,7 @@ dependencies = [ { name = "django-ninja" }, { name = "django-oauth-toolkit" }, { name = "django-resonant-settings", extra = ["allauth", "celery"] }, - { name = "django-resonant-utils", extra = ["allauth", "s3-storage"] }, + { name = "django-resonant-utils", extra = ["allauth", "ninja", "s3-storage"] }, { name = "django-s3-file-field", extra = ["s3"] }, { name = "django-storages", extra = ["s3"] }, { name = "django-stubs-ext" }, @@ -301,7 +301,7 @@ requires-dist = [ { name = "django-ninja" }, { name = "django-oauth-toolkit" }, { name = "django-resonant-settings", extras = ["allauth", "celery"] }, - { name = "django-resonant-utils", extras = ["allauth", "s3-storage"] }, + { name = "django-resonant-utils", extras = ["allauth", "ninja", "s3-storage"] }, { name = "django-resonant-utils", extras = ["minio-storage"], marker = "extra == 'development'" }, { name = "django-s3-file-field", extras = ["minio"], marker = "extra == 'development'" }, { name = "django-s3-file-field", extras = ["s3"] }, @@ -1060,6 +1060,10 @@ allauth = [ minio-storage = [ { name = "django-minio-storage" }, ] +ninja = [ + { name = "django-ninja" }, + { name = "django-oauth-toolkit" }, +] s3-storage = [ { name = "django-storages", extra = ["s3"] }, ]