Skip to content

Commit

Permalink
Let users define their own database as easily as possible. (#10209)
Browse files Browse the repository at this point in the history
* Let users define their own client token.

* Make sure users know that GraphQL schema can also be done via the UI

* Update README.md

* Update setup.js

Co-authored-by: Matthew Sweeney <mail@msweeneydev.com>
Co-authored-by: Joe Haddad <timer150@gmail.com>
  • Loading branch information
3 people committed Jan 22, 2020
1 parent f24aa41 commit 7d419f8
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 3 deletions.
16 changes: 15 additions & 1 deletion examples/with-graphql-faunadb/README.md
Expand Up @@ -16,7 +16,21 @@ By importing a `.gql` or `.graphql` schema into FaunaDB ([see our sample schema

You can start with this template [using `create-next-app`](#using-create-next-app) or by [downloading the repository manually](#download-manually).

To use a live FaunaDB database, create one and import this example's `schema.gql` file using the FaunaDB console. Create a client secret, then paste it into `next.config.js`.
To use a live FaunaDB database, create a database at [dashboard.fauna.com](https://dashboard.fauna.com/) and generate a server token by going to the **Security** tab on the left and then click **New Key**. Give the new key a name and select the 'Server' Role. Copy the token since the setup script will ask for it. Do not use it in the frontend, it has superpowers which you don't want to give to your users.

The database can then be set up with the delivered setup by running:

```
yarn setup
```

This script will ask for the server token. Once you provide it with a valid token, this is what the script automatically does for you:

- **Import the GraphQL schema**, by importing a GraphQL schema in FaunaDB, FaunaDB automatically sets up collections and indexes to support your queries. This is now done for you with this script but can also be done from the [dashboard.fauna.com](https://dashboard.fauna.com/) UI by going to the GraphQL tab
- **Create a role suitable for the Client**, FaunaDB has a security system that allows you to define which resources can be accessed for a specific token. That's how we limit our clients powers, feel free to look at the scripts/setup.js script to see how we make roles and tokens.
- **Create a token for that role** which is printed, this is the token to be used in the frontend.

At the end, the newly generated client token will be printed and should be used to replace the '< GRAPHQL_SECRET >' placeholder in the next.config.js config.

### Using `create-next-app`

Expand Down
2 changes: 1 addition & 1 deletion examples/with-graphql-faunadb/next.config.js
Expand Up @@ -8,7 +8,7 @@ module.exports = {
| https://docs.fauna.com/fauna/current/security/
|--------------------------------------------------
*/
faunaDbSecret: 'fnADcnWRUcACE_6uDSw05MspruDdWKk88ZSmsm2a',
faunaDbSecret: '< GRAPHQL_SECRET >',
faunaDbGraphQlEndpoint: 'https://graphql.fauna.com/graphql',
},
}
8 changes: 7 additions & 1 deletion examples/with-graphql-faunadb/package.json
Expand Up @@ -5,11 +5,17 @@
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
"start": "next start",
"setup": "node ./scripts/setup.js"
},
"dependencies": {
"next": "latest",
"react": "^16.10.2",
"react-dom": "^16.10.2"
},
"devDependencies": {
"faunadb": "2.11.1",
"request": "2.88.0",
"stream-to-promise": "2.2.0"
}
}
103 changes: 103 additions & 0 deletions examples/with-graphql-faunadb/scripts/setup.js
@@ -0,0 +1,103 @@
// This script sets up the database to be used for this example application.
// Look at the code to see what is behind the magic
const faunadb = require('faunadb')
const q = faunadb.query
const request = require('request')
const fs = require('fs')
const streamToPromise = require('stream-to-promise')

const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout,
})

// In order to set up a database, we need a server key, so let's ask the user for a key.
readline.question(`Please provide the FaunaDB server key\n`, serverKey => {
// A graphql schema can be imported in override or merge mode: 'https://docs.fauna.com/fauna/current/api/graphql/endpoints#import'
const options = {
model: 'merge',
uri: 'https://graphql.fauna.com/import',
headers: { Authorization: `Bearer ${serverKey}` },
}
const stream = fs.createReadStream('./schema.gql').pipe(request.post(options))

streamToPromise(stream)
.then(res => {
const readableResult = res.toString()
if (readableResult.startsWith('Invalid authorization header')) {
console.error('You need to provide a secret, closing. Try again')
return readline.close()
} else if (readableResult.startsWith('Invalid database secret')) {
console.error(
'The secret you have provided is not valid, closing. Try again'
)
return readline.close()
} else if (readableResult.includes('success')) {
console.log('1. Successfully imported schema')
return readline.close()
}
})
.catch(err => {
console.error(err)
console.error(`Could not import schema, closing`)
})
.then(res => {
// The GraphQL schema is important, this means that we now have a GuestbookEntry Colleciton and an entries index.
// Then we create a token that can only read and write to that index and collection
var client = new faunadb.Client({ secret: serverKey })
return client
.query(
q.CreateRole({
name: 'GuestbookRole',
privileges: [
{
resource: q.Collection('GuestbookEntry'),
actions: { read: true, write: true },
},
{
resource: q.Index('entries'),
actions: { read: true },
},
],
})
)
.then(res => {
console.log(
'2. Successfully created role to read and write guestbook entries'
)
})
.catch(err => {
if (err.toString().includes('instance already exists')) {
console.log('2. Role already exists.')
} else {
throw err
}
})
})
.catch(err => {
console.error(err)
console.error(`Failed to create role, closing`)
})
.then(res => {
// The GraphQL schema is important, this means that we now have a GuestbookEntry Colleciton and an entries index.
// Then we create a token that can only read and write to that index and collection
var client = new faunadb.Client({ secret: serverKey })
return client
.query(
q.CreateKey({
role: q.Role('GuestbookRole'),
})
)
.then(res => {
console.log('3. Created key to use in client')
console.log(
'Replace the < GRAPHQL_SECRET > placehold in next.config.js with:'
)
console.log(res.secret)
})
})
.catch(err => {
console.error(err)
console.error(`Failed to create key, closing`)
})
})

0 comments on commit 7d419f8

Please sign in to comment.