def is_user_action_permitted_on_project(authenticated_user_id: int,
                                            project_id: int) -> bool:
        """ Is user action permitted on project"""
        project = Project.get(project_id)
        author_id = project.author_id
        allowed_roles = [TeamRoles.PROJECT_MANAGER.value]

        is_admin = UserService.is_user_an_admin(authenticated_user_id)
        is_author = UserService.is_user_the_project_author(
            authenticated_user_id, author_id)
        is_org_manager = False
        if hasattr(project, "organisation_id") and project.organisation_id:
            org_id = project.organisation_id
            org = OrganisationService.get_organisation_by_id_as_dto(
                org_id, authenticated_user_id)
            if org.is_manager:
                is_org_manager = True

        is_manager_team = None
        if hasattr(project, "project_teams") and project.project_teams:
            teams_dto = TeamService.get_project_teams_as_dto(project_id)
            if teams_dto.teams:
                teams_allowed = [
                    team_dto for team_dto in teams_dto.teams
                    if team_dto.role in allowed_roles
                ]
                user_membership = [
                    team_dto.team_id for team_dto in teams_allowed
                    if TeamService.is_user_member_of_team(
                        team_dto.team_id, authenticated_user_id)
                ]
                if user_membership:
                    is_manager_team = True

        return is_admin or is_author or is_org_manager or is_manager_team
示例#2
0
    def test_add_team_project(self):
        team_id = 1
        user_id = 123
        function = 1
        active = True

        with self.assertRaises(TeamServiceError):
            TeamService.add_team_member(team_id, user_id, function, active)
示例#3
0
    def test_get_team_as_dto(self):
        team_id = 1
        user_id = 123
        abbreviated = False

        result = TeamService.get_team_as_dto(team_id, user_id, abbreviated)
        self.assertEqual(result.team_id, 1)
示例#4
0
    def evaluate_mapping_permission(
        project_id: int, user_id: int, mapping_permission: int
    ):
        allowed_roles = [
            TeamRoles.MAPPER.value,
            TeamRoles.VALIDATOR.value,
            TeamRoles.PROJECT_MANAGER.value,
        ]
        is_team_member = TeamService.check_team_membership(
            project_id, allowed_roles, user_id
        )

        # mapping_permission = 1(level),2(teams),3(teamsAndLevel)
        if mapping_permission == MappingPermission.TEAMS.value:
            if not is_team_member:
                return False, MappingNotAllowed.USER_NOT_TEAM_MEMBER

        elif mapping_permission == MappingPermission.LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, MappingNotAllowed.USER_NOT_CORRECT_MAPPING_LEVEL

        elif mapping_permission == MappingPermission.TEAMS_LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, MappingNotAllowed.USER_NOT_CORRECT_MAPPING_LEVEL
            if not is_team_member:
                return False, MappingNotAllowed.USER_NOT_TEAM_MEMBER
示例#5
0
    def get_project_dto_for_mapper(
        project_id, current_user_id, locale="en", abbrev=False
    ) -> ProjectDTO:
        """
        Get the project DTO for mappers
        :param project_id: ID of the Project mapper has requested
        :param locale: Locale the mapper has requested
        :raises ProjectServiceError, NotFound
        """
        project = ProjectService.get_project_by_id(project_id)
        # if project is public and is not draft, we don't need to check permissions
        if not project.private and not project.status == ProjectStatus.DRAFT.value:
            return project.as_dto_for_mapping(current_user_id, locale, abbrev)

        is_allowed_user = True
        is_team_member = None
        is_manager_permission = False

        if current_user_id:
            is_manager_permission = ProjectAdminService.is_user_action_permitted_on_project(
                current_user_id, project_id
            )
        # Draft Projects - admins, authors, org admins & team managers permitted
        if project.status == ProjectStatus.DRAFT.value:
            if not is_manager_permission:
                is_allowed_user = False
                raise ProjectServiceError("Unable to fetch project")

        # Private Projects - allowed_users, admins, org admins &
        # assigned teams (mappers, validators, project managers), authors permitted

        if project.private and not is_manager_permission:
            is_allowed_user = False
            if current_user_id:
                is_allowed_user = (
                    len(
                        [
                            user
                            for user in project.allowed_users
                            if user.id == current_user_id
                        ]
                    )
                    > 0
                )

        if not (is_allowed_user or is_manager_permission):
            if current_user_id:
                allowed_roles = [
                    TeamRoles.MAPPER.value,
                    TeamRoles.VALIDATOR.value,
                    TeamRoles.PROJECT_MANAGER.value,
                ]
                is_team_member = TeamService.check_team_membership(
                    project_id, allowed_roles, current_user_id
                )

        if is_allowed_user or is_manager_permission or is_team_member:
            return project.as_dto_for_mapping(current_user_id, locale, abbrev)
        else:
            raise ProjectServiceError("Unable to fetch project")
 def delete(self, team_id, project_id):
     """
     Deletes the specified team project assignment
     ---
     tags:
       - teams
     produces:
       - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           required: true
           type: string
           default: Token sessionTokenHere==
         - name: message_id
           in: path
           description: Unique message ID
           required: true
           type: integer
           default: 1
     responses:
         200:
             description: Team unassigned of the project
         401:
             description: Forbidden, if user is not a manager of the project
         403:
             description: Forbidden, if user is not authenticated
         404:
             description: Not found
         500:
             description: Internal Server Error
     """
     if not TeamService.is_user_team_manager(team_id,
                                             token_auth.current_user()):
         return {
             "Error": "User is not an admin or a manager for the team"
         }, 401
     try:
         TeamService.delete_team_project(team_id, project_id)
         return {"Success": True}, 200
     except NotFound:
         return {"Error": "No team found"}, 404
     except Exception as e:
         error_msg = f"TeamMembers DELETE - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
示例#7
0
 def check_team_membership(
     project_id: int, allowed_roles: list, user_id: int, action: str
 ):
     teams_dto = TeamService.get_project_teams_as_dto(project_id)
     teams_allowed = [
         team_dto for team_dto in teams_dto.teams if team_dto.role in allowed_roles
     ]
     user_membership = [
         team_dto.team_id
         for team_dto in teams_allowed
         if TeamService.is_user_member_of_team(team_dto.team_id, user_id)
     ]
     if len(user_membership) == 0:
         if action == "MAP":
             return False, MappingNotAllowed.USER_NOT_TEAM_MEMBER
         elif action == "VALIDATE":
             return False, ValidatingNotAllowed.USER_NOT_TEAM_MEMBER
示例#8
0
 def delete(self, team_id):
     """
     Deletes a Team
     ---
     tags:
         - teams
     produces:
         - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           required: true
           type: string
           default: Token sessionTokenHere==
         - name: team_id
           in: path
           description: The unique team ID
           required: true
           type: integer
           default: 1
     responses:
         200:
             description: Team deleted
         401:
             description: Unauthorized - Invalid credentials
         403:
             description: Forbidden - Team has associated projects
         404:
             description: Team not found
         500:
             description: Internal Server Error
     """
     if not TeamService.is_user_team_manager(team_id,
                                             token_auth.current_user()):
         return {"Error": "User is not a manager for the team"}, 401
     try:
         TeamService.delete_team(team_id)
         return {"Success": "Team deleted"}, 200
     except NotFound:
         return {"Error": "Team Not Found"}, 404
     except Exception as e:
         error_msg = f"Team DELETE - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
    def evaluate_mapping_permission(project_id: int, user_id: int,
                                    mapping_permission: int):
        allowed_roles = [
            TeamRoles.MAPPER.value,
            TeamRoles.VALIDATOR.value,
            TeamRoles.PROJECT_MANAGER.value,
        ]
        # mapping_permission = 1(level),2(teams),3(teamsAndLevel)
        if mapping_permission == MappingPermission.TEAMS.value:
            teams_dto = TeamService.get_project_teams_as_dto(project_id)
            teams_allowed = [
                team_dto for team_dto in teams_dto.teams
                if team_dto.role in allowed_roles
            ]
            user_membership = [
                team_dto.team_id for team_dto in teams_allowed if
                TeamService.is_user_member_of_team(team_dto.team_id, user_id)
            ]
            if len(user_membership) == 0:
                return False, MappingNotAllowed.USER_NOT_TEAM_MEMBER

        elif mapping_permission == MappingPermission.LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, MappingNotAllowed.USER_NOT_CORRECT_MAPPING_LEVEL

        elif mapping_permission == MappingPermission.TEAMS_LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, MappingNotAllowed.USER_NOT_CORRECT_MAPPING_LEVEL

            teams_dto = TeamService.get_project_teams_as_dto(project_id)
            teams_allowed = [
                team_dto for team_dto in teams_dto.teams
                if team_dto.role in allowed_roles
            ]
            user_membership = [
                team_dto.team_id for team_dto in teams_allowed if
                TeamService.is_user_member_of_team(team_dto.team_id, user_id)
            ]

            if len(user_membership) == 0:
                return False, MappingNotAllowed.USER_NOT_TEAM_MEMBER
示例#10
0
 def test_search_team(self):
     filters = {
         "user_id": 123,
         "team_name_filter": "TM3-validators",
         "team_role_filter": "MAPPER",
         "member_filter": 123,
         "member_request_filter": 123,
         "manager_filter": 123,
         "organisation_filter": 1,
         "omit_members": False,
     }
     result = TeamService.get_all_teams(**filters)
     self.assertEqual(result.to_primitive(), {"teams": []})
示例#11
0
 def get(self, team_id):
     """
     Retrieves a Team
     ---
     tags:
         - teams
     produces:
         - application/json
     parameters:
         - name: team_id
           in: path
           description: Unique team ID
           required: true
           type: integer
           default: 1
         - in: query
           name: omitMemberList
           type: boolean
           description: Set it to true if you don't want the members list on the response.
           default: False
     responses:
         200:
             description: Team found
         401:
             description: Unauthorized - Invalid credentials
         404:
             description: Team not found
         500:
             description: Internal Server Error
     """
     try:
         authenticated_user_id = token_auth.current_user()
         omit_members = strtobool(
             request.args.get("omitMemberList", "false"))
         if authenticated_user_id is None:
             user_id = 0
         else:
             user_id = authenticated_user_id
         team_dto = TeamService.get_team_as_dto(team_id, user_id,
                                                omit_members)
         return team_dto.to_primitive(), 200
     except NotFound:
         return {"Error": "Team Not Found"}, 404
     except Exception as e:
         error_msg = f"Team GET - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
示例#12
0
    def post_message(chat_dto: ChatMessageDTO, project_id: int,
                     authenticated_user_id: int) -> ProjectChatDTO:
        """ Save message to DB and return latest chat"""
        current_app.logger.debug("Posting Chat Message")

        if UserService.is_user_blocked(authenticated_user_id):
            raise ValueError("User is on read only mode")

        project = ProjectService.get_project_by_id(project_id)
        is_allowed_user = True
        is_manager_permission = ProjectAdminService.is_user_action_permitted_on_project(
            authenticated_user_id, project_id)
        is_team_member = False

        # Draft (public/private) accessible only for is_manager_permission
        if (ProjectStatus(project.status) == ProjectStatus.DRAFT
                and not is_manager_permission):
            raise ValueError("User not permitted to post Comment")

        if project.private:
            is_allowed_user = False
            if not is_manager_permission:
                allowed_roles = [
                    TeamRoles.PROJECT_MANAGER.value,
                    TeamRoles.VALIDATOR.value,
                    TeamRoles.MAPPER.value,
                ]
                is_team_member = TeamService.check_team_membership(
                    project_id, allowed_roles, authenticated_user_id)
                if not is_team_member:
                    is_allowed_user = (len([
                        user for user in project.allowed_users
                        if user.id == authenticated_user_id
                    ]) > 0)

        if is_manager_permission or is_team_member or is_allowed_user:
            chat_message = ProjectChat.create_from_dto(chat_dto)
            MessageService.send_message_after_chat(chat_dto.user_id,
                                                   chat_message.message,
                                                   chat_dto.project_id)
            db.session.commit()
            # Ensure we return latest messages after post
            return ProjectChat.get_messages(chat_dto.project_id, 1)
        else:
            raise ValueError("User not permitted to post Comment")
示例#13
0
    def evaluate_validation_permission(
        project_id: int, user_id: int, validation_permission: int
    ):
        allowed_roles = [TeamRoles.VALIDATOR.value, TeamRoles.PROJECT_MANAGER.value]
        is_team_member = TeamService.check_team_membership(
            project_id, allowed_roles, user_id
        )
        # validation_permission = 1(level),2(teams),3(teamsAndLevel)
        if validation_permission == ValidationPermission.TEAMS.value:
            if not is_team_member:
                return False, ValidatingNotAllowed.USER_NOT_TEAM_MEMBER

        elif validation_permission == ValidationPermission.LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, ValidatingNotAllowed.USER_IS_BEGINNER

        elif validation_permission == ValidationPermission.TEAMS_LEVEL.value:
            if not ProjectService._is_user_intermediate_or_advanced(user_id):
                return False, ValidatingNotAllowed.USER_IS_BEGINNER
            if not is_team_member:
                return False, ValidatingNotAllowed.USER_NOT_TEAM_MEMBER
示例#14
0
 def get(self, team_id):
     """
     Retrieves a Team
     ---
     tags:
         - teams
     produces:
         - application/json
     parameters:
         - name: team_id
           in: path
           description: Unique team ID
           required: true
           type: integer
           default: 1
     responses:
         200:
             description: Team found
         401:
             description: Unauthorized - Invalid credentials
         404:
             description: Team not found
         500:
             description: Internal Server Error
     """
     try:
         authenticated_user_id = token_auth.current_user()
         if authenticated_user_id is None:
             user_id = 0
         else:
             user_id = authenticated_user_id
         team_dto = TeamService.get_team_as_dto(team_id, user_id)
         return team_dto.to_primitive(), 200
     except NotFound:
         return {"Error": "Team Not Found"}, 404
     except Exception as e:
         error_msg = f"Team GET - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
    def is_user_action_permitted_on_project(authenticated_user_id: int,
                                            project_id: int) -> bool:
        """ Is user action permitted on project"""
        project = Project.get(project_id)
        author_id = project.author_id
        allowed_roles = [TeamRoles.PROJECT_MANAGER.value]

        is_admin = UserService.is_user_an_admin(authenticated_user_id)
        is_author = UserService.is_user_the_project_author(
            authenticated_user_id, author_id)
        is_org_manager = False
        is_manager_team = False
        if not (is_admin or is_author):
            if hasattr(project, "organisation_id") and project.organisation_id:
                org_id = project.organisation_id
                is_org_manager = OrganisationService.is_user_an_org_manager(
                    org_id, authenticated_user_id)
                if not is_org_manager:
                    is_manager_team = TeamService.check_team_membership(
                        project_id, allowed_roles, authenticated_user_id)

        return is_admin or is_author or is_org_manager or is_manager_team
示例#16
0
 def get(self, project_id):
     """ Get teams assigned with a project
     ---
     tags:
       - teams
     produces:
       - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           required: true
           type: string
           default: Token sessionTokenHere==
         - name: project_id
           in: path
           description: Unique project ID
           required: true
           type: integer
           default: 1
     responses:
         200:
             description: Teams listed successfully
         403:
             description: Forbidden, if user is not authenticated
         404:
             description: Not found
         500:
             description: Internal Server Error
     """
     try:
         teams_dto = TeamService.get_project_teams_as_dto(project_id)
         return teams_dto.to_primitive(), 200
     except Exception as e:
         error_msg = f"Team GET - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
示例#17
0
    def patch(self, team_id, project_id):
        """ Update role of a team on a project
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: project_id
              in: path
              description: Unique project ID
              required: true
              type: integer
              default: 1
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: The role that the team will have on the project
              schema:
                  properties:
                      role:
                        type: string
        responses:
            201:
                description: Team project assignment created
            401:
                description: Forbidden, if user is not a manager of the project
            403:
                description: Forbidden, if user is not authenticated
            404:
                description: Not found
            500:
                description: Internal Server Error
        """
        if not TeamService.is_user_team_manager(team_id,
                                                token_auth.current_user()):
            return {
                "Error": "User is not an admin or a manager for the team"
            }, 401
        try:
            role = request.get_json(force=True)["role"]
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return str(e), 400

        try:
            TeamService.change_team_role(team_id, project_id, role)
            return {"Status": "Team role updated successfully."}, 200
        except NotFound as e:
            return {"Error": str(e)}, 404
        except TeamServiceError as e:
            return str(e), 402
        except Exception as e:
            error_msg = f"Team-Project PATCH - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#18
0
    def post(self, team_id):
        """
        Updates a team information
        ---
        tags:
            - teams
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for updating a team
              schema:
                properties:
                    name:
                        type: string
                        default: HOT - Mappers
                    logo:
                        type: string
                        default: https://tasks.hotosm.org/assets/img/hot-tm-logo.svg
                    members:
                        type: array
                        items:
                            schema:
                                $ref: "#/definitions/TeamMembers"
                    organisation:
                        type: string
                        default: HOT
                    description:
                        type: string
                        default: HOT's mapping editors
                    inviteOnly:
                        type: boolean
                        default: false
        responses:
            201:
                description: Team updated successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            500:
                description: Internal Server Error
        """
        try:
            team_dto = TeamDTO(request.get_json())
            team_dto.team_id = team_id
            team_dto.validate()

            authenticated_user_id = token_auth.current_user()
            team_details_dto = TeamService.get_team_as_dto(
                team_id, authenticated_user_id)

            org = TeamService.assert_validate_organisation(
                team_dto.organisation_id)
            TeamService.assert_validate_members(team_details_dto)

            if not TeamService.is_user_team_manager(
                    team_id, authenticated_user_id
            ) and not OrganisationService.can_user_manage_organisation(
                    org.id, authenticated_user_id):
                return {
                    "Error": "User is not a admin or a manager for the team"
                }, 401
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            TeamService.update_team(team_dto)
            return {"Status": "Updated"}, 200
        except NotFound as e:
            return {"Error": str(e)}, 404
        except TeamServiceError as e:
            return str(e), 402
        except Exception as e:
            error_msg = f"Team POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#19
0
    def post(self, team_id, project_id):
        """ Assign a team to a project
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: project_id
              in: path
              description: Unique project ID
              required: true
              type: integer
              default: 1
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: The role that the team will have on the project
              schema:
                  properties:
                      role:
                        type: string
        responses:
            201:
                description: Team project assignment created
            401:
                description: Forbidden, if user is not a manager of the project
            403:
                description: Forbidden, if user is not authenticated
            404:
                description: Not found
            500:
                description: Internal Server Error
        """
        if not TeamService.user_is_manager(team_id, token_auth.current_user()):
            return {"Error": "User is not an admin or a manager for the team"}, 401

        try:
            role = request.get_json(force=True)["role"]
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return str(e), 400

        try:
            TeamService.add_team_project(team_id, project_id, role)
            return (
                {
                    "Success": "Team {} assigned to project {} with role {}".format(
                        team_id, project_id, role
                    )
                },
                201,
            )
        except Exception as e:
            error_msg = f"Project Team POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#20
0
 def test_leave_team(self):
     team_id = 1
     username = "******"
     with self.assertRaises(NotFound):
         TeamService.leave_team(team_id, username)
示例#21
0
    def post(self, team_id):
        """
        Message all team members
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for creating message
              schema:
                properties:
                    subject:
                        type: string
                        default: Thanks
                        required: true
                    message:
                        type: string
                        default: Thanks for your contribution
                        required: true
        responses:
            200:
                description: Message sent successfully
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            authenticated_user_id = token_auth.current_user()
            team_id = request.view_args["team_id"]
            message_dto = MessageDTO(request.get_json())
            # Validate if team is present
            try:
                team = TeamService.get_team_by_id(team_id)
            except NotFound:
                return {"Error": "Team not found"}, 404

            is_manager = TeamService.is_user_team_manager(
                team_id, authenticated_user_id)
            if not is_manager:
                raise ValueError
            message_dto.from_user_id = authenticated_user_id
            message_dto.validate()
            if not message_dto.message.strip(
            ) or not message_dto.subject.strip():
                raise DataError({"Validation": "Empty message not allowed"})
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return {"Error": "Request payload did not match validation"}, 400
        except ValueError:
            return {
                "Error": "Unauthorised to send message to team members"
            }, 403

        try:
            threading.Thread(
                target=TeamService.send_message_to_all_team_members,
                args=(team_id, team.name, message_dto),
            ).start()

            return {"Success": "Message sent successfully"}, 200
        except ValueError as e:
            return {"Error": str(e)}, 403
        except Exception as e:
            error_msg = f"Send message all - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to send messages to team members"}, 500
示例#22
0
 def post(self, team_id):
     """
     Removes a user from a team
     ---
     tags:
       - teams
     produces:
       - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           required: true
           type: string
           default: Token sessionTokenHere==
         - name: team_id
           in: path
           description: Unique team ID
           required: true
           type: integer
           default: 1
         - in: body
           name: body
           required: true
           description: JSON object to remove user from team
           schema:
             properties:
                 username:
                     type: string
                     default: 1
                     required: true
     responses:
         200:
             description: Member deleted
         403:
             description: Forbidden, if user attempting to ready other messages
         404:
             description: Not found
         500:
             description: Internal Server Error
     """
     try:
         authenticated_user_id = token_auth.current_user()
         username = request.get_json(force=True)["username"]
         request_user = User.get_by_id(authenticated_user_id)
         if (TeamService.is_user_team_manager(team_id,
                                              authenticated_user_id)
                 or request_user.username == username):
             TeamService.leave_team(team_id, username)
             return {"Success": "User removed from the team"}, 200
         else:
             return (
                 {
                     "Error":
                     "You don't have permissions to remove {} from this team."
                     .format(username)
                 },
                 403,
             )
     except NotFound:
         return {"Error": "No team member found"}, 404
     except Exception as e:
         error_msg = f"TeamMembers DELETE - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": error_msg}, 500
示例#23
0
    def get(self):
        """
        Gets all teams
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - in: query
              name: team_name
              description: name of the team to filter by
              type: str
              default: null
            - in: query
              name: member
              description: user ID to filter teams that the users belongs to, user must be active.
              type: str
              default: null
            - in: query
              name: manager
              description: user ID to filter teams that the users has MANAGER role
              type: str
              default: null
            - in: query
              name: member_request
              description: user ID to filter teams that the user has send invite request to
              type: str
              default: null
            - in: query
              name: team_role
              description: team role for project
              type: str
              default: null
            - in: query
              name: organisation
              description: organisation ID to filter teams
              type: str
              default: null
        responses:
            201:
                description: Team list returned successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            500:
                description: Internal Server Error
        """
        try:
            user_id = token_auth.current_user()
        except Exception as e:
            error_msg = f"Teams GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500

        filters = {}

        filters["user_id"] = user_id
        filters["team_name_filter"] = request.args.get("team_name")
        try:
            member_filter = request.args.get("member")
            filters["member_filter"] = int(
                member_filter) if member_filter else None

            manager_filter = request.args.get("manager")
            filters["manager_filter"] = int(
                manager_filter) if manager_filter else None

            role_filter = request.args.get("team_role")
            filters["team_role_filter"] = role_filter

            member_request_filter = request.args.get("member_request")
            filters["member_request_filter"] = (
                int(member_request_filter) if member_request_filter else None)

            organisation_filter = request.args.get("organisation")
            filters["organisation_filter"] = (int(organisation_filter)
                                              if organisation_filter else None)

            teams = TeamService.get_all_teams(**filters)
            return teams.to_primitive(), 200
        except Exception as e:
            error_msg = f"User GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#24
0
    def patch(self, team_id):
        """
        Take action on a team invite
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object to accept or reject a request to join team
              schema:
                properties:
                    username:
                        type: string
                        required: true
                    type:
                        type: string
                        default: join-response
                        required: true
                    role:
                        type: string
                        default: member
                        required: false
                    action:
                        type: string
                        default: accept
                        required: true
        responses:
            200:
                description: Member added
            403:
                description: Forbidden
            404:
                description: Not found
            500:
                description: Internal Server Error
        """
        try:
            json_data = request.get_json(force=True)
            username = json_data["username"]
            request_type = json_data.get("type", "join-response")
            action = json_data["action"]
            role = json_data.get("role", "member")
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            authenticated_user_id = token_auth.current_user()
            if request_type == "join-response":
                if TeamService.is_user_team_manager(team_id,
                                                    authenticated_user_id):
                    TeamService.accept_reject_join_request(
                        team_id, authenticated_user_id, username, role, action)
                    return {"Success": "True"}, 200
                else:
                    return (
                        {
                            "Error":
                            "You don't have permissions to approve this join team request"
                        },
                        403,
                    )
            elif request_type == "invite-response":
                TeamService.accept_reject_invitation_request(
                    team_id, authenticated_user_id, username, role, action)
                return {"Success": "True"}, 200
        except Exception as e:
            raise
            error_msg = f"Team Join PUT - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#25
0
    def post(self):
        """
        Creates a new team
        ---
        tags:
            - teams
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - in: body
              name: body
              required: true
              description: JSON object for creating team
              schema:
                properties:
                    name:
                        type: string
                        default: HOT - Mappers
                    organisation_id:
                        type: integer
                        default: 1
                    description:
                        type: string
                    visibility:
                        type: string
                        default: PUBLIC
                    inviteOnly:
                        type: boolean
                        default: false
        responses:
            201:
                description: Team created successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Unauthorized - Forbidden
            500:
                description: Internal Server Error
        """
        user_id = token_auth.current_user()

        try:
            team_dto = NewTeamDTO(request.get_json())
            team_dto.creator = user_id
            team_dto.validate()
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            organisation_id = team_dto.organisation_id

            is_org_manager = OrganisationService.is_user_an_org_manager(
                organisation_id, user_id)
            is_admin = UserService.is_user_an_admin(user_id)
            if is_admin or is_org_manager:
                team_id = TeamService.create_team(team_dto)
                return {"teamId": team_id}, 201
            else:
                error_msg = (
                    "Team POST - User not permitted to create team for the Organisation"
                )
                return {"Error": error_msg}, 403
        except TeamServiceError as e:
            return str(e), 400
        except NotFound:
            error_msg = "Team POST - Organisation does not exist"
            return {"Error": error_msg}, 400
        except Exception as e:
            error_msg = f"Team POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
示例#26
0
 def test_delete_team_project(self):
     team_id = 1
     with self.assertRaises(TeamServiceError):
         TeamService.delete_team(team_id)
示例#27
0
    def post_message(
        chat_dto: ChatMessageDTO, project_id: int, authenticated_user_id: int
    ) -> ProjectChatDTO:
        """ Save message to DB and return latest chat"""
        current_app.logger.debug("Posting Chat Message")

        if UserService.is_user_blocked(authenticated_user_id):
            return ValueError("User is on read only mode")

        project = ProjectService.get_project_by_id(project_id)
        if project.private:
            author_id = project.author_id
            allowed_roles = [
                TeamRoles.PROJECT_MANAGER.value,
                TeamRoles.VALIDATOR.value,
                TeamRoles.MAPPER.value,
            ]

            is_admin = UserService.is_user_an_admin(authenticated_user_id)
            is_author = UserService.is_user_the_project_author(
                authenticated_user_id, author_id
            )
            is_org_manager = False
            if hasattr(project, "organisation_id") and project.organisation_id:
                org_id = project.organisation_id
                org = OrganisationService.get_organisation_by_id_as_dto(
                    org_id, authenticated_user_id
                )
                if org.is_manager:
                    is_org_manager = True

            is_team_member = None
            if hasattr(project, "project_teams") and project.project_teams:
                teams_dto = TeamService.get_project_teams_as_dto(project_id)
                if teams_dto.teams:
                    teams_allowed = [
                        team_dto
                        for team_dto in teams_dto.teams
                        if team_dto.role in allowed_roles
                    ]
                    user_membership = [
                        team_dto.team_id
                        for team_dto in teams_allowed
                        if TeamService.is_user_member_of_team(
                            team_dto.team_id, authenticated_user_id
                        )
                    ]
                    if user_membership:
                        is_team_member = True

            for user in project.allowed_users:
                if user.id == authenticated_user_id:
                    is_allowed_user = True
                    break

            if (
                is_admin
                or is_author
                or is_org_manager
                or is_team_member
                or is_allowed_user
            ):
                chat_message = ProjectChat.create_from_dto(chat_dto)
                MessageService.send_message_after_chat(
                    chat_dto.user_id, chat_message.message, chat_dto.project_id
                )
                db.session.commit()
                # Ensure we return latest messages after post
                return ProjectChat.get_messages(chat_dto.project_id, 1)
            else:
                raise ValueError("User not permitted to post Comment")
        else:
            chat_message = ProjectChat.create_from_dto(chat_dto)
            MessageService.send_message_after_chat(
                chat_dto.user_id, chat_message.message, chat_dto.project_id
            )
            db.session.commit()
            # Ensure we return latest messages after post
            return ProjectChat.get_messages(chat_dto.project_id, 1)
示例#28
0
    def post(self, team_id):
        """
        Request to join a team
        ---
        tags:
          - teams
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: team_id
              in: path
              description: Unique team ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object to join team
              schema:
                properties:
                    username:
                        type: string
                        required: true
                    role:
                        type: string
                        required: false
        responses:
            200:
                description: Member added
            403:
                description: Forbidden
            404:
                description: Not found
            500:
                description: Internal Server Error
        """
        try:
            post_data = request.get_json(force=True)
            username = post_data["username"]
            role = post_data.get("role", None)
        except (DataError, KeyError) as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            authenticated_user_id = token_auth.current_user()
            TeamService.join_team(team_id, authenticated_user_id, username,
                                  role)
            if TeamService.is_user_team_manager(team_id,
                                                authenticated_user_id):
                return {"Success": "User added to the team"}, 200
            else:
                return {
                    "Success": "Request to join the team sent successfully."
                }, 200
        except TeamJoinNotAllowed as e:
            return {"Error": str(e)}, 403
        except Exception as e:
            error_msg = f"User POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500