Esempio n. 1
0
    def get(self):
        """
        Get all projects for logged in admin
        ---
        tags:
            - projects
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              required: true
              default: en
        responses:
            200:
                description: All mapped tasks validated
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            404:
                description: Admin has no projects
            500:
                description: Internal Server Error
        """
        try:
            authenticated_user_id = token_auth.current_user()
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a project manager")
        except ValueError as e:
            error_msg = f"ProjectsQueriesOwnerAPI GET: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            search_dto = self.setup_search_dto()
            admin_projects = ProjectAdminService.get_projects_for_admin(
                authenticated_user_id,
                request.environ.get("HTTP_ACCEPT_LANGUAGE"),
                search_dto,
            )
            return admin_projects.to_primitive(), 200
        except NotFound:
            return {"Error": "No comments found"}, 404
        except Exception as e:
            error_msg = f"Project GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Esempio n. 2
0
    def delete(self, campaign_id):
        """
        Deletes an existing campaign
        ---
        tags:
          - campaigns
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              type: string
              required: true
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              required: true
              default: en
            - name: campaign_id
              in: path
              description: Campaign ID
              required: true
              type: integer
              default: 1
        responses:
            200:
                description: Campaign deleted successfully
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                token_auth.current_user()
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"CampaignsRestAPI DELETE: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            campaign = CampaignService.get_campaign(campaign_id)
            CampaignService.delete_campaign(campaign.id)
            return {"Success": "Campaign deleted"}, 200
        except NotFound:
            return {"Error": "Campaign not found"}, 404
        except Exception as e:
            error_msg = f"Campaign DELETE - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Esempio n. 3
0
    def delete(self, interest_id):
        """
        Delete a specified interest
        ---
        tags:
            - interests
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: interest_id
              in: path
              description: Unique interest ID
              required: true
              type: integer
              default: 1
        responses:
            200:
                description: Interest deleted
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            404:
                description: Interest not found
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                tm.authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"InterestsAllAPI DELETE: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            InterestService.delete(interest_id)
            return {"Success": "Interest deleted"}, 200
        except NotFound:
            return {"Error": "Interest Not Found"}, 404
        except Exception as e:
            error_msg = f"License DELETE - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
    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
Esempio n. 5
0
    def get(self, interest_id):
        """
        Get an existing interest
        ---
        tags:
            - interests
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: interest_id
              in: path
              description: Interest ID
              required: true
              type: integer
              default: 1
        responses:
            200:
                description: Interest
            400:
                description: Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                tm.authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"InterestsRestAPI GET: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            interest = InterestService.get(interest_id)
            return interest.to_primitive(), 200
        except Exception as e:
            error_msg = f"Interest GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
    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")
Esempio n. 7
0
    def get(self):
        """
        List and search projects by bounding box
        ---
        tags:
            - projects
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              default: en
            - in: query
              name: bbox
              description: comma separated list xmin, ymin, xmax, ymax
              type: string
              required: true
              default: 34.404,-1.034, 34.717,-0.624
            - in: query
              name: srid
              description: srid of bbox coords
              type: integer
              default: 4326
            - in: query
              name: createdByMe
              description: limit to projects created by authenticated user
              type: boolean
              required: true
              default: false

        responses:
            200:
                description: ok
            400:
                description: Client Error - Invalid Request
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            authenticated_user_id = token_auth.current_user()
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a project manager")
        except ValueError as e:
            error_msg = f"ProjectsQueriesBboxAPI GET: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            search_dto = ProjectSearchBBoxDTO()
            search_dto.bbox = map(float, request.args.get("bbox").split(","))
            search_dto.input_srid = request.args.get("srid")
            search_dto.preferred_locale = request.environ.get("HTTP_ACCEPT_LANGUAGE")
            created_by_me = (
                strtobool(request.args.get("createdByMe"))
                if request.args.get("createdByMe")
                else False
            )
            if created_by_me:
                search_dto.project_author = authenticated_user_id
            search_dto.validate()
        except Exception as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return {"Error": "Unable to fetch projects"}, 400
        try:
            geojson = ProjectSearchService.get_projects_geojson(search_dto)
            return geojson, 200
        except BBoxTooBigError:
            return {"Error": "Bounding Box too large"}, 403
        except ProjectSearchServiceError:
            return {"Error": "Unable to fetch projects"}, 400
        except Exception as e:
            error_msg = f"ProjectsQueriesBboxAPI GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to fetch projects"}, 500
Esempio n. 8
0
    def patch(self, campaign_id):
        """
        Updates an existing campaign
        ---
        tags:
          - campaigns
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              type: string
              required: true
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              required: true
              default: en
            - name: campaign_id
              in: path
              description: Campaign ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for updating a Campaign
              schema:
                properties:
                    name:
                        type: string
                        example: HOT Campaign
                    logo:
                        type: string
                        example: https://tasks.hotosm.org/assets/img/hot-tm-logo.svg
                    url:
                        type: string
                        example: https://hotosm.org
                    organisations:
                        type: array
                        items:
                            type: integer
                        default: [
                            1
                        ]
        responses:
            200:
                description: Campaign updated successfully
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            409:
                description: Resource duplication
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                token_auth.current_user())
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"CampaignsRestAPI PATCH: {str(e)}"
            return {"Error": error_msg}, 403

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

        try:
            campaign = CampaignService.update_campaign(campaign_dto,
                                                       campaign_id)
            return {"Success": "Campaign {} updated".format(campaign.id)}, 200
        except NotFound:
            return {"Error": "Campaign not found"}, 404
        except ValueError:
            error_msg = "Campaign PATCH - name already exists"
            return {"Error": error_msg}, 409
        except Exception as e:
            error_msg = f"Campaign PATCH - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Esempio n. 9
0
    def patch(self, interest_id):
        """
        Update an existing interest
        ---
        tags:
            - interests
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: interest_id
              in: path
              description: Interest ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for creating a new interest
              schema:
                  properties:
                      name:
                          type: string
                          default: Public Domain
        responses:
            200:
                description: Interest updated
            400:
                description: Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                token_auth.current_user())
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"InterestsAllAPI PATCH: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            interest_dto = InterestDTO(request.get_json())
            interest_dto.validate()
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return str(e), 400

        try:
            update_interest = InterestService.update(interest_id, interest_dto)
            return update_interest.to_primitive(), 200
        except Exception as e:
            error_msg = f"Interest PUT - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Esempio n. 10
0
    def post(self):
        """
        Creates a new campaign
        ---
        tags:
          - campaigns
        produces:
          - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              type: string
              required: true
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              required: true
              default: en
            - in: body
              name: body
              required: true
              description: JSON object for creating a new Campaign
              schema:
                properties:
                    name:
                        type: string
                        example: HOT Campaign
                    logo:
                        type: string
                        example: https://tasks.hotosm.org/assets/img/hot-tm-logo.svg
                    url:
                        type: string
                        example: https://hotosm.org
                    organisations:
                        type: array
                        items:
                            type: integer
                        default: [
                            1
                        ]
        responses:
            200:
                description: New campaign created successfully
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                tm.authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"CampaignsAllAPI POST: {str(e)}"
            return {"Error": error_msg}, 403

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

        try:
            campaign = CampaignService.create_campaign(campaign_dto)
            return {"campaignId": campaign.id}, 200
        except Exception as e:
            error_msg = f"Campaign POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Esempio n. 11
0
    def post(self):
        """
        Creates a new interest
        ---
        tags:
            - interests
        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 a new interest
              schema:
                  properties:
                      name:
                          type: string
                          default: Public Domain
        responses:
            200:
                description: New interest created
            400:
                description: Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            orgs_dto = OrganisationService.get_organisations_managed_by_user_as_dto(
                tm.authenticated_user_id
            )
            if len(orgs_dto.organisations) < 1:
                raise ValueError("User not a Org Manager")
        except ValueError as e:
            error_msg = f"InterestsAllAPI POST: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            interest_dto = InterestDTO(request.get_json())
            interest_dto.validate()
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return str(e), 400

        try:
            new_interest = InterestService.create(interest_dto.name)
            return new_interest.to_primitive(), 200
        except IntegrityError:
            return (
                {"error": "Value '{0}' already exists".format(interest_dto.name)},
                400,
            )
        except Exception as e:
            error_msg = f"Interest POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500