Fix Issue #5910: Create validator for assign_to attr
parent
748bf53159
commit
45bb5c4d9b
|
@ -22,10 +22,10 @@ from taiga.base.api import serializers
|
||||||
from taiga.base.api import validators
|
from taiga.base.api import validators
|
||||||
from taiga.base.exceptions import ValidationError
|
from taiga.base.exceptions import ValidationError
|
||||||
from taiga.base.fields import PgArrayField
|
from taiga.base.fields import PgArrayField
|
||||||
|
from taiga.projects.mixins.validators import AssignedToValidator
|
||||||
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
from taiga.projects.tagging.fields import TagsAndTagsColorsField
|
from taiga.projects.tagging.fields import TagsAndTagsColorsField
|
||||||
from taiga.projects.userstories.validators import UserStoryExistsValidator
|
|
||||||
from taiga.projects.validators import ProjectExistsValidator
|
from taiga.projects.validators import ProjectExistsValidator
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ class EpicExistsValidator:
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class EpicValidator(WatchersValidator, EditableWatchedResourceSerializer, validators.ModelValidator):
|
class EpicValidator(AssignedToValidator, WatchersValidator, EditableWatchedResourceSerializer,
|
||||||
|
validators.ModelValidator):
|
||||||
tags = TagsAndTagsColorsField(default=[], required=False)
|
tags = TagsAndTagsColorsField(default=[], required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
|
|
||||||
|
@ -61,7 +62,6 @@ class CreateRelatedUserStoriesBulkValidator(ProjectExistsValidator, EpicExistsVa
|
||||||
bulk_userstories = serializers.CharField()
|
bulk_userstories = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EpicRelatedUserStoryValidator(validators.ModelValidator):
|
class EpicRelatedUserStoryValidator(validators.ModelValidator):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.RelatedUserStory
|
model = models.RelatedUserStory
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
from taiga.base.api import serializers
|
from taiga.base.api import serializers
|
||||||
from taiga.base.api import validators
|
from taiga.base.api import validators
|
||||||
from taiga.base.fields import PgArrayField
|
from taiga.base.fields import PgArrayField
|
||||||
|
from taiga.projects.mixins.validators import AssignedToValidator
|
||||||
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
from taiga.projects.tagging.fields import TagsAndTagsColorsField
|
from taiga.projects.tagging.fields import TagsAndTagsColorsField
|
||||||
|
@ -27,7 +28,7 @@ from taiga.projects.validators import ProjectExistsValidator
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
class IssueValidator(WatchersValidator, EditableWatchedResourceSerializer,
|
class IssueValidator(AssignedToValidator, WatchersValidator, EditableWatchedResourceSerializer,
|
||||||
validators.ModelValidator):
|
validators.ModelValidator):
|
||||||
|
|
||||||
tags = TagsAndTagsColorsField(default=[], required=False)
|
tags = TagsAndTagsColorsField(default=[], required=False)
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from taiga.base.exceptions import ValidationError
|
||||||
|
from taiga.projects.models import Membership
|
||||||
|
|
||||||
|
|
||||||
|
class AssignedToValidator:
|
||||||
|
def validate_assigned_to(self, attrs, source):
|
||||||
|
assigned_to = attrs[source]
|
||||||
|
project = (attrs.get("project", None) or
|
||||||
|
getattr(self.object, "project", None))
|
||||||
|
|
||||||
|
if assigned_to and project:
|
||||||
|
filters = {
|
||||||
|
"project_id": project.id,
|
||||||
|
"user_id": assigned_to.id
|
||||||
|
}
|
||||||
|
|
||||||
|
if not Membership.objects.filter(**filters).exists():
|
||||||
|
raise ValidationError(_("The user must be a project member."))
|
||||||
|
|
||||||
|
return attrs
|
|
@ -23,6 +23,7 @@ from taiga.base.api import validators
|
||||||
from taiga.base.exceptions import ValidationError
|
from taiga.base.exceptions import ValidationError
|
||||||
from taiga.base.fields import PgArrayField
|
from taiga.base.fields import PgArrayField
|
||||||
from taiga.projects.milestones.models import Milestone
|
from taiga.projects.milestones.models import Milestone
|
||||||
|
from taiga.projects.mixins.validators import AssignedToValidator
|
||||||
from taiga.projects.models import TaskStatus
|
from taiga.projects.models import TaskStatus
|
||||||
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
|
@ -33,7 +34,8 @@ from taiga.projects.validators import ProjectExistsValidator
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
class TaskValidator(WatchersValidator, EditableWatchedResourceSerializer, validators.ModelValidator):
|
class TaskValidator(AssignedToValidator, WatchersValidator, EditableWatchedResourceSerializer,
|
||||||
|
validators.ModelValidator):
|
||||||
tags = TagsAndTagsColorsField(default=[], required=False)
|
tags = TagsAndTagsColorsField(default=[], required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ from taiga.base.api import validators
|
||||||
from taiga.base.exceptions import ValidationError
|
from taiga.base.exceptions import ValidationError
|
||||||
from taiga.base.fields import PgArrayField
|
from taiga.base.fields import PgArrayField
|
||||||
from taiga.base.fields import PickledObjectField
|
from taiga.base.fields import PickledObjectField
|
||||||
|
from taiga.base.utils import json
|
||||||
from taiga.projects.milestones.models import Milestone
|
from taiga.projects.milestones.models import Milestone
|
||||||
|
from taiga.projects.mixins.validators import AssignedToValidator
|
||||||
from taiga.projects.models import UserStoryStatus
|
from taiga.projects.models import UserStoryStatus
|
||||||
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
from taiga.projects.notifications.mixins import EditableWatchedResourceSerializer
|
||||||
from taiga.projects.notifications.validators import WatchersValidator
|
from taiga.projects.notifications.validators import WatchersValidator
|
||||||
|
@ -33,8 +35,6 @@ from taiga.projects.validators import ProjectExistsValidator
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class UserStoryExistsValidator:
|
class UserStoryExistsValidator:
|
||||||
def validate_us_id(self, attrs, source):
|
def validate_us_id(self, attrs, source):
|
||||||
|
@ -55,7 +55,8 @@ class RolePointsField(serializers.WritableField):
|
||||||
return json.loads(obj)
|
return json.loads(obj)
|
||||||
|
|
||||||
|
|
||||||
class UserStoryValidator(WatchersValidator, EditableWatchedResourceSerializer, validators.ModelValidator):
|
class UserStoryValidator(AssignedToValidator, WatchersValidator,
|
||||||
|
EditableWatchedResourceSerializer, validators.ModelValidator):
|
||||||
tags = TagsAndTagsColorsField(default=[], required=False)
|
tags = TagsAndTagsColorsField(default=[], required=False)
|
||||||
external_reference = PgArrayField(required=False)
|
external_reference = PgArrayField(required=False)
|
||||||
points = RolePointsField(source="role_points", required=False)
|
points = RolePointsField(source="role_points", required=False)
|
||||||
|
|
|
@ -707,6 +707,7 @@ def create_project(**kwargs):
|
||||||
project.default_issue_type = IssueTypeFactory.create(project=project)
|
project.default_issue_type = IssueTypeFactory.create(project=project)
|
||||||
project.default_us_status = UserStoryStatusFactory.create(project=project)
|
project.default_us_status = UserStoryStatusFactory.create(project=project)
|
||||||
project.default_task_status = TaskStatusFactory.create(project=project)
|
project.default_task_status = TaskStatusFactory.create(project=project)
|
||||||
|
project.default_epic_status = EpicStatusFactory.create(project=project)
|
||||||
|
|
||||||
project.save()
|
project.save()
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,10 @@ from unittest import mock
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
|
from taiga.permissions.choices import MEMBERS_PERMISSIONS, ANON_PERMISSIONS
|
||||||
from taiga.projects.epics import services
|
from taiga.projects.epics import services
|
||||||
from taiga.projects.epics import models
|
from taiga.projects.epics import models
|
||||||
|
from taiga.projects.occ import OCCResourceMixin
|
||||||
|
|
||||||
from .. import factories as f
|
from .. import factories as f
|
||||||
|
|
||||||
|
@ -162,3 +164,119 @@ def test_unset_related_userstory(client):
|
||||||
response = client.delete(url)
|
response = client.delete(url)
|
||||||
assert response.status_code == 204
|
assert response.status_code == 204
|
||||||
assert not models.RelatedUserStory.objects.filter(id=related_us.id).exists()
|
assert not models.RelatedUserStory.objects.filter(id=related_us.id).exists()
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_update_epics(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
epic = f.create_epic(project=project, owner=project.owner, status=project.epic_statuses.all()[0])
|
||||||
|
|
||||||
|
url = reverse('epics-detail', kwargs={"pk": epic.pk})
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_create_epics(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
url = reverse('epics-list')
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
|
@ -28,8 +28,10 @@ from unittest import mock
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from taiga.projects.issues import services, models
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
|
from taiga.permissions.choices import MEMBERS_PERMISSIONS, ANON_PERMISSIONS
|
||||||
|
from taiga.projects.issues import services, models
|
||||||
|
from taiga.projects.occ import OCCResourceMixin
|
||||||
|
|
||||||
from .. import factories as f
|
from .. import factories as f
|
||||||
|
|
||||||
|
@ -592,3 +594,119 @@ def test_custom_fields_csv_generation():
|
||||||
assert row[23] == attr.name
|
assert row[23] == attr.name
|
||||||
row = next(reader)
|
row = next(reader)
|
||||||
assert row[23] == "val1"
|
assert row[23] == "val1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_update_issues(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
issue = f.create_issue(project=project, owner=project.owner)
|
||||||
|
|
||||||
|
url = reverse('issues-detail', kwargs={"pk": issue.pk})
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_create_issues(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
url = reverse('issues-list')
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
|
@ -29,6 +29,8 @@ from unittest import mock
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
|
from taiga.permissions.choices import MEMBERS_PERMISSIONS, ANON_PERMISSIONS
|
||||||
|
from taiga.projects.occ import OCCResourceMixin
|
||||||
from taiga.projects.tasks import services
|
from taiga.projects.tasks import services
|
||||||
|
|
||||||
from .. import factories as f
|
from .. import factories as f
|
||||||
|
@ -861,3 +863,119 @@ def test_api_filters_data(client):
|
||||||
assert next(filter(lambda i: i['name'] == tag1, response.data["tags"]))["count"] == 2
|
assert next(filter(lambda i: i['name'] == tag1, response.data["tags"]))["count"] == 2
|
||||||
assert next(filter(lambda i: i['name'] == tag2, response.data["tags"]))["count"] == 2
|
assert next(filter(lambda i: i['name'] == tag2, response.data["tags"]))["count"] == 2
|
||||||
assert next(filter(lambda i: i['name'] == tag3, response.data["tags"]))["count"] == 1
|
assert next(filter(lambda i: i['name'] == tag3, response.data["tags"]))["count"] == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_update_tasks(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
task = f.create_task(project=project, milestone__project=project, user_story=None, owner=project.owner)
|
||||||
|
|
||||||
|
url = reverse('tasks-detail', kwargs={"pk": task.pk})
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_create_tasks(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
url = reverse('tasks-list')
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
|
@ -28,6 +28,8 @@ from unittest import mock
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
from taiga.base.utils import json
|
from taiga.base.utils import json
|
||||||
|
from taiga.permissions.choices import MEMBERS_PERMISSIONS, ANON_PERMISSIONS
|
||||||
|
from taiga.projects.occ import OCCResourceMixin
|
||||||
from taiga.projects.userstories import services, models
|
from taiga.projects.userstories import services, models
|
||||||
|
|
||||||
from .. import factories as f
|
from .. import factories as f
|
||||||
|
@ -1021,3 +1023,118 @@ def test_get_user_stories_including_attachments(client):
|
||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert len(response.data[0].get("attachments")) == 1
|
assert len(response.data[0].get("attachments")) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_update_userstories(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
userstory = f.create_userstory(project=project, owner=project.owner, status=project.us_statuses.all()[0])
|
||||||
|
|
||||||
|
url = reverse('userstories-detail', kwargs={"pk": userstory.pk})
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 200, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.patch(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_validator_assigned_to_when_create_userstories(client):
|
||||||
|
project = f.create_project(anon_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)),
|
||||||
|
public_permissions=list(map(lambda x: x[0], ANON_PERMISSIONS)))
|
||||||
|
project_member_owner = f.MembershipFactory.create(project=project,
|
||||||
|
user=project.owner,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_member = f.MembershipFactory.create(project=project,
|
||||||
|
is_admin=True,
|
||||||
|
role__project=project,
|
||||||
|
role__permissions=list(map(lambda x: x[0], MEMBERS_PERMISSIONS)))
|
||||||
|
project_no_member = f.MembershipFactory.create(is_admin=True)
|
||||||
|
|
||||||
|
url = reverse('userstories-list')
|
||||||
|
|
||||||
|
# assign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == project_member.user.id
|
||||||
|
|
||||||
|
# unassign
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 201, response.data
|
||||||
|
assert "assigned_to" in response.data
|
||||||
|
assert response.data["assigned_to"] == None
|
||||||
|
|
||||||
|
# assign to invalid user
|
||||||
|
data = {
|
||||||
|
"subject": "test",
|
||||||
|
"project": project.id,
|
||||||
|
"assigned_to": project_no_member.user.id,
|
||||||
|
}
|
||||||
|
|
||||||
|
with mock.patch.object(OCCResourceMixin, "_validate_and_update_version"):
|
||||||
|
client.login(project.owner)
|
||||||
|
|
||||||
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
assert response.status_code == 400, response.data
|
||||||
|
|
Loading…
Reference in New Issue