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
12 changes: 10 additions & 2 deletions ami/exports/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from rest_framework import status
from rest_framework.response import Response

from ami.base.permissions import ObjectPermission
from ami.base.views import ProjectMixin
from ami.exports.serializers import DataExportSerializer
from ami.jobs.models import DataExportJob, Job, SourceImageCollection
Expand All @@ -16,6 +17,7 @@ class ExportViewSet(DefaultViewSet, ProjectMixin):

queryset = DataExport.objects.all()
serializer_class = DataExportSerializer
permission_classes = [ObjectPermission]
ordering_fields = ["id", "format", "file_size", "created_at", "updated_at"]

def get_queryset(self):
Expand Down Expand Up @@ -56,13 +58,19 @@ def create(self, request, *args, **kwargs):
status=status.HTTP_400_BAD_REQUEST,
)

# Create DataExport object
data_export = DataExport.objects.create(
# Create unsaved DataExport instance
data_export = DataExport(
user=request.user,
format=format_type,
filters=filters,
project=project,
)

# Check permissions on the unsaved instance
self.check_object_permissions(request, data_export)

# Save the instance after permission check passes
data_export.save()
data_export.update_record_count()

job_name = f"Export occurrences{f' for collection {collection.pk}' if collection else ''}"
Expand Down
61 changes: 61 additions & 0 deletions ami/main/migrations/0079_alter_project_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Generated by Django 4.2.10 on 2025-12-18 12:16

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("main", "0078_classification_applied_to"),
]

operations = [
migrations.AlterModelOptions(
name="project",
options={
"ordering": ["-priority", "created_at"],
"permissions": [
("create_identification", "Can create identifications"),
("update_identification", "Can update identifications"),
("delete_identification", "Can delete identifications"),
("create_job", "Can create a job"),
("update_job", "Can update a job"),
("run_ml_job", "Can run/retry/cancel ML jobs"),
("run_populate_captures_collection_job", "Can run/retry/cancel Populate Collection jobs"),
("run_data_storage_sync_job", "Can run/retry/cancel Data Storage Sync jobs"),
("run_data_export_job", "Can run/retry/cancel Data Export jobs"),
("run_single_image_ml_job", "Can process a single capture"),
("run_post_processing_job", "Can run/retry/cancel Post-Processing jobs"),
("delete_job", "Can delete a job"),
("create_deployment", "Can create a deployment"),
("delete_deployment", "Can delete a deployment"),
("update_deployment", "Can update a deployment"),
("sync_deployment", "Can sync images to a deployment"),
("create_sourceimagecollection", "Can create a collection"),
("update_sourceimagecollection", "Can update a collection"),
("delete_sourceimagecollection", "Can delete a collection"),
("populate_sourceimagecollection", "Can populate a collection"),
("create_sourceimage", "Can create a source image"),
("update_sourceimage", "Can update a source image"),
("delete_sourceimage", "Can delete a source image"),
("star_sourceimage", "Can star a source image"),
("create_sourceimageupload", "Can create a source image upload"),
("update_sourceimageupload", "Can update a source image upload"),
("delete_sourceimageupload", "Can delete a source image upload"),
("create_s3storagesource", "Can create storage"),
("delete_s3storagesource", "Can delete storage"),
("update_s3storagesource", "Can update storage"),
("test_s3storagesource", "Can test storage connection"),
("create_site", "Can create a site"),
("delete_site", "Can delete a site"),
("update_site", "Can update a site"),
("create_device", "Can create a device"),
("delete_device", "Can delete a device"),
("update_device", "Can update a device"),
("create_dataexport", "Can create a data export"),
("update_dataexport", "Can update a data export"),
("delete_dataexport", "Can delete a data export"),
("view_private_data", "Can view private data"),
],
},
),
]
11 changes: 9 additions & 2 deletions ami/main/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,13 @@ class Permissions:
DELETE_DEVICE = "delete_device"
UPDATE_DEVICE = "update_device"

# Data Export permissions
CREATE_DATA_EXPORT = "create_dataexport"
UPDATE_DATA_EXPORT = "update_dataexport"
DELETE_DATA_EXPORT = "delete_dataexport"

# Other permissions
VIEW_PRIVATE_DATA = "view_private_data"
TRIGGER_EXPORT = "trigger_export"
DELETE_OCCURRENCES = "delete_occurrences"
IMPORT_DATA = "import_data"
MANAGE_MEMBERS = "manage_members"
Expand Down Expand Up @@ -460,9 +464,12 @@ class Meta:
("create_device", "Can create a device"),
("delete_device", "Can delete a device"),
("update_device", "Can update a device"),
# Data Export permissions
("create_dataexport", "Can create a data export"),
("update_dataexport", "Can update a data export"),
("delete_dataexport", "Can delete a data export"),
# Other permissions
("view_private_data", "Can view private data"),
("trigger_exports", "Can trigger data exports"),
]


Expand Down
6 changes: 5 additions & 1 deletion ami/users/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ class BasicMember(Role):


class Researcher(Role):
permissions = BasicMember.permissions | {Project.Permissions.TRIGGER_EXPORT}
permissions = BasicMember.permissions | {
Project.Permissions.CREATE_DATA_EXPORT,
Project.Permissions.UPDATE_DATA_EXPORT,
Project.Permissions.DELETE_DATA_EXPORT,
}


class Identifier(Role):
Expand Down