Add 'max_memberships', 'total_memberships' and 'can_is_private_be_updated' to the project serializer
parent
2176e9a0af
commit
f502a538c2
|
@ -109,6 +109,7 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin,
|
||||||
# Prefetch doesn"t work correctly if then if the field is filtered later (it generates more queries)
|
# Prefetch doesn"t work correctly if then if the field is filtered later (it generates more queries)
|
||||||
# so we add some custom prefetching
|
# so we add some custom prefetching
|
||||||
qs = qs.prefetch_related("members")
|
qs = qs.prefetch_related("members")
|
||||||
|
qs = qs.prefetch_related("memberships")
|
||||||
qs = qs.prefetch_related(Prefetch("notify_policies",
|
qs = qs.prefetch_related(Prefetch("notify_policies",
|
||||||
NotifyPolicy.objects.exclude(notify_level=NotifyLevel.none), to_attr="valid_notify_policies"))
|
NotifyPolicy.objects.exclude(notify_level=NotifyLevel.none), to_attr="valid_notify_policies"))
|
||||||
|
|
||||||
|
|
|
@ -352,11 +352,24 @@ class ProjectDetailSerializer(ProjectSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ProjectDetailAdminSerializer(ProjectDetailSerializer):
|
class ProjectDetailAdminSerializer(ProjectDetailSerializer):
|
||||||
|
max_memberships = serializers.SerializerMethodField(method_name="get_max_memberships")
|
||||||
|
total_memberships = serializers.SerializerMethodField(method_name="get_total_memberships")
|
||||||
|
can_is_private_be_updated = serializers.SerializerMethodField(method_name="get_can_is_private_be_updated")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Project
|
model = models.Project
|
||||||
read_only_fields = ("created_date", "modified_date", "slug", "blocked_code")
|
read_only_fields = ("created_date", "modified_date", "slug", "blocked_code")
|
||||||
exclude = ("logo", "last_us_ref", "last_task_ref", "last_issue_ref")
|
exclude = ("logo", "last_us_ref", "last_task_ref", "last_issue_ref")
|
||||||
|
|
||||||
|
def get_max_memberships(self, obj):
|
||||||
|
return services.get_max_memberships_for_project(obj)
|
||||||
|
|
||||||
|
def get_total_memberships(self, obj):
|
||||||
|
return services.get_total_project_memberships(obj)
|
||||||
|
|
||||||
|
def get_can_is_private_be_updated(self, obj):
|
||||||
|
return services.check_if_project_privacity_can_be_changed(obj)
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
## Liked
|
## Liked
|
||||||
|
|
|
@ -38,6 +38,8 @@ from .logo import get_logo_big_thumbnail_url
|
||||||
from .members import create_members_in_bulk
|
from .members import create_members_in_bulk
|
||||||
from .members import get_members_from_bulk
|
from .members import get_members_from_bulk
|
||||||
from .members import remove_user_from_project, project_has_valid_admins, can_user_leave_project
|
from .members import remove_user_from_project, project_has_valid_admins, can_user_leave_project
|
||||||
|
from .members import get_max_memberships_for_project, get_total_project_memberships
|
||||||
|
from .members import check_if_project_privacity_can_be_changed
|
||||||
|
|
||||||
from .modules_config import get_modules_config
|
from .modules_config import get_modules_config
|
||||||
|
|
||||||
|
|
|
@ -60,3 +60,52 @@ def can_user_leave_project(user, project):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_max_memberships_for_project(project):
|
||||||
|
"""Return tha maximun of membersh for a concrete project.
|
||||||
|
|
||||||
|
:param project: A project object.
|
||||||
|
|
||||||
|
:return: a number or null.
|
||||||
|
"""
|
||||||
|
if project.is_private:
|
||||||
|
return project.owner.max_memberships_private_projects
|
||||||
|
return project.owner.max_memberships_public_projects
|
||||||
|
|
||||||
|
|
||||||
|
def get_total_project_memberships(project):
|
||||||
|
"""Return tha total of memberships of a project (members and unaccepted invitations).
|
||||||
|
|
||||||
|
:param project: A project object.
|
||||||
|
|
||||||
|
:return: a number.
|
||||||
|
"""
|
||||||
|
return project.memberships.count()
|
||||||
|
|
||||||
|
|
||||||
|
def check_if_project_privacity_can_be_changed(project):
|
||||||
|
"""Return if the project privacity can be changed from private to public or viceversa.
|
||||||
|
|
||||||
|
:param project: A project object.
|
||||||
|
|
||||||
|
:return: True if it can be changed or False if can't.
|
||||||
|
"""
|
||||||
|
if project.is_private:
|
||||||
|
current_projects = project.owner.owned_projects.filter(is_private=False).count()
|
||||||
|
max_projects = project.owner.max_public_projects
|
||||||
|
max_memberships = project.owner.max_memberships_public_projects
|
||||||
|
else:
|
||||||
|
current_projects = project.owner.owned_projects.filter(is_private=True).count()
|
||||||
|
max_projects = project.owner.max_private_projects
|
||||||
|
max_memberships = project.owner.max_memberships_private_projects
|
||||||
|
|
||||||
|
if max_projects is not None and current_projects >= max_projects:
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_memberships = project.memberships.count()
|
||||||
|
|
||||||
|
if max_memberships is not None and current_memberships > max_memberships:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
|
@ -1393,3 +1393,195 @@ def test_project_transfer_validate_token_from_admin_member_with_valid_token(clie
|
||||||
response = client.json.post(url, json.dumps(data))
|
response = client.json.post(url, json.dumps(data))
|
||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
####################################################################################
|
||||||
|
# Test taiga.projects.services.members.check_if_project_privacity_can_be_changed
|
||||||
|
####################################################################################
|
||||||
|
|
||||||
|
from taiga.projects.services import check_if_project_privacity_can_be_changed
|
||||||
|
|
||||||
|
# private to public
|
||||||
|
|
||||||
|
def test_private_project_cant_be_public_because_owner_doesnt_have_enought_slot_and_too_much_members(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = 0
|
||||||
|
project.owner.max_memberships_public_projects = 3
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_cant_be_public_because_owner_doesnt_have_enought_slot(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = 0
|
||||||
|
project.owner.max_memberships_public_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_cant_be_public_because_too_much_members(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = 2
|
||||||
|
project.owner.max_memberships_public_projects = 3
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_can_be_public_because_owner_has_enought_slot_and_project_has_enought_members(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = 2
|
||||||
|
project.owner.max_memberships_public_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_can_be_public_because_owner_has_unlimited_slot_and_project_has_unlimited_members(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = None
|
||||||
|
project.owner.max_memberships_public_projects = None
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_can_be_public_because_owner_has_unlimited_slot(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = None
|
||||||
|
project.owner.max_memberships_public_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_private_project_can_be_public_because_project_has_unlimited_members(client):
|
||||||
|
project = f.create_project(is_private=True)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_public_projects = 2
|
||||||
|
project.owner.max_memberships_public_projects = None
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
# public to private
|
||||||
|
|
||||||
|
def test_public_project_cant_be_private_because_owner_doesnt_have_enought_slot_and_too_much_members(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = 0
|
||||||
|
project.owner.max_memberships_private_projects = 3
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_cant_be_private_because_owner_doesnt_have_enought_slot(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = 0
|
||||||
|
project.owner.max_memberships_private_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_cant_be_private_because_too_much_members(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = 2
|
||||||
|
project.owner.max_memberships_private_projects = 3
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_can_be_private_because_owner_has_enought_slot_and_project_has_enought_members(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = 2
|
||||||
|
project.owner.max_memberships_private_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_can_be_private_because_owner_has_unlimited_slot_and_project_has_unlimited_members(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = None
|
||||||
|
project.owner.max_memberships_private_projects = None
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_can_be_private_because_owner_has_unlimited_slot(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = None
|
||||||
|
project.owner.max_memberships_private_projects = 6
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
||||||
|
|
||||||
|
def test_public_project_can_be_private_because_project_has_unlimited_members(client):
|
||||||
|
project = f.create_project(is_private=False)
|
||||||
|
f.MembershipFactory(project=project, user=project.owner)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
f.MembershipFactory(project=project)
|
||||||
|
|
||||||
|
project.owner.max_private_projects = 2
|
||||||
|
project.owner.max_memberships_private_projects = None
|
||||||
|
|
||||||
|
assert check_if_project_privacity_can_be_changed(project) == True
|
||||||
|
|
Loading…
Reference in New Issue