Step 3: Add Permissions and Create Application
This step adds access control to your database types through GraphQL permissions and creates a Tailor application that exposes your database through a GraphQL API endpoint. This makes your data accessible to client applications while maintaining security controls.
What This Step Does
In this step, you:
- Add GraphQL permission policies to all three database types (User, Project, Task)
- Configure permissions to allow all actions for everyone (suitable for development)
- Create a Tailor application named
project-management - Configure CORS settings to allow local development access
- Set up IP address restrictions (allowing all IPs for development)
- Connect the application to the TailorDB database through a subgraph configuration
The application serves as the API gateway that client applications will use to interact with your data. The GraphQL permissions ensure that access to data is controlled and secure.
Configuration Files
To follow along, review the configuration files for this step here.
tailordb.tf (Updated)
The database configuration now includes GraphQL permission resources for each type:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_tailordb_gql_permission" "user" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb.prj_mgmt_db.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb_type.user.name</span></span>
<span><span style="color: var(--shiki-color-text)"> policies </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [{</span></span>
<span><span style="color: var(--shiki-color-text)"> actions </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">"all"</span><span style="color: var(--shiki-color-text)">]</span></span>
<span><span style="color: var(--shiki-color-text)"> permit </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow"</span></span>
<span><span style="color: var(--shiki-color-text)"> description </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow all actions for everyone"</span></span>
<span><span style="color: var(--shiki-color-text)"> }]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_tailordb_gql_permission" "project" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb.prj_mgmt_db.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb_type.project.name</span></span>
<span><span style="color: var(--shiki-color-text)"> policies </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [{</span></span>
<span><span style="color: var(--shiki-color-text)"> actions </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">"all"</span><span style="color: var(--shiki-color-text)">]</span></span>
<span><span style="color: var(--shiki-color-text)"> permit </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow"</span></span>
<span><span style="color: var(--shiki-color-text)"> description </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow all actions for everyone"</span></span>
<span><span style="color: var(--shiki-color-text)"> }]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_tailordb_gql_permission" "task" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb.prj_mgmt_db.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb_type.task.name</span></span>
<span><span style="color: var(--shiki-color-text)"> policies </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [{</span></span>
<span><span style="color: var(--shiki-color-text)"> actions </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">"all"</span><span style="color: var(--shiki-color-text)">]</span></span>
<span><span style="color: var(--shiki-color-text)"> permit </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow"</span></span>
<span><span style="color: var(--shiki-color-text)"> description </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"allow all actions for everyone"</span></span>
<span><span style="color: var(--shiki-color-text)"> }]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
applications.tf (New)
This file creates the application that exposes your database through a GraphQL API:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_application" "project_management" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"project-management"</span></span>
<span><span style="color: var(--shiki-color-text)"> cors </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"http://localhost:8080"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"http://localhost:8081"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)"> allowed_ip_addresses </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"0.0.0.0/0"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)"> subgraphs </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"tailordb"</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb.prj_mgmt_db.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Key Features
GraphQL Permissions
The tailor_tailordb_gql_permission resources control access to GraphQL operations on each type:
- actions: Set to
["all"]to allow all GraphQL operations (queries, mutations, subscriptions) - permit: Set to
"allow"to grant access - description: Documents the purpose of the permission policy
In production environments, you would typically configure more restrictive permissions based on user roles, authentication status, or other conditions. The "allow all" policy used here is suitable for development and prototyping.
Application Configuration
The tailor_application resource creates an API gateway with several important configurations:
CORS (Cross-Origin Resource Sharing)
The cors field specifies which origins are allowed to make requests to your API:
<span><span style="color: var(--shiki-color-text)">cors </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"http://localhost:8080"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"http://localhost:8081"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">]</span></span>
<span></span>
This allows frontend applications running on these local ports to access your API during development.
IP Address Restrictions
The allowed_ip_addresses field controls which IP addresses can access your application:
<span><span style="color: var(--shiki-color-text)">allowed_ip_addresses </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"0.0.0.0/0"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">]</span></span>
<span></span>
The value 0.0.0.0/0 allows access from any IP address. In production, you would typically restrict this to specific IP ranges.
Subgraphs
The subgraphs configuration connects your application to backend services:
<span><span style="color: var(--shiki-color-text)">subgraphs </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"tailordb"</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_tailordb.prj_mgmt_db.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">]</span></span>
<span></span>
This creates a GraphQL subgraph that exposes all the types and operations from your TailorDB database. The application automatically generates a unified GraphQL schema that includes all the queries and mutations for your types.
Expected Outcome
After applying this configuration with terraform apply, you should see:
- GraphQL permissions configured for all three types (User, Project, Task)
- A Tailor application named "project-management" created in your workspace
- A GraphQL API endpoint URL provided by the Tailor Platform
- The application connected to your TailorDB database namespace
You can verify the setup by:
- Viewing the application in the Tailor Console
- Accessing the GraphQL API endpoint (the URL will be displayed in the console)
- Using the GraphQL playground to explore the auto-generated schema
The GraphQL API will include full CRUD operations (Create, Read, Update, Delete) for all your types, along with relationship traversal capabilities.
Next step
Continue to Step 4: Add Authentication.