server: improve DX for heroku integration

## Description ✍️
This PR aims to improve the developer experience when using a heroku postgres instance as source database. Better error messages and relevant documentation are added as a part of this PR.

## Changelog ✍️

__Component__ : server

__Type__: enhancement

__Product__: community-edition

### Short Changelog

Improve DX for heroku integration

### Related Issues ✍
https://hasurahq.atlassian.net/browse/GS-202

### Steps to test and verify ✍
- Add a new heroku postgres instance as DB source in Hasura
- Try adding an event trigger
- Improved error message will be emitted:
```json
{
    "arguments": [],
    "error": {
        "description": null,
        "exec_status": "FatalError",
        "hint": null,
        "message": "pgcrypto can only be created in heroku_ext schema. Hint: You can set \"extensions_schema\" to provide the schema to install the extensions. Refer to the documentation here: https://hasura.io/docs/latest/deployment/postgres-requirements/#pgcrypto-in-pg-search-path",
        "status_code": "P0001"
    },
    "prepared": false,
    "statement": "CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA public"
}
```

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6630
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Sean Park-Ross <94021366+seanparkross@users.noreply.github.com>
GitOrigin-RevId: a46d7c129a4e0378b7f33445f9bda11e0bddbd74
This commit is contained in:
Puru Gupta 2022-11-08 00:09:39 +05:30 committed by hasura-bot
parent 4f0ee2a648
commit a4eb5ad95d
4 changed files with 61 additions and 14 deletions

View File

@ -10,6 +10,8 @@ keywords:
sidebar_position: 40
---
import Thumbnail from '@site/src/components/Thumbnail';
# Postgres requirements
## Supported Postgres versions {#postgres-version-support}
@ -33,7 +35,7 @@ dedicated metadata database as described
### User Database Permissions
- (required) Read access to the `information_schema` and `pg_catalog` schemas, to query for list of tables. Note that
these permissions are usually available by default to all postgres users via
these permissions are usually available by default to all Postgres users via
[PUBLIC](https://www.postgresql.org/docs/current/sql-grant.html) grant.
- (required) Read access to the schemas (`public` or otherwise) if you only want to support queries.
- (optional) Write access to the schemas if you want to support mutations as well.
@ -82,7 +84,7 @@ CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- tables/schemas you want give to hasura. If you want expose the public
-- schema for GraphQL query then give permissions on public schema to the
-- hasura user.
-- Be careful to use these in your production db. Consult the postgres manual or
-- Be careful to use these in your production db. Consult the Postgres manual or
-- your DBA and give appropriate permissions.
-- grant all privileges on all tables in the public schema. This can be customised:
@ -148,7 +150,7 @@ GRANT SELECT ON ALL TABLES IN SCHEMA pg_catalog TO hasurauser;
-- tables/schemas you want give to hasura. If you want expose the public
-- schema for GraphQL query then give permissions on public schema to the
-- hasura user.
-- Be careful to use these in your production db. Consult the postgres manual or
-- Be careful to use these in your production db. Consult the Postgres manual or
-- your DBA and give appropriate permissions.
-- grant all privileges on all tables in the public schema. This can be customised:
@ -178,7 +180,7 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS;
### Notes for managed databases (AWS RDS, GCP Cloud SQL, etc.)
Hasura works out of the box with the default superuser, usually called "postgres", created by most managed cloud
Hasura works out of the box with the default superuser, usually called `postgres`, created by most managed cloud
database providers.
On some cloud providers, like **Google Cloud SQL**, if you are creating a new user and giving the
@ -218,10 +220,9 @@ You can **ignore** these warnings/errors or skip granting these permission as us
## **pgcrypto** in PG search path
Hasura GraphQL engine needs the `pgcrypto` Postgres extension to function.
During initialization, Hasura GraphQL engine tries to install the `pgcrypto` extension in the `public` schema, if it is
not already installed.
Hasura GraphQL Engine needs the `pgcrypto` Postgres extension for the following:
- Metadata Database
- User Database (only if Event Triggers are used)
It needs to be ensured that `pgcrypto` is installed in a schema which is in the Postgres
[search path](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) for the Postgres user/role that
@ -240,6 +241,31 @@ ALTER DATABASE <database_name> SET search_path TO schema1,schema2;
ALTER ROLE <hasura_role> SET search_path TO schema1,schema2;
```
### Metadata Database
During initialization, Hasura GraphQL Engine attempts to install the `pgcrypto` extension in the `public` schema if
it is not already installed. You may choose to install the Postgres extensions in a different schema by setting that
schema name in the `HASURA_GRAPHQL_METADATA_DATABASE_EXTENSIONS_SCHEMA` environment variable.
### User Database
Hasura's Event Triggers depend on the Postgres `pgcrypto` extension. Hasura GraphQL Engine creates this extension in
the source database if it hasn't already been installed when the first Event Trigger on the source is created. By
default, the extensions are created in the `public` schema but if you want to install the Postgres extensions in a
custom schema you can achieve this by specifying the schema name in the `extensions_schema` field of the source
configuration.
<Thumbnail src='/img/deployment/set-pg-extensions-schema.png' alt='Update extensions schema from console' width='1000px' />
:::info Note
If you're using Heroku Postgres instance for the first time, you will get an error `pgcrypto can only be created in heroku_ext schema`.
For metadata database, set environment variable `HASURA_GRAPHQL_METADATA_DATABASE_EXTENSIONS_SCHEMA: heroku_ext` and
for user database with event triggers, set `extensions_schema: heroku_ext` in source configuration.
:::
## Managed Postgres permissions {#managed-pg-permissions}
Hasura works out of the box with the default superuser, usually called `postgres`, created by most managed cloud

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -120,8 +120,12 @@ type TxT m a = TxET PGTxErr m a
catchE :: (Functor m) => (e -> e') -> TxET e m a -> TxET e' m a
catchE f action = TxET $ mapReaderT (withExceptT f) $ txHandler action
data PGTxErr
= PGTxErr !Text ![PrepArg] !Bool !PGErrInternal
data PGTxErr = PGTxErr
{ pgteStatement :: !Text,
pgteArguments :: ![PrepArg],
pgteIsPrepared :: !Bool,
pgteError :: !PGErrInternal
}
-- PGCustomErr !T.Text
deriving stock (Eq)

View File

@ -217,13 +217,30 @@ enablePgcryptoExtension (ExtensionsSchema extensionsSchema) = do
where
needsPGCryptoError e@(PG.PGTxErr _ _ _ err) =
case err of
PG.PGIUnexpected _ -> requiredError
PG.PGIUnexpected _ -> requiredError e
PG.PGIStatement pgErr -> case PG.edStatusCode pgErr of
Just "42501" -> err500 PostgresError permissionsMessage
_ -> requiredError
Just "P0001" -> requiredError (addHintForExtensionError pgErr)
_ -> requiredError e
where
requiredError =
(err500 PostgresError requiredMessage) {qeInternal = Just $ ExtraInternal $ toJSON e}
addHintForExtensionError pgErrDetail =
e
{ PG.pgteError =
PG.PGIStatement $
PG.PGStmtErrDetail
{ PG.edExecStatus = PG.edExecStatus pgErrDetail,
PG.edStatusCode = PG.edStatusCode pgErrDetail,
PG.edMessage =
liftA2
(<>)
(PG.edMessage pgErrDetail)
(Just ". Hint: You can set \"extensions_schema\" to provide the schema to install the extensions. Refer to the documentation here: https://hasura.io/docs/latest/deployment/postgres-requirements/#pgcrypto-in-pg-search-path"),
PG.edDescription = PG.edDescription pgErrDetail,
PG.edHint = PG.edHint pgErrDetail
}
}
requiredError pgTxErr =
(err500 PostgresError requiredMessage) {qeInternal = Just $ ExtraInternal $ toJSON pgTxErr}
requiredMessage =
"pgcrypto extension is required, but it could not be created;"
<> " encountered unknown postgres error"