mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-13 19:33:55 +03:00
parent
d775d94fc4
commit
b26e023483
@ -44,6 +44,7 @@
|
||||
- console: add the ability to delete a role in permissions summary page (close #3353) (#4987)
|
||||
- console: fix styling of table row contents on tables on relationship page (#4974)
|
||||
- cli: handle missing files during metadata apply (close #5163) (#5170)
|
||||
- docs: add pages on remote joins (close #4911) (#5132)
|
||||
- docs: add page on scheduled triggers (close #4913) (#5141)
|
||||
- docs: add page on Relay schema (close #4912) (#5150)
|
||||
|
||||
|
1
community/boilerplates/remote-schemas/auth0-wrapper/.gitignore
vendored
Normal file
1
community/boilerplates/remote-schemas/auth0-wrapper/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
@ -0,0 +1,65 @@
|
||||
# Auth0 wrapper - Boilerplate to write a GraphQL server that wraps Auth0's REST API
|
||||
|
||||
This boilerplate gives an example of writing a GraphQL service to wrap [Auth0](http://auth0.com/)'s REST API.
|
||||
You can add this Auth0 wrapper as a remote schema in Hasura.
|
||||
|
||||
## Stack
|
||||
|
||||
Node 14.4
|
||||
|
||||
Apollo Server (GraphQL framework)
|
||||
|
||||
## REST API
|
||||
|
||||
GET: `https://[YOUR AUTH0 ROOT].auth0.com/api/v2/users/{id}`
|
||||
|
||||
GET: `https://[YOUR AUTH0 ROOT].auth0.com/api/v2/users`
|
||||
|
||||
You can get a token via [Auth0's Management API](https://auth0.com/docs/api/management/v2).
|
||||
|
||||
## GraphQL API
|
||||
|
||||
We convert the above REST API into the following GraphQL API:
|
||||
|
||||
```
|
||||
type Query {
|
||||
auth0 (auth0_id: String, email: String): Auth0Info
|
||||
}
|
||||
|
||||
type Auth0Info {
|
||||
user_id: String,
|
||||
email: String,
|
||||
email_verified: Boolean,
|
||||
name: String,
|
||||
picture: String,
|
||||
nickname: String,
|
||||
created_at: String,
|
||||
last_login: String,
|
||||
logins_count: Int
|
||||
}
|
||||
```
|
||||
|
||||
## Deployment (Using Heroku)
|
||||
|
||||
You need a Heroku account and `heroku-cli` installed. Execute the following commands in a terminal:
|
||||
|
||||
1. Log into Heroku
|
||||
|
||||
```bash
|
||||
heroku login
|
||||
```
|
||||
|
||||
2. Create GRAPHQL API app
|
||||
|
||||
```bash
|
||||
# in current directory (community/boilerplates/remote-schemas/auth0-wrapper)
|
||||
heroku create
|
||||
```
|
||||
|
||||
3. Deploy GRAPHQL API app
|
||||
|
||||
```bash
|
||||
git push heroku master
|
||||
```
|
||||
|
||||
The final step will also return a HTTPS URL in the output. Now, you can go to Hasura console and add this URL as a remote schema to allow querying it via Hasura.
|
94
community/boilerplates/remote-schemas/auth0-wrapper/index.js
Normal file
94
community/boilerplates/remote-schemas/auth0-wrapper/index.js
Normal file
@ -0,0 +1,94 @@
|
||||
const fetch = require('node-fetch');
|
||||
const { ApolloServer, ApolloError } = require('apollo-server');
|
||||
const { makeExecutableSchema } = require('graphql-tools');
|
||||
|
||||
const ADMIN_TOKEN = process.env.AUTH0_ADMIN_TOKEN;
|
||||
const ENDPOINT = process.env.AUTH0_ENDPOINT
|
||||
|
||||
const OPTIONS = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Authorization": `Bearer ${ADMIN_TOKEN}`
|
||||
}
|
||||
};
|
||||
|
||||
const getUserFromAuth0 = async (auth0_id) => {
|
||||
if (!ADMIN_TOKEN) {
|
||||
throw new ApolloError("no admin token provided");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
`${ENDPOINT}/${auth0_id}`,
|
||||
OPTIONS
|
||||
);
|
||||
|
||||
try {
|
||||
const respObj = await response.json();
|
||||
return respObj;
|
||||
} catch (e) {
|
||||
throw new ApolloError(e);
|
||||
}
|
||||
}
|
||||
|
||||
const getUserFromAuth0Email = async (email) => {
|
||||
if (!ADMIN_TOKEN) {
|
||||
throw new ApolloError("no admin token provided");
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
ENDPOINT,
|
||||
OPTIONS
|
||||
);
|
||||
|
||||
try {
|
||||
const respObj = await response.json();
|
||||
return respObj.find(u => u.email === email);
|
||||
} catch (e) {
|
||||
throw new ApolloError(e);
|
||||
}
|
||||
}
|
||||
|
||||
const typeDefs = `
|
||||
type Query {
|
||||
auth0 (auth0_id: String, email: String): Auth0Info
|
||||
}
|
||||
|
||||
type Auth0Info {
|
||||
user_id: String,
|
||||
email: String,
|
||||
email_verified: Boolean,
|
||||
name: String,
|
||||
picture: String,
|
||||
nickname: String,
|
||||
created_at: String,
|
||||
last_login: String,
|
||||
logins_count: Int
|
||||
}
|
||||
`;
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
auth0: async (_, args) => {
|
||||
let response;
|
||||
try {
|
||||
if (args.auth0_id) {
|
||||
response = await getUserFromAuth0(args.auth0_id);
|
||||
|
||||
} else {
|
||||
response = await getUserFromAuth0Email(args.email);
|
||||
}
|
||||
return response;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schema = makeExecutableSchema({ typeDefs, resolvers });
|
||||
|
||||
const server = new ApolloServer({ schema, introspection: true, playground: true });
|
||||
|
||||
server.listen(process.env.PORT || 3000).then(({ url }) => {
|
||||
console.log('Listening at ' + url);
|
||||
});
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "auth0-graphql",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-server": "^2.9.0",
|
||||
"graphql": "^14.5.3",
|
||||
"graphql-tools": "^4.0.5",
|
||||
"node-fetch": "^2.6.0"
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ Relationships
|
||||
*************
|
||||
|
||||
Custom object types can be connected to the rest of the graph by setting up
|
||||
:ref:`relationships <relationships>` with tables/views.
|
||||
:ref:`table relationships <table_relationships>` with tables/views.
|
||||
|
||||
**For example**, given the object type:
|
||||
|
||||
|
@ -156,7 +156,7 @@ the author's ID*):
|
||||
Using relationships or nested objects
|
||||
*************************************
|
||||
|
||||
You can leverage :ref:`relationships <relationships>` to define permission rules with fields
|
||||
You can leverage :ref:`table relationships <table_relationships>` to define permission rules with fields
|
||||
from a nested object.
|
||||
|
||||
**For example**, let's say you have an object relationship called ``agent`` from the ``authors`` table to another table
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
.. _getting_started:
|
||||
|
||||
Getting started
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
.. contents:: Table of contents
|
||||
|
@ -2,9 +2,9 @@
|
||||
:description: Hasura GraphQL engine documentation
|
||||
:keywords: hasura, docs, manual, graphql engine
|
||||
|
||||
.. title:: Hasura GraphQL engine Documentation
|
||||
.. title:: Hasura GraphQL Engine Documentation
|
||||
|
||||
Hasura GraphQL engine documentation
|
||||
Hasura GraphQL Engine Documentation
|
||||
===================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
@ -33,7 +33,7 @@ The Hasura GraphQL engine lets you set up a GraphQL server and event triggers ov
|
||||
Deploying <deployment/index>
|
||||
hasura-cli/index
|
||||
API Reference <api-reference/index>
|
||||
How it works <how-it-works/index>
|
||||
How It Works <how-it-works/index>
|
||||
Troubleshooting <troubleshooting/index>
|
||||
guides/index
|
||||
security-disclosure/index
|
||||
|
@ -12,7 +12,7 @@ Nested object queries
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
You can use the object (one-to-one) or array (one-to-many) :ref:`relationships <relationships>` defined
|
||||
You can use the object (one-to-one) or array (one-to-many) :ref:`relationships <table_relationships>` defined
|
||||
in your schema to make a nested query i.e. fetch data for a type along with data from a nested or related type.
|
||||
|
||||
The **name of the nested object** is the same as the name of the object/array relationship configured in
|
||||
|
124
docs/graphql/manual/remote-schemas/adding-schema.rst
Normal file
124
docs/graphql/manual/remote-schemas/adding-schema.rst
Normal file
@ -0,0 +1,124 @@
|
||||
.. meta::
|
||||
:description: Add a remote schema with Hasura
|
||||
:keywords: hasura, docs, remote schema, add
|
||||
|
||||
.. _adding_schema:
|
||||
|
||||
Adding a remote schema
|
||||
======================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Follow the steps below to add a remote schema to the Hasura GraphQL engine.
|
||||
|
||||
Step 1: Write a custom GraphQL server
|
||||
-------------------------------------
|
||||
|
||||
You need to create a custom GraphQL server with a schema and corresponding resolvers that solve your use case
|
||||
(*if you already have a functional GraphQL server that meets your requirements, you can skip this step*).
|
||||
|
||||
You can use any language/framework of your choice to author this server and deploy it anywhere. A great way to get
|
||||
started is to use one of our boilerplates:
|
||||
|
||||
- `Boilerplates <https://github.com/hasura/graphql-engine/tree/master/community/boilerplates/remote-schemas>`__
|
||||
|
||||
.. _merge_remote_schema:
|
||||
|
||||
Step 2: Merge remote schema
|
||||
---------------------------
|
||||
|
||||
To merge your remote schema with the GraphQL engine's auto-generated schema:
|
||||
|
||||
Head to the ``Remote Schemas`` tab of the console and click on the ``Add`` button.
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/business-logic/add-remote-schemas-interface.png
|
||||
:alt: Merge remote schema
|
||||
|
||||
You need to enter the following information:
|
||||
|
||||
- **Remote Schema name**: an alias for the remote schema that must be unique on an instance of the GraphQL engine.
|
||||
- **GraphQL server URL**: the endpoint at which your remote GraphQL server is available. This value can be entered
|
||||
manually or by specifying an environment variable that contains this information.
|
||||
|
||||
.. note::
|
||||
|
||||
During **local development** with the remote schema server on localhost, ensure that the Hasura Docker container can reach
|
||||
the server endpoint on the host. A common way to do this is to use the domain ``host.docker.internal`` on Docker for Mac and Windows or the Docker bridge IP on Linux (typically ``172.17.0.1`` - the IP address of ``docker0`` interface. use ``ip addr show docker0``) instead of ``127.0.0.1``.
|
||||
|
||||
Similarly, if you are adding the URL using env variable, then run the Hasura docker container with the env variable added during `docker run`. Example ``-e REMOTE_SCHEMA_ENDPOINT=http://host.docker.internal:4000/mycustomgraphql``
|
||||
|
||||
- **Headers**: configure the headers to be sent to your custom GraphQL server:
|
||||
|
||||
- Toggle forwarding all headers sent by the client (when making a GraphQL query) to your remote GraphQL server.
|
||||
- Send additional headers to your remote server - these can be static header name-value pairs; and/or pairs of
|
||||
"header name-environment variable name". You can specify the value of the header to be picked up from the environment
|
||||
variable.
|
||||
|
||||
**Example**: Let's say your remote GraphQL server needs a ``X-Api-Key`` as a header. As this value contains
|
||||
sensitive data (like API key in this example), you can configure the name of an environment variable which will hold
|
||||
the value. This environment variable needs to be present when you start the GraphQL engine. When Hasura sends
|
||||
requests to your remote server, it will pick up the value from this environment variable.
|
||||
|
||||
.. admonition:: Using environment variables
|
||||
|
||||
If you are using environment variables in the remote schema configuration - either
|
||||
for URL or headers - **the environment variables need to be present** with valid values
|
||||
when adding the remote schema i.e. the GraphQL engine should be started with these environment variables.
|
||||
|
||||
Click on the ``Add Remote Schema`` button to merge the remote schema.
|
||||
|
||||
Step 3: Make queries to the remote server from Hasura
|
||||
-----------------------------------------------------
|
||||
Now you can head to the ``GraphiQL`` tab and make queries to your remote server from Hasura.
|
||||
|
||||
You can query your remote server by making requests to the Hasura GraphQL endpoint (``/v1/graphql``).
|
||||
|
||||
Points to remember
|
||||
------------------
|
||||
|
||||
Remote schema fields nomenclature
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Top-level field names need to be unique across all merged schemas (*case-sensitive match*).
|
||||
- Types with the *exact same name and structure* will be merged. But types with the *same name but different
|
||||
structure* will result in type conflicts.
|
||||
|
||||
|
||||
Schema refreshing
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
For versions <= ``v1.0.0-beta.2``, GraphQL schema of each added remote server is refreshed every time a
|
||||
metadata modifying operation like adding tables/functions, defining relationships/permissions etc. is done.
|
||||
|
||||
From ``v1.0.0-beta.3`` onwards, a remote server's GraphQL schema is cached and refreshed only when user
|
||||
explicitly reloads remote schema by clicking the ``Reload`` button on the console or
|
||||
by making a :ref:`reload_remote_schema<api_remote_schemas>` metadata API request
|
||||
|
||||
|
||||
Current limitations
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Nodes from different GraphQL servers cannot be used in the same query/mutation. All top-level fields have to be
|
||||
from the same GraphQL server.
|
||||
- Subscriptions on remote GraphQL servers are not supported.
|
||||
|
||||
These limitations will be addressed in upcoming versions.
|
||||
|
||||
Extending the auto-generated GraphQL schema fields
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For some use cases, you may need to extend the GraphQL schema fields exposed by the Hasura GraphQL engine
|
||||
(and not merely augment as we have done :ref:`here <merge_remote_schema>`) with a custom schema/server. To support them, you can use
|
||||
community tooling to write your own client-facing GraphQL gateway that interacts with the GraphQL engine.
|
||||
|
||||
.. note::
|
||||
|
||||
**Adding an additional layer on top of the Hasura GraphQL engine significantly impacts the performance provided by
|
||||
it out of the box** (*by as much as 4x*). If you need any help with remodelling these kinds of use cases to use the
|
||||
built-in remote schemas feature, please get in touch with us on `Discord <https://discord.gg/vBPpJkS>`__.
|
@ -4,14 +4,17 @@
|
||||
|
||||
.. _remote_schemas:
|
||||
|
||||
Remote schemas
|
||||
Remote Schemas
|
||||
==============
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Hasura gives you CRUD + realtime GraphQL APIs with authorization & access control. However, in many cases, you will
|
||||
need to write APIs (queries, mutations) that contain custom logic. For example, implementing a payment API, or
|
||||
querying data that is not in your database.
|
||||
@ -34,7 +37,6 @@ Use cases
|
||||
- Custom business logic, like a payment API
|
||||
- Querying data that is not available in your database
|
||||
|
||||
|
||||
You can handle these use cases by writing resolvers in a custom GraphQL server
|
||||
and making Hasura merge this "remote schema" with the existing auto-generated
|
||||
schema. You can also add multiple remote schemas. Think of the merged schema as
|
||||
@ -46,204 +48,15 @@ a union of top-level nodes from each of the sub-schemas.
|
||||
app users to the GraphQL APIs that are auto-generated via Hasura, head to
|
||||
:ref:`auth`
|
||||
|
||||
Adding a remote schema
|
||||
----------------------
|
||||
Remote schema relationships
|
||||
---------------------------
|
||||
|
||||
Follow the steps below to add a "remote schema" to the Hasura GraphQL engine:
|
||||
You can create remote relationships between your tables and tables from your remote schema. Read more about this in the :ref:`remote_schema_relationships` section.
|
||||
|
||||
Step 1: Write a custom GraphQL server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
**See:**
|
||||
|
||||
You need to create a custom GraphQL server with a schema and corresponding resolvers that solve your use case
|
||||
(*if you already have a functional GraphQL server that meets your requirements, you can skip this step*).
|
||||
|
||||
You can use any language/framework of your choice to author this server and deploy it anywhere. A great way to get
|
||||
started is to use one of our boilerplates:
|
||||
|
||||
- `Boilerplates <https://github.com/hasura/graphql-engine/tree/master/community/boilerplates/remote-schemas>`__
|
||||
|
||||
.. _merge_remote_schema:
|
||||
|
||||
Step 2: Merge remote schema
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To merge your remote schema with the GraphQL engine's auto-generated schema:
|
||||
|
||||
Head to the ``Remote Schemas`` tab of the console and click on the ``Add`` button.
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/business-logic/add-remote-schemas-interface.png
|
||||
:alt: Merge remote schema
|
||||
|
||||
You need to enter the following information:
|
||||
|
||||
- **Remote Schema name**: an alias for the remote schema that must be unique on an instance of the GraphQL engine.
|
||||
- **GraphQL server URL**: the endpoint at which your remote GraphQL server is available. This value can be entered
|
||||
manually or by specifying an environment variable that contains this information.
|
||||
|
||||
.. note::
|
||||
|
||||
During **local development** with the remote schema server on localhost, ensure that the Hasura Docker container can reach
|
||||
the server endpoint on the host. A common way to do this is to use the domain ``host.docker.internal`` on Docker for Mac and Windows or the Docker bridge IP on Linux (typically ``172.17.0.1`` - the IP address of ``docker0`` interface. use ``ip addr show docker0``) instead of ``127.0.0.1``.
|
||||
|
||||
Similarly, if you are adding the URL using env variable, then run the Hasura docker container with the env variable added during `docker run`. Example ``-e REMOTE_SCHEMA_ENDPOINT=http://host.docker.internal:4000/mycustomgraphql``
|
||||
|
||||
- **Headers**: configure the headers to be sent to your custom GraphQL server:
|
||||
|
||||
- Toggle forwarding all headers sent by the client (when making a GraphQL query) to your remote GraphQL server.
|
||||
- Send additional headers to your remote server - these can be static header name-value pairs; and/or pairs of
|
||||
"header name-environment variable name". You can specify the value of the header to be picked up from the environment
|
||||
variable.
|
||||
|
||||
**Example**: Let's say your remote GraphQL server needs a ``X-Api-Key`` as a header. As this value contains
|
||||
sensitive data (like API key in this example), you can configure the name of an environment variable which will hold
|
||||
the value. This environment variable needs to be present when you start the GraphQL engine. When Hasura sends
|
||||
requests to your remote server, it will pick up the value from this environment variable.
|
||||
|
||||
.. admonition:: Using environment variables
|
||||
|
||||
If you are using environment variables in the remote schema configuration - either
|
||||
for URL or headers - **the environment variables need to be present** with valid values
|
||||
when adding the remote schema i.e. the GraphQL engine should be started with these environment variables.
|
||||
|
||||
Click on the ``Add Remote Schema`` button to merge the remote schema.
|
||||
|
||||
Step 3: Make queries to the remote server from Hasura
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Now you can head to the ``GraphiQL`` tab and make queries to your remote server from Hasura.
|
||||
|
||||
You can query your remote server by making requests to the Hasura GraphQL endpoint (``/v1/graphql``).
|
||||
|
||||
Points to remember
|
||||
------------------
|
||||
|
||||
Remote schema fields nomenclature
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Top-level field names need to be unique across all merged schemas (*case-sensitive match*).
|
||||
- Types with the *exact same name and structure* will be merged. But types with the *same name but different
|
||||
structure* will result in type conflicts.
|
||||
|
||||
|
||||
Schema refreshing
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
For versions <= ``v1.0.0-beta.2``, GraphQL schema of each added remote server is refreshed every time a
|
||||
metadata modifying operation like adding tables/functions, defining relationships/permissions etc. is done.
|
||||
|
||||
From ``v1.0.0-beta.3`` onwards, a remote server's GraphQL schema is cached and refreshed only when user
|
||||
explicitly reloads remote schema by clicking the ``Reload`` button on the console or
|
||||
by making a :ref:`reload_remote_schema<api_remote_schemas>` metadata API request
|
||||
|
||||
|
||||
Current limitations
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Nodes from different GraphQL servers cannot be used in the same query/mutation. All top-level fields have to be
|
||||
from the same GraphQL server.
|
||||
- Subscriptions on remote GraphQL servers are not supported.
|
||||
|
||||
These limitations will be addressed in upcoming versions.
|
||||
|
||||
Extending the auto-generated GraphQL schema fields
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For some use cases, you may need to extend the GraphQL schema fields exposed by the Hasura GraphQL engine
|
||||
(*and not merely augment as we have done above*) with a custom schema/server. To support them, you can use
|
||||
community tooling to write your own client-facing GraphQL gateway that interacts with the GraphQL engine.
|
||||
|
||||
.. note::
|
||||
|
||||
**Adding an additional layer on top of the Hasura GraphQL engine significantly impacts the performance provided by
|
||||
it out of the box** (*by as much as 4x*). If you need any help with remodelling these kinds of use cases to use the
|
||||
built-in remote schemas feature, please get in touch with us on `Discord <https://discord.gg/vBPpJkS>`__.
|
||||
|
||||
|
||||
Authorization in your remote schema server
|
||||
------------------------------------------
|
||||
|
||||
Hasura will forward the resolved ``x-hasura-*`` values as headers to your remote
|
||||
schema. You can use this information to apply authorization rules in your
|
||||
server. You don't have to redo authentication in your remote schema server.
|
||||
|
||||
You can also configure Hasura to have (as shown :ref:`above <merge_remote_schema>`):
|
||||
|
||||
1. static header values that are sent to the remote server
|
||||
2. forward all headers from the client (like ``Authorization``, ``Cookie`` headers etc.)
|
||||
|
||||
In case there are multiple headers with same name, the order of precedence is:
|
||||
configuration headers > resolved user (``x-hasura-*``) variables > client headers.
|
||||
|
||||
So for example, if the client sends an ``Authorization`` header, and the
|
||||
configuration also has an ``Authorization`` header, the configuration header value
|
||||
will selected.
|
||||
|
||||
.. note::
|
||||
|
||||
The headers from the client behave similarly to the authorization system. If
|
||||
``x-hasura-admin-secret`` is sent, then all ``x-hasura-*`` values from the
|
||||
client are respected, otherwise they are ignored.
|
||||
|
||||
Cookie header from your remote GraphQL servers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
``Set-Cookie`` headers from your remote schema servers are sent back to the
|
||||
client over HTTP transport. **Over websocket transport there exists no means
|
||||
of sending headers after a query/mutation and hence the ``Set-Cookie`` headers are
|
||||
not sent to the client.** Use HTTP transport if your remote servers set cookies.
|
||||
|
||||
|
||||
Bypassing Hasura's authorization system for remote schema requests
|
||||
------------------------------------------------------------------
|
||||
|
||||
It might be necessary sometimes to bypass Hasura's authorization system (calling
|
||||
the configured webhook, or validating the JWT), for requests that are for a
|
||||
remote GraphQL server.
|
||||
|
||||
**For example**, you have a remote GraphQL server which does authentication,
|
||||
i.e. signup and login, and you have added it as a remote schema. In this case,
|
||||
you would not want to perform Hasura's authorization when the user is making a
|
||||
login/signup request.
|
||||
|
||||
There is no first-class option to currently do this via any configuration in
|
||||
Hasura. However a similar solution can be achieved by the following workarounds:
|
||||
|
||||
Bypassing webhook authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have a :ref:`webhook authorization setup <auth_webhooks>`, in the normal scenario, your authorization
|
||||
webhook would return ``200`` on success and ``401`` if it is either unable to authorize the current request or if
|
||||
the authorization information is absent (like cookie, authorization header etc.)
|
||||
|
||||
To bypass the webhook auth:
|
||||
|
||||
- the webhook should respond with ``200`` and ``x-hasura-role: anonymous`` instead of a ``401`` when the
|
||||
authorization information is absent or if it fails to resolve the authorization information.
|
||||
- when adding the remote schema, check the ``Forward all headers from client`` option so that the remote server
|
||||
will get the relevant cookie/header (from the client) and the role ``anonymous``.
|
||||
|
||||
Bypassing JWT authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have a :ref:`JWT authorization setup <auth_jwt>`, to bypass the JWT auth:
|
||||
|
||||
- your authentication server should generate a static JWT token for ``anonymous`` i.e. unauthenticated users.
|
||||
- when adding the remote schema, check the ``Forward all headers from client`` option so that the remote server
|
||||
will get the JWT (from the client).
|
||||
|
||||
For example, the generated JWT can be:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"sub": "0000000000",
|
||||
"iat": 1516239022,
|
||||
"role": "anonymous",
|
||||
"https://hasura.io/jwt/claims": {
|
||||
"x-hasura-allowed-roles": ["anonymous"],
|
||||
"x-hasura-default-role": "anonymous"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Hasura will get this JWT and successfully validate it. When your remote server receives this JWT, it should
|
||||
specifically validate the JWT and, for example, check for the ``role`` key in the JWT. If it is set to ``anonymous``,
|
||||
then it should consider the request as unauthenticated.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
adding-schema
|
||||
schema-auth
|
||||
|
108
docs/graphql/manual/remote-schemas/schema-auth.rst
Normal file
108
docs/graphql/manual/remote-schemas/schema-auth.rst
Normal file
@ -0,0 +1,108 @@
|
||||
.. meta::
|
||||
:description: Authorization in your remote schema server with Hasura
|
||||
:keywords: hasura, docs, remote schema, authorization
|
||||
|
||||
.. _schema_auth:
|
||||
|
||||
Authorization in your remote schema server
|
||||
==========================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This page gives an overview of how to manage authorization for your remote schemas.
|
||||
|
||||
Authorization basics
|
||||
--------------------
|
||||
|
||||
Hasura will forward the resolved ``x-hasura-*`` values as headers to your remote
|
||||
schema. You can use this information to apply authorization rules in your
|
||||
server. You don't have to redo authentication in your remote schema server. Native fine grained access control for remote schemas will be released soon.
|
||||
|
||||
You can also configure Hasura to have (as shown :ref:`here <merge_remote_schema>`):
|
||||
|
||||
1. static header values that are sent to the remote server
|
||||
2. forward all headers from the client (like ``Authorization``, ``Cookie`` headers etc.)
|
||||
|
||||
In case there are multiple headers with same name, the order of precedence is:
|
||||
configuration headers > resolved user (``x-hasura-*``) variables > client headers.
|
||||
|
||||
So for example, if the client sends an ``Authorization`` header, and the
|
||||
configuration also has an ``Authorization`` header, the configuration header value
|
||||
will selected.
|
||||
|
||||
.. note::
|
||||
|
||||
The headers from the client behave similarly to the authorization system. If
|
||||
``x-hasura-admin-secret`` is sent, then all ``x-hasura-*`` values from the
|
||||
client are respected, otherwise they are ignored.
|
||||
|
||||
Cookie header from your remote GraphQL servers
|
||||
----------------------------------------------
|
||||
``Set-Cookie`` headers from your remote schema servers are sent back to the
|
||||
client over HTTP transport. **Over websocket transport there exists no means
|
||||
of sending headers after a query/mutation and hence the ``Set-Cookie`` headers are
|
||||
not sent to the client.** Use HTTP transport if your remote servers set cookies.
|
||||
|
||||
|
||||
Bypassing Hasura's authorization system for remote schema requests
|
||||
------------------------------------------------------------------
|
||||
|
||||
It might be necessary sometimes to bypass Hasura's authorization system (calling
|
||||
the configured webhook, or validating the JWT), for requests that are for a
|
||||
remote GraphQL server.
|
||||
|
||||
**For example**, you have a remote GraphQL server which does authentication,
|
||||
i.e. signup and login, and you have added it as a remote schema. In this case,
|
||||
you would not want to perform Hasura's authorization when the user is making a
|
||||
login/signup request.
|
||||
|
||||
There is no first-class option to currently do this via any configuration in
|
||||
Hasura. However a similar solution can be achieved by the following workarounds:
|
||||
|
||||
Bypassing webhook authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have a :ref:`webhook authorization setup <auth_webhooks>`, in the normal scenario, your authorization
|
||||
webhook would return ``200`` on success and ``401`` if it is either unable to authorize the current request or if
|
||||
the authorization information is absent (like cookie, authorization header etc.)
|
||||
|
||||
To bypass the webhook auth:
|
||||
|
||||
- the webhook should respond with ``200`` and ``x-hasura-role: anonymous`` instead of a ``401`` when the
|
||||
authorization information is absent or if it fails to resolve the authorization information.
|
||||
- when adding the remote schema, check the ``Forward all headers from client`` option so that the remote server
|
||||
will get the relevant cookie/header (from the client) and the role ``anonymous``.
|
||||
|
||||
Bypassing JWT authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have a :ref:`JWT authorization setup <auth_jwt>`, to bypass the JWT auth:
|
||||
|
||||
- your authentication server should generate a static JWT token for ``anonymous`` i.e. unauthenticated users.
|
||||
- when adding the remote schema, check the ``Forward all headers from client`` option so that the remote server
|
||||
will get the JWT (from the client).
|
||||
|
||||
For example, the generated JWT can be:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"sub": "0000000000",
|
||||
"iat": 1516239022,
|
||||
"role": "anonymous",
|
||||
"https://hasura.io/jwt/claims": {
|
||||
"x-hasura-allowed-roles": ["anonymous"],
|
||||
"x-hasura-default-role": "anonymous"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Hasura will get this JWT and successfully validate it. When your remote server receives this JWT, it should
|
||||
specifically validate the JWT and, for example, check for the ``role`` key in the JWT. If it is set to ``anonymous``,
|
||||
then it should consider the request as unauthenticated.
|
@ -102,7 +102,7 @@ The return table must be tracked to define such a computed field.
|
||||
|
||||
**Example:**
|
||||
|
||||
In a simple ``author <-> article`` schema, we can define a :ref:`relationship <relationships>` on the ``author``
|
||||
In a simple ``author <-> article`` schema, we can define a :ref:`table relationship <table_relationships>` on the ``author``
|
||||
table to fetch authors along with their articles.
|
||||
|
||||
We can make use of computed fields to fetch the author's articles with a search parameter.
|
||||
|
@ -29,7 +29,8 @@ Postgres constructs.
|
||||
:maxdepth: 1
|
||||
|
||||
Basics <basics>
|
||||
Relationships <relationships/index>
|
||||
Table relationships <table-relationships/index>
|
||||
Remote relationships <remote-relationships/index>
|
||||
Extend with views <views>
|
||||
Extend with SQL functions <custom-functions>
|
||||
Default field values <default-values/index>
|
||||
|
@ -0,0 +1,203 @@
|
||||
.. meta::
|
||||
:description: Adding an action relationship with Hasura
|
||||
:keywords: hasura, docs, action relationship, remote join
|
||||
|
||||
.. _action_relationships:
|
||||
|
||||
|
||||
Action relationships
|
||||
====================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
:ref:`Actions <actions>` are a way to extend Hasura’s schema with custom business logic using custom queries and mutations. The resolvers for these custom fields are written in REST endpoints. They are especially useful for setting up serverless functions as resolvers.
|
||||
|
||||
Create an action relationship
|
||||
-----------------------------
|
||||
|
||||
Step 0: Create an action
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
First, create an action, either :ref:`from scratch <create_actions>` or :ref:`derive it from an existing mutation <derive_actions>`.
|
||||
|
||||
Step 1: Open the action relationship section
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- From your action, go to the ``Relationships`` tab.
|
||||
- Click ``Add a relationship``.
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/remote-joins/action-rel.png
|
||||
:alt: Opening the action relationship section
|
||||
:width: 559px
|
||||
|
||||
In this example, we're creating a relationship for the ``createUser`` action.
|
||||
|
||||
Step 2: Define the relationship
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following values can be defined for an action relationship:
|
||||
|
||||
- **Relationship type**: Select a :ref:`type of relationship <relationship_database_modelling>`.
|
||||
|
||||
- **Object relationship**: For one-to-one relationships.
|
||||
- **Array relationship**: For one-to-many relationships.
|
||||
|
||||
- **Relationship name**: Create a name for the relationship.
|
||||
- **Reference schema**: Select a reference schema from your database.
|
||||
- **Reference table**: Select a table from your database.
|
||||
- **From**: Select a field returned in the action response.
|
||||
- **To**: Select a column from the reference table to join the field to.
|
||||
|
||||
.. rst-class:: api_tabs
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Console
|
||||
|
||||
In the section opened by the above step, fill out the following fields:
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/remote-joins/define-action-rel.png
|
||||
:alt: Defining the relationship
|
||||
:width: 850px
|
||||
|
||||
.. tab:: CLI
|
||||
|
||||
You can add an action relationship by adding it to the respective custom type in the ``actions.yaml`` file inside the ``metadata`` directory:
|
||||
|
||||
.. code-block:: yaml
|
||||
:emphasize-lines: 4-11
|
||||
|
||||
- custom_types
|
||||
- objects
|
||||
- name: UserOutput
|
||||
relationships:
|
||||
- remote_table:
|
||||
schema: public
|
||||
name: users
|
||||
name: user
|
||||
type: object
|
||||
field_mapping:
|
||||
id: id
|
||||
|
||||
Apply the metadata by running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
hasura metadata apply
|
||||
|
||||
.. tab:: API
|
||||
|
||||
You can create an action relationship when defining custom types via the :ref:`set_custom_types metadata API <set_custom_types>`:
|
||||
|
||||
.. code-block:: http
|
||||
:emphasize-lines: 20-29
|
||||
|
||||
POST /v1/query HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "set_custom_types",
|
||||
"args": {
|
||||
"scalars": [],
|
||||
"enums": [],
|
||||
"input_objects": [],
|
||||
"objects": [
|
||||
{
|
||||
"name": "UserOutput",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "Int!"
|
||||
}
|
||||
],
|
||||
"relationships": [
|
||||
{
|
||||
"name": "user",
|
||||
"type": "object",
|
||||
"remote_table": "users",
|
||||
"field_mapping": {
|
||||
"id": "id"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
In this example, we're creating a relationship called ``user``, from the ``id`` field returned in the action response, to the ``id`` column of the ``users`` table.
|
||||
|
||||
Step 3: Explore with GraphiQL
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the GraphiQL tab, test out your action relationship.
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
mutation {
|
||||
createUser(name: "Hodor") {
|
||||
id
|
||||
user {
|
||||
name
|
||||
auth0_id
|
||||
}
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"createUser": {
|
||||
"id": "7ffd68ba-535e-4c72-9051-17cd4e8ed594",
|
||||
"user": {
|
||||
"name": "Hodor",
|
||||
"auth0_id": "hodor|hodor"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
If your table has an existing :ref:`remote relationship <remote_schema_relationships>`, you can also query the fields from the remote schema.
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
mutation {
|
||||
createUser(name: "Hodor") {
|
||||
id
|
||||
user {
|
||||
name
|
||||
auth0_id
|
||||
auth0_profile {
|
||||
email
|
||||
nickname
|
||||
last_login
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"createUser": {
|
||||
"id": "7ffd68ba-535e-4c72-9051-17cd4e8ed594",
|
||||
"user": {
|
||||
"name": "Hodor",
|
||||
"auth0_id": "hodor|hodor",
|
||||
"auth0_profile": {
|
||||
"email": "hodor@hodor.com",
|
||||
"nickname": "Hodor",
|
||||
"last_login": "2016-05-22T01:35:48.863Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
In the :ref:`remote_schema_relationships` section, we joined our ``users`` table with a remote `Auth0 <https://auth0.com/>`__ schema. Here, we're able to get the Auth0 profile data of the user returned from our action.
|
50
docs/graphql/manual/schema/remote-relationships/index.rst
Normal file
50
docs/graphql/manual/schema/remote-relationships/index.rst
Normal file
@ -0,0 +1,50 @@
|
||||
.. meta::
|
||||
:description: Manage remote relationships in Hasura
|
||||
:keywords: hasura, docs, schema, relationship, remote relationship
|
||||
|
||||
.. _remote_relationships:
|
||||
|
||||
Relationships between tables and external sources
|
||||
=================================================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Hasura has a unique way of bringing data sources together and solving the data federation problem. This is done via remote joins wherein you can join data between data sources, similar to table relationships.
|
||||
|
||||
With remote joins, the join, authorization, and consistency checks (of added sources) all happen at the Hasura layer via metadata. This allows underlying data sources and APIs to evolve independently. Your applications have a unified API to query the full data landscape in your org.
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
Hasura's :ref:`authorization model <authorization>` gives you role-based access control. This extends to actions and remote schemas as well. In actions, you can go to the ``Permissions`` tab and choose which fields to expose for which roles. For remote schemas, Hasura will :ref:`forward your session variables <schema_auth>` which can be used to implement custom authorization in your remote schemas. Native role-based permissions on remote schemas is in the works.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
Hasura strives for optimal performance. It creates an efficient execution plan which pushes down most of the heavy-lifting involved to underlying sources. For example, Hasura creates a single efficient query to your database and batches calls to remote schemas to avoid the `n+1 problem <https://hasura.io/learn/graphql/intro-graphql/graphql-server/>`__ . More improvements to performance are upcoming.
|
||||
|
||||
Schema integrity & consistency
|
||||
------------------------------
|
||||
|
||||
Hasura has metadata consistency checks at every level. Whenever you add a table, remote schema, or action, Hasura makes sure that the graph that is exposed is consistent, and that all the relationships make sense at a type level. This helps you in creating robust workflows to test changes in your CI and making safe deployments of your unified graph.
|
||||
|
||||
Remote relationships modelling guides
|
||||
-------------------------------------
|
||||
|
||||
The following guides will help you model the different types of remote relationships in the database:
|
||||
|
||||
- :ref:`remote_schema_relationships`
|
||||
- :ref:`action_relationships`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
remote-schema-relationships
|
||||
action-relationships
|
@ -0,0 +1,168 @@
|
||||
.. meta::
|
||||
:description: Adding a remote schema relationship with Hasura
|
||||
:keywords: hasura, docs, remote schema relationship, remote join, remote schema, data federation
|
||||
|
||||
.. _remote_schema_relationships:
|
||||
|
||||
Remote schema relationships
|
||||
===========================
|
||||
|
||||
.. contents:: Table of contents
|
||||
:backlinks: none
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Remote schema relationships extend the concept of joining data across tables, to joining across tables *and* remote data sources. Once you create relationships between types from your database and types created from APIs, you can then "join" them by running GraphQL queries.
|
||||
|
||||
These APIs can be custom GraphQL servers you write, 3rd party SaaS APIs, or even other Hasura instances.
|
||||
|
||||
Because Hasura is meant to be a GraphQL server that you can expose directly to your apps, Hasura also handles security and authorization while providing remote joins.
|
||||
|
||||
.. note::
|
||||
|
||||
To see example use cases, check out this `blog post <https://hasura.io/blog/remote-joins-a-graphql-api-to-join-database-and-other-data-sources/>`__.
|
||||
|
||||
.. admonition:: Supported from
|
||||
|
||||
Remote schema relationships are supported from versions ``v.1.3.0`` and above.
|
||||
|
||||
Create remote schema relationships
|
||||
----------------------------------
|
||||
|
||||
Step 0: Add a remote schema
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Add a remote schema as described :ref:`here <adding_schema>`.
|
||||
|
||||
Step 1: Open the remote relationship section
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- From your table, go to the ``Relationships`` tab.
|
||||
- Click the ``Add a remote relationship`` button.
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/remote-joins/add.png
|
||||
:alt: Opening the remote relationship section
|
||||
:width: 1000px
|
||||
|
||||
Step 2: Define the relationship
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following fields can be defined for a remote schema relationship:
|
||||
|
||||
- **Name**: Define a name for the relationship.
|
||||
- **Remote Schema**: Select a remote schema among all the ones you've created.
|
||||
- **Configuration**: Set up the join configuration, to inject values as input arguments of the remote schema field.
|
||||
|
||||
- **From column**: Input injected from table column values.
|
||||
- **From static value**: Input injected from a static value of your choice.
|
||||
|
||||
For this example, we assume that our schema has a ``users`` table with the fields ``name`` and ``auth0_id``.
|
||||
|
||||
.. rst-class:: api_tabs
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Console
|
||||
|
||||
.. thumbnail:: /img/graphql/manual/remote-joins/define.png
|
||||
:alt: Defining the relationship
|
||||
:width: 800px
|
||||
|
||||
.. tab:: CLI
|
||||
|
||||
You can add a remote schema relationship by adding it to the ``tables.yaml`` in the ``metadata`` directory:
|
||||
|
||||
.. code-block:: yaml
|
||||
:emphasize-lines: 4-13
|
||||
|
||||
- table:
|
||||
schema: public
|
||||
name: users
|
||||
remote_relationships:
|
||||
- definition:
|
||||
remote_field:
|
||||
auth0profile:
|
||||
arguments:
|
||||
id: $auth0_id
|
||||
hasura_fields:
|
||||
- auth0_id
|
||||
remote_schema: auth0
|
||||
name: auth0
|
||||
|
||||
Apply the metadata by running:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
hasura metadata apply
|
||||
|
||||
.. tab:: API
|
||||
|
||||
You can add a remote schema relationship by using the :ref:`create_remote_relationship metadata API <create_remote_relationship>`:
|
||||
|
||||
.. code-block:: http
|
||||
|
||||
POST /v1/query HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "create_remote_relationship",
|
||||
"args": {
|
||||
"name": "auth0_profile",
|
||||
"table": "users",
|
||||
"hasura_fields": [
|
||||
"auth0_id"
|
||||
],
|
||||
"remote_schema": "auth0",
|
||||
"remote_field": {
|
||||
"auth0": {
|
||||
"arguments": {
|
||||
"auth0_id": "$auth0_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
In this example, we've added a remote schema which is a wrapper around `Auth0 <https://auth0.com/>`__'s REST API (see example
|
||||
`here <https://github.com/hasura/graphql-engine/tree/master/community/boilerplates/remote-schemas/auth0-wrapper>`__).
|
||||
|
||||
1. We name the relationship ``auth0_profile``.
|
||||
2. We select the ``auth0`` schema that we've added.
|
||||
3. We set up the config to join the ``auth0_id`` input argument of our remote schema field to the ``auth0_id`` column of this table (in this case, the ``users`` table).
|
||||
|
||||
Step 3: Explore with GraphiQL
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In the GraphiQL tab, test out your remote schema relationship.
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query {
|
||||
users {
|
||||
name
|
||||
auth0_profile {
|
||||
nickname
|
||||
email
|
||||
last_login
|
||||
}
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"name": "Daenerys Targaryen",
|
||||
"auth0_profile": {
|
||||
"nickname": "Stormborn",
|
||||
"email": "mother.of.dragons@unburnt.com",
|
||||
"last_login": "2019-05-19T01:35:48.863Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -12,6 +12,9 @@ Creating relationships
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A relationship from one table/view to another can be created by defining a link between a column of the table/view to a
|
||||
column of the other table/view.
|
||||
|
@ -12,6 +12,9 @@ Modelling many-to-many table relationships
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A ``many-to-many`` relationship between two tables can be established by creating a table typically called as
|
||||
**bridge/junction/join table** and adding **foreign-key constraints** from it to the original tables.
|
||||
|
||||
@ -36,8 +39,8 @@ These two tables are related via a ``many-to-many`` relationship. i.e:
|
||||
- an ``article`` can have many ``tags``
|
||||
- a ``tag`` has many ``articles``
|
||||
|
||||
Set up a table relationship in the database
|
||||
-------------------------------------------
|
||||
Step 1: Set up a table relationship in the database
|
||||
---------------------------------------------------
|
||||
|
||||
This ``many-to-many`` relationship can be established in the database by:
|
||||
|
||||
@ -61,8 +64,8 @@ This ``many-to-many`` relationship can be established in the database by:
|
||||
The table ``article_tag`` sits between the two tables involved in the many-to-many relationship and captures possible
|
||||
permutations of their association via the foreign keys.
|
||||
|
||||
Set up GraphQL relationships
|
||||
----------------------------
|
||||
Step 2: Set up GraphQL relationships
|
||||
------------------------------------
|
||||
|
||||
To access the nested objects via the GraphQL API, :ref:`create the following relationships <create_relationships>`:
|
||||
|
||||
@ -71,8 +74,8 @@ To access the nested objects via the GraphQL API, :ref:`create the following rel
|
||||
- Array relationship, ``tag_articles`` from ``tag`` table using ``article_tag :: tag_id -> id``
|
||||
- Object relationship, ``article`` from ``article_tag`` table using ``article_id -> article :: id``
|
||||
|
||||
Query using relationships
|
||||
-------------------------
|
||||
Step 3: Query using relationships
|
||||
---------------------------------
|
||||
|
||||
We can now:
|
||||
|
@ -12,6 +12,9 @@ Modelling one-to-many table relationships
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A ``one-to-many`` relationship between two tables can be established via a **foreign key constraint**.
|
||||
|
||||
Say we have the following two tables in our database schema:
|
||||
@ -35,8 +38,8 @@ These two tables are related via a ``one-to-many`` relationship. i.e:
|
||||
- an ``author`` can have many ``articles``
|
||||
- an ``article`` has one ``author``
|
||||
|
||||
Set up a table relationship in the database
|
||||
-------------------------------------------
|
||||
Step 1: Set up a table relationship in the database
|
||||
---------------------------------------------------
|
||||
|
||||
This ``one-to-many`` relationship can be established in the database by:
|
||||
|
||||
@ -46,16 +49,16 @@ This ``one-to-many`` relationship can be established in the database by:
|
||||
This will ensure that the value of ``author_id`` column in the ``article`` table is present in the ``id`` column of
|
||||
the ``author`` table.
|
||||
|
||||
Set up GraphQL relationships
|
||||
----------------------------
|
||||
Step 2: Set up GraphQL relationships
|
||||
------------------------------------
|
||||
|
||||
To access the nested objects via the GraphQL API, :ref:`create the following relationships <create_relationships>`:
|
||||
|
||||
- Array relationship, ``articles`` from ``author`` table using ``article :: author_id -> id``
|
||||
- Object relationship, ``author`` from ``article`` table using ``author_id -> author :: id``
|
||||
|
||||
Query using relationships
|
||||
-------------------------
|
||||
Step 3: Query using relationships
|
||||
---------------------------------
|
||||
|
||||
We can now:
|
||||
|
@ -12,6 +12,9 @@ Modelling one-to-one table relationships
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
A ``one-to-one`` relationship between two tables can be established via a **unique foreign key constraint**.
|
||||
|
||||
Say we have the following two tables in our database schema:
|
||||
@ -35,8 +38,8 @@ These two tables are related via a ``one-to-one`` relationship. i.e.:
|
||||
- an ``author`` can have one ``passport_info``
|
||||
- a ``passport_info`` has one ``owner``
|
||||
|
||||
Set up a table relationship in the database
|
||||
-------------------------------------------
|
||||
Step 1: Set up a table relationship in the database
|
||||
---------------------------------------------------
|
||||
|
||||
This ``one-to-one`` relationship can be established in the database by:
|
||||
|
||||
@ -48,16 +51,16 @@ This ``one-to-one`` relationship can be established in the database by:
|
||||
This will ensure that the value of the ``owner_id`` column in ``passport_info`` table is present in the ``id`` column of
|
||||
the ``author`` table and there will be only one row with a particular ``owner_id``.
|
||||
|
||||
Set up GraphQL relationships
|
||||
----------------------------
|
||||
Step 2: Set up GraphQL relationships
|
||||
------------------------------------
|
||||
|
||||
To access the nested objects via the GraphQL API, :ref:`create the following relationships <create_relationships>`:
|
||||
|
||||
- Object relationship, ``passport_info`` from the ``author`` table using ``id -> passport_info :: owner_id``
|
||||
- Object relationship, ``owner`` from the ``passport_info`` table using ``owner_id -> author :: id``
|
||||
|
||||
Query using relationships
|
||||
-------------------------
|
||||
Step 3: Query using relationships
|
||||
---------------------------------
|
||||
|
||||
We can now:
|
||||
|
@ -2,7 +2,7 @@
|
||||
:description: Manage relationships between tables/views in Hasura
|
||||
:keywords: hasura, docs, schema, relationship
|
||||
|
||||
.. _relationships:
|
||||
.. _table_relationships:
|
||||
|
||||
Relationships between tables/views
|
||||
==================================
|
||||
@ -12,13 +12,14 @@ Relationships between tables/views
|
||||
:depth: 1
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
To make :ref:`nested object queries <nested_object_queries>`, the tables/views in your database need to
|
||||
be connected via relationships.
|
||||
|
||||
Let's say we have the following tables in our database: ``author``, ``passport_info``, ``article`` and ``tag``.
|
||||
|
||||
.. _table_relationships:
|
||||
|
||||
Table relationships
|
||||
-------------------
|
||||
|
@ -38,7 +38,7 @@ To track all tables and views present in the database:
|
||||
Step 2: Track foreign-keys
|
||||
--------------------------
|
||||
|
||||
Tracking a foreign-key means creating a :ref:`relationship <relationships>` between the tables involved in the
|
||||
Tracking a foreign-key means creating a :ref:`relationship <table_relationships>` between the tables involved in the
|
||||
foreign-key.
|
||||
|
||||
To track a foreign-key between two tables in the database:
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
.. _security_protocol:
|
||||
|
||||
Security vulnerability protocol
|
||||
Security Vulnerability Protocol
|
||||
===============================
|
||||
|
||||
.. contents:: Table of contents
|
||||
|
@ -224,7 +224,7 @@ First, create a view ``poll_results`` to give the result of the poll:
|
||||
This view will have the following fields: ``poll_id``, ``option_id`` and ``votes``, i.e. it gives the number of votes
|
||||
received by each option for a poll.
|
||||
|
||||
Next, :ref:`setup relationships <relationships>` ``poll`` and ``option`` between the ``poll_results`` view
|
||||
Next, :ref:`set up relationships <table_relationships>` ``poll`` and ``option`` between the ``poll_results`` view
|
||||
and the ``poll`` and ``option`` tables using the ``poll_id`` and ``option_id`` fields respectively.
|
||||
|
||||
Now we can use the following subscription to display the latest poll result:
|
||||
|
BIN
docs/img/graphql/manual/remote-joins/action-rel.png
Normal file
BIN
docs/img/graphql/manual/remote-joins/action-rel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/graphql/manual/remote-joins/add.png
Normal file
BIN
docs/img/graphql/manual/remote-joins/add.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
docs/img/graphql/manual/remote-joins/define-action-rel.png
Normal file
BIN
docs/img/graphql/manual/remote-joins/define-action-rel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
docs/img/graphql/manual/remote-joins/define.png
Normal file
BIN
docs/img/graphql/manual/remote-joins/define.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 148 KiB |
@ -17,4 +17,4 @@ Table of Contents
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
Hasura GraphQL engine <graphql/manual/index>
|
||||
Hasura GraphQL Engine <graphql/manual/index>
|
||||
|
Loading…
Reference in New Issue
Block a user