Ejemplo n.º 1
0
    def get(self, project_id, task_id):
        """
        Get comments for a task
        ---
        tags:
            - comments
        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: Project ID the task is associated with
              required: true
              type: integer
              default: 1
            - name: task_id
              in: path
              description: Unique task ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object representing the comment
              schema:
                id: TaskComment
                required:
                    - comment
                properties:
                    comment:
                        type: string
                        description: user comment about the task
        responses:
            200:
                description: Comment retrieved
            400:
                description: Client Error
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            404:
                description: Task not found
            500:
                description: Internal Server Error
        """
        try:
            task_comment = TaskCommentDTO(request.get_json())
            task_comment.user_id = token_auth.current_user()
            task_comment.task_id = task_id
            task_comment.project_id = project_id
            task_comment.validate()
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return {"Error": "Unable to fetch task comments"}, 400

        try:
            # NEW FUNCTION HAS TO BE ADDED
            # task = MappingService.add_task_comment(task_comment)
            # return task.to_primitive(), 200
            return
        except NotFound:
            return {"Error": "Task Not Found"}, 404
        except MappingServiceError as e:
            return {"Error": str(e)}, 403
        except Exception as e:
            error_msg = f"Task Comment API - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Ejemplo n.º 2
0
    def post(self):
        """
        Creates a tasking-manager project
        ---
        tags:
            - projects
        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 draft project
              schema:
                properties:
                    cloneFromProjectId:
                        type: int
                        default: 1
                        description: Specify this value if you want to clone a project, otherwise avoid information
                    projectName:
                        type: string
                        default: HOT Project
                    areaOfInterest:
                        schema:
                            properties:
                                type:
                                    type: string
                                    default: FeatureCollection
                                features:
                                    type: array
                                    items:
                                        schema:
                                            $ref: "#/definitions/GeoJsonFeature"
                        tasks:
                            schema:
                                properties:
                                    type:
                                        type: string
                                        default: FeatureCollection
                                    features:
                                        type: array
                                        items:
                                            schema:
                                                $ref: "#/definitions/GeoJsonFeature"
                        arbitraryTasks:
                            type: boolean
                            default: false
        responses:
            201:
                description: Draft project created successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        try:
            draft_project_dto = DraftProjectDTO(request.get_json())
            draft_project_dto.user_id = token_auth.current_user()
            draft_project_dto.validate()
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return {"Error": "Unable to create project"}, 400

        try:
            draft_project_id = ProjectAdminService.create_draft_project(
                draft_project_dto)
            return {"projectId": draft_project_id}, 201
        except ProjectAdminServiceError as e:
            return {"Error": str(e)}, 403
        except (InvalidGeoJson, InvalidData):
            return {"Error": "Invalid GeoJson"}, 400
        except Exception as e:
            error_msg = f"Project PUT - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to create project"}, 500
Ejemplo n.º 3
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
Ejemplo n.º 4
0
    def post(self, project_id):
        """
        Add a message to project chat
        ---
        tags:
          - comments
        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: Project ID to attach the chat message to
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for creating a new mapping license
              schema:
                  properties:
                      message:
                          type: string
                          default: This is an awesome project
        responses:
            201:
                description: Message posted successfully
            400:
                description: Invalid Request
            500:
                description: Internal Server Error
        """
        authenticated_user_id = token_auth.current_user()
        if UserService.is_user_blocked(authenticated_user_id):
            return {"Error": "User is on read only mode."}, 403

        try:
            chat_dto = ChatMessageDTO(request.get_json())
            chat_dto.user_id = authenticated_user_id
            chat_dto.project_id = project_id
            chat_dto.validate()
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return {"Error": "Unable to add chat message"}, 400

        try:
            project_messages = ChatService.post_message(
                chat_dto, project_id, authenticated_user_id
            )
            return project_messages.to_primitive(), 201
        except ValueError as e:
            error_msg = f"CommentsProjectsRestAPI POST: {str(e)}"
            return {"Error": error_msg}, 403
        except Exception as e:
            error_msg = f"Chat POST - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to add chat message"}, 500
Ejemplo n.º 5
0
    def get(self, project_id):
        """
        Get a specified project including it's area
        ---
        tags:
            - projects
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: false
              type: string
              default: Token sessionTokenHere==
            - in: header
              name: Accept-Language
              description: Language user is requesting
              type: string
              required: true
              default: en
            - name: project_id
              in: path
              description: Unique project ID
              required: true
              type: integer
              default: 1
            - in: query
              name: as_file
              type: boolean
              description: Set to true if file download is preferred
              default: False
            - in: query
              name: abbreviated
              type: boolean
              description: Set to true if only state information is desired
              default: False
        responses:
            200:
                description: Project found
            403:
                description: Forbidden
            404:
                description: Project not found
            500:
                description: Internal Server Error
        """
        try:
            authenticated_user_id = token_auth.current_user()
            as_file = (strtobool(request.args.get("as_file"))
                       if request.args.get("as_file") else False)
            abbreviated = (strtobool(request.args.get("abbreviated"))
                           if request.args.get("abbreviated") else False)

            project_dto = ProjectService.get_project_dto_for_mapper(
                project_id,
                authenticated_user_id,
                request.environ.get("HTTP_ACCEPT_LANGUAGE"),
                abbreviated,
            )

            if project_dto:
                project_dto = project_dto.to_primitive()
                if as_file:
                    return send_file(
                        io.BytesIO(geojson.dumps(project_dto).encode("utf-8")),
                        mimetype="application/json",
                        as_attachment=True,
                        attachment_filename=f"project_{str(project_id)}.json",
                    )

                return project_dto, 200
            else:
                return {"Error": "Private Project"}, 403
        except NotFound:
            return {"Error": "Project Not Found"}, 404
        except ProjectServiceError as e:
            return {"Error": str(e)}, 403
        except Exception as e:
            error_msg = f"Project GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to fetch project"}, 500
        finally:
            # this will try to unlock tasks that have been locked too long
            try:
                ProjectService.auto_unlock_tasks(project_id)
            except Exception as e:
                current_app.logger.critical(str(e))
Ejemplo n.º 6
0
 def get(self):
     """
     List and search for projects
     ---
     tags:
         - projects
     produces:
         - application/json
     parameters:
         - in: header
           name: Authorization
           description: Base64 encoded session token
           type: string
           default: Token sessionTokenHere==
         - in: header
           name: Accept-Language
           description: Language user is requesting
           type: string
           required: true
           default: en
         - in: query
           name: mapperLevel
           type: string
         - in: query
           name: orderBy
           type: string
           default: priority
           enum: [id,mapper_level,priority,status,last_updated,due_date]
         - in: query
           name: orderByType
           type: string
           default: ASC
           enum: [ASC, DESC]
         - in: query
           name: mappingTypes
           type: string
         - in: query
           name: mappingTypesExact
           type: boolean
           default: false
           description: if true, limits projects to match the exact mapping types requested
         - in: query
           name: organisationName
           description: Organisation name to search for
           type: string
         - in: query
           name: organisationId
           description: Organisation ID to search for
           type: integer
         - in: query
           name: campaign
           description: Campaign name to search for
           type: string
         - in: query
           name: page
           description: Page of results user requested
           type: integer
           default: 1
         - in: query
           name: textSearch
           description: Text to search
           type: string
         - in: query
           name: country
           description: Project country
           type: string
         - in: query
           name: action
           description: Filter projects by possible actions
           enum: [map, validate, any]
           type: string
         - in: query
           name: projectStatuses
           description: Authenticated PMs can search for archived or draft statuses
           type: string
         - in: query
           name: lastUpdatedFrom
           description: Filter projects whose last update date is equal or greater than a date
           type: string
         - in: query
           name: lastUpdatedTo
           description: Filter projects whose last update date is equal or lower than a date
           type: string
         - in: query
           name: createdFrom
           description: Filter projects whose creation date is equal or greater than a date
           type: string
         - in: query
           name: createdTo
           description: Filter projects whose creation date is equal or lower than a date
           type: string
         - in: query
           name: interests
           type: string
           description: Filter by interest on project
           default: null
         - in: query
           name: createdByMe
           description: Limit to projects created by the authenticated user
           type: boolean
           default: false
         - in: query
           name: mappedByMe
           description: Limit to projects mapped/validated by the authenticated user
           type: boolean
           default: false
         - in: query
           name: favoritedByMe
           description: Limit to projects favorited by the authenticated user
           type: boolean
           default: false
         - in: query
           name: managedByMe
           description:
             Limit to projects that can be managed by the authenticated user,
             excluding the ones created by them
           type: boolean
           default: false
         - in: query
           name: teamId
           type: string
           description: Filter by team on project
           default: null
           name: omitMapResults
           type: boolean
           description: If true, it will not return the project centroid's geometries.
           default: false
     responses:
         200:
             description: Projects found
         404:
             description: No projects found
         500:
             description: Internal Server Error
     """
     try:
         user = None
         user_id = token_auth.current_user()
         if user_id:
             user = UserService.get_user_by_id(user_id)
         search_dto = self.setup_search_dto()
         results_dto = ProjectSearchService.search_projects(
             search_dto, user)
         return results_dto.to_primitive(), 200
     except NotFound:
         return {"mapResults": {}, "results": []}, 200
     except (KeyError, ValueError) as e:
         error_msg = f"Projects GET - {str(e)}"
         return {"Error": error_msg}, 400
     except Exception as e:
         error_msg = f"Projects GET - unhandled error: {str(e)}"
         current_app.logger.critical(error_msg)
         return {"Error": "Unable to fetch projects"}, 500
Ejemplo n.º 7
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
            - 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 and not authenticated_user_id:
            return (
                {
                    "Error": "Unauthorized - Filter by manager_user_id is not allowed to unauthenticated requests"
                },
                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 organisations 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
Ejemplo n.º 8
0
    def patch(self, project_id):
        """
        Updates a Tasking-Manager project
        ---
        tags:
            - projects
        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
            - in: body
              name: body
              required: true
              description: JSON object for updating an existing project
              schema:
                properties:
                    projectStatus:
                        type: string
                        default: DRAFT
                    projectPriority:
                        type: string
                        default: MEDIUM
                    defaultLocale:
                        type: string
                        default: en
                    mapperLevel:
                        type: string
                        default: BEGINNER
                    validation_permission:
                        type: string
                        default: ANY
                    mapping_permission:
                        type: string
                        default: ANY
                    private:
                        type: boolean
                        default: false
                    changesetComment:
                        type: string
                        default: hotosm-project-1
                    dueDate:
                        type: date
                        default: "2017-04-11T12:38:49"
                    imagery:
                        type: string
                        default: http//www.bing.com/maps/
                    josmPreset:
                        type: string
                        default: josm preset goes here
                    mappingTypes:
                        type: array
                        items:
                            type: string
                        default: [BUILDINGS, ROADS]
                    mappingEditors:
                        type: array
                        items:
                            type: string
                        default: [ID, JOSM, POTLATCH_2, FIELD_PAPERS]
                    validationEditors:
                        type: array
                        items:
                            type: string
                        default: [ID, JOSM, POTLATCH_2, FIELD_PAPERS]
                    campaign:
                        type: string
                        default: malaria
                    organisation:
                        type: integer
                        default: 1
                    countryTag:
                          type: array
                          items:
                              type: string
                          default: []
                    licenseId:
                        type: integer
                        default: 1
                        description: Id of imagery license associated with the project
                    allowedUsernames:
                        type: array
                        items:
                            type: string
                        default: ["Iain Hunter", LindaA1]
                    priorityAreas:
                        type: array
                        items:
                            schema:
                                $ref: "#/definitions/GeoJsonPolygon"
                    projectInfoLocales:
                        type: array
                        items:
                            schema:
                                $ref: "#/definitions/ProjectInfo"
                    taskCreationMode:
                        type: integer
                        default: GRID
        responses:
            200:
                description: Project updated
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            404:
                description: Project not found
            500:
                description: Internal Server Error
        """
        authenticated_user_id = token_auth.current_user()
        try:
            ProjectAdminService.is_user_action_permitted_on_project(
                authenticated_user_id, project_id)
        except ValueError as e:
            error_msg = f"ProjectsRestAPI PATCH: {str(e)}"
            return {"Error": error_msg}, 403

        try:
            project_dto = ProjectDTO(request.get_json())
            project_dto.project_id = project_id
            project_dto.validate()
        except DataError as e:
            current_app.logger.error(f"Error validating request: {str(e)}")
            return {"Error": "Unable to update project"}, 400

        try:
            ProjectAdminService.update_project(project_dto,
                                               authenticated_user_id)
            return {"Status": "Updated"}, 200
        except InvalidGeoJson as e:
            return {"Invalid GeoJson": str(e)}, 400
        except NotFound as e:
            return {"Error": str(e) or "Project Not Found"}, 404
        except ProjectAdminServiceError as e:
            return {"Error": str(e)}, 400
        except Exception as e:
            error_msg = f"ProjectsRestAPI PATCH - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to update project"}, 500
Ejemplo n.º 9
0
    def post(self):
        """
        Creates a new organisation
        ---
        tags:
            - organisations
        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 organisation
              schema:
                properties:
                    name:
                        type: string
                        default: HOT
                    logo:
                        type: string
                        default: https://cdn.hotosm.org/tasking-manager/uploads/1588741335578_hot-logo.png
                    url:
                        type: string
                        default: https://hotosm.org
                    managers:
                        type: array
                        items:
                            type: string
                        default: [
                            user_1,
                            user_2
                        ]
        responses:
            201:
                description: Organisation created successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            402:
                description: Duplicate Name - Organisation name already exists
            500:
                description: Internal Server Error
        """
        request_user = User.get_by_id(token_auth.current_user())
        if request_user.role != 1:
            return {"Error": "Only admin users can create organisations."}, 403

        try:
            organisation_dto = NewOrganisationDTO(request.get_json())
            if request_user.username not in organisation_dto.managers:
                organisation_dto.managers.append(request_user.username)
            organisation_dto.validate()
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            org_id = OrganisationService.create_organisation(organisation_dto)
            return {"organisationId": org_id}, 201
        except OrganisationServiceError as e:
            return str(e), 400
        except Exception as e:
            error_msg = f"Organisation PUT - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Ejemplo n.º 10
0
    def patch(self, organisation_id):
        """
        Updates an organisation
        ---
        tags:
            - organisations
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - name: organisation_id
              in: path
              description: The unique organisation ID
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object for updating an organisation
              schema:
                properties:
                    name:
                        type: string
                        default: HOT
                    logo:
                        type: string
                        default: https://tasks.hotosm.org/assets/img/hot-tm-logo.svg
                    url:
                        type: string
                        default: https://hotosm.org
                    managers:
                        type: array
                        items:
                            type: string
                        default: [
                            user_1,
                            user_2
                        ]
        responses:
            201:
                description: Organisation updated successfully
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            403:
                description: Forbidden
            500:
                description: Internal Server Error
        """
        if not OrganisationService.can_user_manage_organisation(
            organisation_id, token_auth.current_user()
        ):
            return {"Error": "User is not an admin for the org"}, 403
        try:
            organisation_dto = UpdateOrganisationDTO(request.get_json())
            organisation_dto.organisation_id = organisation_id
            # Don't update organisation type if user is not admin
            if User.get_by_id(token_auth.current_user()).role != 1:
                org_type = OrganisationService.get_organisation_by_id(
                    organisation_id
                ).type
                organisation_dto.type = OrganisationType(org_type).name
            organisation_dto.validate()
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            OrganisationService.update_organisation(organisation_dto)
            return {"Status": "Updated"}, 200
        except NotFound as e:
            return {"Error": str(e)}, 404
        except OrganisationServiceError as e:
            return str(e), 402
        except Exception as e:
            error_msg = f"Organisation PATCH - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Ejemplo n.º 11
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
            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 Exception as e:
            error_msg = f"Campaign PUT - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": error_msg}, 500
Ejemplo n.º 12
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
Ejemplo n.º 13
0
    def patch(self):
        """
        Updates user info
        ---
        tags:
          - users
        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 to update a user
              schema:
                  properties:
                      name:
                          type: string
                          example: Your Name
                      city:
                          type: string
                          example: Your City
                      country:
                          type: string
                          example: Your Country
                      emailAddress:
                          type: string
                          example: [email protected]
                      twitterId:
                          type: string
                          example: twitter handle without @
                      facebookId:
                          type: string
                          example: facebook username
                      linkedinId:
                          type: string
                          example: linkedin username
                      gender:
                          type: string
                          description: gender
                      selfDescriptionGender:
                          type: string
                          description: gender self-description
        responses:
            200:
                description: Details saved
            400:
                description: Client Error - Invalid Request
            401:
                description: Unauthorized - Invalid credentials
            500:
                description: Internal Server Error
        """
        try:
            user_dto = UserDTO(request.get_json())
            if user_dto.email_address == "":
                user_dto.email_address = (
                    None  # Replace empty string with None so validation doesn't break
                )

            user_dto.validate()
            authenticated_user_id = token_auth.current_user()
            if authenticated_user_id != user_dto.id:
                return {"Error": "Unable to authenticate"}, 401
        except ValueError as e:
            return {"Error": str(e)}, 400
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return {"Error": "Unable to update user details"}, 400

        try:
            verification_sent = UserService.update_user_details(
                authenticated_user_id, user_dto)
            return verification_sent, 200
        except NotFound:
            return {"Error": "User not found"}, 404
        except Exception as e:
            error_msg = f"User GET - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"Error": "Unable to update user details"}, 500
Ejemplo n.º 14
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
        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

        # Obtain organisations
        try:
            results_dto = OrganisationService.get_organisations_as_dto(
                manager_user_id, 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
Ejemplo n.º 15
0
    def delete(self, project_id):
        """
        Delete a list of tasks from a project
        ---
        tags:
            - tasks
        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: Project ID the task is associated with
              required: true
              type: integer
              default: 1
            - in: body
              name: body
              required: true
              description: JSON object with a list of tasks to delete
              schema:
                  properties:
                      tasks:
                          type: array
                          items:
                              type: integer
                          default: [ 1, 2 ]
        responses:
            200:
                description: Task(s) deleted
            400:
                description: Bad request
            403:
                description: Forbidden
            404:
                description: Project or Task Not Found
            500:
                description: Internal Server Error
        """
        user_id = token_auth.current_user()
        user = UserService.get_user_by_id(user_id)
        if user.role != UserRole.ADMIN.value:
            return {
                "Error": "This endpoint action is restricted to ADMIN users."
            }, 403

        tasks_ids = request.get_json().get("tasks")
        if tasks_ids is None:
            return {"Error": "Tasks ids not provided"}, 400
        if type(tasks_ids) != list:
            return {"Error": "Tasks were not provided as a list"}, 400

        try:
            ProjectService.delete_tasks(project_id, tasks_ids)
            return {"Success": "Task(s) deleted"}, 200
        except NotFound as e:
            return {"Error": f"Project or Task Not Found: {e}"}, 404
        except ProjectServiceError as e:
            return {"Error": str(e)}, 403
        except Exception as e:
            current_app.logger.critical(e)
            return {"Error": "Unable to delete tasks"}, 500