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

Add additional message verbs to messaging endpoint #2321

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 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
46 changes: 43 additions & 3 deletions onadata/apps/api/tests/viewsets/test_project_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
from onadata.apps.api.viewsets.xform_viewset import XFormViewSet
from onadata.apps.logger.models import Project, XForm, XFormVersion
from onadata.apps.main.models import MetaData
from onadata.apps.messaging.constants import (
XFORM, PROJECT, USER, PROJECT_CREATED,
FORM_CREATED, PROJECT_DELETED
)
from onadata.libs import permissions as role
from onadata.libs.models.share_project import ShareProject
from onadata.libs.utils.cache_tools import PROJ_OWNER_CACHE, safe_key
Expand Down Expand Up @@ -96,8 +100,10 @@ def tearDown(self):
super().tearDown()

# pylint: disable=invalid-name
@patch("onadata.apps.api.viewsets.project_viewset.send_message")
@patch("onadata.apps.main.forms.requests")
def test_publish_xlsform_using_url_upload(self, mock_requests):
def test_publish_xlsform_using_url_upload(
self, mock_requests, mock_send_message):
with HTTMock(enketo_mock):
self._project_create()
view = ProjectViewSet.as_view({"post": "forms"})
Expand Down Expand Up @@ -125,6 +131,7 @@ def test_publish_xlsform_using_url_upload(self, mock_requests):
post_data = {"xls_url": xls_url}
request = self.factory.post("/", data=post_data, **self.extra)
response = view(request, pk=project_id)
xform = self.user.xforms.get(id_string="transportation_2015_01_07")

mock_requests.get.assert_called_with(xls_url)
xls_file.close()
Expand All @@ -137,6 +144,16 @@ def test_publish_xlsform_using_url_upload(self, mock_requests):
1,
)

# send message upon form deletion
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=xform.id,
target_id=xform.id,
target_type=XFORM,
user=request.user,
message_verb=FORM_CREATED
)

def test_projects_list(self):
self._project_create()
request = self.factory.get("/", **self.extra)
Expand Down Expand Up @@ -407,7 +424,8 @@ def test_projects_tags(self):
self.assertEqual(response.data, [])
self.assertEqual(get_latest_tags(self.project), [])

def test_projects_create(self):
@patch("onadata.apps.api.viewsets.project_viewset.send_message")
def test_projects_create(self, mock_send_message):
self._project_create()
self.assertIsNotNone(self.project_data)

Expand All @@ -418,6 +436,16 @@ def test_projects_create(self):
self.assertEqual(self.user, project.created_by)
self.assertEqual(self.user, project.organization)

# send message upon project creation
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=self.project.id,
target_id=self.project.id,
target_type=PROJECT,
user=self.user,
message_verb=PROJECT_CREATED
)

def test_project_create_other_account(self): # pylint: disable=invalid-name
"""
Test that a user cannot create a project in a different user account
Expand Down Expand Up @@ -2516,7 +2544,8 @@ def test_project_list_by_owner(self):
users,
)

def test_projects_soft_delete(self):
@patch("onadata.apps.api.viewsets.project_viewset.send_message")
def test_projects_soft_delete(self, mock_send_message):
self._project_create()

view = ProjectViewSet.as_view({"get": "list", "delete": "destroy"})
Expand All @@ -2537,6 +2566,17 @@ def test_projects_soft_delete(self):
request = self.factory.delete("/", **self.extra)
request.user = self.user
response = view(request, pk=project_id)

# send message upon project creation
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=self.project.id,
target_id=self.user.id,
target_type=USER,
user=self.user,
message_verb=PROJECT_DELETED
)

self.assertEqual(response.status_code, 204)

self.project = Project.objects.get(pk=project_id)
Expand Down
95 changes: 89 additions & 6 deletions onadata/apps/api/tests/viewsets/test_xform_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@
from onadata.apps.logger.models.xform_version import XFormVersion
from onadata.apps.logger.xform_instance_parser import XLSFormError
from onadata.apps.main.models import MetaData
from onadata.apps.messaging.constants import FORM_UPDATED, XFORM
from onadata.apps.messaging.constants import (
FORM_UPDATED, XFORM, PROJECT, FORM_DELETED, FORM_CREATED,
FORM_RENAMED, FORM_ACTIVE
)
from onadata.apps.viewer.models import Export
from onadata.apps.viewer.models.export import ExportTypeError
from onadata.libs.permissions import (
Expand Down Expand Up @@ -1326,7 +1329,8 @@ def test_login_enketo_online_url_using_jwt(self):
self.assertEqual(username_cookie.split(":")[0], "bob")
self.assertEqual(uid_cookie.split(":")[0], "bob")

def test_publish_xlsform(self):
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
def test_publish_xlsform(self, mock_send_message):
with HTTMock(enketo_urls_mock):
view = XFormViewSet.as_view({"post": "create"})
data = {
Expand Down Expand Up @@ -1378,6 +1382,16 @@ def test_publish_xlsform(self):
versions_count = XFormVersion.objects.filter(xform=xform).count()
self.assertEqual(versions_count, 1)

# send message upon form publishing
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=xform.id,
target_id=xform.pk,
target_type=XFORM,
user=request.user,
message_verb=FORM_CREATED
)

def test_publish_xlsforms_with_same_id_string(self):
with HTTMock(enketo_urls_mock):
counter = XForm.objects.count()
Expand Down Expand Up @@ -1476,8 +1490,10 @@ def test_publish_xlsforms_with_same_id_string(self):
self.assertEqual(counter + 2, XForm.objects.count())

# pylint: disable=invalid-name
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
@patch("onadata.apps.main.forms.requests")
def test_publish_xlsform_using_url_upload(self, mock_requests):
def test_publish_xlsform_using_url_upload(
self, mock_requests, mock_send_message):
with HTTMock(enketo_mock):
view = XFormViewSet.as_view({"post": "create"})

Expand All @@ -1503,13 +1519,24 @@ def test_publish_xlsform_using_url_upload(self, mock_requests):
post_data = {"xls_url": xls_url}
request = self.factory.post("/", data=post_data, **self.extra)
response = view(request)
xform = self.user.xforms.get(id_string="transportation_2015_01_07")

mock_requests.get.assert_called_with(xls_url)
xls_file.close()

self.assertEqual(response.status_code, 201)
self.assertEqual(XForm.objects.count(), pre_count + 1)

# send message upon form publishing
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=xform.id,
target_id=xform.id,
target_type=XFORM,
user=request.user,
message_verb=FORM_CREATED
)

# pylint: disable=invalid-name
@patch("onadata.apps.main.forms.requests")
def test_publish_xlsform_using_url_with_no_extension(self, mock_requests):
Expand Down Expand Up @@ -1797,7 +1824,8 @@ def test_publish_invalid_xls_form_no_choices(self):
)
self.assertEqual(response.data.get("text"), error_msg)

def test_partial_update(self):
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
def test_partial_update(self, mock_send_message):
with HTTMock(enketo_mock):
self._publish_xls_form_to_project()
view = XFormViewSet.as_view({"patch": "partial_update"})
Expand All @@ -1821,6 +1849,38 @@ def test_partial_update(self):
request = self.factory.patch("/", data=data, **self.extra)
response = view(request, pk=self.xform.id)
self.assertEqual(response.status_code, 200)

# send messages upon form update
self.assertTrue(mock_send_message.called)

# check calls to send_message triggered by patch request
mock_calls = mock_send_message.call_args_list
args, kwargs = mock_calls[0]
# test form rename message
message_kwargs = {
"instance_id": self.xform.id,
"target_id": self.xform.id,
"target_type": XFORM,
"user": self.xform.user,
"message_verb": FORM_RENAMED,
"custom_message": {
"old_title": "transportation_2011_07_25",
"new_title": "Hello & World!"
}
}
self.assertEqual(kwargs, message_kwargs)

# test form status message
args, kwargs = mock_calls[1]
message_kwargs = {
"instance_id": self.xform.id,
"target_id": self.xform.id,
"target_type": XFORM,
"user": self.xform.user,
"message_verb": FORM_ACTIVE,
}
self.assertEqual(kwargs, message_kwargs)

xform_old_hash = self.xform.hash
self.xform.refresh_from_db()
self.assertTrue(self.xform.downloadable)
Expand Down Expand Up @@ -1956,7 +2016,8 @@ def test_form_add_project_cache(self):
cache.get(f"{PROJ_FORMS_CACHE}{self.project.pk}"), cleared_cache_content
)

def test_form_delete(self):
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
def test_form_delete(self, mock_send_message):
with HTTMock(enketo_mock):
self._publish_xls_form_to_project()

Expand All @@ -1976,6 +2037,17 @@ def test_form_delete(self):
formid = self.xform.pk
request = self.factory.delete("/", **self.extra)
response = view(request, pk=formid)

# send message upon form deletion
self.assertTrue(mock_send_message.called)
mock_send_message.assert_called_with(
instance_id=self.xform.id,
target_id=self.xform.project.pk,
target_type=PROJECT,
user=request.user,
message_verb=FORM_DELETED
)

self.assertEqual(response.data, None)
self.assertEqual(response.status_code, 204)

Expand Down Expand Up @@ -3503,8 +3575,9 @@ def test_survey_preview_endpoint(self):
self.assertEqual(response.data.get("detail"), error_message)

@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
@patch("onadata.apps.api.tasks.get_async_status")
def test_delete_xform_async(self, mock_get_status):
def test_delete_xform_async(self, mock_get_status, mock_send_msg):
with HTTMock(enketo_mock):
mock_get_status.return_value = {"job_status": "PENDING"}
self._publish_xls_form_to_project()
Expand Down Expand Up @@ -3533,6 +3606,16 @@ def test_delete_xform_async(self, mock_get_status):
self.assertEqual(response.status_code, 202)
self.assertEqual(response.data, {"job_status": "PENDING"})

# send message upon form deletion
self.assertTrue(mock_send_msg.called)
mock_send_msg.assert_called_with(
instance_id=self.xform.id,
target_id=self.xform.project.pk,
target_type=XFORM,
user=request.user,
message_verb=FORM_DELETED
)

xform = XForm.objects.get(pk=formid)

self.assertIsNotNone(xform.deleted_at)
Expand Down
18 changes: 18 additions & 0 deletions onadata/apps/api/viewsets/export_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
"""
import os

from rest_framework import status
from rest_framework.mixins import DestroyModelMixin
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.viewsets import ReadOnlyModelViewSet

from onadata.apps.api.permissions import ExportDjangoObjectPermission
from onadata.apps.messaging.constants import EXPORT_DELETED, XFORM
from onadata.apps.messaging.serializers import send_message
from onadata.apps.viewer.models.export import Export
from onadata.libs import filters
from onadata.libs.authentication import TempTokenURLParameterAuthentication
Expand Down Expand Up @@ -57,3 +61,17 @@ def retrieve(self, request, *args, **kwargs):
file_path=export.filepath,
show_date=False,
)

def destroy(self, request, *args, **kwargs):
"""Deletes Export Object"""
export = self.get_object()
export_id = export.id
export.delete()
send_message(
instance_id=export_id,
target_id=export.xform.id,
target_type=XFORM,
user=request.user,
message_verb=EXPORT_DELETED,
)
return Response(status=status.HTTP_204_NO_CONTENT)
Loading