Skip to content

Commit

Permalink
Adding @verify_status decorator to unlock endpoints (#4612)
Browse files Browse the repository at this point in the history
* Adding verify_status decorator to unlock endpoints

* Import cleanup
  • Loading branch information
phildominguez-gsa authored Jan 13, 2025
1 parent d760250 commit b722bbc
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 35 deletions.
44 changes: 44 additions & 0 deletions backend/audit/verify_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import logging

from django.shortcuts import redirect
from django.core.exceptions import PermissionDenied

from audit.models import SingleAuditChecklist


logging.basicConfig(
format="%(asctime)s %(levelname)-8s %(module)s:%(lineno)d %(message)s"
)
logger = logging.getLogger(__name__)


def verify_status(status):
"""
Decorator to be applied to view request methods (i.e. get, post) to verify
that the submission is in the correct state before allowing the user to
proceed. An incorrect status usually happens via direct URL access. If the
given status does not match the submission's, it will redirect them back to
the submission progress page.
"""

def decorator_verify_status(request_method):
def verify(view, request, *args, **kwargs):
report_id = kwargs["report_id"]

try:
sac = SingleAuditChecklist.objects.get(report_id=report_id)
except SingleAuditChecklist.DoesNotExist:
raise PermissionDenied("You do not have access to this audit.")

# Return to checklist, the Audit is not in the correct state.
if sac.submission_status != status:
logger.warning(
f"Expected submission status {status} but it's currently {sac.submission_status}"
)
return redirect(f"/audit/submission-progress/{sac.report_id}")
else:
return request_method(view, request, *args, **kwargs)

return verify

return decorator_verify_status
5 changes: 5 additions & 0 deletions backend/audit/views/unlock_after_certification.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.shortcuts import render, redirect
from django.views import generic
from django.urls import reverse

from audit.forms import UnlockAfterCertificationForm
from audit.mixins import (
SingleAuditChecklistAccessRequiredMixin,
Expand All @@ -13,6 +14,8 @@
)
from audit.models.models import STATUS
from audit.models.viewflow import sac_transition
from audit.verify_status import verify_status


logger = logging.getLogger(__name__)

Expand All @@ -25,6 +28,7 @@ class UnlockAfterCertificationView(
READY_FOR_CERTIFICATION.
"""

@verify_status(STATUS.READY_FOR_CERTIFICATION)
def get(self, request, *args, **kwargs):
report_id = kwargs["report_id"]

Expand All @@ -51,6 +55,7 @@ def get(self, request, *args, **kwargs):
except SingleAuditChecklist.DoesNotExist:
raise PermissionDenied("You do not have access to this audit.")

@verify_status(STATUS.READY_FOR_CERTIFICATION)
def post(self, request, *args, **kwargs):
report_id = kwargs["report_id"]

Expand Down
37 changes: 2 additions & 35 deletions backend/audit/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from django.http import JsonResponse

from audit.fixtures.excel import FORM_SECTIONS, UNKNOWN_WORKBOOK


from audit.forms import (
AuditorCertificationStep1Form,
AuditorCertificationStep2Form,
Expand All @@ -38,11 +36,12 @@
from audit.models.models import STATUS
from audit.models.viewflow import sac_transition
from audit.intakelib.exceptions import ExcelExtractionError
from audit.utils import FORM_SECTION_HANDLERS
from audit.validators import (
validate_auditee_certification_json,
validate_auditor_certification_json,
)
from audit.utils import FORM_SECTION_HANDLERS
from audit.verify_status import verify_status

from dissemination.remove_workbook_artifacts import remove_workbook_artifacts
from dissemination.file_downloads import get_download_url, get_filename
Expand All @@ -61,38 +60,6 @@ def _friendly_status(status):
return dict(SingleAuditChecklist.STATUS_CHOICES)[status]


def verify_status(status):
"""
Decorator to be applied to view request methods (i.e. get, post) to verify
that the submission is in the correct state before allowing the user to
proceed. An incorrect status usually happens via direct URL access. If the
given status does not match the submission's, it will redirect them back to
the submission progress page.
"""

def decorator_verify_status(request_method):
def verify(view, request, *args, **kwargs):
report_id = kwargs["report_id"]

try:
sac = SingleAuditChecklist.objects.get(report_id=report_id)
except SingleAuditChecklist.DoesNotExist:
raise PermissionDenied("You do not have access to this audit.")

# Return to checklist, the Audit is not in the correct state.
if sac.submission_status != status:
logger.warning(
f"Expected submission status {status} but it's currently {sac.submission_status}"
)
return redirect(f"/audit/submission-progress/{sac.report_id}")
else:
return request_method(view, request, *args, **kwargs)

return verify

return decorator_verify_status


class MySubmissions(LoginRequiredMixin, generic.View):
redirect_field_name = "Home"

Expand Down

0 comments on commit b722bbc

Please sign in to comment.