Including max_public_projects and max_private_projets in importing process

remotes/origin/logger
Jesús Espino 2016-01-20 16:46:07 +01:00 committed by David Barragán Merino
parent b8fd768d01
commit 6fbf81c3d6
5 changed files with 165 additions and 10 deletions

View File

@ -36,6 +36,7 @@ from taiga.projects.models import Project, Membership
from taiga.projects.issues.models import Issue from taiga.projects.issues.models import Issue
from taiga.projects.tasks.models import Task from taiga.projects.tasks.models import Task
from taiga.projects.serializers import ProjectSerializer from taiga.projects.serializers import ProjectSerializer
from taiga.users import services as users_service
from . import mixins from . import mixins
from . import serializers from . import serializers
@ -90,6 +91,10 @@ class ProjectImporterViewSet(mixins.ImportThrottlingPolicyMixin, CreateModelMixi
data = request.DATA.copy() data = request.DATA.copy()
data['owner'] = data.get('owner', request.user.email) data['owner'] = data.get('owner', request.user.email)
is_private = data.get('is_private', False)
if not users_service.has_available_slot_for_project(self.request.user, is_private=is_private):
raise exc.BadRequest(_("The user can't have more projects of this type"))
# Create Project # Create Project
project_serialized = service.store_project(data) project_serialized = service.store_project(data)
@ -202,17 +207,22 @@ class ProjectImporterViewSet(mixins.ImportThrottlingPolicyMixin, CreateModelMixi
try: try:
dump = json.load(reader(dump)) dump = json.load(reader(dump))
is_private = dump["is_private"]
except Exception: except Exception:
raise exc.WrongArguments(_("Invalid dump format")) raise exc.WrongArguments(_("Invalid dump format"))
if Project.objects.filter(slug=dump['slug']).exists(): if Project.objects.filter(slug=dump['slug']).exists():
del dump['slug'] del dump['slug']
user = request.user
if not users_service.has_available_slot_for_project(user, is_private=is_private):
raise exc.BadRequest(_("The user can't have more projects of this type"))
if settings.CELERY_ENABLED: if settings.CELERY_ENABLED:
task = tasks.load_project_dump.delay(request.user, dump) task = tasks.load_project_dump.delay(user, dump)
return response.Accepted({"import_id": task.id}) return response.Accepted({"import_id": task.id})
project = dump_service.dict_to_project(dump, request.user.email) project = dump_service.dict_to_project(dump, request.user)
response_data = ProjectSerializer(project).data response_data = ProjectSerializer(project).data
return response.Created(response_data) return response.Created(response_data)

View File

@ -18,6 +18,7 @@
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from taiga.projects.models import Membership from taiga.projects.models import Membership
from taiga.users import services as users_service
from . import serializers from . import serializers
from . import service from . import service
@ -89,7 +90,9 @@ def store_tags_colors(project, data):
def dict_to_project(data, owner=None): def dict_to_project(data, owner=None):
if owner: if owner:
data["owner"] = owner data["owner"] = owner.email
if not users_service.has_available_slot_for_project(owner, is_private=data["is_private"]):
raise TaigaImportError(_("The user can't have more projects of this type"))
project_serialized = service.store_project(data) project_serialized = service.store_project(data)

View File

@ -25,7 +25,7 @@ from taiga.projects.models import Project
from taiga.export_import.renderers import ExportRenderer from taiga.export_import.renderers import ExportRenderer
from taiga.export_import.dump_service import dict_to_project, TaigaImportError from taiga.export_import.dump_service import dict_to_project, TaigaImportError
from taiga.export_import.service import get_errors from taiga.export_import.service import get_errors
from taiga.users.models import User
class Command(BaseCommand): class Command(BaseCommand):
args = '<dump_file> <owner-email>' args = '<dump_file> <owner-email>'
@ -58,7 +58,9 @@ class Command(BaseCommand):
except Project.DoesNotExist: except Project.DoesNotExist:
pass pass
signals.post_delete.receivers = receivers_back signals.post_delete.receivers = receivers_back
dict_to_project(data, args[1])
user = User.objects.get(email=args[1])
dict_to_project(data, user)
except TaigaImportError as e: except TaigaImportError as e:
print("ERROR:", end=" ") print("ERROR:", end=" ")
print(e.message) print(e.message)

View File

@ -79,7 +79,7 @@ def delete_project_dump(project_id, project_slug, task_id):
@app.task @app.task
def load_project_dump(user, dump): def load_project_dump(user, dump):
try: try:
project = dict_to_project(dump, user.email) project = dict_to_project(dump, user)
except Exception: except Exception:
ctx = { ctx = {
"user": user, "user": user,

View File

@ -23,6 +23,7 @@ from django.core.urlresolvers import reverse
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from taiga.base.utils import json from taiga.base.utils import json
from taiga.export_import.dump_service import dict_to_project, TaigaImportError
from taiga.projects.models import Project, Membership from taiga.projects.models import Project, Membership
from taiga.projects.issues.models import Issue from taiga.projects.issues.models import Issue
from taiga.projects.userstories.models import UserStory from taiga.projects.userstories.models import UserStory
@ -72,6 +73,85 @@ def test_valid_project_import_without_extra_data(client):
assert response_data["watchers"] == [user.email, user_watching.email] assert response_data["watchers"] == [user.email, user_watching.email]
def test_valid_project_without_enough_public_projects_slots(client):
user = f.UserFactory.create(max_public_projects=0)
url = reverse("importer-list")
data = {
"slug": "public-project-without-slots",
"name": "Imported project",
"description": "Imported project",
"roles": [{"name": "Role"}],
"is_private": False
}
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 400
assert "can't have more projects" in response.data["_error_message"]
assert Project.objects.filter(slug="public-project-without-slots").count() == 0
def test_valid_project_without_enough_private_projects_slots(client):
user = f.UserFactory.create(max_private_projects=0)
url = reverse("importer-list")
data = {
"slug": "private-project-without-slots",
"name": "Imported project",
"description": "Imported project",
"roles": [{"name": "Role"}],
"is_private": True
}
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 400
assert "can't have more projects" in response.data["_error_message"]
assert Project.objects.filter(slug="private-project-without-slots").count() == 0
def test_valid_project_with_enough_public_projects_slots(client):
user = f.UserFactory.create(max_public_projects=1)
url = reverse("importer-list")
data = {
"slug": "public-project-with-slots",
"name": "Imported project",
"description": "Imported project",
"roles": [{"name": "Role"}],
"is_private": False
}
client.login(user)
response = client.json.post(url, json.dumps(data))
print(response.content)
assert response.status_code == 201
assert Project.objects.filter(slug="public-project-with-slots").count() == 1
def test_valid_project_with_enough_private_projects_slots(client):
user = f.UserFactory.create(max_private_projects=1)
url = reverse("importer-list")
data = {
"slug": "private-project-with-slots",
"name": "Imported project",
"description": "Imported project",
"roles": [{"name": "Role"}],
"is_private": True
}
client.login(user)
response = client.json.post(url, json.dumps(data))
assert response.status_code == 201
assert Project.objects.filter(slug="private-project-with-slots").count() == 1
def test_valid_project_import_with_not_existing_memberships(client): def test_valid_project_import_with_not_existing_memberships(client):
user = f.UserFactory.create() user = f.UserFactory.create()
client.login(user) client.login(user)
@ -930,6 +1010,22 @@ def test_milestone_import_duplicated_milestone(client):
assert response_data["milestones"][0]["name"][0] == "Name duplicated for the project" assert response_data["milestones"][0]["name"][0] == "Name duplicated for the project"
def test_dict_to_project_with_no_slots_available(client):
user = f.UserFactory.create(max_private_projects=0)
data = {
"slug": "valid-project",
"name": "Valid project",
"description": "Valid project desc",
"is_private": True
}
with pytest.raises(TaigaImportError) as excinfo:
project = dict_to_project(data, owner=user)
assert "can't have more projects" in str(excinfo.value)
def test_invalid_dump_import(client): def test_invalid_dump_import(client):
user = f.UserFactory.create() user = f.UserFactory.create()
client.login(user) client.login(user)
@ -986,7 +1082,8 @@ def test_valid_dump_import_with_celery_disabled(client, settings):
data = ContentFile(bytes(json.dumps({ data = ContentFile(bytes(json.dumps({
"slug": "valid-project", "slug": "valid-project",
"name": "Valid project", "name": "Valid project",
"description": "Valid project desc" "description": "Valid project desc",
"is_private": True
}), "utf-8")) }), "utf-8"))
data.name = "test" data.name = "test"
@ -1008,7 +1105,8 @@ def test_valid_dump_import_with_celery_enabled(client, settings):
data = ContentFile(bytes(json.dumps({ data = ContentFile(bytes(json.dumps({
"slug": "valid-project", "slug": "valid-project",
"name": "Valid project", "name": "Valid project",
"description": "Valid project desc" "description": "Valid project desc",
"is_private": True
}), "utf-8")) }), "utf-8"))
data.name = "test" data.name = "test"
@ -1028,7 +1126,8 @@ def test_dump_import_duplicated_project(client):
data = ContentFile(bytes(json.dumps({ data = ContentFile(bytes(json.dumps({
"slug": project.slug, "slug": project.slug,
"name": "Test import", "name": "Test import",
"description": "Valid project desc" "description": "Valid project desc",
"is_private": True
}), "utf-8")) }), "utf-8"))
data.name = "test" data.name = "test"
@ -1051,7 +1150,8 @@ def test_dump_import_throttling(client, settings):
data = ContentFile(bytes(json.dumps({ data = ContentFile(bytes(json.dumps({
"slug": project.slug, "slug": project.slug,
"name": "Test import", "name": "Test import",
"description": "Valid project desc" "description": "Valid project desc",
"is_private": True
}), "utf-8")) }), "utf-8"))
data.name = "test" data.name = "test"
@ -1059,3 +1159,43 @@ def test_dump_import_throttling(client, settings):
assert response.status_code == 201 assert response.status_code == 201
response = client.post(url, {'dump': data}) response = client.post(url, {'dump': data})
assert response.status_code == 429 assert response.status_code == 429
def test_valid_dump_import_without_enough_public_projects_slots(client):
user = f.UserFactory.create(max_public_projects=0)
client.login(user)
url = reverse("importer-load-dump")
data = ContentFile(bytes(json.dumps({
"slug": "public-project-without-slots",
"name": "Valid project",
"description": "Valid project desc",
"is_private": False
}), "utf-8"))
data.name = "test"
response = client.post(url, {'dump': data})
assert response.status_code == 400
assert "can't have more projects" in response.data["_error_message"]
assert Project.objects.filter(slug="public-project-without-slots").count() == 0
def test_valid_dump_import_without_enough_private_projects_slots(client):
user = f.UserFactory.create(max_private_projects=0)
client.login(user)
url = reverse("importer-load-dump")
data = ContentFile(bytes(json.dumps({
"slug": "private-project-without-slots",
"name": "Valid project",
"description": "Valid project desc",
"is_private": True
}), "utf-8"))
data.name = "test"
response = client.post(url, {'dump': data})
assert response.status_code == 400
assert "can't have more projects" in response.data["_error_message"]
assert Project.objects.filter(slug="private-project-without-slots").count() == 0