Exemple #1
0
def explore(resource_id, owner, table):
    """
    Database exploration: returns the first rows of
    a database table. The db credentials are retrieved from
    Pyrog. The number of returned rows may be specified using
    query params (eg: /explore/<resource_id>/<table>?first=10).
    """
    limit = request.args.get("first", 10, type=int)
    # Get headers
    authorization_header = request.headers.get("Authorization")

    pyrog_client = pyrog.PyrogClient(authorization_header)
    resource = pyrog_client.get_resource(resource_id)

    # Get credentials
    if not resource["source"]["credential"]:
        raise OperationOutcome("credentialId is required to explore the DB.")

    credentials = resource["source"]["credential"]

    # Get filters
    filters = resource["filters"]

    try:
        explorer = DatabaseExplorer(credentials)
        return jsonify(
            explorer.explore(owner, table, limit=limit, filters=filters))
    except OperationalError as e:
        if "could not connect to server" in str(e):
            raise OperationOutcome(f"Could not connect to the database: {e}")
        else:
            raise OperationOutcome(e)
    except Exception as e:
        raise OperationOutcome(e)
Exemple #2
0
def get_owner_schema(owner):
    credentials = request.get_json()

    try:
        explorer = DatabaseExplorer(credentials)
        db_schema = explorer.get_owner_schema(owner)
        return jsonify(db_schema)
    except OperationalError as e:
        if "could not connect to server" in str(e):
            raise OperationOutcome(f"Could not connect to the database: {e}")
        else:
            raise OperationOutcome(e)
    except Exception as e:
        raise OperationOutcome(e)
Exemple #3
0
 def get_resource(self, resource_id):
     resp = self.run_graphql_query(resource_query,
                                   variables={"resourceId": resource_id})
     resource = resp["data"]["resource"]
     if not resource:
         raise OperationOutcome(
             f"Resource with id {resource_id} does not exist")
     return resource
Exemple #4
0
    def __init__(self, db_config: Optional[dict] = None):
        self._db_model = db_config.get("model")
        if self._db_model not in DB_DRIVERS:
            raise OperationOutcome(f"Database type {self._db_model} is unknown")

        self._sql_engine = create_engine(get_sql_url(self._db_model, db_config))
        self._metadata = MetaData(bind=self._sql_engine)

        self.db_schema = {}
Exemple #5
0
    def run_graphql_query(self,
                          graphql_query,
                          variables=None,
                          auth_required=True):
        """
        This function queries a GraphQL endpoint and returns a json parsed
        response. If auth_required is true, the auth token will be passed
        in an Authorization header (an error will be raised if
        the token is missing).
        """
        if not PYROG_URL:
            raise OperationOutcome("PYROG_URL is missing from environment")

        try:
            response = requests.post(
                PYROG_URL,
                headers=self.headers,
                json={
                    "query": graphql_query,
                    "variables": variables
                },
            )
        except requests.exceptions.ConnectionError:
            raise OperationOutcome("Could not connect to the Pyrog service")

        if response.status_code != 200:
            raise OperationOutcome(
                "Graphql query failed with returning code "
                f"{response.status_code}\n{response.json()}.")
        body = response.json()
        if "errors" in body:
            status_code = body["errors"][0].get("statusCode")
            error_message = body["errors"][0].get("message")
            if status_code == 401:
                raise AuthenticationError(error_message)
            if status_code == 403:
                raise AuthorizationError(
                    "You don't have the rights to perform this action.")
            raise OperationOutcome(
                f"GraphQL query failed with errors: {[err['message'] for err in body['errors']]}."
            )

        return body
Exemple #6
0
 def __init__(self, auth_header):
     if not auth_header:
         # Note that the id token is not mandatory because pyrog-server can
         # introspect the access to token with Hydra
         raise OperationOutcome(
             "An authorization token is required to forward queries to Pyrog-server"
         )
     self.headers = {
         "content-type": "application/json",
         "Authorization": auth_header
     }
Exemple #7
0
    def explore(self, owner: str, table_name: str, limit: int, filters=[]):
        """
        Returns the first rows of a table alongside the column names.
        """
        self.check_connection_exists()

        with session_scope(self) as session:
            try:
                return self.get_table_rows(
                    session=session,
                    owner=owner,
                    table_name=table_name,
                    limit=limit,
                    filters=filters,
                )
            except InvalidRequestError as e:
                if "requested table(s) not available" in str(e):
                    raise OperationOutcome(f"Table {table_name} does not exist in database")
                else:
                    raise OperationOutcome(e)
            except Exception as e:
                raise OperationOutcome(e)
Exemple #8
0
 def check_connection_exists(self):
     if not self._sql_engine:
         raise OperationOutcome("DatabaseExplorer was not provided with any credentials.")