Exemplo n.º 1
0
def finalize_response(path: str, obj: Dict[str, Any]) -> Dict[str, Any]:
    """
    finalize response objects by removing properties which are not readable and correcting path
    of nested objects.
    :param path: Path of the collection or non-collection class.
    :param obj: object being finalized
    :return: An object not containing any `readable=False` properties and having proper path
             of any nested object's url.
    """
    for prop in get_doc().parsed_classes[path]["class"].supportedProperty:
        # Skip not required properties which are not inserted yet.
        if not prop.required and prop.title not in obj:
            continue
        if prop.read is False:
            obj.pop(prop.title, None)
        elif isinstance(prop.prop, HydraLink):
            hydra_link = prop.prop
            range_class = hydra_link.range.replace("vocab:", "")
            nested_path, is_collection = get_nested_class_path(range_class)
            if is_collection:
                id = obj[prop.title]
                obj[prop.title] = "/{}/{}/{}".format(get_api_name(),
                                                     nested_path, id)
            else:
                obj[prop.title] = "/{}/{}".format(get_api_name(), nested_path)
        elif 'vocab:' in prop.prop:
            prop_class = prop.prop.replace("vocab:", "")
            id = obj[prop.title]
            obj[prop.title] = crud.get(id, prop_class, get_api_name(),
                                       get_session())
    return obj
Exemplo n.º 2
0
    def on_post(self, req, resp, id_: int, type_: str):
        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST.

        :param id_ - ID of Item to be updated
        :param type_ - Type(Class name) of Item to be updated
        """
        if get_authentication(resp):
            if req.auth is None:
                return failed_authentication(resp)
            else:
                try:
                    auth = check_authorization(req, get_session(resp))
                    if auth is False:
                        return failed_authentication(resp)
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)

        class_type = get_doc(
            resp).collections[type_]["collection"].class_.title

        if checkClassOp(resp, class_type, "POST"):
            # Check if class_type supports POST operation
            object_ = req.media
            obj_type = getType(resp, class_type, "POST")
            # Load new object and type
            if validObject(object_):
                if object_["@type"] == obj_type:
                    try:
                        # Update the right ID if the object is valid and matches
                        # type of Item
                        object_id = crud.update(object_=object_,
                                                id_=id_,
                                                type_=object_["@type"],
                                                session=get_session(resp),
                                                api_name=get_api_name(resp))
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url(resp) + get_api_name(resp) +
                            "/" + type_ + "/" + str(object_id)
                        }]
                        response = {
                            "message":
                            "Object with ID %s successfully updated" %
                            (object_id)
                        }
                        resp.media = response
                        return set_response_headers(resp, headers=headers_[0])
                    except Exception as e:
                        status_code, message = e.get_HTTP()
                        resp.media = message
                        return set_response_headers(resp, status_code)

            return set_response_headers(resp, status_code=falcon.HTTP_400)

        resp.status = falcon.HTTP_405
Exemplo n.º 3
0
def hydrafy(object_: Dict[str, Any], path: Optional[str]) -> Dict[str, Any]:
    """Add hydra context to objects."""
    if path == object_["@type"]:
        object_["@context"] = "/{}/contexts/{}.jsonld".format(
            get_api_name(), object_["@type"])
    else:
        object_["@context"] = "/{}/contexts/{}.jsonld".format(
            get_api_name(), path)
    return object_
Exemplo n.º 4
0
def hydrafy(object_: Dict[str, Any], path: Optional[str]) -> Dict[str, Any]:
    """Add hydra context to objects."""
    if path == object_["@type"]:
        object_["@context"] = "/" + get_api_name() + "/contexts/" + \
            object_["@type"] + ".jsonld"
    else:
        object_["@context"] = "/" + get_api_name() + "/contexts/" + \
            path + ".jsonld"
    return object_
Exemplo n.º 5
0
    def put(self, type_):
        """Add item to ItemCollection."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                try:
                    auth = check_authorization(request, get_session())
                    if auth is False:
                        return failed_authentication()
                except Exception as e:
                    status_code, message = e.get_HTTP()
                    return set_response_headers(jsonify(message), status_code=status_code)

        if checkEndpoint("PUT", type_):
            object_ = json.loads(request.data.decode('utf-8'))

            # Collections
            if type_ in get_doc().collections:

                collection = get_doc().collections[type_]["collection"]
                obj_type = collection.class_.title

                if validObject(object_):

                    if object_["@type"] == obj_type:
                        try:
                            object_id = crud.insert(object_=object_, session=get_session())
                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"+str(object_id)}]
                            response = {"message": "Object with ID %s successfully deleted" % (object_id)}
                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
                        except Exception as e:
                            status_code, message = e.get_HTTP()
                            return set_response_headers(jsonify(message), status_code=status_code)

                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)

            # Non Collection classes
            elif type_ in get_doc().parsed_classes and type_+"Collection" not in get_doc().collections:
                obj_type = getType(type_, "PUT")

                if object_["@type"] == obj_type:

                    if validObject(object_):
                        try:
                            object_id = crud.insert(object_=object_, session=get_session())
                            headers_ = [{"Location": get_hydrus_server_url()+get_api_name()+"/"+type_+"/"}]
                            response = {"message": "Object successfully added"}
                            return set_response_headers(jsonify(response), headers=headers_, status_code=201)
                        except Exception as e:
                            status_code, message = e.get_HTTP()
                            return set_response_headers(jsonify(message), status_code=status_code)

                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)

        abort(405)
Exemplo n.º 6
0
    def post(self, id_: int, type_: str) -> Response:
        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                try:
                    auth = check_authorization(request, get_session())
                    if auth is False:
                        return failed_authentication()
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        class_type = get_doc().collections[type_]["collection"].class_.title

        if checkClassOp(class_type, "POST"):

            object_ = json.loads(request.data.decode('utf-8'))
            obj_type = getType(class_type, "POST")

            if validObject(object_):

                if object_["@type"] == obj_type:
                    try:
                        object_id = crud.update(object_=object_,
                                                id_=id_,
                                                type_=object_["@type"],
                                                session=get_session(),
                                                api_name=get_api_name())
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url() + get_api_name() + "/" +
                            type_ + "/" + str(object_id)
                        }]
                        response = {
                            "message":
                            "Object with ID %s successfully updated" %
                            (object_id)
                        }
                        return set_response_headers(jsonify(response),
                                                    headers=headers_)

                    except Exception as e:
                        status_code, message = e.get_HTTP()  # type: ignore
                        return set_response_headers(jsonify(message),
                                                    status_code=status_code)

            return set_response_headers(jsonify({400: "Data is not valid"}),
                                        status_code=400)

        abort(405)
Exemplo n.º 7
0
    def on_post(self, req, resp, type_: str):
        """
        Method executed for POST requests.
        Used to update a non-collection class.

        :param type_ - Item type
        """
        if get_authentication(resp):
            if req.auth is None:
                return failed_authentication(resp)
            else:
                try:
                    auth = check_authorization(req, get_session(resp))
                    if auth is False:
                        return failed_authentication(resp)
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)

        endpoint_ = checkEndpoint(resp, "POST", type_)
        if endpoint_['method']:
            object_ = req.media
            if type_ in get_doc(
                    resp
            ).parsed_classes and type_ + "Collection" not in get_doc(
                    resp).collections:
                obj_type = getType(resp, type_, "POST")
                if validObject(object_):
                    if object_["@type"] == obj_type:
                        try:
                            crud.update_single(object_=object_,
                                               session=get_session(resp),
                                               api_name=get_api_name(resp))
                            headers_ = [{
                                "Location":
                                get_hydrus_server_url(resp) +
                                get_api_name(resp) + "/" + type_ + "/"
                            }]
                            response = {
                                "message": "Object successfully updated"
                            }
                            resp.media = response
                            return set_response_headers(resp,
                                                        headers=headers_[0])
                        except Exception as e:
                            status_code, message = e.get_HTTP()
                            resp.media = message
                            return set_response_headers(
                                resp, status_code=status_code)

                return set_response_headers(resp, status_code=falcon.HTTP_400)
Exemplo n.º 8
0
    def post(self, id_: str, path: str) -> Response:
        """Update object of type<path> at ID<id_> with new object_ using HTTP POST.

        :param id_ - ID of Item to be updated
        :param path - Path for Item type( Specified in APIDoc @id)
        """
        id_ = str(id_)
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response

        class_type = get_doc().collections[path]["collection"].class_.title

        if checkClassOp(class_type, "POST"):
            # Check if class_type supports POST operation
            object_ = json.loads(request.data.decode('utf-8'))
            obj_type = getType(class_type, "POST")
            # Load new object and type
            if validObject(object_):
                if object_["@type"] == obj_type:
                    try:
                        # Update the right ID if the object is valid and matches
                        # type of Item
                        object_id = crud.update(object_=object_,
                                                id_=id_,
                                                type_=object_["@type"],
                                                session=get_session(),
                                                api_name=get_api_name())
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url() + get_api_name() + "/" +
                            path + "/" + str(object_id)
                        }]
                        response = {
                            "message":
                            "Object with ID %s successfully updated" %
                            (object_id)
                        }
                        return set_response_headers(jsonify(response),
                                                    headers=headers_)

                    except (ClassNotFound, InstanceNotFound, InstanceExists,
                            PropertyNotFound) as e:
                        status_code, message = e.get_HTTP()
                        return set_response_headers(jsonify(message),
                                                    status_code=status_code)

            return set_response_headers(jsonify({400: "Data is not valid"}),
                                        status_code=400)

        abort(405)
Exemplo n.º 9
0
    def post(self, id_: int, type_: str) -> Response:
        """Update object of type<type_> at ID<id_> with new object_ using HTTP POST.

        :param id_ - ID of Item to be updated
        :param type_ - Type(Class name) of Item to be updated
        """
        auth_response = check_authentication_response()
        if type(auth_response) == Response:
            return auth_response

        class_type = get_doc().collections[type_]["collection"].class_.title

        if checkClassOp(class_type, "POST"):
            # Check if class_type supports POST operation
            object_ = json.loads(request.data.decode('utf-8'))
            obj_type = getType(class_type, "POST")
            # Load new object and type
            if validObject(object_):
                if object_["@type"] == obj_type:
                    try:
                        # Update the right ID if the object is valid and matches
                        # type of Item
                        object_id = crud.update(object_=object_,
                                                id_=id_,
                                                type_=object_["@type"],
                                                session=get_session(),
                                                api_name=get_api_name())
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url() + get_api_name() + "/" +
                            type_ + "/" + str(object_id)
                        }]
                        response = {
                            "message":
                            "Object with ID %s successfully updated" %
                            (object_id)
                        }
                        return set_response_headers(jsonify(response),
                                                    headers=headers_)

                    except Exception as e:
                        status_code, message = e.get_HTTP()  # type: ignore
                        return set_response_headers(jsonify(message),
                                                    status_code=status_code)

            return set_response_headers(jsonify({400: "Data is not valid"}),
                                        status_code=400)

        abort(405)
Exemplo n.º 10
0
    def on_get(self, req, resp, type_):
        """Retrieve a collection of items from the database."""
        if get_authentication(resp):
            if req.auth is None:
                return failed_authentication(resp)
            else:
                try:
                    auth = check_authorization(req, get_session(resp))
                    if auth is False:
                        return failed_authentication(resp)
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)

        if checkEndpoint(resp, "GET", type_):
            # Collections
            if type_ in get_doc(resp).collections:

                collection = get_doc(resp).collections[type_]["collection"]
                try:
                    resp.media = crud.get_collection(get_api_name(resp),
                                                     collection.class_.title,
                                                     session=get_session(resp))
                    return set_response_headers(resp)

                except Exception as e:
                    status_code, message = e.get_HTTP()
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)

            # Non Collection classes
            elif type_ in get_doc(
                    resp
            ).parsed_classes and type_ + "Collection" not in get_doc(
                    resp).collections:
                try:
                    resp.media = hydrafy(
                        resp,
                        crud.get_single(type_,
                                        api_name=get_api_name(resp),
                                        session=get_session(resp)))
                    return set_response_headers(resp)

                except Exception as e:
                    status_code, message = e.get_HTTP()
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)
Exemplo n.º 11
0
    def get(self, type_: str) -> Response:
        """Retrieve a collection of items from the database."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                try:
                    auth = check_authorization(request, get_session())
                    if auth is False:
                        return failed_authentication()
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        endpoint_ = checkEndpoint("GET", type_)
        if endpoint_['method']:
            # Collections
            if type_ in get_doc().collections:

                collection = get_doc().collections[type_]["collection"]
                try:
                    response = crud.get_collection(get_api_name(),
                                                   collection.class_.title,
                                                   session=get_session())
                    return set_response_headers(jsonify(hydrafy(response)))

                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

            # Non Collection classes
            elif type_ in get_doc(
            ).parsed_classes and type_ + "Collection" not in get_doc(
            ).collections:
                try:
                    response = crud.get_single(type_,
                                               api_name=get_api_name(),
                                               session=get_session())
                    return set_response_headers(jsonify(hydrafy(response)))

                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        abort(endpoint_['status'])
Exemplo n.º 12
0
    def post(self, type_: str) -> Response:
        """Update Non Collection class item."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                try:
                    auth = check_authorization(request, get_session())
                    if auth is False:
                        return failed_authentication()
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        endpoint_ = checkEndpoint("POST", type_)
        if endpoint_['method']:
            object_ = json.loads(request.data.decode('utf-8'))

            if type_ in get_doc(
            ).parsed_classes and type_ + "Collection" not in get_doc(
            ).collections:
                obj_type = getType(type_, "POST")

                if validObject(object_):

                    if object_["@type"] == obj_type:
                        # try:
                        crud.update_single(object_=object_,
                                           session=get_session(),
                                           api_name=get_api_name())
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url() + get_api_name() + "/" +
                            type_ + "/"
                        }]
                        response = {"message": "Object successfully updated"}
                        return set_response_headers(jsonify(response),
                                                    headers=headers_)
                    # except Exception as e:
                    #     status_code, message = e.get_HTTP()
                    #     return set_response_headers(jsonify(message), status_code=status_code)

                return set_response_headers(jsonify({400:
                                                     "Data is not valid"}),
                                            status_code=400)

        abort(endpoint_['status'])
Exemplo n.º 13
0
    def get(self, id_: int, type_: str) -> Response:
        """
        GET object with id = id_ from the database.

        :param id : Item ID
        :param type_ : Item type
        """
        auth_response = check_authentication_response()
        if type(auth_response) == Response:
            return auth_response

        class_type = get_doc().collections[type_]["collection"].class_.title

        if checkClassOp(class_type, "GET"):
            # Check if class_type supports GET operation
            try:
                # Try getting the Item based on ID and Class type
                response = crud.get(id_,
                                    class_type,
                                    api_name=get_api_name(),
                                    session=get_session())
                return set_response_headers(jsonify(hydrafy(response)))

            except Exception as e:
                status_code, message = e.get_HTTP()  # type: ignore
                return set_response_headers(jsonify(message),
                                            status_code=status_code)
        abort(405)
Exemplo n.º 14
0
    def get(self, id_, type_):
        """GET object with id = id_ from the database."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                auth = check_authorization(request, get_session())
                if auth is False:
                    return failed_authentication()

        class_type = get_doc().collections[type_]["collection"].class_.title

        if checkClassOp(class_type, "GET"):

            try:
                response = crud.get(id_,
                                    class_type,
                                    api_name=get_api_name(),
                                    session=get_session())
                return set_response_headers(jsonify(hydrafy(response)))

            except Exception as e:
                status_code, message = e.get_HTTP()
                return set_response_headers(jsonify(message),
                                            status_code=status_code)

        abort(405)
Exemplo n.º 15
0
def set_response_headers(resp: falcon.Response, ct: str="application/ld+json", headers: Dict[str, Any]={}, status_code = falcon.HTTP_200) -> falcon.Response:
    resp.status = status_code
    resp.set_headers(headers)
    resp.set_header('Content-type', ct)
    resp.set_header('Link' ,'<' + get_hydrus_server_url(resp) + \
        get_api_name(resp)+'/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"')
    return resp
Exemplo n.º 16
0
    def put(self, id_: str, path: str) -> Response:
        """Add new object_ optional <id_> parameter using HTTP PUT.

        :param id_ - ID of Item to be updated
        :param path - Path for Item type( Specified in APIDoc @id) to be updated
        """
        id_ = str(id_)
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response

        class_type = get_doc().collections[path]["collection"].class_.title
        if checkClassOp(class_type, "PUT"):
            # Check if class_type supports PUT operation
            object_ = json.loads(request.data.decode('utf-8'))
            obj_type = getType(class_type, "PUT")
            # Load new object and type
            if validObject(object_) and object_["@type"] == obj_type:
                    try:
                        # Add the object with given ID
                        object_id = crud.insert(object_=object_, id_=id_, session=get_session())
                        headers_ = [{"Location": "{}{}/{}/{}".format(
                                get_hydrus_server_url(), get_api_name(), path, object_id)}]
                        response = {
                            "message": "Object with ID {} successfully added".format(object_id)}
                        return set_response_headers(
                            jsonify(response), headers=headers_, status_code=201)
                    except (ClassNotFound, InstanceExists, PropertyNotFound) as e:
                        status_code, message = e.get_HTTP()
                        return set_response_headers(jsonify(message), status_code=status_code)
            else:
                return set_response_headers(jsonify({400: "Data is not valid"}), status_code=400)
        else:
            abort(405)
Exemplo n.º 17
0
    def on_get(self, req, resp, id_, type_):
        """GET object with id = id_ from the database."""

        if get_authentication(resp):
            if req.auth is None:
                return failed_authentication(resp)
            else:
                try:
                    auth = check_authorization(req, get_session(resp))
                    if auth is False:
                        return failed_authentication(resp)
                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    resp.media = message
                    return set_response_headers(resp, status_code=status_code)

        class_type = get_doc(resp).collections[type_]["collection"].class_.title

        if checkClassOp(resp, class_type, "GET"):

            try:
                resp.media = hydrafy(resp, crud.get(id_, class_type, api_name=get_api_name(resp), session=get_session(resp)))
                return set_response_headers(resp)

            except Exception as e:
                status_code, message = e.get_HTTP()
                resp.media = message
                return set_response_headers(resp, status_code= status_code)

        resp.status = falcon.HTTP_405
Exemplo n.º 18
0
    def get(self, id_: str, path: str) -> Response:
        """
        GET object with id = id_ from the database.

        :param id : Item ID
        :param path : Path for Item ( Specified in APIDoc @id)
        """
        id_ = str(id_)
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response

        class_type = get_doc().collections[path]["collection"].class_.title

        if checkClassOp(class_type, "GET"):
            # Check if class_type supports GET operation
            try:
                # Try getting the Item based on ID and Class type
                response = crud.get(id_,
                                    class_type,
                                    api_name=get_api_name(),
                                    session=get_session())

                return set_response_headers(
                    jsonify(hydrafy(response, path=path)))

            except (ClassNotFound, InstanceNotFound) as e:
                status_code, message = e.get_HTTP()
                return set_response_headers(jsonify(message),
                                            status_code=status_code)
        abort(405)
Exemplo n.º 19
0
    def put(self, path, int_list="") -> Response:
        """
        To insert multiple objects into the database
        :param path: endpoint
        :param int_list: Optional String containing ',' separated ID's
        :return:
        """
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response

        endpoint_ = checkEndpoint("PUT", path)
        if endpoint_['method']:
            # If endpoint and PUT method is supported in the API
            object_ = json.loads(request.data.decode('utf-8'))
            object_ = object_["data"]
            if path in get_doc().collections:
                # If collection name in document's collections
                collection = get_doc().collections[path]["collection"]
                # title of HydraClass object corresponding to collection
                obj_type = collection.class_.title
                if validObjectList(object_):
                    type_result = type_match(object_, obj_type)
                    # If Item in request's JSON is a valid object
                    # ie. @type is one of the keys in object_
                    if type_result:
                        # If the right Item type is being added to the
                        # collection
                        try:
                            # Insert object and return location in Header
                            object_id = crud.insert_multiple(
                                objects_=object_,
                                session=get_session(),
                                id_=int_list)
                            headers_ = [{
                                "Location":
                                "{}/{}/{}".format(get_hydrus_server_url(),
                                                  get_api_name(), path,
                                                  object_id)
                            }]
                            response = {
                                "message":
                                "Object with ID {} successfully added".format(
                                    object_id)
                            }
                            return set_response_headers(jsonify(response),
                                                        headers=headers_,
                                                        status_code=201)
                        except (ClassNotFound, InstanceExists,
                                PropertyNotFound) as e:
                            status_code, message = e.get_HTTP()
                            return set_response_headers(
                                jsonify(message), status_code=status_code)

                return set_response_headers(jsonify({400:
                                                     "Data is not valid"}),
                                            status_code=400)

        abort(endpoint_['status'])
Exemplo n.º 20
0
    def get(self, path: str) -> Response:
        """
        Retrieve a collection of items from the database.
        """
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response
        endpoint_ = checkEndpoint("GET", path)
        if endpoint_['method']:
            # If endpoint and GET method is supported in the API
            if path in get_doc().collections:
                # If collection name in document's collections
                collection = get_doc().collections[path]["collection"]
                try:
                    # Get collection details from the database
                    response = crud.get_collection(get_api_name(),
                                                   collection.class_.title,
                                                   session=get_session(),
                                                   path=path)
                    return set_response_headers(
                        jsonify(hydrafy(response, path=path)))

                except ClassNotFound as e:
                    status_code, message = e.get_HTTP()
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

            # If class is supported
            elif path in get_doc(
            ).parsed_classes and path + "Collection" not in get_doc(
            ).collections:
                try:
                    class_type = get_doc().parsed_classes[path]['class'].title
                    response = crud.get_single(class_type,
                                               api_name=get_api_name(),
                                               session=get_session(),
                                               path=path)
                    return set_response_headers(
                        jsonify(hydrafy(response, path=path)))

                except (ClassNotFound, InstanceNotFound) as e:
                    status_code, message = e.get_HTTP()
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        abort(endpoint_['status'])
Exemplo n.º 21
0
    def post(self, path: str) -> Response:
        """
        Method executed for POST requests.
        Used to update a non-collection class.

        :param path - Path for Item type ( Specified in APIDoc @id)
        """
        auth_response = check_authentication_response()
        if isinstance(auth_response, Response):
            return auth_response

        endpoint_ = checkEndpoint("POST", path)
        if endpoint_['method']:
            object_ = json.loads(request.data.decode('utf-8'))
            if path in get_doc().parsed_classes and "{}Collection".format(path) not in get_doc(
            ).collections:
                obj_type = getType(path, "POST")
                if check_read_only_props(obj_type, object_):
                    if object_["@type"] == obj_type and check_required_props(
                            obj_type, object_) and validObject(object_):
                        try:
                            crud.update_single(
                                object_=object_,
                                session=get_session(),
                                api_name=get_api_name(),
                                path=path)

                            headers_ = [
                                {"Location": "{}/{}/".format(
                                    get_hydrus_server_url(), get_api_name(), path)}]
                            response = {
                                "message": "Object successfully updated"}
                            return set_response_headers(
                                jsonify(response), headers=headers_)
                        except (ClassNotFound, InstanceNotFound,
                                InstanceExists, PropertyNotFound) as e:
                            status_code, message = e.get_HTTP()
                            return set_response_headers(
                                jsonify(message), status_code=status_code)

                    return set_response_headers(
                        jsonify({400: "Data is not valid"}), status_code=400)
                else:
                    abort(405)

        abort(endpoint_['status'])
Exemplo n.º 22
0
def finalize_response(path: str, obj: Dict[str, Any]) -> Dict[str, Any]:
    """
    finalize response objects by removing properties which are not readable and correcting path
    of nested objects.
    :param path: Path of the collection or non-collection class.
    :param obj: object being finalized
    :return: An object not containing any `readable=False` properties and having proper path
             of any nested object's url.
    """
    collections, parsed_classes = get_collections_and_parsed_classes()
    expanded_base_url = DocUrl.doc_url
    if path in collections:
        members = list()
        for member in obj["members"]:
            member_id = member[0]
            member_type = member[1]
            member_path = get_path_from_type(member_type)
            member = {
                "@type":
                "hydra:Link",
                "@id":
                f"{get_host_domain()}/{get_api_name()}/{member_path}/{member_id}",
            }
            members.append(member)
        obj['members'] = members
        return obj
    else:
        # path is of a non-collection class
        supported_properties = get_doc(
        ).parsed_classes[path]["class"].supportedProperty
        expanded_base_url = DocUrl.doc_url
        for prop in supported_properties:
            # Skip not required properties which are not inserted yet.
            if not prop.required and prop.title not in obj:
                continue
            # if prop.read is False:
            #     obj.pop(prop.title, None)
            elif isinstance(prop.prop, HydraLink):
                hydra_link = prop.prop
                range_class = hydra_link.range.split(expanded_base_url)[1]
                nested_path, is_collection = get_nested_class_path(range_class)
                if is_collection:
                    id = obj[prop.title]
                    obj[prop.title] = f"/{get_api_name()}/{nested_path}/{id}"
                else:
                    obj[prop.title] = f"/{get_api_name()}/{nested_path}"
            elif expanded_base_url in prop.prop:
                prop_class = prop.prop.split(expanded_base_url)[1]
                prop_class_path = parsed_classes[prop_class]['class'].path
                id = obj[prop.title]
                class_resp = crud.get(id,
                                      prop_class,
                                      get_api_name(),
                                      get_session(),
                                      path=prop_class_path)
                obj[prop.title] = finalize_response(prop_class_path,
                                                    class_resp)
        return obj
Exemplo n.º 23
0
    def post(self, type_: str) -> Response:
        """
        Method executed for POST requests.
        Used to update a non-collection class.

        :param type_ - Item type
        """
        auth_response = check_authentication_response()
        if type(auth_response) == Response:
            return auth_response

        endpoint_ = checkEndpoint("POST", type_)
        if endpoint_['method']:
            object_ = json.loads(request.data.decode('utf-8'))
            if type_ in get_doc(
            ).parsed_classes and type_ + "Collection" not in get_doc(
            ).collections:
                obj_type = getType(type_, "POST")
                if validObject(object_):
                    if object_["@type"] == obj_type:
                        try:
                            crud.update_single(object_=object_,
                                               session=get_session(),
                                               api_name=get_api_name())
                            headers_ = [{
                                "Location":
                                get_hydrus_server_url() + get_api_name() +
                                "/" + type_ + "/"
                            }]
                            response = {
                                "message": "Object successfully updated"
                            }
                            return set_response_headers(jsonify(response),
                                                        headers=headers_)
                        except (ClassNotFound, InstanceNotFound,
                                InstanceExists, PropertyNotFound) as e:
                            status_code, message = e.get_HTTP()
                            return set_response_headers(
                                jsonify(message), status_code=status_code)

                return set_response_headers(jsonify({400:
                                                     "Data is not valid"}),
                                            status_code=400)

        abort(endpoint_['status'])
Exemplo n.º 24
0
def set_response_headers(resp, ct="application/ld+json", headers=[], status_code=200):
    """Set the response headers."""
    resp.status_code = status_code
    for header in headers:
        resp.headers[list(header.keys())[0]] = header[list(header.keys())[0]]
    resp.headers['Content-type'] = ct
    resp.headers['Link'] = '<' + get_hydrus_server_url() + \
        get_api_name()+'/vocab>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"'
    return resp
Exemplo n.º 25
0
    def get(self, type_: str) -> Response:
        """
        Retrieve a collection of items from the database.
        """
        auth_response = check_authentication_response()
        if type(auth_response) == Response:
            return auth_response
        endpoint_ = checkEndpoint("GET", type_)
        if endpoint_['method']:
            # If endpoint and GET method is supported in the API
            if type_ in get_doc().collections:
                # If collection name in document's collections
                collection = get_doc().collections[type_]["collection"]
                try:
                    # Get collection details from the database
                    response = crud.get_collection(get_api_name(),
                                                   collection.class_.title,
                                                   session=get_session())
                    return set_response_headers(jsonify(hydrafy(response)))

                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

            # If class is supported
            elif type_ in get_doc(
            ).parsed_classes and type_ + "Collection" not in get_doc(
            ).collections:
                try:
                    response = crud.get_single(type_,
                                               api_name=get_api_name(),
                                               session=get_session())
                    return set_response_headers(jsonify(hydrafy(response)))

                except Exception as e:
                    status_code, message = e.get_HTTP()  # type: ignore
                    return set_response_headers(jsonify(message),
                                                status_code=status_code)

        abort(endpoint_['status'])
Exemplo n.º 26
0
def finalize_response(class_type: str, obj: Dict[str, Any]) -> Dict[str, Any]:
    """
    finalize response objects by removing write-only properties and correcting path
    of nested objects.
    :param class_type: class name of the object
    :param obj: object being finalized
    :return: An object not containing any write-only properties and having proper path
             of any nested object's url.
    """
    for prop in get_doc().parsed_classes[class_type]["class"].supportedProperty:
        if prop.write:
            obj.pop(prop.title, None)
        elif 'vocab:' in prop.prop:
            prop_class = prop.prop.replace("vocab:", "")
            nested_path, is_collection = get_nested_class_path(prop_class)
            if is_collection:
                id = obj[prop.title]
                obj[prop.title] = "/{}/{}/{}".format(get_api_name(), nested_path, id)
            else:
                obj[prop.title] = "/{}/{}".format(get_api_name(), nested_path)
    return obj
Exemplo n.º 27
0
def items_post_check_support(id_, object_, class_path, path, is_collection):
    """Check if class_type supports POST operation"""
    collections, parsed_classes = get_collections_and_parsed_classes()
    if path in parsed_classes:
        class_path = path
        obj_type = getType(path, "PUT")
    elif path in collections:
        collection = collections[path]["collection"]
        class_path = collection.path
        obj_type = collection.name
    link_props, link_type_check = get_link_props(class_path, object_)
    # Load new object and type
    if (validate_object(object_, obj_type, class_path) and link_type_check):
        if is_collection:
            object_ = parse_collection_members(object_)
        try:
            # Update the right ID if the object is valid and matches
            # type of Item
            object_id = crud.update(object_=object_,
                                    id_=id_,
                                    type_=object_["@type"],
                                    session=get_session(),
                                    api_name=get_api_name(),
                                    collection=is_collection)
            method = "POST"
            resource_url = f"{get_hydrus_server_url()}{get_api_name()}/{path}/{object_id}"
            last_job_id = crud.get_last_modification_job_id(
                session=get_session())
            new_job_id = crud.insert_modification_record(method,
                                                         resource_url,
                                                         session=get_session())
            send_sync_update(socketio=socketio,
                             new_job_id=new_job_id,
                             last_job_id=last_job_id,
                             method=method,
                             resource_url=resource_url)
            headers_ = [{"Location": resource_url}]
            status_description = (f"Object with ID {object_id} successfully "
                                  "updated")
            status = HydraStatus(code=200,
                                 title="Object updated",
                                 desc=status_description)
            return set_response_headers(jsonify(status.generate()),
                                        headers=headers_)

        except (ClassNotFound, InstanceNotFound, InstanceExists,
                PropertyNotFound) as e:
            error = e.get_HTTP()
            return error_response(error)
    else:
        error = HydraError(code=400, title="Data is not valid")
        return error_response(error)
Exemplo n.º 28
0
def set_response_headers(resp: Response,
                         ct: str = "application/ld+json",
                         headers: List[Dict[str, Any]] = [],
                         status_code: int = 200) -> Response:
    """Set the response headers."""
    resp.status_code = status_code
    for header in headers:
        resp.headers[list(header.keys())[0]] = header[list(header.keys())[0]]
    resp.headers['Content-type'] = ct
    link = "http://www.w3.org/ns/hydra/core#apiDocumentation"
    resp.headers['Link'] = '<{}{}/vocab>; rel="{}"'.format(
        get_hydrus_server_url(), get_api_name(), link)
    return resp
Exemplo n.º 29
0
def item_collection_get_response(path: str) -> Response:
    """
    Handles GET operation on item collection classes.

    :param path: Path for Item Collection
    :type path: str
    :return: Appropriate response for the GET operation.
    :rtype: Response
    """
    search_params = request.args.to_dict()
    collections, parsed_classes = get_collections_and_parsed_classes()
    api_name = get_api_name()
    expanded_base_url = DocUrl.doc_url
    # If endpoint and GET method is supported in the API and class is supported
    if path in parsed_classes:
        abort(405)
    if path in collections:
        collection = collections[path]["collection"]
        class_name = collection.manages["object"].split(expanded_base_url)[1]
        collection_manages_class = parsed_classes[class_name]["class"]
        class_type = collection_manages_class.title
        class_path = collection_manages_class.path
    try:
        # Get collection details from the database
        # create partial function for crud operation
        crud_response = partial(crud.get_collection,
                                api_name,
                                class_type,
                                session=get_session(),
                                path=path,
                                search_params=search_params,
                                collection=False)
        if get_pagination():
            # Get paginated response
            response = crud_response(paginate=True, page_size=get_page_size())
        else:
            # Get whole collection
            response = crud_response(paginate=False)

        response["search"] = add_iri_template(path=class_path,
                                              API_NAME=api_name,
                                              collection_path=path)

        return set_response_headers(jsonify(hydrafy(response, path=path)))

    except (ClassNotFound, PageNotFound, InvalidSearchParameter,
            OffsetOutOfRange) as e:
        error = e.get_HTTP()
        return error_response(error)
Exemplo n.º 30
0
    def put(self, id_, type_):
        """Add new object_ optional <id_> parameter using HTTP PUT."""
        if get_authentication():
            if request.authorization is None:
                return failed_authentication()
            else:
                auth = check_authorization(request, get_session())
                if auth is False:
                    return failed_authentication()

        class_type = get_doc().collections[type_]["collection"].class_.title

        if checkClassOp(class_type, "PUT"):

            object_ = json.loads(request.data.decode('utf-8'))
            obj_type = getType(class_type, "PUT")

            if validObject(object_):

                if object_["@type"] == obj_type:
                    try:
                        object_id = crud.insert(object_=object_,
                                                id_=id_,
                                                session=get_session())
                        headers_ = [{
                            "Location":
                            get_hydrus_server_url() + get_api_name() + "/" +
                            type_ + "/" + str(object_id)
                        }]
                        response = {
                            "message":
                            "Object with ID %s successfully added" %
                            (object_id)
                        }
                        return set_response_headers(jsonify(response),
                                                    headers=headers_,
                                                    status_code=201)

                    except Exception as e:
                        status_code, message = e.get_HTTP()
                        return set_response_headers(jsonify(message),
                                                    status_code=status_code)

            return set_response_headers(jsonify({400: "Data is not valid"}),
                                        status_code=400)

        abort(405)