diff --git a/taiga/permissions/service.py b/taiga/permissions/service.py index a430e082..adf8cb38 100644 --- a/taiga/permissions/service.py +++ b/taiga/permissions/service.py @@ -37,6 +37,20 @@ def _get_object_project(obj): return project +def is_project_owner(user, obj): + if user.is_superuser: + return True + + project = _get_object_project(obj) + if project is None: + return False + + if user.id == project.owner.id: + return True + + return False + + def is_project_admin(user, obj): if user.is_superuser: return True diff --git a/taiga/projects/api.py b/taiga/projects/api.py index b7a712f4..6d057807 100644 --- a/taiga/projects/api.py +++ b/taiga/projects/api.py @@ -104,6 +104,7 @@ class ProjectViewSet(LikedResourceMixin, HistoryResourceMixin, def get_queryset(self): qs = super().get_queryset() + qs = qs.select_related("owner") # Prefetch doesn"t work correctly if then if the field is filtered later (it generates more queries) # so we add some custom prefetching qs = qs.prefetch_related("members") diff --git a/taiga/projects/serializers.py b/taiga/projects/serializers.py index 5650b351..e892f93e 100644 --- a/taiga/projects/serializers.py +++ b/taiga/projects/serializers.py @@ -33,7 +33,7 @@ from taiga.users.serializers import ProjectRoleSerializer from taiga.users.validators import RoleExistsValidator from taiga.permissions.service import get_user_project_permissions -from taiga.permissions.service import is_project_admin +from taiga.permissions.service import is_project_admin, is_project_owner from taiga.projects.mixins.serializers import ValidateDuplicatedNameInProjectMixin from . import models @@ -130,6 +130,7 @@ class MembershipSerializer(serializers.ModelSerializer): project_name = serializers.SerializerMethodField("get_project_name") project_slug = serializers.SerializerMethodField("get_project_slug") invited_by = UserBasicInfoSerializer(read_only=True) + is_owner = serializers.SerializerMethodField("get_is_owner") class Meta: model = models.Membership @@ -147,6 +148,10 @@ class MembershipSerializer(serializers.ModelSerializer): def get_project_slug(self, obj): return obj.project.slug if obj and obj.project else "" + def get_is_owner(self, obj): + return (obj and obj.user_id and obj.project_id and obj.project.owner_id and + obj.user_id == obj.project.owner_id) + def validate_email(self, attrs, source): project = attrs.get("project", None) if project is None: @@ -241,6 +246,9 @@ class ProjectSerializer(FanResourceSerializerMixin, WatchedResourceModelSerializ anon_permissions = PgArrayField(required=False) public_permissions = PgArrayField(required=False) my_permissions = serializers.SerializerMethodField("get_my_permissions") + + owner = UserBasicInfoSerializer(read_only=True) + i_am_owner = serializers.SerializerMethodField("get_i_am_owner") i_am_admin = serializers.SerializerMethodField("get_i_am_admin") i_am_member = serializers.SerializerMethodField("get_i_am_member") @@ -256,7 +264,7 @@ class ProjectSerializer(FanResourceSerializerMixin, WatchedResourceModelSerializ class Meta: model = models.Project - read_only_fields = ("created_date", "modified_date", "owner", "slug", "blocked_code") + read_only_fields = ("created_date", "modified_date", "slug", "blocked_code") exclude = ("logo", "last_us_ref", "last_task_ref", "last_issue_ref", "issues_csv_uuid", "tasks_csv_uuid", "userstories_csv_uuid", "transfer_token") @@ -266,6 +274,11 @@ class ProjectSerializer(FanResourceSerializerMixin, WatchedResourceModelSerializ return get_user_project_permissions(self.context["request"].user, obj) return [] + def get_i_am_owner(self, obj): + if "request" in self.context: + return is_project_owner(self.context["request"].user, obj) + return False + def get_i_am_admin(self, obj): if "request" in self.context: return is_project_admin(self.context["request"].user, obj) @@ -341,7 +354,7 @@ class ProjectDetailSerializer(ProjectSerializer): class ProjectDetailAdminSerializer(ProjectDetailSerializer): class Meta: model = models.Project - read_only_fields = ("created_date", "modified_date", "owner", "slug", "blocked_code") + read_only_fields = ("created_date", "modified_date", "slug", "blocked_code") exclude = ("logo", "last_us_ref", "last_task_ref", "last_issue_ref") diff --git a/taiga/users/serializers.py b/taiga/users/serializers.py index 204852ad..55473a30 100644 --- a/taiga/users/serializers.py +++ b/taiga/users/serializers.py @@ -133,7 +133,7 @@ class UserAdminSerializer(UserSerializer): class UserBasicInfoSerializer(UserSerializer): class Meta: model = User - fields = ("username", "full_name_display","photo", "big_photo", "is_active") + fields = ("username", "full_name_display","photo", "big_photo", "is_active", "id") class RecoverySerializer(serializers.Serializer):