diff --git a/docs/docs/resources/use-case/_category_.json b/docs/docs/resources/use-case/_category_.json new file mode 100644 index 00000000000..7f5e6bf8c41 --- /dev/null +++ b/docs/docs/resources/use-case/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Hasura Use Cases", + "position": 3 +} diff --git a/docs/docs/resources/use-case/api-gateway.mdx b/docs/docs/resources/use-case/api-gateway.mdx new file mode 100644 index 00000000000..8d6684340d5 --- /dev/null +++ b/docs/docs/resources/use-case/api-gateway.mdx @@ -0,0 +1,183 @@ +--- +description: Building an API Gateway for existing APIs using Hasura +title: Building a Gateway Microservice with Hasura +keywords: + - hasura + - use-case + - gateway +sidebar_label: Building a Gateway microservice with Hasura +sidebar_position: 4 +toc_max_heading_level: 5 +--- + +import Thumbnail from '@site/src/components/Thumbnail'; + +# Building an API Gateway for existing APIs with Hasura + +## Introduction + +Hasura can serve as a gateway to your existing APIs. It creates a bridge between clients and servers, enabling secure +and efficient data communication. Hasura's Data Federation enables one to compose data from different sources that +reside in independent data stores but are semantically related. Add existing data APIs (REST APIs, GRAPHQL APIs) with +Remote Schemas or Actions in Hasura as a single GraphQL schema without writing any custom code and add it to a Hasura +project to create a gateway which is secure and scalable that deliver high-performance data access. + +## Sample use case + +This tutorial assumes you have a separate server running with a set of APIs that need to be added behind the gateway. + +Let's assume we have two services that needed to be added behind a gateway. The first service is a Hasura project +connected with postgres which contains the order details and can get all the orders for a user and can add a new order. +The second service is a microservice and exposes a REST API, which contains payment-related details. + + + +When signing in with Hasura for the first time and clicking for use-case as `Using Hasura as Gateway for existing API` +it creates a Hasura project which we will use to create the gateway. + +## Step 1: Connect Hasura project + +Create a new project on [Hasura Cloud](https://cloud.hasura.io) for all your services and launch the Console to add the +existing microservice to Hasura. + +## Step 2: Connect custom services to Hasura + +### Step 2.1: Using Remote Schema + +Hasura has the ability to merge your remote GraphQL schemas and provide you with a single, unified GraphQL API using +Remote Schemas. This enables you to write queries and mutations to disparate sources, all from your single Hasura +endpoint. + +If the custom server has graphql endpoints, add the server to Hasura as a +[Remote Schema](/remote-schemas/adding-schema.mdx). + +1. Head to the `Remote Schemas` tab of the Console and click `Add` on the left sidebar. +2. 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. +3. Toggle forwarding all headers sent by the client (when making a GraphQL query) to your remote GraphQL server. +4. Add the required details and click on the `Add Remote Schema` button to merge the Remote Schema. + + + +### Step 2.2: Using Actions + +Actions are a convenient and secure way to connect to REST APIs to achieve any business logic you may need, directly +from your GraphQL API. + +If the custom server exposes endpoints as a REST API, add the server to Hasura as an +[Action](/actions/rest-connectors.mdx). REST Connectors for Actions are used to integrate existing REST APIs to the +GraphQL API without needing any middleware or modifications to the upstream code. + +1. Head to the `Actions` tab of the Console and click `Create` on the left sidebar and then click `New Action`. +2. Define your mutation or query and associated types for your REST API. + + + +3. Scroll down to `Configure the REST connectors` + + + +The context variables available in transforms are: + +| Context variable | Value | +| ------------------ | --------------------------------------- | +| $body | Original body of action request | +| $base_url | Original configured webhook handler URL | +| $session_variables | Session variables | + +The Console allows you to preview your transforms while configuring them. To avoid exposing sensitive information on the +console UI the actual environment variables configured on the server are not resolved while displaying the previews + +**For example:** If your webhook handler is set as an env var as shown below then pass a mock value for that env var in +the sample context: + + + +4. Add Request Method: You can change the request method to adapt to your API's expected format. + + + +5. Request URL: The Request URL template allows you to configure the exact API endpoint to call. + + + +6. Request Body: You can generate a custom request body by configuring a template to transform the default payload to a + custom payload. + + + +7. Response Body: You can transform the default body of your HTTP API response by configuring a response transform + template. + + + +9. Click on `Create Action` and you can navigate to API tab and check out the Action on the Console. + +## Step 3: Add the custom service Hasura project to Gateway + +Navigate to the Hasura Console for gateway project. If you do not have a Hasura project created, create a new project +using [Hasura Cloud](https://cloud.hasura.io). Add all the Hasura project's GraphQL endpoints as separate remote schema +by providing GraphQL Service URL as Hasura's GraphQL endpoint. + + + +## Step 4: Explore GraphQL API + +Navigate to API tab. On the explorer we can see all the endpoints available in the gateway from all the services. + + + +## Step 5: Add remote schema permissions + +### Step 5.1: Enable remote schema permissions + +Navigate to [Hasura cloud](https://cloud.hasura.io) and open the project associated with the gateway. Navigate to env +vars and add `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS` as `true`. This env var +`HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS` allows you to set permissions for Remote Schemas. + + + +### Step 5.2: Add remote schema permissions + +Remote Schema have role-based permissions, allowing you to expose only a certain part of the Remote Schema for the +selected role. You can choose to remove any fields from objects, interfaces and input object types. Doing this will +ensure that these fields are not exposed for the role and they will not be able to query the fields that have been +hidden. Follow along with this [document](/remote-schemas/auth/remote-schema-permissions.mdx) to add permissions for +Remote Schemas. + +## Advanced topics + +### Logging + +Integrate [logging](/observability/overview.mdx) for gateway using Datadog, New Relic, Azure Monitor, Prometheus, or +OpenTelemetry. Navigate to Hasura cloud and, open the gateway project and, navigate the Integration tab to add the +logging service. These are available on Hasura's Professional tier. + +### Enable rate limiting + +Restricts number of GraphQL operations per minute. This uses a sliding window approach. This means whenever Hasura Pro +receives a request, it will count the rate of that client starting from the current time to last one minute. By default, +the rate-limit happens on the role_name i.e the value provided in `X-HASURA-ROLE`. + +1. Navigate to the monitoring section on Hasura Console. +2. Click on `API Limits` and click on `security`. +3. Click on `Rate Limit` and set the values on `Request Rate Limit`. + + + +### Adding relationship for remote schema. + +Remote Schema to Remote Schema relationships (a.k.a GraphQL joins) extend the concept of joining data across tables, to +joining across remote GraphQL sources. Once you create relationships between types from the GraphQL schemas, you can +then "join" them by running GraphQL queries. + +1. Head to the Remote Schema -> [remote-schema-name] -> Relationships tab. +2. Click the Add a new relationship button. +3. Define the relationship and hit Add Relationship. + + + +## Conclusion + +Hasura offers a powerful solution for creating a gateway for existing APIs. By leveraging Hasura's features, developers +can improve their API security, performance, and scalability, as well as streamline their development workflow. diff --git a/docs/docs/resources/use-case/data-api.mdx b/docs/docs/resources/use-case/data-api.mdx new file mode 100644 index 00000000000..df9911b1b63 --- /dev/null +++ b/docs/docs/resources/use-case/data-api.mdx @@ -0,0 +1,398 @@ +--- +description: Building a Data API on existing data using Hasura +title: Building a Data API with Hasura +sidebar_position: 1 +keywords: + - hasura + - use-case + - data-api +sidebar_label: Building a Data API with Hasura +toc_max_heading_level: 5 +--- + +import Thumbnail from '@site/src/components/Thumbnail'; +import Player from '@site/src/components/Player'; +import HeadingIcon from '@site/src/components/HeadingIcon'; + +# Building a Data API on existing data sources with Hasura + +## Introduction + +Hasura connects to your databases, REST endpoints and GraphQL endpoints to instantly provide a scalable, highly +available, globally distributed, fully managed, secure GraphQL API as a service! + +Let's break the above statement down. + +As data is no longer in a single data-source, without Hasura you have to build an API that is able to connect to +multiple data-sources, absorb some domain-specific logic, and provide the required security and performance/concurrency. +This process is time consuming and hard to get right. + +Instead of spending months writing code to map thousands of tables, embed authorization rules and building APIs, Hasura +allows developers to declaratively configure a web-server in minutes and expose a production-ready API. From building +something by hand to getting that “as a service”. + +Take a look at this diagram to understand where Hasura fits in your product. + + + +Hasura also supports many advanced features like authentication, caching, security, monitoring, streaming subscriptions, +running async code on database events, federating data from multiple data sources, REST endpoints and other GraphQL +schemas to build a unified api, and much more. + +
+ +## Step 1: Connect a Database + +Let's get started by adding your first database to Hasura! + +:::info Note + +We will be using the Hasura Console in the next few steps, which is a web app to set up Hasura by just making some +clicks! If you landed on this doc and do not have the Hasura console open, we recommend you to go through one of the +quickstart guides [here](/getting-started/overview.mdx) first. + +Also assuming that you are connecting to an already running Postgres database instance. The steps are going to be the +same for other databases for the most part. But if required, you can reference [this](/databases/overview.mdx) section +if you are stuck. + +::: + +1. In your Hasura Console, navigate to the `Data` tab in the top navbar. +2. Click on `Connect Database` button and enter your Postgres database connection string. You can enter the connection + string directly in the `Database URL` input section. (If you are using a different data source, you can select it via + `Data Source Driver` dropdown). +3. Once done, click on `Connect Database`. + +This should add the database and there should be a notification. You can select `View Database` in the notification to +view you database. + + + +## Step 2: Track tables/relationships + +After adding the database, you will see a list of all the tables that you have under the database schemas. Tables can be +present in the underlying Postgres database without being exposed over the GraphQL API. In order to expose a table over +the GraphQL API, it needs to be tracked. + +You can track your tables by hitting the `Track All` button, or track some of them selectively. + + + +As soon as a table is tracked, the corresponding GraphQL schema types and query/mutation/subscription fields will be +automatically generated. These auto-generated fields will allow you to query and mutate data in the table. + +Before querying, let's add some relationships. You might have some foreign key relationships in your database tables. We +need to tell hasura to use those relationships, or any other custom relationships and include in the GraphQL API. Using +these relationships, you can then make nested queries. All this will be super clear when we start making queries. But +let's first add some relationships. + +1. Once you track a table, go to the table using the left sidebar. +2. Go to `Relationships` tab. +3. Hasura should be auto suggesting some relationships if you have foreign keys set on the table. Add one of the + suggested relationship. + +In the example below, I have a schema for a slack like group chat app with users, channels, and workspaces. I'll now add +a relationship `channel_member` in users table. + + + +## Step 3: Explore GraphQL API + +That was it! We got an instant Graphql API on your data already. The Hasura GraphQL Engine automatically generates +GraphQL query/mutation/subscription fields for inserting, updating, deleting or streaming data based on your database's +schema. For any tracked table, a set of queries/mutations/subscriptions are generated and exposed as part of the GraphQL +API. + +### Step 3.1: Query the data + +With the Hasura GraphQL Engine, you get powerful, full-coverage queries right out of the box. As soon as you connect +your database, you'll be able to query all your related and deeply nested data easily with the power of GraphQL. You'll +also be able to aggregate, filter, sort, and paginate results. Let's make our first query! + +1. On the Hasura Console, navigate to `API` tab in the top navbar. API tab is a playground or say a client, where you + can test your query/mutation/subscription responses. +2. You should be able to see your schema tables in the left navbar. +3. Build a GraphQL Query. GraphQL queries are nested queries in which we ask exactly what data we need. + +An example query would look something like this. Here I'm querying the users and the `channel_members` info that the +user is related to. Querying channel members is possible due to the relationship we added in the above step: + +```graphql +query GetUsers { + users { + name + phone_number + channel_members { + id + } + } +} +``` + + + +### Step 3.2: Make a mutation + +The Hasura GraphQL Engine automatically generates GraphQL mutation fields for inserting, updating, or deleting data +based on your database's schema. For any tracked table, a set of mutations are generated and exposed as part of the +GraphQL API. Let's make our first mutation! + +1. On the API tab, select `mutation` from the `Add New` dropdown at the bottom, and click on the plus icon. +2. You should be able to see some autogenerated mutations on your schema. Build a mutation using the explorer on left + navbar, and hit the play button. + +For example, I'm inserting a user in my user table in the gif below. The mutation looks like this: + +```graphql +mutation AddUser { + insert_users(objects: { email: "jhondoe@gmail.com", name: "John Doe", password: "secretPassword" }) { + affected_rows + } +} +``` + + + +### Step 3.3: Make a subscription + +Subscriptions enable you to push data from your database to your clients in real-time, making them a powerful tool for +building reactive applications without the need for continuous server polling. Let's make a subscription now! + +For making a subscription, I'll continue using the same example. I have an `online_users` view which checks tells if a +user is online by checking the last seen of the user. We will subscribe to this view, and when we add a new user, we +should see the subscription push the data of the new user in real time! + +1. Let's add a subscription by selecting the `Subscription` option from the `Add New` dropdown. My subscription looks + like this: + +```graphql +subscription MySubscription { + online_users { + id + last_seen + } +} +``` + +2. Next I'll open my same hasura project in a new tab, and use the `API` explorer to add a mutation to insert a new + user. Then, in the previous tab, I should be able to see the data of the inserted user in real time. + +```graphql +mutation MyMutation { + insert_users( + objects: { email: "jhondoe@gmail.com", last_seen: "now()", name: "John Doe", password: "secretPassword" } + ) { + affected_rows + returning { + id + } + } +} +``` + + + +## Step 4: Add Authorization + +:::info Note + +As auth is a complex topic, we assume you have some prior knowledge of how it works. Otherwise just ride along and use +the link at the bottom to read more about auth with Hasura. + +::: + +Authentication verifies the identity of a user or service, and authorization determines their access rights to the +service. The basic premise here is this: + +- There might be some publicly available information in your app (for example public channels in a group chat app that + anyone can access without signing in). This information won't need any auth. +- There might be some user specific information in your app, that only the user should be able to see (for example a + user's address information). This information will only be accessible to user if the users sends some info with the + request telling Hasura about their identity. + +For working with the user specific information, users need to be authenticated. Actual authentication is handled outside +Hasura. So you need to either have a custom auth service, or use one of the auth providers (like Auth0). Once a user is +authenticated with your auth service, you can either provide a JWT to the Hasura GraphQL Engine containing session +variables like user role, or specify a webhook in order to fetch the session variables on each request. + +For authorization, Hasura helps you define granular, role and session variable based permission rules to control access +to your data. These permissions utilize the session variables returned by your authentication service and are granular +enough to control access to every row or column in your database. + +Let's take a look at a high-level overview of how this works when Hasura GraphQL Engine receives a request: + + + +Hasura uses the role, session variables and the actual GraphQL query itself to validate against the authorization +permission rules defined by you. If the operation is allowed, it generates an optimized SQL query, which includes the +constraints from the permission rules, and sends it to the database to perform the required operation; fetching the +required rows for queries or inserting, editing or deleting rows for mutations. + +#### Authentication + +Hasura gives you the power to authenticate users how you want, integrating with many popular auth services or your own +existing custom solution hosted elsewhere. + +There are 2 ways to authenticate a user: + +1. JWT +2. Webhook + +In JWT based authentication, a client requests your auth service to get a JWT. Then you can directly pass the JWT to +Hasura, this JWT should have some custom claims (like user role) which will be used to decide what information to show +to the user. + +In Webhook based authentication, a client directly calls hasura with some headers. Hasura calls the webhook service with +each request. The webhook service will use your request headers to determine the auth status of the user and return the +user role and any other information as session variables in the response body. + +#### Authorization + +Hasura also provides role based authorization, using which you can manage access to your data and APIs by defining roles +and permissions. Hasura's fine-grained access control system allows you to specify which users can access which data +ensuring that your application is secure and robust. + +Once you authenticate a user, you will get some session variables which will contain user information like user role, +etc. This information can be used to set up role based access control. + +Let's go through a simple example. In my group chat app, I have a `users` table. I want to set access control on this +table such that a user can only access their own information. + +Let's go through the steps to do it: + +1. Go to `users` table, and open `Permissions` tab. +2. You should see the role `admin` has full access to the table by default. +3. Add a new role `user` in the `Enter new role` input. +4. Let's define some permissions on `user` role. Click on `select` column, and it will open a card. Here we are setting + some permission on selection/querying of the data. +5. In the `Row select permissions`, select `With custom check` and add the permission + `{"id":{"_eq":"X-Hasura-User-Id"}}`. This will tell Hasura to only send the rows which match the above rule. Here the + rule states that the `id` column should be equal to the value of session variable `X-Hasura-User-Id`. +6. Open the `Column select permissions` dropdown, and click `Toggle All` button. This defines which columns the given + role can access. + +And we are done. Let's go to the API tab to see this in action. + +1. Navigate to `API` tab from top navbar. +2. Query `users` table and don't provide any role based information. We should see all the data as we are providing the + admin secret so we are making this query in the admin role. +3. Now I'll add the `X-Hasura-Role` and `X-Hasura-User-Id` in the headers. This will tell Hasura about the user and role + information. Hitting play button again will only give me the selected user's information. + + + +As you probably have guessed, in a production environment these header values will come from session variables (either +using JWT or webhook). So the actual flow will be something like, the front-end client calls a auth service to generate +a JWT with claims containing `X-Hasura-Role` and other info. This JWT will be sent to Hasura by the client. Hasura +decodes the JWT and gets these header values, and the rest of the flow remains the same. + +This was just a tip of the iceberg to the many functionalities Hasura provides for doing Auth. You can read more about +it [here](/auth/overview.mdx). + +
+ +## Advanced topics + +There are many more advanced features that hasura provides to handle custom business logic, security, caching, +monitoring and much more. Below we will be going through some of these commonly used features. + +### Actions + +Actions are a convenient and secure way to connect to REST APIs to achieve any business logic you may need, directly +from your GraphQL API. In the simplest of terms actions send a POST request to your endpoint with a payload. + +It is useful in cases like needing to validate user, process or enrich some data, call another API, or log a user in. +With Actions you can connect to a REST endpoint which can be your own custom server, a public API, or a serverless +function. You can also import your existing rest endpoints as actions, from an OpenAPI spec. + +[Read more about actions](/actions/overview.mdx) + +### Event Triggers + +Hasura Event triggers are a way to automate asynchronous logic when changes are made in a connected database. + +Event Triggers can be configured to activate when there is an INSERT, UPDATE or DELETE event in a table. Additionally, +you can manually trigger an event through a button set up in the Hasura Console. One example use case of Event triggers +is sending an email to a newly signed up user. + +[Read more about Event Triggers](/event-triggers/overview.mdx) + +### Caching + +Hasura provides a caching layer that can be used to cache the response of a GraphQL query. This can help reduce the +number of requests to your datasources and improve the performance of your application. + +You have full control over the cache lifetime and can choose to force the cache to refresh when you need to. With Hasura +Caching, your application is highly-optimized and performant, reducing the load on your servers. + +[Read more about caching](/caching/overview.mdx) + +### Observability + +Hasura Observability is a set of tools that help you monitor and debug your Hasura instance. With Observability, you can +check on the performance of your GraphQL API, debug errors, and get insights into your GraphQL API usage. We provide +detailed error reporting, usage summaries, detailed metrics of graphql operations like query latency, request count, and +error rate. + +We offer integrations with popular monitoring tools like Datadog, Prometheus, and OpenTelemetry and you can quickly get +set up with these tools using one of our guides. + +[Read more about Observability](/observability/overview.mdx) + +### Setting limits on API + +Setting some limits on API requests can help prevent API performance issues caused by malicious or poorly implemented +queries, and helps preventing attacks like Denial of Service. You can easily set up various kinds of limits on your API +using the hasura console. There are multiple type of API limits offered by Hasura. + +- Rate limits restricts number of GraphQL operations per minute. +- Depth limits restricts a GraphQL operation based on its depth, preventing deeply nested queries. +- Node limits restricts a GraphQL operation based on the number of nodes. This helps in limiting the number of different + pieces of related data to be fetched. +- Time limits restricts the time that a GraphQL operation is allowed to take. +- Batch Limits restricts the number of GraphQL operations in a batched request. + +[Read more about API limits](/security/api-limits.mdx) + +## Next steps + +For a full hands-on tour of Hasura, check out our +[30-Minute Hasura Basics Tutorial](https://hasura.io/learn/graphql/hasura/introduction/). diff --git a/docs/docs/resources/use-case/data-federation.mdx b/docs/docs/resources/use-case/data-federation.mdx new file mode 100644 index 00000000000..1c595ae1d2c --- /dev/null +++ b/docs/docs/resources/use-case/data-federation.mdx @@ -0,0 +1,339 @@ +--- +description: Building a federated API across data sources +title: Building a federated API +sidebar_label: Building a Data Federation with Hasura +keywords: + - hasura + - graphql + - data + - federation + - resource +sidebar_position: 3 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Player from '@site/src/components/Player'; +import Thumbnail from '@site/src/components/Thumbnail'; +import GraphiQLIDE from '@site/src/components/GraphiQLIDE'; + +# Building a federated API across data sources with Hasura + +## Introduction + +Hasura's data federation capabilities allow you to compose data from different sources that reside in independent data +stores but are semantically related. + +Hasura creates a single GraphQL schema from multiple data sources thereby making the data access process self-serve, +allowing you to query, mutate or federate in real-time and stream data across services without writing any custom code. + + + +Following are the possibilities Hasura offers for connecting different data sources under the same instance and defining +relationships among them: + +- [Database to database relationships](/schema/postgres/remote-relationships/remote-source-relationships.mdx): Hasura + allows you to stitch data from multiple database sources together. +- [Database to remote-schema relationships](/schema/postgres/remote-relationships/remote-schema-relationships.mdx) and + [vice versa](/remote-schemas/remote-relationships/remote-schema-db-relationships.mdx): A remote graphl server can be + connected to a database under a single GraphQL API. +- [Remote Schema to remote schema relationships](/remote-schemas/remote-relationships/remote-schema-db-relationships.mdx): + Multiple remote GraphQL sources (for eg: remote Graphql API servers like Spotify, Auth0) can be stitched together + under a single GrahQL API. +- [Database to Actions](/schema/postgres/remote-relationships/action-relationships.mdx): A REST API exposed as a Hasura + [Action](/actions/overview.mdx) can be connected to other data sources under the same hood. + +## Sample use case + +For this example, we'll be stitching 3 different database instances to create a federated API using Hasura. + + + +Consider an E-commerce app with 4 tables distributed among 3 different databases, where `users` related information +resides in the first db, the Order Management System (`orders` and `order_items`) lies in the second and the Inventory +(`products`) lies in the third. + +## Step 1: Set up databases + +:::info Note + +We will be using Hasura Console in the next few steps, which is a web app to set up Hasura by just making some clicks! +If you landed on this doc and do not have the Hasura console open, we recommend you to go through one of the quickstart +guides [here](/getting-started/overview.mdx) first. + +Also assuming that you are connecting to an already running Postgres database instance. The steps are going to be the +same for other databases for the most part. But if required, you can reference [this](/databases/overview.mdx) section +if you are stuck. + +::: + +- To keep this simple, we'll create 3 Postgres databases using [Neon](https://neon.tech/) from Hasura console. Checkout + the [list](/databases/overview.mdx#supported-databases) of supported databases by Hasura. +- Head over to `Data` -> `Data Manager` -> `Connect New Database` and click on `Connect Neon Database`. This will create + a free Postgres database instance and add it as a data source to Hasura. +- Paste the following raw SQL in the SQL tab to set up the initial schema and seed data for the respective database/s. + Make sure the `Track this` is checked while running the SQL commands to make sure the created tables are tracked by + Hasura. +- Repeat the process for the other databases as well. + + + + +```sql +SET standard_conforming_strings = off; +SET check_function_bodies = false; +SET escape_string_warning = off; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE TABLE public.users ( + id uuid DEFAULT public.uuid_generate_v1() NOT NULL, + name text NOT NULL, + email text NOT NULL UNIQUE, + password text NOT NULL, + address text NOT NULL +); +ALTER TABLE ONLY public.users + ADD CONSTRAINT users_pkey PRIMARY KEY (id); + +INSERT INTO public.users (id, name, email, password, address) VALUES ('7cf0a66c-65b7-11ed-b904-fb49f034fbbb', 'Sean', 'seandemo@hasura.io.com', 'SeanUsesHasura', '14 Fornham Road, Bury St. Edmunds, IP32 6AH'); +INSERT INTO public.users (id, name, email, password, address) VALUES ('82001336-65b7-11ed-b905-7fa26a16d198', 'Rob', 'robdemo@hasura.io.com', 'RobUsesHasura', '8 Ilderton Crescent, Seaton Delaval, NE25 0FH'); +INSERT INTO public.users (id, name, email, password, address) VALUES ('86d5fba0-65b7-11ed-b906-afb985970e2e', 'Marion', 'mariondemo@hasura.io.com', 'MarionUsesHasura', '25 Kirkfields, Baildon, BD17 6HY'); +INSERT INTO public.users (id, name, email, password, address) VALUES ('8dea1160-65b7-11ed-b907-e3c5123cb650', 'Sandeep', 'sandeepdemo@hasura.io.com', 'SandeepUsesHasura', 'Six Bricks, Smithy Banks, Holmrook, CA19 1TP'); +INSERT INTO public.users (id, name, email, password, address) VALUES ('9bd9d300-65b7-11ed-b908-571fef22d2ba', 'Abby', 'abbydemo@hasura.io.com', 'AbbyUsesHasura', '3 Eardley Place, Grange Farm, MK8 0PN'); +``` + + + + +```sql +SET standard_conforming_strings = off; +SET check_function_bodies = false; +SET escape_string_warning = off; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE TABLE public.orders ( + id uuid DEFAULT public.uuid_generate_v1() NOT NULL, + user_id uuid NOT NULL, + order_date timestamp with time zone NOT NULL +); +CREATE TABLE public.order_items ( + id uuid DEFAULT public.uuid_generate_v1() NOT NULL, + order_id uuid NOT NULL, + product_id uuid NOT NULL, + quantity int NOT NULL +); +ALTER TABLE ONLY public.orders + ADD CONSTRAINT orders_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.order_items + ADD CONSTRAINT order_items_pkey PRIMARY KEY (id); +ALTER TABLE ONLY public.order_items + ADD CONSTRAINT order_items_order_id_foreign FOREIGN KEY (order_id) REFERENCES public.orders(id); + +INSERT INTO public.orders (id, user_id, order_date) VALUES ('452230eb-8955-4bfb-add3-37d89326f136', +'7cf0a66c-65b7-11ed-b904-fb49f034fbbb', '2023-03-23T07:02:29.581199+00:00'); INSERT INTO public.orders (id, user_id, +order_date) VALUES ('51aec62a-0be9-4950-89ce-ca8babe5104f', '82001336-65b7-11ed-b905-7fa26a16d198', +'2022-03-23T07:02:29.581199+00:00'); INSERT INTO public.orders (id, user_id, order_date) VALUES +('87487a6d-0560-4305-aad3-70a75231cf17', '86d5fba0-65b7-11ed-b906-afb985970e2e', '2023-03-24T07:02:29.581199+00:00'); +INSERT INTO public.orders (id, user_id, order_date) VALUES ('34f64d2c-7897-48eb-b5be-4886808b7826', +'86d5fba0-65b7-11ed-b906-afb985970e2e', '2019-01-12T07:02:29.581199+00:00'); INSERT INTO public.orders (id, user_id, +order_date) VALUES ('a9968bb0-1cf2-4ebd-b2b9-3e9b7ac7891e', '8dea1160-65b7-11ed-b907-e3c5123cb650', +'2021-03-14T07:02:29.581199+00:00'); INSERT INTO public.orders (id, user_id, order_date) VALUES +('7e5155cf-9543-49c5-aee7-fa2296bf65d5', '9bd9d300-65b7-11ed-b908-571fef22d2ba', '2021-11-19T07:02:29.581199+00:00'); + +INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES ('6b5b09de-b2bc-4f81-907f-eea8ef58bcd4', +'452230eb-8955-4bfb-add3-37d89326f136', '5a053b73-8196-4a88-aea2-2deb3404995c', 2); INSERT INTO public.order_items (id, +order_id, product_id, quantity) VALUES ('dd676acb-2917-4e64-acd7-bff2b85ff8a0', '452230eb-8955-4bfb-add3-37d89326f136', +'89604b69-f1d0-4da9-bb18-9bb002cba5bd', 1); INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES +('37f63337-f3c8-4b08-b129-1e0a16117cb6', '51aec62a-0be9-4950-89ce-ca8babe5104f', '8286d91e-63df-4202-a367-a43da1e5d52a', +5); INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES ('34b97156-aedb-44c4-8a3e-36df05ec9f70', +'51aec62a-0be9-4950-89ce-ca8babe5104f', 'a84f5433-511e-4a50-9770-11ed97dfdc93', 1); INSERT INTO public.order_items (id, +order_id, product_id, quantity) VALUES ('2a9db620-0f5d-439a-b8f9-89b5a90a743b', '87487a6d-0560-4305-aad3-70a75231cf17', +'35480a9a-0651-4d79-89e5-03447ca127fc', 1); INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES +('21f85fcc-e1af-47ca-a706-daa0aeeafac1', '34f64d2c-7897-48eb-b5be-4886808b7826', '35480a9a-0651-4d79-89e5-03447ca127fc', +8); INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES ('fabc21f0-487d-41dc-8339-cbd8d4910ba2', +'34f64d2c-7897-48eb-b5be-4886808b7826', '41182cd6-c312-4fba-b5d3-125b805c9313', 6); INSERT INTO public.order_items (id, +order_id, product_id, quantity) VALUES ('4b6528fb-359c-4d39-96eb-c4bcb1282411', 'a9968bb0-1cf2-4ebd-b2b9-3e9b7ac7891e', +'35480a9a-0651-4d79-89e5-03447ca127fc', 10); INSERT INTO public.order_items (id, order_id, product_id, quantity) VALUES +('617f628b-b6f2-4b40-bcd2-c2b041611398', '7e5155cf-9543-49c5-aee7-fa2296bf65d5', '41182cd6-c312-4fba-b5d3-125b805c9313', +2); +``` + + + + +```sql +SET standard_conforming_strings = off; +SET check_function_bodies = false; +SET escape_string_warning = off; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE TABLE public.products ( + id uuid DEFAULT public.uuid_generate_v1() NOT NULL, + manufacturer text NOT NULL, + stock int NOT NULL +); +ALTER TABLE ONLY public.products + ADD CONSTRAINT products_pkey PRIMARY KEY (id); + +INSERT INTO public.products (id, manufacturer, stock) VALUES ('5a053b73-8196-4a88-aea2-2deb3404995c', 'Ivy', 10); +INSERT INTO public.products (id, manufacturer, stock) VALUES ('89604b69-f1d0-4da9-bb18-9bb002cba5bd', 'Brigham', 12); +INSERT INTO public.products (id, manufacturer, stock) VALUES ('8286d91e-63df-4202-a367-a43da1e5d52a', 'Arn', 100); +INSERT INTO public.products (id, manufacturer, stock) VALUES ('a84f5433-511e-4a50-9770-11ed97dfdc93', 'Karly', 420); +INSERT INTO public.products (id, manufacturer, stock) VALUES ('35480a9a-0651-4d79-89e5-03447ca127fc', 'Peter', 2); +INSERT INTO public.products (id, manufacturer, stock) VALUES ('41182cd6-c312-4fba-b5d3-125b805c9313', 'Atlas', 25); +``` + + + + + + +## Step 2: Add Relationships + +[Relationships](https://hasura.io/docs/latest/schema/postgres/remote-relationships/index/) are a way to join data across +different data sources. With remote joins, the join, authorization, and consistency checks of added sources all happen +at the Hasura layer via metadata. Think of it as foreign keys but neither limited within a single data source nor +necessary a one-one entity. + +In our example, we'll be adding a many-one relationship (`order_items` -> `order`) within our Order Management System +and a one-one relationship (`users` <-> `orders` and `order_items` <-> `products` respectively) among remote databases. + +- For adding the suggested relationship within the database: + - Head to `Data` tab -> `orders` table -> `Relationships` -> `Suggested Array Relationships` + - Hit `Add` next to the suggested array relationship of `order_items` <-> `orders`. + - Similarly, head to `Data` tab -> `order_items` table -> `Relationships` -> `Suggested Object Relationships` + - Hit `Add` next to the suggested object relationship of `order_items` <-> `orders`. + + + +- For adding remote database relationships: + - Head to `Data` tab -> `users` table -> `Relationships` -> `Remote Database Relationships` + - Define an Object relationship between `users` and `orders` with reference fields as `id` and `user_id` respectively. + Let's name this relationship `user_orders`. Hit `Save`. + - Similarly, in the `order_items` table, define an Object relationship between `order_items` and `products` with + reference fields as `product_id` and `id` respectively. Let's name this `order_items_products`. Hit `Save`. + + + +## Step 3: Add Permissions + +Hasura's fine-grained access control system allows you to specify which users can access which data, ensuring that your +application is secure and robust. [Read more](/auth/overview.mdx) on Authentication and Authorization in Hasura. + +One of the primary features of Hasura is that it provides Role Based Access Control (RBAC) with granularity i.e. it +enables users to create roles and define custom granular row/column level properties on them. + +In our case: + +- `users` table contains sensitive information like the `password` field which ideally should only be exposed to the + `admin` role. Column-level permissions i.e. restricted access to columns based on the role defined comes in handy + here. +- Also, a user should not be allowed to read other users' data in the same table. Row-level permissions can be used here + by defining custom checks based on the role. + +To implement this: + +- Head over to the `users` table -> `Permissions` tab. By default, an `admin` role is already present with access to all + CRUD operations. Let's create a custom role called `user` and define only `select` level permissions for them. +- Click on the edit icon against the `select` tab: + - Define `Row select permissions` with a custom check `{"email":{"_eq":"x-hasura-user-email"}}`. For every request + made, this will ensure to check the email passed as `x-hasura-user-email` header and return rows specific to only + those emails. + - Define `Column Level Permissions` by selecting only columns that should be accessible to the user. These will be + `name`, `email`, and `address` in our case. + - Click on `Save Permissions`. + + + +## Step 4: Explore GraphQL API + +Voila! Your data federated API is ready to use. + +Let's say you wanna query a specific user from `users` with a known email, their `orders`, `order items`, and the +details of the `products` in those orders in a single request. Hasura enables you to query this stitched data from +different sources in a single GraphQL API call. + +Head over to the `API` tab and test out the following GraphQL query: + + + +:::info Note + +If `x-hasura-admin-secret` is present in `Request Headers` under `API` tab, the role will default to `admin`. You can +read more on admin access [here](https://hasura.io/docs/latest/auth/authentication/admin-secret-access/#admin-secret). + +::: + +## Advanced topics + +### Remote Schemas as a data source + +- Hasura enables you to write queries and mutations to disparate sources (eg.: remote GraphQL API), all from your single + Hasura endpoint. +- With respect to the above example, if the inventory management system was a remote Graphql API server, Hasura will + make it possible to stitch this API by defining remote relationships with other data sources. +- [Read more](https://hasura.io/docs/latest/remote-schemas/quickstart/) on how to go about adding a remote schema as a + data source. + +### REST Endpoints as a data source + +- Actions are a way to extend Hasura's schema with REST APIs. You need to provide the schema for the API and the REST + API endpoint which is then called for resolving the result. +- [Read more](https://hasura.io/docs/latest/actions/quickstart/) on how to set up a REST endpoint as an action. + +### Caching + +- Hasura Cloud and Enterprise Edition provide support for caching query responses, to improve performance for queries + that are executed frequently. This includes Actions and queries against Remote Schemas. +- Cached responses are stored for a period of time in a LRU (least-recently used) cache, and removed from the cache as + needed based on usage. +- [Read more](https://hasura.io/docs/latest/queries/response-caching/) on Hasura Query Response Caching. diff --git a/docs/docs/resources/use-case/gql-backend.mdx b/docs/docs/resources/use-case/gql-backend.mdx new file mode 100644 index 00000000000..de74deadc6a --- /dev/null +++ b/docs/docs/resources/use-case/gql-backend.mdx @@ -0,0 +1,427 @@ +--- +description: Building a GraphQL backend for an application using Hasura +title: Building a GraphQL backend for an application +sidebar_label: Building a GraphQL backend with Hasura +keywords: + - hasura + - graphql + - backend + - tutorial + - resource +sidebar_position: 2 +--- + +import Thumbnail from '@site/src/components/Thumbnail'; + +# Building a GraphQL backend for an application with Hasura + +## Introduction + +The Hasura GraphQL Engine is a blazing-fast GraphQL server that gives you instant, real-time GraphQL APIs over many +popular databases and other data sources. Using Hasura you can build a powerful GraphQL backend that makes it easy to +build scalable and secure applications just by connecting a database and defining a schema. + +## Example + +This guide will outline the steps required to set up a Hasura GraphQL backend for a todos app as an example. + +Our `todos app` will have the following features: + +- Users can create personal to-dos +- User can mark their to-dos as completed +- Users can view public to-dos +- View a list of currently online users using the app + +:::info Note + +We will be using the Hasura Console in the next few steps, which is a web app to setup Hasura by just making some +clicks! If you landed on this doc and do not have the Hasura console open, we recommend you to go through one of the +quickstart guides [here](/getting-started/overview.mdx) first. + +Hasura Console is a web-based graphical user interface (GUI) tool that allows users to interact with and manage their +Hasura GraphQL APIs. It provides an intuitive interface for exploring the schema, creating tables, modifying data, and +testing queries, among other things. + +::: + +## Step 1: Connect Database + +To set up Hasura as a GraphQL backend, the first step is to establish a connection between a database and Hasura. Hasura +provides support for a wide range of databases, which can be found in the +[supported databases](/databases/overview.mdx/#supported-databases) section. + +To connect your database you should navigate to the `Data` -> `Manage` -> `Connect Database` -> +`Connect Existing Database` tab in Hasura Console and enter the `Database Display Name` , `Database URL` and click the +`Connect Database` button. + + + +If you dont have a database to connect, you can get started with a free Neon Postgres +database by navigating to the `Data` -> `Manage` -> `Connect Database` -> `Connect New Database` tab in Hasura Console +and clicking on the `Connect Neon Database` button. + +After successfully connecting the database you can select `View Database` in the notification to view your database. + +## Step 2: Data modeling + +Data modeling is a crucial step in building a backend for your application. Its important to define your schema based on +the backend logic of your app. This involves considering the relationships between your data and how it will be stored +and retrieved. + +In the `todos app` example, we have two main models in this app: `users` and `todos`, each with its own set of +properties. + +The final model looks like the following: + +![Schema Todo app](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/voyager-schema.png) + +As we create tables using the Console or directly on postgres, the Hasura GraphQL Engine automatically creates GraphQL +APIs to access the data. + +### Step 2.1: Create Tables + +Hasura makes this easy by providing a schema builder that allows you to create tables and relationships visually. + +After you have connected a database, to create a table, click on the `Data` tab in the Hasura Console, and then click +the `Create Table` button. You'll be prompted to enter a table name and the columns you want to include in the table. +You can also specify relationships between tables, which will be used to generate GraphQL queries and mutations +automatically. + +For the todo-app let's get started by creating the `users` table. + +The `users` table will have the following columns: + +- `id` (type Text and Unique), +- `name` (type Text), +- `created_at` (type Timestamp and default now()) +- `last_seen` (type Timestamp and nullable) + +The columns are associated with properties of users. The `last_seen` column is used to store the latest timestamp of +when the user was online. + +![Create table users](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/create-table-users.png) + +Once you are done, click on `Add Table` button to create the table. + +Similarly we can create a `todos` table having following items: + +- `id` (type Integer (auto-increment)), +- `title` (type Text), +- `is_completed` (type Boolean and default false) +- `is_public` (type Boolean and default false) +- `created_at` (type Timestamp and default now()) +- `user_id` (type Text) + +## Step 3: Explore GraphQL API + +To query data using Hasura, you can use any GraphQL client that supports HTTP requests, such as GraphQL Playground, +Postman, or Insomnia. + +Hasura gives you instant GraphQL APIs over tables and views existing in your database. For example, for the todos app, +you can start exploring the GraphQL API for the users table. We are going to use GraphiQL to explore the API. + +GraphiQL is the GraphQL integrated development environment (IDE). It's a powerful tool to interact with the API. + +You can access GraphiQL by heading over to the `API` tab. + +Here's how to explore the GraphQL APIs for the todos app example: + +### Step 3.1: Mutation {#mutation} + +We can add a user using a [GraphQL Mutation](https://hasura.io/learn/graphql/intro-graphql/graphql-queries/). Copy the +following code into the GraphiQL interface. + +```graphql +mutation { + insert_users(objects: [{ id: "1", name: "user_1" }]) { + affected_rows + } +} +``` + +Click on the `Play` button on the GraphiQL interface to execute the query. + +You should get a response looking something like this: + + + +Great! You have just successfully run a mutation on the `users` table that you just created. + +**Tip**: You can use the `Explorer` on the GraphiQL interface to generate the mutation in a few clicks. + +### Step 3.2: Query {#query} + +Here is how to [query](https://hasura.io/docs/latest/queries/index/) the data that we just inserted. + +```graphql +query { + users { + id + name + created_at + } +} +``` + +You should get a response that looks something like this: + + + +Note that some columns like `created_at` have default values, even though you did not insert them during the mutation. + +### Step 3.3: Subscription {#subscription} + +If a client subscribes to a specific query using a GraphQL subscription, it will receive real-time updates whenever +there are changes to the data returned by that query. This means that if a new record is added to the database that +matches the subscribed query, the client will immediately receive a notification about the new data, without having to +make a new API request. + +For the `todos app`, we can run a [subscription](https://hasura.io/docs/latest/subscriptions/index/) over `users` table +to watch for changes to the table in realtime without having to query every time. + +```graphql +subscription { + users { + id + name + created_at + } +} +``` + +In a new tab, try adding more records into your `users` table and see the records being updated in the running +subscription. + +## Step 4: Create Relationships + +Relationships are the connections between different tables in a relational database. By defining relationships between +tables in a database schema, you can access data across tables using GraphQL queries without having to write complex SQL +join statements. + +GraphQL schema relationships can be either + +- **object relationships (one-to-one)**: In a one-to-one relationship, one object is linked to only one other object of + another type. For our `todo app` example, a single `to-do` entry corresponds only to only one user. may have one + profile picture. In this case, the `to-do` object type would have a single field that references the `user` object + type. This type of relationship is useful when you have a strict one-to-one mapping between objects. + +- **array relationships (one-to-many)**: In a in a one-to-many relationship, one object is linked to multiple objects of + another type. For our `todo app`example, a `user` may have many `to-dos` In this case, the `user` object type would + have a field that returns a list of `to-do` objects. This type of relationship is useful when you have multiple + related objects of the same type. + +### Step 4.1: Create Foreign Key + +A foreign key is a type of database constraint that ensures that the values in a column or set of columns in one table +match the values in another table's primary key. In other words, it creates a link between two tables that is enforced +by the database. + +For the `todos app` in the `todos` table, the value of `user_id` column must be ideally present in the `id` column of +`users` table. Otherwise, it would result in inconsistent data. + +Here we can define a foreign key called `user_id` column in `todos`. For this head over to `Console` -> `DATA` -> +`todos` -> `Modify` page. + +![Todos Modify Page](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/todos-modify-page.png) + +Scroll down to `Foreign Keys` section at the bottom and click on `Add`. + +![user_id foreign key](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/user-id-foreign-key.png) + +- Select the Reference table as `users` +- Choose the From column as `user_id` and To column as `id` + +We are enforcing that the `user_id` column of `todos` table must be one of the values of `id` in `users` table. + +Click on `Save` to create the foreign key. + +Great! Now you have ensured data consistency. + +### Step 4.2: Create Relationship + +Now that the foreign key constraint is created, Hasura Console automatically suggests relationships based on that. + +Head over to `Relationships` tab under `todos` table and you should see a suggested relationship like below: + +![Todos Relationships Page](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/todos-relationship-page.png) + +Click on `Add` in the suggested object relationship. + +Enter the relationship name as `user` (already pre-filled) and click on `Save`. + +![User Object Relationship](https://graphql-engine-cdn.hasura.io/learn-hasura/assets/graphql-hasura/todos-relationship-user.png) + +A relationship has now been established between todos and users table. We can now run queries with nesting. + +```graphql +query { + todos { + id + title + user { + id + name + } + } +} +``` + +You can see the response in the following format: + + + +Great! Now you know the basics of setting up Hasura Graphql Backend and using the Instantly Generated GraphQL APIs. + +## Step 5: Set Authorization rules + +Hasura provides a robust access control system that enables users to specify which users can access specific data, +ensuring that their application is secure. Hasura offers Role-Based Access Control (RBAC) with granular row/column level +properties. Access control rules help in restricting querying on a table based on certain conditions. + +In this realtime `todos app` example, certain columns in tables do not need to be exposed to the user. The aim of the +app is to allow users to manage their own todos only but should be able to view all the public todos. + +To implement this in Hasura, head over to the `Permissions` tab under `todos` table to add relevant permissions. We want +to allow logged-in users creating a new todo entry to only specify the `is_public` and `title` columns. + +- In the enter new role textbox, type in `user` +- Click on edit (pencil) icon for `insert` permissions. This would open up a section below, which lets you configure + custom checks and allow columns. +- In the custom check, choose the following condition + +```json +{ "user_id": { "_eq": "X-Hasura-User-Id" } } +``` + +Under "Column insert permissions", select the `title` and `is_public` columns. Below "Column presets", select `user_id` +from `from session variable` mapping to `X-HASURA-USER-ID`. + + + +:::info Session variables are key-value pairs returned from the authentication service for each request. When a user +makes a request, the session token maps to a `USER-ID`. This `USER-ID` can be used in permission to show that inserts +into a table are only allowed if the `user_id` column has a value equal to that of `USER-ID`, the session variable. ::: +Click on `Save Permissions`. + +Similarly you can setup `Select`, `Update` and `Delete`permissions and permissions for the `todos table`. + +## Advanced topics + +Up until now, we have addressed the data-modeling and relationships part of constructing a backend. However, Hasura +offers numerous sophisticated functionalities for handling custom business logic, security, caching, monitoring, and a +variety of other features. In the following section, we will discuss some of the very useful topics briefly. + +### Actions + +Actions are a way to execute arbitrary code or scripts in response to a GraphQL mutation. With actions, you can extend +your GraphQL API beyond simple database queries and mutations, and incorporate business logic, third-party APIs, and +other external services. + +To add an action to send todo notification via the Hasura console, follow these steps: + +Open the Hasura console and navigate to the `Actions` tab. Click on the `Create` button to create a new action. In the +Action Definition section, define a GraphQL mutation with the required input parameters for the action. + + + +For example, if you want to add a new todo and send a notification to the user who created it, you can define a mutation +like this: + +```graphql +mutation AddTodoAndNotify($todo: String!, $userId: Int!) { + insert_todos(objects: { todo: $todo, user_id: $userId }) { + affected_rows + } + send_notification(name: "john_doe", message: "A new todo has been added") +} +``` + +In the `Webhook (HTTP/S) Handler` section, enter the `URL` of the endpoint that will receive the action request and +process it. + +In the `Configure REST Connectors` section, modify the payload if necessary to send the required data to the endpoint. + +Click the `Create Action` button to save the action and test it by going to the API Explorer and selecting the +corresponding mutation. Provide the input parameters and execute the mutation to trigger the action. + +### Event triggers + +Event triggers are a way to execute a GraphQL mutation in response to a database event such as an insert, update, or +delete. With event triggers, you can automate workflows and perform real-time processing of data changes. + +For our `todos app` we can set up an event trigger to send welcome email for new user who signs up. We can do this by +creating an Event Trigger that calls out to a webhook whenever a new user is inserted into the users table. The webhook +payload will contain the user's email address, and we can use this in the endpoint which we create to send them the +welcome email. + +Navigate to the `Event` tab in the Console and click the `Create` button while on the `Event Triggers` tab in the left +navigation. + + + +On the Event Trigger creation page, input the name of the trigger, `send_welcome_email`, and select the database, schema +and table that the trigger will be listening to. In this case we'll be listening to the `users` table for an INSERT +event. + +In the `Webhook (HTTP/S) Handler` section, enter the `URL` of the endpoint to be called when the event is triggered. + +Click `Create Event Trigger` button to save the event trigger and test it by going to the API Explorer and selecting the +corresponding mutation. Provide the input parameters and execute the mutation to trigger the action. + + + +### Authentication + +Hasura authentication is a feature that allows users to authenticate with Hasura and access data through GraphQL +queries. The authentication process involves two main components: authentication providers and authorization rules. + +Authentication providers are services that handle the authentication process for Hasura. Hasura supports several +authentication providers, including email/password, social media logins (such as Google, Facebook, and GitHub), and +third-party authentication services (such as Auth0 and Firebase). + +In case of `todos app` example, we have a users table in the database. The data of customers signing up can go into this +table. With Hasura, it is very easy to set up JWT based authentication. + +Here's what the flow for a login with JWT looks like. + + + +The REST API call to your custom Node.js server can be queried via GraphQL on the same endpoint that Hasura provides. + +Hasura Actions can be used to extend the auto-generated GraphQL types. Actions are a way to extend Hasura’s schema with +custom business logic using custom queries and mutations. + +Custom mutation for signup would look very simple: + +```graphql +mutation { + signup(name: "user_1", id: "1", password: "password") { + id + token + } +} +``` + +The server generates JWT token using a custom secret shared with Hasura and returns the token back to the client after +inserting the user into the database. + +On the other hand, you can also make use of Auth providers like Auth0, Firebase, Cognito which works well with +[Hasura's Auth system](/auth/authentication/index.mdx). + +## Conclusion + +Using Hasura as a GraphQL backend can simplify the process of building complex applications. By defining your data +schema, adding business logic, and securing your API with Hasura, you can focus on building a great user experience. diff --git a/docs/static/img/data-federation/add_permissions.webm b/docs/static/img/data-federation/add_permissions.webm new file mode 100644 index 00000000000..db1c395efb4 Binary files /dev/null and b/docs/static/img/data-federation/add_permissions.webm differ diff --git a/docs/static/img/data-federation/add_relationships.webm b/docs/static/img/data-federation/add_relationships.webm new file mode 100644 index 00000000000..58907a8a92b Binary files /dev/null and b/docs/static/img/data-federation/add_relationships.webm differ diff --git a/docs/static/img/data-federation/add_remote_relationships.webm b/docs/static/img/data-federation/add_remote_relationships.webm new file mode 100644 index 00000000000..9f67d39b4af Binary files /dev/null and b/docs/static/img/data-federation/add_remote_relationships.webm differ diff --git a/docs/static/img/data-federation/hasura_data_federation.png b/docs/static/img/data-federation/hasura_data_federation.png new file mode 100644 index 00000000000..3836b539369 Binary files /dev/null and b/docs/static/img/data-federation/hasura_data_federation.png differ diff --git a/docs/static/img/data-federation/hasura_data_federation_ecommerce_app.png b/docs/static/img/data-federation/hasura_data_federation_ecommerce_app.png new file mode 100644 index 00000000000..c2717eae441 Binary files /dev/null and b/docs/static/img/data-federation/hasura_data_federation_ecommerce_app.png differ diff --git a/docs/static/img/data-federation/setup_databases.webm b/docs/static/img/data-federation/setup_databases.webm new file mode 100644 index 00000000000..4c082f45a99 Binary files /dev/null and b/docs/static/img/data-federation/setup_databases.webm differ diff --git a/docs/static/img/getting-started/Erd-remote-schemas.png b/docs/static/img/getting-started/Erd-remote-schemas.png new file mode 100644 index 00000000000..ec25cbb5037 Binary files /dev/null and b/docs/static/img/getting-started/Erd-remote-schemas.png differ diff --git a/docs/static/img/getting-started/action-definition.png b/docs/static/img/getting-started/action-definition.png new file mode 100644 index 00000000000..e04d8ec1a3b Binary files /dev/null and b/docs/static/img/getting-started/action-definition.png differ diff --git a/docs/static/img/getting-started/env-var-remote-schema.png b/docs/static/img/getting-started/env-var-remote-schema.png new file mode 100644 index 00000000000..5399a34c085 Binary files /dev/null and b/docs/static/img/getting-started/env-var-remote-schema.png differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-connect-db.webm b/docs/static/img/getting-started/hasura-use-case/data-api-connect-db.webm new file mode 100644 index 00000000000..097df78476d Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-connect-db.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-intro-gif.gif b/docs/static/img/getting-started/hasura-use-case/data-api-intro-gif.gif new file mode 100644 index 00000000000..314fa85eb1c Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-intro-gif.gif differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-make-mutation.webm b/docs/static/img/getting-started/hasura-use-case/data-api-make-mutation.webm new file mode 100644 index 00000000000..5368406c089 Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-make-mutation.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-make-query.webm b/docs/static/img/getting-started/hasura-use-case/data-api-make-query.webm new file mode 100644 index 00000000000..cacd2bc8fda Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-make-query.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-set-relationship.webm b/docs/static/img/getting-started/hasura-use-case/data-api-set-relationship.webm new file mode 100644 index 00000000000..48324cdba7e Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-set-relationship.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-subscription.webm b/docs/static/img/getting-started/hasura-use-case/data-api-subscription.webm new file mode 100644 index 00000000000..632b0971569 Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-subscription.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/data-api-track-tables.webm b/docs/static/img/getting-started/hasura-use-case/data-api-track-tables.webm new file mode 100644 index 00000000000..180e1561327 Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/data-api-track-tables.webm differ diff --git a/docs/static/img/getting-started/hasura-use-case/set-permissions.webm b/docs/static/img/getting-started/hasura-use-case/set-permissions.webm new file mode 100644 index 00000000000..a7765148607 Binary files /dev/null and b/docs/static/img/getting-started/hasura-use-case/set-permissions.webm differ diff --git a/docs/static/img/getting-started/remote-schema-for-gateway.png b/docs/static/img/getting-started/remote-schema-for-gateway.png new file mode 100644 index 00000000000..47ac166d8ea Binary files /dev/null and b/docs/static/img/getting-started/remote-schema-for-gateway.png differ diff --git a/docs/static/img/getting-started/remote-schema-query.png b/docs/static/img/getting-started/remote-schema-query.png new file mode 100644 index 00000000000..176e2a2fde0 Binary files /dev/null and b/docs/static/img/getting-started/remote-schema-query.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/Mutation.png b/docs/static/img/resources/hasura-as-gql-backend/Mutation.png new file mode 100644 index 00000000000..be5261e20ae Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/Mutation.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/auth-jwt-mode.png b/docs/static/img/resources/hasura-as-gql-backend/auth-jwt-mode.png new file mode 100644 index 00000000000..2bc82d6a33a Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/auth-jwt-mode.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/cloud_dashboard.png b/docs/static/img/resources/hasura-as-gql-backend/cloud_dashboard.png new file mode 100644 index 00000000000..07e32fbe643 Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/cloud_dashboard.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/data-api-connect-db.gif b/docs/static/img/resources/hasura-as-gql-backend/data-api-connect-db.gif new file mode 100644 index 00000000000..4f5b45d3ef4 Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/data-api-connect-db.gif differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/insert-permission.png b/docs/static/img/resources/hasura-as-gql-backend/insert-permission.png new file mode 100644 index 00000000000..cdba21fe9b3 Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/insert-permission.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/nested-query.png b/docs/static/img/resources/hasura-as-gql-backend/nested-query.png new file mode 100644 index 00000000000..3cf24d3903a Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/nested-query.png differ diff --git a/docs/static/img/resources/hasura-as-gql-backend/query.png b/docs/static/img/resources/hasura-as-gql-backend/query.png new file mode 100644 index 00000000000..6c4d136902b Binary files /dev/null and b/docs/static/img/resources/hasura-as-gql-backend/query.png differ