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

Cannot respond to a transfer after first response #3255

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Harvest attribution roles [#3149](https://github.com/opendatateam/udata/pull/3149)
- Allow super-admins to change objects' owners [#3260](https://github.com/opendatateam/udata/pull/3260)
- Cannot respond to a transfer after first response [#3255](https://github.com/opendatateam/udata/pull/3255)
- Fix contact point permissions [#3253](https://github.com/opendatateam/udata/pull/3253)
- Fix wrong marshal for community resource uploads [#3261](https://github.com/opendatateam/udata/pull/3261)
- Return harvesters's errors details only for super-admins [#3264](https://github.com/opendatateam/udata/pull/3264)
Expand Down
11 changes: 7 additions & 4 deletions udata/features/transfer/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flask import request
from flask import abort, request

from udata.api import API, api, base_reference, fields
from udata.core.dataservices.models import Dataservice
Expand Down Expand Up @@ -27,7 +27,7 @@
"recipient": fields.Nested(
base_reference,
required=True,
description=("The transfer recipient, " "either an user or an organization"),
description=("The transfer recipient, either an user or an organization"),
),
"comment": fields.String(
description="An explanation about the transfer request", required=True
Expand Down Expand Up @@ -68,12 +68,12 @@
"owner": fields.Polymorph(
person_mapping,
readonly=True,
description=("The user or organization currently owning " "the transfered object"),
description=("The user or organization currently owning the transfered object"),
),
"recipient": fields.Polymorph(
person_mapping,
readonly=True,
description=("The user or organization receiving " "the transfered object"),
description=("The user or organization receiving the transfered object"),
),
"subject": fields.Polymorph(
subject_mapping, readonly=True, description="The transfered object"
Expand Down Expand Up @@ -186,6 +186,9 @@ def post(self, id):
"""Respond to a transfer request"""
transfer = Transfer.objects.get_or_404(id=id_or_404(id))

if transfer.status != "pending":
abort(400, "Cannot update transfer after accepting/refusing")

data = request.json
comment = data.get("comment")

Expand Down
38 changes: 38 additions & 0 deletions udata/tests/api/test_transfer_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
from flask import url_for

from udata.core.dataset.factories import DatasetFactory
from udata.core.dataset.models import Dataset
from udata.core.organization.factories import OrganizationFactory
from udata.core.user.factories import UserFactory
from udata.core.user.models import User
from udata.utils import faker

from . import APITestCase
Expand Down Expand Up @@ -214,3 +216,39 @@ def test_400_on_bad_recipient(self):
data = response.json

self.assertIn("recipient", data["errors"])

def test_cannot_accept_or_refuse_transfer_after_accepting_or_refusing(self):
user = self.login()
new_user = UserFactory()
dataset = DatasetFactory(owner=user)

response = self._create_transfer(dataset, new_user)
self.assert201(response)

transfer = response.json

self.login(new_user)
response = self.post(url_for("api.transfer", id=transfer["id"]), {"response": "accept"})
self.assert200(response)

response = self.post(url_for("api.transfer", id=transfer["id"]), {"response": "accept"})
self.assert400(response)

response = self.post(url_for("api.transfer", id=transfer["id"]), {"response": "refuse"})
self.assert400(response)

def _create_transfer(self, source: Dataset, destination: User):
return self.post(
url_for("api.transfers"),
{
"subject": {
"class": "Dataset",
"id": str(source.id),
},
"recipient": {
"class": "User",
"id": str(destination.id),
},
"comment": "Some comment",
},
)