Skip to content
Closed
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
31 changes: 31 additions & 0 deletions temba/channels/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,37 @@ def test_log_counts(self):
mock.assert_called_with(self.admin, "temba.ivr_outgoing", {"count": 1})


class ChannelEventCRUDLTest(CRUDLTestMixin, TembaTest):
def test_read(self):
contact = self.create_contact("Joe", phone="+250788111222")
e1 = ChannelEvent.objects.create(
org=self.org,
channel=self.channel,
event_type=ChannelEvent.TYPE_STOP_CONTACT,
contact=contact,
created_on=timezone.now() - timedelta(days=3),
occurred_on=timezone.now() - timedelta(days=3),
)
e2 = ChannelEvent.objects.create(
org=self.org,
channel=self.channel,
event_type=ChannelEvent.TYPE_DELETE_CONTACT,
contact=contact,
created_on=timezone.now() - timedelta(days=2),
occurred_on=timezone.now() - timedelta(days=3),
)
self.assertEqual(2, ChannelEvent.objects.all().count())

# 404 for non delete request event type
response = self.client.get(reverse("channels.channelevent_read", args=[e1.uuid]))
self.assertEqual(404, response.status_code)

# success for event of type delete request
response = self.client.get(reverse("channels.channelevent_read", args=[e2.uuid]))
self.assertEqual(200, response.status_code)
self.assertContains(response, f"Confirmation code: {e2.uuid}")


class ChannelEventTest(TembaTest):
def test_trim_task(self):
contact = self.create_contact("Joe", phone="+250788111222")
Expand Down
9 changes: 7 additions & 2 deletions temba/channels/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from .android.views import register, sync
from .models import Channel
from .views import ChannelCRUDL, ChannelLogCRUDL
from .views import ChannelCRUDL, ChannelEventCRUDL, ChannelLogCRUDL

# we iterate all our channel types, finding all the URLs they want to wire in
courier_urls = []
Expand All @@ -27,7 +27,12 @@


urlpatterns = [
re_path(r"^channels/", include(ChannelCRUDL().as_urlpatterns() + ChannelLogCRUDL().as_urlpatterns())),
re_path(
r"^channels/",
include(
ChannelCRUDL().as_urlpatterns() + ChannelLogCRUDL().as_urlpatterns() + ChannelEventCRUDL().as_urlpatterns()
),
),
re_path(r"^c/", include(courier_urls)),
re_path(r"^channels/types/", include(type_urls)),
re_path(r"^relayers/relayer/sync/(\d+)/$", sync, {}, "sync"),
Expand Down
24 changes: 23 additions & 1 deletion temba/channels/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from temba.utils.models import patch_queryset_count
from temba.utils.views.mixins import ComponentFormMixin, ContextMenuMixin, ModalFormMixin, SpaMixin

from .models import Channel, ChannelCount, ChannelLog
from .models import Channel, ChannelCount, ChannelEvent, ChannelLog

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -850,6 +850,28 @@ def get_context_data(self, **kwargs):
return context


class ChannelEventCRUDL(SmartCRUDL):
model = ChannelEvent
path = "events" # urls like /channels/events/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@norkans7 @ericnewcomer maybe this url.. should be something in the contacts app? E.g.

contact/forgetme/<contact-uuid>

And then when the contact is deleted... it says contact deleted

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we use the channel event UUID since that is the one we are creating on courier at the moment we receive the callback, retrieving the contact UUID i would be a challenge I guess and an issue if we cannot find the contact

I think if we can use the contact/forgetme/<event-uuid> with the channel event UUID that would be fine so not the contact UUID.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can't find the contact.. then there's no channel event and nothing to return and we noop

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL is the one we return as confirmation URL in courier
https://github.com/nyaruka/courier/pull/834/files#diff-45e8b1f3d84682ed837b92e0ff2e697b5d885ca171ecc8c3e0d766debedb7f81R258

Do you mean we need to make courier query for the contact before adding the channel event?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Courier has to query to know if we even own the contact in question and channel events are associated with a contact.. so I think I've convinced myself that the delete status URL is just a public facing view with the contact UUID in the URL... @ericnewcomer ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked on the current approach to query the contact, and the logic we have is that we try to get a contact for a URN and if it does not exists we create a contact for it as that is the logic we want for messages
But we can adjust that to make the creation optional

actions = ("read",)

class Read(SpaMixin, SmartReadView):
"""
Detail view for a single channel event that is a delete request event type
"""

permission = None
slug_url_kwarg = "uuid"

def derive_queryset(self, **kwargs):
return ChannelEvent.objects.filter(event_type=ChannelEvent.TYPE_DELETE_CONTACT)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["event"] = self.object
return context


class ChannelLogCRUDL(SmartCRUDL):
model = ChannelLog
path = "logs" # urls like /channels/logs/
Expand Down
17 changes: 17 additions & 0 deletions templates/channels/channelevent_read.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% extends "no_nav.html" %}
{% load smartmin compress temba %}
{% load i18n %}

{% block head-title %}
{% trans "Data deletion request" %}
{% endblock head-title %}
{% block page-top %}
{% endblock page-top %}
{% block content %}
<div class="flex flex-col h-full">
<div class="inner">
<div class="page-title mb-2">{% trans "Data deletion request received" %}</div>
<div class="centered mt-8">{% trans "Confirmation code" %}: {{ event.uuid }}</div>
</div>
</div>
{% endblock content %}