mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 14:35:17 -05:00
w
This commit is contained in:
@@ -864,12 +864,13 @@ class PhotoSubmission(StateMachineMixin, TrackedModel):
|
||||
self.save()
|
||||
|
||||
def auto_approve(self) -> None:
|
||||
"""Auto - approve submissions from moderators"""
|
||||
"""Auto-approve submissions from moderators."""
|
||||
# Get user role safely
|
||||
user_role = getattr(self.user, "role", None)
|
||||
|
||||
# If user is moderator or above, auto-approve
|
||||
# If user is moderator or above, claim then approve
|
||||
if user_role in ["MODERATOR", "ADMIN", "SUPERUSER"]:
|
||||
self.claim(user=self.user)
|
||||
self.approve(self.user)
|
||||
|
||||
def escalate(self, moderator: UserType = None, notes: str = "", user=None) -> None:
|
||||
|
||||
@@ -1718,6 +1718,148 @@ class EditSubmissionViewSet(viewsets.ModelViewSet):
|
||||
except Exception as e:
|
||||
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@action(detail=False, methods=["post"], permission_classes=[IsModeratorOrAdmin], url_path="release-expired")
|
||||
def release_expired_locks(self, request):
|
||||
"""
|
||||
Release all expired claim locks.
|
||||
|
||||
This is typically handled by a Celery task, but can be triggered manually.
|
||||
Claims are expired after 30 minutes by default.
|
||||
"""
|
||||
from datetime import timedelta
|
||||
|
||||
expiry_threshold = timezone.now() - timedelta(minutes=30)
|
||||
|
||||
expired_claims = EditSubmission.objects.filter(
|
||||
status="CLAIMED",
|
||||
claimed_at__lt=expiry_threshold
|
||||
)
|
||||
|
||||
released_count = 0
|
||||
for submission in expired_claims:
|
||||
submission.status = "PENDING"
|
||||
submission.claimed_by = None
|
||||
submission.claimed_at = None
|
||||
submission.save(update_fields=["status", "claimed_by", "claimed_at"])
|
||||
released_count += 1
|
||||
|
||||
return Response({
|
||||
"released_count": released_count,
|
||||
"message": f"Released {released_count} expired lock(s)"
|
||||
})
|
||||
|
||||
@action(detail=True, methods=["post"], permission_classes=[IsAdminOrSuperuser], url_path="admin-release")
|
||||
def admin_release(self, request, pk=None):
|
||||
"""
|
||||
Admin/superuser force release of a specific claim.
|
||||
"""
|
||||
submission = self.get_object()
|
||||
|
||||
if submission.status != "CLAIMED":
|
||||
return Response(
|
||||
{"error": "Submission is not claimed"},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
submission.status = "PENDING"
|
||||
submission.claimed_by = None
|
||||
submission.claimed_at = None
|
||||
submission.save(update_fields=["status", "claimed_by", "claimed_at"])
|
||||
|
||||
return Response({
|
||||
"success": True,
|
||||
"message": f"Lock released on submission {submission.id}"
|
||||
})
|
||||
|
||||
@action(detail=False, methods=["post"], permission_classes=[IsAdminOrSuperuser], url_path="admin-release-all")
|
||||
def admin_release_all(self, request):
|
||||
"""
|
||||
Admin/superuser force release of all active claims.
|
||||
"""
|
||||
claimed_submissions = EditSubmission.objects.filter(status="CLAIMED")
|
||||
|
||||
released_count = 0
|
||||
for submission in claimed_submissions:
|
||||
submission.status = "PENDING"
|
||||
submission.claimed_by = None
|
||||
submission.claimed_at = None
|
||||
submission.save(update_fields=["status", "claimed_by", "claimed_at"])
|
||||
released_count += 1
|
||||
|
||||
return Response({
|
||||
"released_count": released_count,
|
||||
"message": f"Released all {released_count} active lock(s)"
|
||||
})
|
||||
|
||||
@action(detail=True, methods=["post"], permission_classes=[IsModeratorOrAdmin], url_path="reassign")
|
||||
def reassign(self, request, pk=None):
|
||||
"""
|
||||
Reassign a submission to a different moderator.
|
||||
|
||||
Only admins can reassign submissions claimed by other moderators.
|
||||
The submission must be in CLAIMED status.
|
||||
"""
|
||||
submission = self.get_object()
|
||||
new_moderator_id = request.data.get("new_moderator_id")
|
||||
|
||||
if not new_moderator_id:
|
||||
return Response(
|
||||
{"error": "new_moderator_id is required"},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
try:
|
||||
new_moderator = User.objects.get(pk=new_moderator_id)
|
||||
except User.DoesNotExist:
|
||||
return Response(
|
||||
{"error": "Moderator not found"},
|
||||
status=status.HTTP_404_NOT_FOUND
|
||||
)
|
||||
|
||||
# Check moderator permissions
|
||||
if new_moderator.role not in ["MODERATOR", "ADMIN", "SUPERUSER"]:
|
||||
return Response(
|
||||
{"error": "User is not a moderator"},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
# Update the claim
|
||||
submission.claimed_by = new_moderator
|
||||
submission.claimed_at = timezone.now()
|
||||
submission.save(update_fields=["claimed_by", "claimed_at"])
|
||||
|
||||
return Response({
|
||||
"success": True,
|
||||
"message": f"Submission reassigned to {new_moderator.username}"
|
||||
})
|
||||
|
||||
@action(detail=False, methods=["post"], permission_classes=[IsModeratorOrAdmin], url_path="audit-log")
|
||||
def log_admin_action(self, request):
|
||||
"""
|
||||
Log an admin action for audit trail.
|
||||
|
||||
This creates an audit log entry for moderator actions.
|
||||
"""
|
||||
action_type = request.data.get("action_type", "")
|
||||
action_details = request.data.get("action_details", {})
|
||||
target_entity = request.data.get("target_entity", {})
|
||||
|
||||
# Create audit log entry
|
||||
logger.info(
|
||||
f"[AdminAction] User {request.user.username} - {action_type}",
|
||||
extra={
|
||||
"user_id": request.user.id,
|
||||
"action_type": action_type,
|
||||
"action_details": action_details,
|
||||
"target_entity": target_entity,
|
||||
}
|
||||
)
|
||||
|
||||
return Response({
|
||||
"success": True,
|
||||
"message": "Action logged successfully"
|
||||
})
|
||||
|
||||
@action(detail=False, methods=["get"], permission_classes=[IsModeratorOrAdmin], url_path="my-active-claim")
|
||||
def my_active_claim(self, request):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user