diff --git a/todo/services/team_service.py b/todo/services/team_service.py index a8a3c736..0a3698b7 100644 --- a/todo/services/team_service.py +++ b/todo/services/team_service.py @@ -6,7 +6,7 @@ from todo.models.common.pyobjectid import PyObjectId from todo.repositories.team_creation_invite_code_repository import TeamCreationInviteCodeRepository from todo.repositories.team_repository import TeamRepository, UserTeamDetailsRepository -from todo.constants.messages import AppMessages +from todo.constants.messages import AppMessages, ApiErrors from todo.constants.role import RoleName from todo.utils.invite_code_utils import generate_invite_code from typing import List @@ -345,6 +345,9 @@ def update_team(cls, team_id: str, dto: UpdateTeamDTO, updated_by_user_id: str) if not existing_team: raise ValueError(f"Team with id {team_id} not found") + if dto.poc_id is not None: + cls._validate_poc_update_permissions(team_id, updated_by_user_id, existing_team) + # Prepare update data update_data = {} if dto.name is not None: @@ -507,6 +510,16 @@ def _validate_remove_member_permissions(cls, user_id: str, team_id: str, removed if not UserRoleService.has_role(removed_by_user_id, RoleName.ADMIN.value, RoleScope.TEAM.value, team_id): raise NotTeamAdminException() + @classmethod + def _validate_poc_update_permissions(cls, team_id: str, updated_by_user_id: str, team): + if str(team.created_by) == updated_by_user_id: + return + + if UserRoleService.has_role(updated_by_user_id, RoleName.ADMIN.value, RoleScope.TEAM.value, team_id): + return + + raise PermissionError(ApiErrors.UNAUTHORIZED_TITLE) + @classmethod def remove_member_from_team(cls, user_id: str, team_id: str, removed_by_user_id: str): cls._validate_remove_member_permissions(user_id, team_id, removed_by_user_id) diff --git a/todo/tests/unit/services/test_team_service.py b/todo/tests/unit/services/test_team_service.py index 6e3b8f30..400bcf4f 100644 --- a/todo/tests/unit/services/test_team_service.py +++ b/todo/tests/unit/services/test_team_service.py @@ -2,6 +2,7 @@ from unittest.mock import patch from datetime import datetime, timezone +from todo.constants.messages import ApiErrors from todo.exceptions.team_exceptions import ( CannotRemoveOwnerException, CannotRemoveTeamPOCException, @@ -13,6 +14,7 @@ from todo.models.common.pyobjectid import PyObjectId from todo.dto.user_dto import UserDTO from todo.dto.team_dto import TeamDTO +from todo.constants.role import RoleName, RoleScope class TeamServiceTests(TestCase): @@ -300,3 +302,21 @@ def test_user_can_remove_themselves( self.assertEqual(log_entry.action, "member_left_team") self.assertEqual(str(log_entry.team_id), self.team_id) self.assertEqual(str(log_entry.performed_by), self.member_id) + + @patch("todo.services.team_service.UserRoleService.has_role") + def test_poc_update_permissions_team_admin_success(self, mock_has_role): + mock_has_role.return_value = True + + result = TeamService._validate_poc_update_permissions(self.team_id, self.admin_id, self.team_model) + self.assertIsNone(result) + mock_has_role.assert_called_once_with(self.admin_id, RoleName.ADMIN.value, RoleScope.TEAM.value, self.team_id) + + @patch("todo.services.team_service.UserRoleService.has_role") + def test_poc_update_permissions_regular_member_fails(self, mock_has_role): + mock_has_role.return_value = False + + with self.assertRaises(PermissionError) as context: + TeamService._validate_poc_update_permissions(self.team_id, self.member_id, self.team_model) + + self.assertIn(ApiErrors.UNAUTHORIZED_TITLE, str(context.exception)) + mock_has_role.assert_called_once_with(self.member_id, RoleName.ADMIN.value, RoleScope.TEAM.value, self.team_id)