Skip to content

Commit

Permalink
Adding project info on about slots when import/create/edit fails
Browse files Browse the repository at this point in the history
  • Loading branch information
superalex committed Mar 1, 2016
1 parent e4ba94f commit 2457e8b
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 17 deletions.
4 changes: 3 additions & 1 deletion settings/common.py
Expand Up @@ -433,7 +433,9 @@
# Extra expose header related to Taiga APP (see taiga.base.middleware.cors=)
APP_EXTRA_EXPOSE_HEADERS = [
"taiga-info-total-opened-milestones",
"taiga-info-total-closed-milestones"
"taiga-info-total-closed-milestones",
"taiga-info-project-memberships",
"taiga-info-project-is-private"
]

DEFAULT_PROJECT_TEMPLATE = "scrum"
Expand Down
20 changes: 20 additions & 0 deletions taiga/base/exceptions.py
Expand Up @@ -202,10 +202,27 @@ class NotAuthenticated(NotAuthenticated):


class Blocked(APIException):
"""
Exception used on blocked projects
"""
status_code = status.HTTP_451_BLOCKED
default_detail = _("Blocked element")


class NotEnoughSlotsForProject(BaseException):
"""
Exception used on import/edition/creation project errors where the user
hasn't slots enough
"""
default_detail = _("Not enough slots for project.")

def __init__(self, is_private, total_memberships, detail=None):
self.detail = detail or self.default_detail
self.project_data = {
"is_private": is_private,
"total_memberships": total_memberships
}

def format_exception(exc):
if isinstance(exc.detail, (dict, list, tuple,)):
detail = exc.detail
Expand Down Expand Up @@ -237,6 +254,9 @@ def exception_handler(exc):
headers["WWW-Authenticate"] = exc.auth_header
if getattr(exc, "wait", None):
headers["X-Throttle-Wait-Seconds"] = "%d" % exc.wait
if getattr(exc, "project_data", None):
headers["Taiga-Info-Project-Memberships"] = exc.project_data["total_memberships"]
headers["Taiga-Info-Project-Is-Private"] = exc.project_data["is_private"]

detail = format_exception(exc)
return response.Response(detail, status=exc.status_code, headers=headers)
Expand Down
13 changes: 3 additions & 10 deletions taiga/export_import/api.py
Expand Up @@ -97,7 +97,7 @@ def create(self, request, *args, **kwargs):
project=Project(is_private=is_private, id=None)
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(is_private, 1, not_enough_slots_error)

# Create Project
project_serialized = service.store_project(data)
Expand All @@ -122,7 +122,7 @@ def create(self, request, *args, **kwargs):
members=max(members, 1)
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(is_private, max(members, 1), not_enough_slots_error)
service.store_memberships(project_serialized.object, data)

try:
Expand Down Expand Up @@ -224,13 +224,6 @@ def load_dump(self, request):
raise exc.WrongArguments(_("Invalid dump format"))

user = request.user
(enough_slots, not_enough_slots_error) = users_service.has_available_slot_for_project(
user,
project=Project(is_private=is_private, id=None)
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)

slug = dump.get('slug', None)
if slug is not None and Project.objects.filter(slug=slug).exists():
del dump['slug']
Expand All @@ -242,7 +235,7 @@ def load_dump(self, request):
members=max(members, 1)
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(is_private, max(members, 1), not_enough_slots_error)

if settings.CELERY_ENABLED:
task = tasks.load_project_dump.delay(user, dump)
Expand Down
15 changes: 9 additions & 6 deletions taiga/projects/api.py
Expand Up @@ -378,7 +378,7 @@ def transfer_accept(self, request, pk=None):
members=members
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(project.is_private, members, not_enough_slots_error)

reason = request.DATA.get('reason', None)
services.accept_project_transfer(project, request.user, token, reason)
Expand Down Expand Up @@ -414,8 +414,9 @@ def _set_base_permissions(self, obj):
def pre_save(self, obj):
user = self.request.user
(enough_slots, not_enough_slots_error) = users_service.has_available_slot_for_project(user, project=obj)
members = max(obj.memberships.count(), 1)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(obj.is_private, members, not_enough_slots_error)

if not obj.id:
obj.owner = user
Expand Down Expand Up @@ -624,13 +625,14 @@ def bulk_create(self, request, **kwargs):
# of handling explicit exception catchin here.

if "bulk_memberships" in data and isinstance(data["bulk_memberships"], list):
members = len(data["bulk_memberships"])
(enough_slots, not_enough_slots_error) = users_service.has_available_slot_for_project(
request.user,
project=project,
members=len(data["bulk_memberships"])
members=members
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(project.is_private, members, not_enough_slots_error)

try:
members = services.create_members_in_bulk(data["bulk_memberships"],
Expand Down Expand Up @@ -660,13 +662,14 @@ def pre_delete(self, obj):

def pre_save(self, obj):
if not obj.id:
members = 1
(enough_slots, not_enough_slots_error) = users_service.has_available_slot_for_project(
self.request.user,
project=obj.project,
members=1
members=members
)
if not enough_slots:
raise exc.BadRequest(not_enough_slots_error)
raise exc.NotEnoughSlotsForProject(obj.project.is_private, members, not_enough_slots_error)

if not obj.token:
obj.token = str(uuid.uuid1())
Expand Down
8 changes: 8 additions & 0 deletions tests/integration/test_importer_api.py
Expand Up @@ -91,6 +91,8 @@ def test_valid_project_without_enough_public_projects_slots(client):
assert response.status_code == 400
assert "can't have more public projects" in response.data["_error_message"]
assert Project.objects.filter(slug="public-project-without-slots").count() == 0
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "False"


def test_valid_project_without_enough_private_projects_slots(client):
Expand All @@ -110,6 +112,8 @@ def test_valid_project_without_enough_private_projects_slots(client):

assert response.status_code == 400
assert "can't have more private projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "True"
assert Project.objects.filter(slug="private-project-without-slots").count() == 0


Expand Down Expand Up @@ -1249,6 +1253,8 @@ def test_valid_dump_import_without_enough_public_projects_slots(client):
response = client.post(url, {'dump': data})
assert response.status_code == 400
assert "can't have more public projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "False"
assert Project.objects.filter(slug="public-project-without-slots").count() == 0


Expand All @@ -1269,6 +1275,8 @@ def test_valid_dump_import_without_enough_private_projects_slots(client):
response = client.post(url, {'dump': data})
assert response.status_code == 400
assert "can't have more private projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "True"
assert Project.objects.filter(slug="private-project-without-slots").count() == 0


Expand Down
8 changes: 8 additions & 0 deletions tests/integration/test_projects.py
Expand Up @@ -70,6 +70,8 @@ def test_create_private_project_without_enough_private_projects_slots(client):

assert response.status_code == 400
assert "can't have more private projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "True"


def test_create_public_project_without_enough_public_projects_slots(client):
Expand All @@ -86,6 +88,8 @@ def test_create_public_project_without_enough_public_projects_slots(client):

assert response.status_code == 400
assert "can't have more public projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "False"


def test_change_project_from_private_to_public_without_enough_public_projects_slots(client):
Expand All @@ -102,6 +106,8 @@ def test_change_project_from_private_to_public_without_enough_public_projects_sl

assert response.status_code == 400
assert "can't have more public projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "False"


def test_change_project_from_public_to_private_without_enough_private_projects_slots(client):
Expand All @@ -118,6 +124,8 @@ def test_change_project_from_public_to_private_without_enough_private_projects_s

assert response.status_code == 400
assert "can't have more private projects" in response.data["_error_message"]
assert response["Taiga-Info-Project-Memberships"] == "1"
assert response["Taiga-Info-Project-Is-Private"] == "True"


def test_create_private_project_with_enough_private_projects_slots(client):
Expand Down

0 comments on commit 2457e8b

Please sign in to comment.