endoreg-db 0.8.1__py3-none-any.whl → 0.8.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of endoreg-db might be problematic. Click here for more details.
- endoreg_db/helpers/download_segmentation_model.py +31 -0
- endoreg_db/models/media/video/pipe_1.py +13 -1
- endoreg_db/serializers/anonymization.py +3 -0
- endoreg_db/services/pdf_import.py +0 -30
- endoreg_db/services/video_import.py +301 -98
- endoreg_db/urls/__init__.py +0 -2
- endoreg_db/urls/media.py +201 -4
- endoreg_db/urls/report.py +0 -30
- endoreg_db/urls/video.py +30 -88
- endoreg_db/views/anonymization/validate.py +5 -2
- endoreg_db/views/media/__init__.py +38 -2
- endoreg_db/views/media/pdf_media.py +1 -1
- endoreg_db/views/media/segments.py +71 -0
- endoreg_db/views/media/sensitive_metadata.py +314 -0
- endoreg_db/views/media/video_segments.py +596 -0
- endoreg_db/views/pdf/reimport.py +18 -8
- endoreg_db/views/video/__init__.py +0 -8
- endoreg_db/views/video/correction.py +26 -26
- endoreg_db/views/video/reimport.py +15 -12
- endoreg_db/views/video/video_stream.py +168 -50
- {endoreg_db-0.8.1.dist-info → endoreg_db-0.8.2.dist-info}/METADATA +2 -2
- {endoreg_db-0.8.1.dist-info → endoreg_db-0.8.2.dist-info}/RECORD +34 -33
- endoreg_db/urls/pdf.py +0 -0
- endoreg_db/urls/sensitive_meta.py +0 -36
- endoreg_db/views/video/media/__init__.py +0 -23
- /endoreg_db/views/video/{media/task_status.py → task_status.py} +0 -0
- /endoreg_db/views/video/{media/video_analyze.py → video_analyze.py} +0 -0
- /endoreg_db/views/video/{media/video_apply_mask.py → video_apply_mask.py} +0 -0
- /endoreg_db/views/video/{media/video_correction.py → video_correction.py} +0 -0
- /endoreg_db/views/video/{media/video_download_processed.py → video_download_processed.py} +0 -0
- /endoreg_db/views/video/{media/video_media.py → video_media.py} +0 -0
- /endoreg_db/views/video/{media/video_meta.py → video_meta.py} +0 -0
- /endoreg_db/views/video/{media/video_processing_history.py → video_processing_history.py} +0 -0
- /endoreg_db/views/video/{media/video_remove_frames.py → video_remove_frames.py} +0 -0
- /endoreg_db/views/video/{media/video_reprocess.py → video_reprocess.py} +0 -0
- {endoreg_db-0.8.1.dist-info → endoreg_db-0.8.2.dist-info}/WHEEL +0 -0
- {endoreg_db-0.8.1.dist-info → endoreg_db-0.8.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# Modern Media Framework: Sensitive Metadata Management
|
|
2
|
+
from rest_framework.decorators import api_view, permission_classes
|
|
3
|
+
from rest_framework.response import Response
|
|
4
|
+
from rest_framework import status
|
|
5
|
+
from django.db import transaction
|
|
6
|
+
from django.db.models import Q
|
|
7
|
+
from django.shortcuts import get_object_or_404
|
|
8
|
+
from endoreg_db.utils.permissions import EnvironmentAwarePermission
|
|
9
|
+
from endoreg_db.models import VideoFile, RawPdfFile, SensitiveMeta
|
|
10
|
+
from endoreg_db.serializers.meta import (
|
|
11
|
+
SensitiveMetaDetailSerializer,
|
|
12
|
+
SensitiveMetaUpdateSerializer,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# === VIDEO SENSITIVE METADATA ===
|
|
16
|
+
|
|
17
|
+
@api_view(['GET', 'PATCH'])
|
|
18
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
19
|
+
def video_sensitive_metadata(request, pk):
|
|
20
|
+
"""
|
|
21
|
+
GET /api/media/videos/<pk>/sensitive-metadata/
|
|
22
|
+
PATCH /api/media/videos/<pk>/sensitive-metadata/
|
|
23
|
+
|
|
24
|
+
Get or update sensitive metadata for a video.
|
|
25
|
+
Video-scoped: Uses video ID to locate related sensitive metadata.
|
|
26
|
+
"""
|
|
27
|
+
video = get_object_or_404(VideoFile, pk=pk)
|
|
28
|
+
|
|
29
|
+
# Get related sensitive metadata
|
|
30
|
+
if not video.sensitive_meta:
|
|
31
|
+
return Response(
|
|
32
|
+
{"error": f"No sensitive metadata found for video {pk}"},
|
|
33
|
+
status=status.HTTP_404_NOT_FOUND
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
sensitive_meta = video.sensitive_meta
|
|
37
|
+
|
|
38
|
+
if request.method == 'GET':
|
|
39
|
+
serializer = SensitiveMetaDetailSerializer(sensitive_meta)
|
|
40
|
+
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
41
|
+
|
|
42
|
+
elif request.method == 'PATCH':
|
|
43
|
+
serializer = SensitiveMetaUpdateSerializer(
|
|
44
|
+
sensitive_meta,
|
|
45
|
+
data=request.data,
|
|
46
|
+
partial=True
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if serializer.is_valid():
|
|
50
|
+
updated_instance = serializer.save()
|
|
51
|
+
response_serializer = SensitiveMetaDetailSerializer(updated_instance)
|
|
52
|
+
|
|
53
|
+
return Response({
|
|
54
|
+
"message": "Sensitive metadata updated successfully",
|
|
55
|
+
"sensitive_meta": response_serializer.data,
|
|
56
|
+
"video_id": pk
|
|
57
|
+
}, status=status.HTTP_200_OK)
|
|
58
|
+
|
|
59
|
+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@api_view(['POST'])
|
|
63
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
64
|
+
@transaction.atomic
|
|
65
|
+
def video_sensitive_metadata_verify(request, pk):
|
|
66
|
+
"""
|
|
67
|
+
POST /api/media/videos/<pk>/sensitive-metadata/verify/
|
|
68
|
+
|
|
69
|
+
Update verification state for video sensitive metadata.
|
|
70
|
+
|
|
71
|
+
Expected payload:
|
|
72
|
+
{
|
|
73
|
+
"dob_verified": true,
|
|
74
|
+
"names_verified": true
|
|
75
|
+
}
|
|
76
|
+
"""
|
|
77
|
+
video = get_object_or_404(VideoFile, pk=pk)
|
|
78
|
+
|
|
79
|
+
if not video.sensitive_meta:
|
|
80
|
+
return Response(
|
|
81
|
+
{"error": f"No sensitive metadata found for video {pk}"},
|
|
82
|
+
status=status.HTTP_404_NOT_FOUND
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
sensitive_meta = video.sensitive_meta
|
|
86
|
+
|
|
87
|
+
dob_verified = request.data.get('dob_verified')
|
|
88
|
+
names_verified = request.data.get('names_verified')
|
|
89
|
+
|
|
90
|
+
if dob_verified is None and names_verified is None:
|
|
91
|
+
return Response(
|
|
92
|
+
{"error": "At least one of dob_verified or names_verified must be provided"},
|
|
93
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
state = sensitive_meta.get_or_create_state()
|
|
97
|
+
|
|
98
|
+
if dob_verified is not None:
|
|
99
|
+
state.dob_verified = dob_verified
|
|
100
|
+
if names_verified is not None:
|
|
101
|
+
state.names_verified = names_verified
|
|
102
|
+
|
|
103
|
+
state.save()
|
|
104
|
+
|
|
105
|
+
response_serializer = SensitiveMetaDetailSerializer(sensitive_meta)
|
|
106
|
+
return Response({
|
|
107
|
+
"message": "Verification state updated successfully",
|
|
108
|
+
"sensitive_meta": response_serializer.data,
|
|
109
|
+
"video_id": pk,
|
|
110
|
+
"state_verified": state.is_verified
|
|
111
|
+
}, status=status.HTTP_200_OK)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# === PDF SENSITIVE METADATA ===
|
|
115
|
+
|
|
116
|
+
@api_view(['GET', 'PATCH'])
|
|
117
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
118
|
+
def pdf_sensitive_metadata(request, pk):
|
|
119
|
+
"""
|
|
120
|
+
GET /api/media/pdfs/<pk>/sensitive-metadata/
|
|
121
|
+
PATCH /api/media/pdfs/<pk>/sensitive-metadata/
|
|
122
|
+
|
|
123
|
+
Get or update sensitive metadata for a PDF.
|
|
124
|
+
PDF-scoped: Uses PDF ID to locate related sensitive metadata.
|
|
125
|
+
"""
|
|
126
|
+
pdf = get_object_or_404(RawPdfFile, pk=pk)
|
|
127
|
+
|
|
128
|
+
# Get related sensitive metadata
|
|
129
|
+
if not pdf.sensitive_meta:
|
|
130
|
+
return Response(
|
|
131
|
+
{"error": f"No sensitive metadata found for PDF {pk}"},
|
|
132
|
+
status=status.HTTP_404_NOT_FOUND
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
sensitive_meta = pdf.sensitive_meta
|
|
136
|
+
|
|
137
|
+
if request.method == 'GET':
|
|
138
|
+
serializer = SensitiveMetaDetailSerializer(sensitive_meta)
|
|
139
|
+
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
140
|
+
|
|
141
|
+
elif request.method == 'PATCH':
|
|
142
|
+
serializer = SensitiveMetaUpdateSerializer(
|
|
143
|
+
sensitive_meta,
|
|
144
|
+
data=request.data,
|
|
145
|
+
partial=True
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if serializer.is_valid():
|
|
149
|
+
updated_instance = serializer.save()
|
|
150
|
+
response_serializer = SensitiveMetaDetailSerializer(updated_instance)
|
|
151
|
+
|
|
152
|
+
return Response({
|
|
153
|
+
"message": "Sensitive metadata updated successfully",
|
|
154
|
+
"sensitive_meta": response_serializer.data,
|
|
155
|
+
"pdf_id": pk
|
|
156
|
+
}, status=status.HTTP_200_OK)
|
|
157
|
+
|
|
158
|
+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@api_view(['POST'])
|
|
162
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
163
|
+
@transaction.atomic
|
|
164
|
+
def pdf_sensitive_metadata_verify(request, pk):
|
|
165
|
+
"""
|
|
166
|
+
POST /api/media/pdfs/<pk>/sensitive-metadata/verify/
|
|
167
|
+
|
|
168
|
+
Update verification state for PDF sensitive metadata.
|
|
169
|
+
|
|
170
|
+
Expected payload:
|
|
171
|
+
{
|
|
172
|
+
"dob_verified": true,
|
|
173
|
+
"names_verified": true
|
|
174
|
+
}
|
|
175
|
+
"""
|
|
176
|
+
pdf = get_object_or_404(RawPdfFile, pk=pk)
|
|
177
|
+
|
|
178
|
+
if not pdf.sensitive_meta:
|
|
179
|
+
return Response(
|
|
180
|
+
{"error": f"No sensitive metadata found for PDF {pk}"},
|
|
181
|
+
status=status.HTTP_404_NOT_FOUND
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
sensitive_meta = pdf.sensitive_meta
|
|
185
|
+
|
|
186
|
+
dob_verified = request.data.get('dob_verified')
|
|
187
|
+
names_verified = request.data.get('names_verified')
|
|
188
|
+
|
|
189
|
+
if dob_verified is None and names_verified is None:
|
|
190
|
+
return Response(
|
|
191
|
+
{"error": "At least one of dob_verified or names_verified must be provided"},
|
|
192
|
+
status=status.HTTP_400_BAD_REQUEST
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
state = sensitive_meta.get_or_create_state()
|
|
196
|
+
|
|
197
|
+
if dob_verified is not None:
|
|
198
|
+
state.dob_verified = dob_verified
|
|
199
|
+
if names_verified is not None:
|
|
200
|
+
state.names_verified = names_verified
|
|
201
|
+
|
|
202
|
+
state.save()
|
|
203
|
+
|
|
204
|
+
response_serializer = SensitiveMetaDetailSerializer(sensitive_meta)
|
|
205
|
+
return Response({
|
|
206
|
+
"message": "Verification state updated successfully",
|
|
207
|
+
"sensitive_meta": response_serializer.data,
|
|
208
|
+
"pdf_id": pk,
|
|
209
|
+
"state_verified": state.is_verified
|
|
210
|
+
}, status=status.HTTP_200_OK)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# === LIST ENDPOINTS (Collection-Level) ===
|
|
214
|
+
|
|
215
|
+
@api_view(['GET'])
|
|
216
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
217
|
+
def sensitive_metadata_list(request):
|
|
218
|
+
"""
|
|
219
|
+
GET /api/media/sensitive-metadata/
|
|
220
|
+
|
|
221
|
+
List all sensitive metadata (combined PDFs and Videos).
|
|
222
|
+
Supports filtering by content_type, status, etc.
|
|
223
|
+
|
|
224
|
+
Query parameters:
|
|
225
|
+
- content_type: 'pdf' | 'video' (optional)
|
|
226
|
+
- verified: Filter by verification status
|
|
227
|
+
- ordering: Sort field
|
|
228
|
+
- search: Search in patient names
|
|
229
|
+
"""
|
|
230
|
+
from endoreg_db.serializers.meta import SensitiveMetaDetailSerializer
|
|
231
|
+
|
|
232
|
+
# Get all sensitive metadata
|
|
233
|
+
queryset = SensitiveMeta.objects.select_related('state').all()
|
|
234
|
+
|
|
235
|
+
# Filter by content type
|
|
236
|
+
content_type = request.query_params.get('content_type')
|
|
237
|
+
if content_type == 'pdf':
|
|
238
|
+
# Only PDFs - filter by existence of related PDFs
|
|
239
|
+
queryset = queryset.filter(raw_pdf_files__isnull=False).distinct()
|
|
240
|
+
elif content_type == 'video':
|
|
241
|
+
# Only Videos - filter by existence of related video
|
|
242
|
+
queryset = queryset.filter(video_file__isnull=False).distinct()
|
|
243
|
+
|
|
244
|
+
# Filter by verification status
|
|
245
|
+
verified = request.query_params.get('verified')
|
|
246
|
+
if verified is not None:
|
|
247
|
+
verified_bool = verified.lower() in ('true', '1', 'yes')
|
|
248
|
+
queryset = queryset.filter(state__is_verified=verified_bool)
|
|
249
|
+
|
|
250
|
+
# Search in patient names
|
|
251
|
+
search = request.query_params.get('search')
|
|
252
|
+
if search:
|
|
253
|
+
queryset = queryset.filter(
|
|
254
|
+
Q(patient_first_name__icontains=search) |
|
|
255
|
+
Q(patient_last_name__icontains=search)
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Ordering
|
|
259
|
+
ordering = request.query_params.get('ordering', '-id')
|
|
260
|
+
queryset = queryset.order_by(ordering)
|
|
261
|
+
|
|
262
|
+
# Pagination
|
|
263
|
+
from rest_framework.pagination import PageNumberPagination
|
|
264
|
+
paginator = PageNumberPagination()
|
|
265
|
+
paginator.page_size = 20
|
|
266
|
+
page = paginator.paginate_queryset(queryset, request)
|
|
267
|
+
|
|
268
|
+
if page is not None:
|
|
269
|
+
serializer = SensitiveMetaDetailSerializer(page, many=True)
|
|
270
|
+
return paginator.get_paginated_response(serializer.data)
|
|
271
|
+
|
|
272
|
+
serializer = SensitiveMetaDetailSerializer(queryset, many=True)
|
|
273
|
+
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@api_view(['GET'])
|
|
277
|
+
@permission_classes([EnvironmentAwarePermission])
|
|
278
|
+
def pdf_sensitive_metadata_list(request):
|
|
279
|
+
"""
|
|
280
|
+
GET /api/media/pdfs/sensitive-metadata/
|
|
281
|
+
|
|
282
|
+
List sensitive metadata for PDFs only.
|
|
283
|
+
Replaces legacy /api/pdf/sensitivemeta/list/
|
|
284
|
+
"""
|
|
285
|
+
from endoreg_db.serializers.meta import SensitiveMetaDetailSerializer
|
|
286
|
+
|
|
287
|
+
# Get all PDFs with sensitive metadata
|
|
288
|
+
queryset = SensitiveMeta.objects.select_related('state').filter(
|
|
289
|
+
raw_pdf_files__isnull=False
|
|
290
|
+
).distinct()
|
|
291
|
+
|
|
292
|
+
# Apply filters
|
|
293
|
+
search = request.query_params.get('search')
|
|
294
|
+
if search:
|
|
295
|
+
queryset = queryset.filter(
|
|
296
|
+
Q(patient_first_name__icontains=search) |
|
|
297
|
+
Q(patient_last_name__icontains=search)
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
ordering = request.query_params.get('ordering', '-id')
|
|
301
|
+
queryset = queryset.order_by(ordering)
|
|
302
|
+
|
|
303
|
+
# Pagination
|
|
304
|
+
from rest_framework.pagination import PageNumberPagination
|
|
305
|
+
paginator = PageNumberPagination()
|
|
306
|
+
paginator.page_size = 20
|
|
307
|
+
page = paginator.paginate_queryset(queryset, request)
|
|
308
|
+
|
|
309
|
+
if page is not None:
|
|
310
|
+
serializer = SensitiveMetaDetailSerializer(page, many=True)
|
|
311
|
+
return paginator.get_paginated_response(serializer.data)
|
|
312
|
+
|
|
313
|
+
serializer = SensitiveMetaDetailSerializer(queryset, many=True)
|
|
314
|
+
return Response(serializer.data, status=status.HTTP_200_OK)
|