def can_user_manage_organisation(organisation_id: int, user_id: int):
     """ Check that the user is an admin for the org or a global admin"""
     if UserService.is_user_an_admin(user_id):
         return True
     else:
         return OrganisationService.is_user_an_org_manager(
             organisation_id, user_id)
    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
Beispiel #3
0
    def get_team_as_dto(team_id: int, user_id: int) -> TeamDTO:
        team = TeamService.get_team_by_id(team_id)

        if team is None:
            raise NotFound()

        team_dto = TeamDetailsDTO()
        team_dto.team_id = team.id
        team_dto.name = team.name
        team_dto.invite_only = team.invite_only
        team_dto.visibility = TeamVisibility(team.visibility).name
        team_dto.description = team.description
        team_dto.logo = team.organisation.logo
        team_dto.organisation = team.organisation.name
        team_dto.organisation_id = team.organisation.id

        if user_id != 0:
            if UserService.is_user_an_admin(user_id):
                team_dto.is_general_admin = True

            if OrganisationService.is_user_an_org_manager(
                    team.organisation.id, user_id):
                team_dto.is_org_admin = True
        else:
            team_dto.is_general_admin = False
            team_dto.is_org_admin = False

        team_members = TeamService._get_team_members(team_id)
        for member in team_members:
            user = UserService.get_user_by_id(member.user_id)
            member_dto = TeamMembersDTO()
            member_dto.username = user.username
            member_dto.pictureUrl = user.picture_url
            member_dto.function = TeamMemberFunctions(member.function).name
            member_dto.picture_url = user.picture_url
            member_dto.active = member.active

            team_dto.members.append(member_dto)

        team_projects = TeamService.get_projects_by_team_id(team.id)
        for team_project in team_projects:
            project_team_dto = TeamProjectDTO()
            project_team_dto.project_name = team_project.name
            project_team_dto.project_id = team_project.project_id
            project_team_dto.role = TeamRoles(team_project.role).name

            team_dto.team_projects.append(project_team_dto)

        org_projects = OrganisationService.get_projects_by_organisation_id(
            team.organisation.id)
        for org_project in org_projects:
            org_project_dto = OrganisationProjectsDTO()
            org_project_dto.project_id = org_project.id
            org_project_dto.project_name = org_project.name
            team_dto.organisation_projects.append(org_project_dto)

        return team_dto
Beispiel #4
0
    def user_is_manager(team_id: int, user_id: int):
        if UserService.is_user_an_admin(user_id):
            return True

        managers = TeamService._get_team_managers(team_id)
        for member in managers:
            if member.user_id == user_id:
                return True

        return False
    def create_draft_project(draft_project_dto: DraftProjectDTO) -> int:
        """
        Validates and then persists draft projects in the DB
        :param draft_project_dto: Draft Project DTO with data from API
        :raises InvalidGeoJson
        :returns ID of new draft project
        """
        user_id = draft_project_dto.user_id
        is_admin = UserService.is_user_an_admin(user_id)
        user_orgs = OrganisationService.get_organisations_managed_by_user_as_dto(
            user_id)
        is_org_manager = len(user_orgs.organisations) > 0

        # First things first, we need to validate that the author_id is a PM. issue #1715
        if not (is_admin or is_org_manager):
            user = UserService.get_user_by_id(user_id)
            raise (ProjectAdminServiceError(
                f"User {user.username} is not permitted to create project"))

        # If we're cloning we'll copy all the project details from the clone, otherwise create brand new project
        if draft_project_dto.cloneFromProjectId:
            draft_project = Project.clone(draft_project_dto.cloneFromProjectId,
                                          user_id)
        else:
            draft_project = Project()
            org = OrganisationService.get_organisation_by_id(
                draft_project_dto.organisation)
            if org is None:
                raise NotFound("Organisation does not exist")
            draft_project_dto.organisation = org
            draft_project.create_draft_project(draft_project_dto)

        draft_project.set_project_aoi(draft_project_dto)

        # if arbitrary_tasks requested, create tasks from aoi otherwise use tasks in DTO
        if draft_project_dto.has_arbitrary_tasks:
            tasks = GridService.tasks_from_aoi_features(
                draft_project_dto.area_of_interest)
            draft_project.task_creation_mode = TaskCreationMode.ARBITRARY.value
        else:
            tasks = draft_project_dto.tasks
        ProjectAdminService._attach_tasks_to_project(draft_project, tasks)

        if draft_project_dto.cloneFromProjectId:
            draft_project.save()  # Update the clone
        else:
            draft_project.create()  # Create the new project

        draft_project.set_default_changeset_comment()
        draft_project.set_country_info()
        return draft_project.id
 def _user_can_validate_task(user_id: int, mapped_by: int) -> bool:
     """
     check whether a user is able to validate a task.  Users cannot validate their own tasks unless they are a PM
     (admin counts as project manager too)
     :param user_id: id of user attempting to validate
     :param mapped_by: id of user who mapped the task
     :return: Boolean
     """
     is_admin = UserService.is_user_an_admin(user_id)
     if is_admin:
         return True
     else:
         mapped_by_me = mapped_by == user_id
         if not mapped_by_me:
             return True
         return False
    def delete_project(project_id: int, authenticated_user_id: int):
        """ Deletes project if it has no completed tasks """

        project = ProjectAdminService._get_project_by_id(project_id)
        is_admin = UserService.is_user_an_admin(authenticated_user_id)
        user_orgs = OrganisationService.get_organisations_managed_by_user_as_dto(
            authenticated_user_id)
        is_org_manager = len(user_orgs.organisations) > 0

        if is_admin or is_org_manager:
            if project.can_be_deleted():
                project.delete()
            else:
                raise ProjectAdminServiceError(
                    "Project has mapped tasks, cannot be deleted")
        else:
            raise ProjectAdminServiceError(
                "User does not have permissions to delete project")
    def is_user_team_manager(team_id: int, user_id: int):
        # Admin manages all teams
        if UserService.is_user_an_admin(user_id):
            return True

        managers = TeamService._get_team_managers(team_id)
        for member in managers:
            if member.user_id == user_id:
                return True

        # Org admin manages teams attached to their org
        user_managed_orgs = [
            org.id for org in OrganisationService.get_organisations(user_id)
        ]
        if Team.get(team_id).organisation_id in user_managed_orgs:
            return True

        return False
Beispiel #9
0
    def get_team_as_dto(team_id: int, user_id: int,
                        abbreviated: bool) -> TeamDetailsDTO:
        team = TeamService.get_team_by_id(team_id)

        if team is None:
            raise NotFound()

        team_dto = TeamDetailsDTO()
        team_dto.team_id = team.id
        team_dto.name = team.name
        team_dto.invite_only = team.invite_only
        team_dto.visibility = TeamVisibility(team.visibility).name
        team_dto.description = team.description
        team_dto.logo = team.organisation.logo
        team_dto.organisation = team.organisation.name
        team_dto.organisation_id = team.organisation.id
        team_dto.organisation_slug = team.organisation.slug

        if user_id != 0:
            if UserService.is_user_an_admin(user_id):
                team_dto.is_general_admin = True

            if OrganisationService.is_user_an_org_manager(
                    team.organisation.id, user_id):
                team_dto.is_org_admin = True
        else:
            team_dto.is_general_admin = False
            team_dto.is_org_admin = False

        if abbreviated:
            return team_dto

        team_dto.members = [
            team.as_dto_team_member(member) for member in team.members
        ]

        team_projects = TeamService.get_projects_by_team_id(team.id)

        team_dto.team_projects = [
            team.as_dto_team_project(project) for project in team_projects
        ]

        return team_dto
    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
Beispiel #11
0
    def get_all_teams(
        user_id: int = None,
        team_name_filter: str = None,
        team_role_filter: str = None,
        member_filter: int = None,
        member_request_filter: int = None,
        manager_filter: int = None,
        organisation_filter: int = None,
        omit_members: bool = False,
    ) -> TeamsListDTO:

        query = db.session.query(Team)

        orgs_query = None
        is_admin = UserService.is_user_an_admin(user_id)

        if organisation_filter:
            orgs_query = query.filter(
                Team.organisation_id == organisation_filter)

        if manager_filter and not (manager_filter == user_id and is_admin):
            manager_teams = query.filter(
                TeamMembers.user_id == manager_filter,
                TeamMembers.active == True,  # noqa
                TeamMembers.function == TeamMemberFunctions.MANAGER.value,
                Team.id == TeamMembers.team_id,
            )

            manager_orgs_teams = query.filter(
                Team.organisation_id.in_([
                    org.id for org in OrganisationService.get_organisations(
                        manager_filter)
                ]))

            query = manager_teams.union(manager_orgs_teams)

        if team_name_filter:
            query = query.filter(Team.name.ilike("%" + team_name_filter +
                                                 "%"), )

        if team_role_filter:
            try:
                role = TeamRoles[team_role_filter.upper()].value
                project_teams = (db.session.query(ProjectTeams).filter(
                    ProjectTeams.role == role).subquery())
                query = query.join(project_teams)
            except KeyError:
                pass

        if member_filter:
            team_member = (db.session.query(TeamMembers).filter(
                TeamMembers.user_id == member_filter,
                TeamMembers.active.is_(True)).subquery())
            query = query.join(team_member)

        if member_request_filter:
            team_member = (db.session.query(TeamMembers).filter(
                TeamMembers.user_id == member_request_filter,
                TeamMembers.active.is_(False),
            ).subquery())
            query = query.join(team_member)
        if orgs_query:
            query = query.union(orgs_query)

        teams_list_dto = TeamsListDTO()

        for team in query.all():
            team_dto = TeamDTO()
            team_dto.team_id = team.id
            team_dto.name = team.name
            team_dto.invite_only = team.invite_only
            team_dto.visibility = TeamVisibility(team.visibility).name
            team_dto.description = team.description
            team_dto.logo = team.organisation.logo
            team_dto.organisation = team.organisation.name
            team_dto.organisation_id = team.organisation.id
            team_dto.members = []
            is_team_member = TeamService.is_user_an_active_team_member(
                team.id, user_id)
            # Skip if members are not included
            if not omit_members:
                team_members = team.members

                team_dto.members = [
                    team.as_dto_team_member(member) for member in team_members
                ]

            if team_dto.visibility == "PRIVATE" and not is_admin:
                if is_team_member:
                    teams_list_dto.teams.append(team_dto)
            else:
                teams_list_dto.teams.append(team_dto)
        return teams_list_dto
    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
Beispiel #13
0
    def get(self):
        """
        List all organisations
        ---
        tags:
          - organisations
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              type: string
              default: Token sessionTokenHere==
            - name: manager_user_id
              in: query
              description: Filter projects on managers with this user_id
              required: false
              type: integer
        responses:
            200:
                description: Organisations found
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Unauthorized - Not allowed
            404:
                description: Organisations not found
            500:
                description: Internal Server Error
        """

        # Restrict some of the parameters to some permissions
        try:
            manager_user_id = int(request.args.get("manager_user_id"))
        except Exception:
            manager_user_id = None

        if manager_user_id is not None:
            try:
                # Verify login
                verify_token(
                    request.environ.get("HTTP_AUTHORIZATION").split(None,
                                                                    1)[1])

                # Check whether user is admin (can do any query) or user is checking for own projects
                if (not UserService.is_user_an_admin(tm.authenticated_user_id)
                        and tm.authenticated_user_id != manager_user_id):
                    raise ValueError

            except Exception:
                return {"Error": "Unauthorized - Not allowed"}, 403

        # Obtain organisations
        try:
            results_dto = OrganisationService.get_organisations_as_dto(
                manager_user_id, tm.authenticated_user_id)
            return results_dto.to_primitive(), 200
        except NotFound:
            return {"Error": "No projects found"}, 404
        except Exception as e:
            error_msg = f"Organisations GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Beispiel #14
0
    def get_all_teams(
        user_id: int = None,
        team_name_filter: str = None,
        team_role_filter: str = None,
        member_filter: int = None,
        member_request_filter: int = None,
        manager_filter: int = None,
        organisation_filter: int = None,
    ) -> TeamsListDTO:

        query = db.session.query(Team).outerjoin(TeamMembers).outerjoin(
            ProjectTeams)

        orgs_query = None
        is_admin = UserService.is_user_an_admin(user_id)

        if organisation_filter:
            orgs_query = query.filter(
                Team.organisation_id.in_(organisation_filter))

        if manager_filter and not (manager_filter == user_id and is_admin):
            query = query.filter(
                TeamMembers.user_id == manager_filter,
                TeamMembers.active == True,  # noqa
                TeamMembers.function == TeamMemberFunctions.MANAGER.value,
            )

        if team_name_filter:
            query = query.filter(Team.name.contains(team_name_filter))

        if team_role_filter:
            try:
                role = TeamRoles[team_role_filter.upper()].value
                query = query.filter(ProjectTeams.role == role)
            except KeyError:
                pass

        if member_filter:
            query = query.filter(
                TeamMembers.user_id == member_filter,
                TeamMembers.active == True  # noqa
            )

        if member_request_filter:
            query = query.filter(
                TeamMembers.user_id == member_request_filter,
                TeamMembers.active == False,  # noqa
            )

        if orgs_query:
            query = query.union(orgs_query)

        teams_list_dto = TeamsListDTO()

        for team in query.all():
            team_dto = TeamDTO()
            team_dto.team_id = team.id
            team_dto.name = team.name
            team_dto.invite_only = team.invite_only
            team_dto.visibility = TeamVisibility(team.visibility).name
            team_dto.description = team.description
            team_dto.logo = team.organisation.logo
            team_dto.organisation = team.organisation.name
            team_dto.organisation_id = team.organisation.id
            team_dto.members = []
            team_members = TeamService._get_team_members(team.id)
            is_team_manager = False
            is_team_member = False
            for member in team_members:
                user = UserService.get_user_by_id(member.user_id)
                member_dto = TeamMembersDTO()
                member_dto.username = user.username
                member_dto.function = TeamMemberFunctions(member.function).name
                if member.user_id == user_id:
                    is_team_member = True
                    if member_dto.function == "MANAGER":
                        is_team_manager = True
                member_dto.picture_url = user.picture_url
                member_dto.active = member.active

                team_dto.members.append(member_dto)
            if team_dto.visibility == "PRIVATE" and not is_admin:
                if is_team_manager or is_team_member:
                    teams_list_dto.teams.append(team_dto)
            else:
                teams_list_dto.teams.append(team_dto)

        return teams_list_dto
    def get_organisations_managed_by_user(user_id: int):
        """ Get all organisations a user manages """
        if UserService.is_user_an_admin(user_id):
            return Organisation.get_all_organisations()

        return Organisation.get_organisations_managed_by_user(user_id)
Beispiel #16
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)
    def get(self):
        """
        List all organisations
        ---
        tags:
          - organisations
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              type: string
              default: Token sessionTokenHere==
            - name: manager_user_id
              in: query
              description: Filter projects on managers with this user_id
              required: false
              type: integer
            - in: query
              name: omitManagerList
              type: boolean
              description: Set it to true if you don't want the managers list on the response.
              default: False
        responses:
            200:
                description: Organisations found
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Unauthorized - Not allowed
            404:
                description: Organisations not found
            500:
                description: Internal Server Error
        """

        # Restrict some of the parameters to some permissions
        authenticated_user_id = token_auth.current_user()
        try:
            manager_user_id = int(request.args.get("manager_user_id"))
        except Exception:
            manager_user_id = None

        if manager_user_id is not None:
            try:
                # Check whether user is admin (can do any query) or user is checking for own projects
                if (not UserService.is_user_an_admin(authenticated_user_id)
                        and authenticated_user_id != manager_user_id):
                    raise ValueError

            except Exception:
                return {"Error": "Unauthorized - Not allowed"}, 403

        # Validate abbreviated.
        omit_managers = strtobool(request.args.get("omitManagerList", "false"))
        # Obtain organisations
        try:
            results_dto = OrganisationService.get_organisations_as_dto(
                manager_user_id, authenticated_user_id, omit_managers)
            return results_dto.to_primitive(), 200
        except NotFound:
            return {"Error": "No projects found"}, 404
        except Exception as e:
            error_msg = f"Organisations GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500