Skip to content

Commit

Permalink
add community boilerplates and examples (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
ecthiender authored and shahidhk committed Sep 13, 2018
1 parent be20a11 commit acd62c3
Show file tree
Hide file tree
Showing 255 changed files with 58,711 additions and 19 deletions.
1 change: 1 addition & 0 deletions .ciignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ LICENSE
scripts/*
assets/*
docs/*
community/*
.circleci/*
.ciignore
.gitignore
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
npm-debug.log
*.temp
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ consisting of 3 components. Each have their own contributing guides:
All of the three components have a single version, denoted by either the git
tag, or a combination of branch name and git commit SHA.

### Docs

Contributing guide for docs can be found at [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md).

### Community content

There is no specific contributing guide for community content. Anything that can
help GraphQL Engine community/users can go into the section. We have identified
[boilerplates](community/boilerplates), [examples](community/examples) and
[tools](community/tools) as primary candidates. Feel free to submit a pull
request if you have something to add (not necessarily belonging to the
before-mentioned sections).

## Issues

### Reporting an Issue
Expand Down
24 changes: 24 additions & 0 deletions LICENSE-community
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
MIT Licence

Copyright (c) 2018-present, Hasura Technologies Private Limited

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
92 changes: 83 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ Read more at [hasura.io](https://hasura.io) and the [docs](https://docs.hasura.i
------------------

![Hasura GraphQL Enigne Demo](assets/demo.gif)
---

------------------

![Hasura GraphQL Engine Readltime Demo](assets/realtime.gif)

-------------------

## Features

* **Make powerful queries**: Built-in filtering, pagination, pattern search, bulk insert, update, delete mutations
* **Realtime**: Convert any GraphQL query to a live query by using subscriptions
* **Trigger webhooks or serverless functions**: On Postgres insert/update/delete events ([read more](event-triggers.md))
Expand All @@ -33,12 +37,26 @@ Read more at [hasura.io](https://hasura.io) and the [docs](https://docs.hasura.i

Read more at: [https://hasura.io](https://hasura.io) and the [docs](https://docs.hasura.io).

## Demos

* [Add GraphQL to a self-hosted GitLab instance](https://www.youtube.com/watch?v=a2AhxKqd82Q) (*3:44 mins*)
* [Todo app with Auth0 and GraphQL backend](https://www.youtube.com/watch?v=15ITBYnccgc) (*4:00 mins*)
* [GraphQL on GitLab integrated with GitLab auth](https://www.youtube.com/watch?v=m1ChRhRLq7o) (*4:05 mins*)
* [Dashboard for 10million rides with geo-location (PostGIS, Timescale)](https://www.youtube.com/watch?v=tsY573yyGWA) (*3:06 mins*)
## Table of contents
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**

- [Quickstart:](#quickstart)
- [One-click deployment on Heroku](#one-click-deployment-on-heroku)
- [Other deployment methods](#other-deployment-methods)
- [Architecture](#architecture)
- [Client-side tooling](#client-side-tooling)
- [Add business logic](#add-business-logic)
- [Custom resolvers](#custom-resolvers)
- [Trigger webhooks on database events](#trigger-webhooks-on-database-events)
- [Demos](#demos)
- [Realtime applications](#realtime-applications)
- [Videos](#videos)
- [Support & Troubleshooting](#support--troubleshooting)
- [Contributing](#contributing)
- [License](#license)

<!-- markdown-toc end -->

## Quickstart:

Expand Down Expand Up @@ -74,6 +92,51 @@ You can also place the engine behind a central GraphQL proxy that fronts multipl

Hasura works with any GraphQL client. We recommend using [Apollo Client](https://github.com/apollographql/apollo-client). See [awesome-graphql](https://github.com/chentsulin/awesome-graphql) for a list of clients.

## Add business logic

### Custom resolvers

Add custom resolvers in addition to Hasura GraphQL engine. Ideal for delegating
to HTTP APIs, making direct calls to another data-source or writing business
logic in code - [read more](community/boilerplates/custom-resolvers).

### Trigger webhooks on database events

Add asynchronous business logic that is triggered based on database events.
Ideal for notifications, data-pipelines from Postgres or asynchronous
processing - [read more](event-triggers.md).

## Demos

Checkout all the example applications in the
[community/examples](community/examples) directory.

### Realtime applications

- Group Chat application built with React, includes a typing indicator, online users & new
message notifications.
- [Try it out](https://chat-example-trial-roar.herokuapp.com/)
- [Tutorial](community/examples/realtime-chat)
- [Browse APIs](https://hasura-realtime-group-chat.herokuapp.com/)

- Live location tracking app that shows a running vehicle changing current GPS
coordinates moving on a map.
- [Try it out](https://hasura.github.io/realtime-location-app/)
- [Tutorial](community/examples/realtime-location-tracking)
- [Browse APIs](https://realtime-backend.herokuapp.com/)

- A realtime dashboard for data aggregations on continuously changing data.
- [Try it out](https://shahidh.in/hasura-realtime-poll/)
- [Tutorial](community/examples/realtime-poll)
- [Browse APIs](https://hasura-realtime-poll.herokuapp.com/)

### Videos

* [Add GraphQL to a self-hosted GitLab instance](https://www.youtube.com/watch?v=a2AhxKqd82Q) (*3:44 mins*)
* [Todo app with Auth0 and GraphQL backend](https://www.youtube.com/watch?v=15ITBYnccgc) (*4:00 mins*)
* [GraphQL on GitLab integrated with GitLab auth](https://www.youtube.com/watch?v=m1ChRhRLq7o) (*4:05 mins*)
* [Dashboard for 10million rides with geo-location (PostGIS, Timescale)](https://www.youtube.com/watch?v=tsY573yyGWA) (*3:06 mins*)


## Support & Troubleshooting

Expand All @@ -92,6 +155,17 @@ Check out our [contributing guide](CONTRIBUTING.md) for more details.

## License

GraphQL Engine is available under the [GNU Affero General Public License v3](https://www.gnu.org/licenses/agpl-3.0.en.html) (AGPL-3.0), the same license as [MongoDB](https://www.mongodb.com/community/licensing). We have written more about what you can and cannot do under AGPL [here](https://github.com/hasura/graphql-engine/wiki/License-Explained).
The core GraphQL Engine is available under the [GNU Affero General Public
License v3](https://www.gnu.org/licenses/agpl-3.0.en.html) (AGPL-3.0), the same
license as [MongoDB](https://www.mongodb.com/community/licensing). We have
written more about what you can and cannot do under AGPL
[here](https://github.com/hasura/graphql-engine/wiki/License-Explained).

**Commercial licenses** that bundle the Hasura GraphQL Engine with support, and
SLAs are available on request. Please feel free to contact us at [email protected]
or on our [website chat](https://hasura.io).

**Commercial licenses** that bundle the Hasura GraphQL Engine with support, and SLAs are available on request. Please feel free to contact us at [email protected] or on our [website chat](https://hasura.io).
All **other contents** (except those in [`server`](server), [`cli`](cli) and
[`console`](console) directories) are under [MIT License](LICENSE-community).
This includes everything in the [`docs`](docs) and [`community`](community)
directories.
16 changes: 16 additions & 0 deletions community/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Community

This directory contains community contributed code and content that supplements
Hasura GraphQL Engine. It includes several example applications built using
GraphQL Engine to demonstrate it's features, several boilerplates for users to get
started with auth webhooks, triggers etc. and some community tooling around the Engine.

Feel free to open pull requests to add more content here.

- [Boilerplates](boilerplates)
- [Examples](examples)
- [Tools](tools)

## License

All contents of this directory are under [MIT License](../LICENSE-community).
1 change: 1 addition & 0 deletions community/boilerplates/auth-webhooks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.temp
12 changes: 12 additions & 0 deletions community/boilerplates/auth-webhooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Boilerplates for auth webhooks

This directory is a compilation of code samples (boilerplates) that can be used to implement custom auth webhooks for the Hasura GraphQL engine.

## Contributing

- Please fork this repo and submit a PR with your changes
- Please create a directory name, lowercase, hyphenated
- Please add a helpful README that has the following sections:
- Overview
- Deployment instructions
- Creation of any specific environment variables or secrets
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Sample Firebase Cloud Function Auth Webhook for Hasura GraphQL engine

Further reading: [Firebase SDK for Cloud Functions](https://firebase.google.com/docs/functions/)


## Install and deploy

1. Create a Firebase Project using the [Firebase Console](https://console.firebase.google.com).
1. Clone or download this repo and go to `cd firebase-cloud-functions` directory.
1. You must have the Firebase CLI installed. If you don't have it install it with `npm install -g firebase-tools` and then configure it with `firebase login`.
1. Configure the CLI locally by using `firebase init` and select your project in the list.
1. Follow [Add the Firebase Admin SDK to Your Server](https://firebase.google.com/docs/admin/setup) and save it as config.js
1. Copy index.js and config.js to functions folder by: `cp index.js config.js functions/`
1. Install Cloud Functions dependencies locally by running: `cd functions; npm install`
1. Deploy to Firebase Cloud Functions by `firebase deploy`

Once deployed endpoint like this will be created and displayed:

```bash
https://us-central1-xxxxx-auth.cloudfunctions.net/hasuraWebhook
```

## Add webhook endpoint to Hasura GraphQL

Set `--auth-hook` or `HASURA_GRAPHQL_AUTH_HOOK` to the endpoint obtained above.

[GraphQL engine server flags reference](https://docs.hasura.io/1.0/graphql/manual/deployment/graphql-engine-flags/reference.html) for details.

## Create table and set permission

Follow [Common roles and auth examples](https://docs.hasura.io/1.0/graphql/manual/auth/common-roles-auth-examples.html)
on Hasura doc for details of how to setup permission to a table.

Make sure to change id column of user table to TXT type as uid sent from webhook is firebase User UID format (e.g. 0LnvZc7405TjRTbjURhZYYVXPI52)

## How to call webhook from frontend JS code (React, VueJS, Angular etc...)

postAxios.js
```bash
import axiosBase from 'axios'
import * as firebase from 'firebase'

const getIdToken = async () => {
return new Promise((resolve, reject) => {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
resolve(firebase.auth().currentUser.getIdToken())
} else {
reject(Error('user logged out'))
}
})
})
}

export const postAxios = async (queryString) => {
const idToken = await getIdToken()

const axios = axiosBase.create({
baseURL: 'https://YOURHASURADOMAIN/v1alpha1/graphql',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + idToken
},
responseType: 'json',
method: 'post'
})

return await axios({
data: {
query: queryString
}
}).catch(({response: r}) => console.log(r))
}
```

userService.js
```bash
import { postAxios } from './postAxios'

export default {
async getUsers () {
const queryString = `
query {
user
{
id
name
}
}
 `

const result = await postAxios(queryString)
return result.data.data.user
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const functions = require('firebase-functions');

var admin = require('firebase-admin');
var serviceAccount = require('./config.json');

exports.hasuraWebhook = functions.https.onRequest((request, response) => {
var error = null;

if (serviceAccount) {
try {
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
} catch (e) {
error = e;
}
}

var authHeaders = request.get('Authorization');
// Send anonymous role if there are no auth headers
if (!authHeaders) {
response.json({'x-hasura-role': 'anonymous'});
return;
} else {
// Validate the received id_tokenolp;
var idToken = extractToken(authHeaders);
console.log(idToken);
admin.auth().verifyIdToken(idToken)
.then((decodedToken) => {
console.log('decodedToken', decodedToken);
var hasuraVariables = {
'X-Hasura-User-Id': decodedToken.uid,
'X-Hasura-Role': 'user'
};
console.log(hasuraVariables); // For debug
// Send appropriate variables
response.json(hasuraVariables);
return;
})
.catch((e) => {
// Throw authentication error
console.log(e);
response.json({'x-hasura-role': 'anonymous'});
});
}
});

const extractToken = (bearerToken) => {
const regex = /^(Bearer) (.*)$/g;
const match = regex.exec(bearerToken);
if (match && match[2]) {
return match[2];
}
return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*node_modules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node server.js
Loading

0 comments on commit acd62c3

Please sign in to comment.