Including max_public_projects and max_private_projets in importing process
parent
b8fd768d01
commit
6fbf81c3d6
|
@ -36,6 +36,7 @@ from taiga.projects.models import Project, Membership
|
|||
from taiga.projects.issues.models import Issue
|
||||
from taiga.projects.tasks.models import Task
|
||||
from taiga.projects.serializers import ProjectSerializer
|
||||
from taiga.users import services as users_service
|
||||
|
||||
from . import mixins
|
||||
from . import serializers
|
||||
|
@ -90,6 +91,10 @@ class ProjectImporterViewSet(mixins.ImportThrottlingPolicyMixin, CreateModelMixi
|
|||
data = request.DATA.copy()
|
||||
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
|
||||
project_serialized = service.store_project(data)
|
||||
|
||||
|
@ -202,17 +207,22 @@ class ProjectImporterViewSet(mixins.ImportThrottlingPolicyMixin, CreateModelMixi
|
|||
|
||||
try:
|
||||
dump = json.load(reader(dump))
|
||||
is_private = dump["is_private"]
|
||||
except Exception:
|
||||
raise exc.WrongArguments(_("Invalid dump format"))
|
||||
|
||||
if Project.objects.filter(slug=dump['slug']).exists():
|
||||
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:
|
||||
task = tasks.load_project_dump.delay(request.user, dump)
|
||||
task = tasks.load_project_dump.delay(user, dump)
|
||||
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
|
||||
return response.Created(response_data)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
from django.utils.translation import ugettext as _
|
||||
|
||||
from taiga.projects.models import Membership
|
||||
from taiga.users import services as users_service
|
||||
|
||||
from . import serializers
|
||||
from . import service
|
||||
|
@ -89,7 +90,9 @@ def store_tags_colors(project, data):
|
|||
|
||||
def dict_to_project(data, owner=None):
|
||||
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)
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ from taiga.projects.models import Project
|
|||
from taiga.export_import.renderers import ExportRenderer
|
||||
from taiga.export_import.dump_service import dict_to_project, TaigaImportError
|
||||
from taiga.export_import.service import get_errors
|
||||
|
||||
from taiga.users.models import User
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = '<dump_file> <owner-email>'
|
||||
|
@ -58,7 +58,9 @@ class Command(BaseCommand):
|
|||
except Project.DoesNotExist:
|
||||
pass
|
||||
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:
|
||||
print("ERROR:", end=" ")
|
||||
print(e.message)
|
||||
|
|
|
@ -79,7 +79,7 @@ def delete_project_dump(project_id, project_slug, task_id):
|
|||
@app.task
|
||||
def load_project_dump(user, dump):
|
||||
try:
|
||||
project = dict_to_project(dump, user.email)
|
||||
project = dict_to_project(dump, user)
|
||||
except Exception:
|
||||
ctx = {
|
||||
"user": user,
|
||||
|
|
|
@ -23,6 +23,7 @@ from django.core.urlresolvers import reverse
|
|||
from django.core.files.base import ContentFile
|
||||
|
||||
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.issues.models import Issue
|
||||
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]
|
||||
|
||||
|
||||
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):
|
||||
user = f.UserFactory.create()
|
||||
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"
|
||||
|
||||
|
||||
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):
|
||||
user = f.UserFactory.create()
|
||||
client.login(user)
|
||||
|
@ -986,7 +1082,8 @@ def test_valid_dump_import_with_celery_disabled(client, settings):
|
|||
data = ContentFile(bytes(json.dumps({
|
||||
"slug": "valid-project",
|
||||
"name": "Valid project",
|
||||
"description": "Valid project desc"
|
||||
"description": "Valid project desc",
|
||||
"is_private": True
|
||||
}), "utf-8"))
|
||||
data.name = "test"
|
||||
|
||||
|
@ -1008,7 +1105,8 @@ def test_valid_dump_import_with_celery_enabled(client, settings):
|
|||
data = ContentFile(bytes(json.dumps({
|
||||
"slug": "valid-project",
|
||||
"name": "Valid project",
|
||||
"description": "Valid project desc"
|
||||
"description": "Valid project desc",
|
||||
"is_private": True
|
||||
}), "utf-8"))
|
||||
data.name = "test"
|
||||
|
||||
|
@ -1028,7 +1126,8 @@ def test_dump_import_duplicated_project(client):
|
|||
data = ContentFile(bytes(json.dumps({
|
||||
"slug": project.slug,
|
||||
"name": "Test import",
|
||||
"description": "Valid project desc"
|
||||
"description": "Valid project desc",
|
||||
"is_private": True
|
||||
}), "utf-8"))
|
||||
data.name = "test"
|
||||
|
||||
|
@ -1051,7 +1150,8 @@ def test_dump_import_throttling(client, settings):
|
|||
data = ContentFile(bytes(json.dumps({
|
||||
"slug": project.slug,
|
||||
"name": "Test import",
|
||||
"description": "Valid project desc"
|
||||
"description": "Valid project desc",
|
||||
"is_private": True
|
||||
}), "utf-8"))
|
||||
data.name = "test"
|
||||
|
||||
|
@ -1059,3 +1159,43 @@ def test_dump_import_throttling(client, settings):
|
|||
assert response.status_code == 201
|
||||
response = client.post(url, {'dump': data})
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue