Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨(dashboard) add admin actions for updating consent statuses #318

Merged
merged 1 commit into from
Jan 13, 2025
Merged
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
2 changes: 2 additions & 0 deletions src/dashboard/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to
- add internationalization and language switcher
- add dashboard homepage
- add consent form to manage consents of one or many entities
- add admin integration for Entity, DeliveryPoint and Consent
- add mass admin action (make revoked and make awaiting) for consents
- integration of custom 403, 404 and 500 pages
- sentry integration
- added a signal on the creation of a delivery point. This signal allows the creation
Expand Down
27 changes: 26 additions & 1 deletion src/dashboard/apps/consent/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
"""Dashboard consent admin."""

from django.contrib import admin
from django.contrib import admin, messages
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from . import AWAITING, REVOKED
from .models import Consent


Expand All @@ -23,3 +26,25 @@ class ConsentAdmin(admin.ModelAdmin):
]
list_filter = ["status"]
date_hierarchy = "start"
actions = ["make_revoked", "make_awaiting"]

@admin.action(description=_("Mark selected consents as revoked"))
def make_revoked(self, request, queryset):
"""Mark selected consents as revoked."""
now = timezone.now()
queryset.update(status=REVOKED, revoked_at=now, updated_at=now)
self.message_user(
request,
_("Selected consents have been marked as revoked."),
messages.SUCCESS,
)

@admin.action(description=_("Mark selected consents as awaiting"))
def make_awaiting(self, request, queryset):
"""Mark selected consents as awaiting."""
queryset.update(status=AWAITING, updated_at=timezone.now(), revoked_at=None)
self.message_user(
request,
_("Selected consents have been marked as awaiting."),
messages.SUCCESS,
)
11 changes: 11 additions & 0 deletions src/dashboard/apps/consent/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import datetime

import pytest
from django.utils import timezone

FAKE_TIME = datetime.datetime(2025, 1, 6, 17, 5, 55, 0, tzinfo=datetime.timezone.utc)

Expand All @@ -17,3 +18,13 @@ def now(cls, tz=datetime.timezone.utc):
return FAKE_TIME

monkeypatch.setattr(datetime, "datetime", FakeDatetime)


@pytest.fixture
def patch_timezone_now(monkeypatch):
"""Monkeypatch timezone.now to return a frozen date (`FAKE_TIME`)."""

def mock_now():
return FAKE_TIME

monkeypatch.setattr(timezone, "now", mock_now)
66 changes: 66 additions & 0 deletions src/dashboard/apps/consent/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
from django.contrib.admin.sites import AdminSite
from django.urls import reverse

from apps.auth.factories import AdminUserFactory
from apps.consent import AWAITING, REVOKED, VALIDATED
from apps.consent.admin import ConsentAdmin
from apps.consent.models import Consent
from apps.consent.tests.conftest import FAKE_TIME
from apps.core.factories import DeliveryPointFactory


@pytest.mark.django_db
Expand All @@ -29,3 +33,65 @@ def test_admin_manager_name(rf):
# The manager name must be the default Django manager: `objects`.
manager_name = queryset.model._default_manager.name
assert manager_name == "objects"


@pytest.mark.django_db
def test_make_revoked_action(client, patch_timezone_now):
"""Tests the 'make_revoked' action for ConsentAdmin."""
# Initialize admin user
admin_user = AdminUserFactory()

# create a consent
assert Consent.objects.count() == 0
DeliveryPointFactory()
assert Consent.objects.count() == 1

# Post action with selected consent
consent = Consent.objects.first()
assert consent.status == AWAITING
data = {
"action": "make_revoked",
"_selected_action": [
consent.id,
],
}
client.force_login(admin_user)
client.post(reverse("admin:qcd_consent_consent_changelist"), data)

consent.refresh_from_db()
assert consent.status == REVOKED
jmaupetit marked this conversation as resolved.
Show resolved Hide resolved
assert consent.revoked_at == FAKE_TIME
assert consent.updated_at == FAKE_TIME


@pytest.mark.django_db
def test_make_awaiting_action(client, patch_timezone_now):
"""Tests the 'make_awaiting' action for ConsentAdmin."""
# Initialize admin user
admin_user = AdminUserFactory()

# create a consent
assert Consent.objects.count() == 0
DeliveryPointFactory()
assert Consent.objects.count() == 1

# Select and update consent status to AWAITING
consent = Consent.objects.first()
consent.status = VALIDATED
consent.save()
assert consent.status == VALIDATED

# Post action with selected consent
data = {
"action": "make_awaiting",
"_selected_action": [
consent.id,
],
}
client.force_login(admin_user)
client.post(reverse("admin:qcd_consent_consent_changelist"), data)

consent.refresh_from_db()
assert consent.status == AWAITING
jmaupetit marked this conversation as resolved.
Show resolved Hide resolved
assert consent.revoked_at is None
assert consent.updated_at == FAKE_TIME
Loading