Compare commits

..

16 Commits

Author SHA1 Message Date
Szilárd Dóró
1446a8f13b Merge pull request #395 from nhost/changeset-release/main
chore: update versions
2022-04-12 14:54:23 +02:00
Johan Eliasson
ff75998e93 Merge pull request #397 from nhost/contributors-readme-action-v-3ccBloq6
contributors readme action update
2022-04-12 14:36:51 +02:00
github-actions[bot]
9cc044ca9f contrib-readme-action has updated readme 2022-04-12 12:28:41 +00:00
Johan Eliasson
c65e44b8d6 Merge pull request #396 from nhost/test/messaging-gql-be
Messaging test
2022-04-12 14:28:24 +02:00
Johan Eliasson
9ec73b4c22 edit readme 2022-04-12 14:25:47 +02:00
github-actions[bot]
94b70e0ce9 chore: update versions 2022-04-12 12:04:21 +00:00
Pilou
d108dff4f4 Merge pull request #387 from nhost/fix/sync-auth-state
fix onTokenChanged
2022-04-12 13:03:38 +01:00
Szilárd Dóró
7a8e771a72 Merge pull request #385 from gdangelo/patch-1
Add a table to detail the data returned by `useUserData`
2022-04-12 13:48:31 +02:00
Szilárd Dóró
f8fb4bbedd Merge pull request #393 from nhost/contributors-readme-action-L56J6ymmkI
contributors readme action update
2022-04-12 13:06:10 +02:00
github-actions[bot]
c6b1c33a8e contrib-readme-action has updated readme 2022-04-12 10:51:37 +00:00
Szilárd Dóró
65b36eff13 Merge pull request #391 from gdangelo/patch-2
Update example with the latest version of React Router, v6
2022-04-12 12:51:21 +02:00
Grégory D'Angelo
c192cb9503 refact: Remove additional props to simplify example 2022-04-12 11:44:36 +02:00
Grégory D'Angelo
94ff290264 fix: Return Outlet in ProtectedRoute component + add missing closing tag + add explanation 2022-04-12 11:40:03 +02:00
Grégory D'Angelo
78781ebfec Update example with the latest version of React Router, v6 2022-04-12 09:04:28 +02:00
Pierre-Louis Mercereau
63d6059981 fix: fix onTokenChanged bugs 2022-04-11 20:55:02 +01:00
Grégory D'Angelo
022d49fb25 Add a table to detail the data returned by useUserData 2022-04-11 19:06:30 +02:00
21 changed files with 212 additions and 76 deletions

View File

@@ -1,8 +1,8 @@
<div align="center">
<img width="237" src="https://raw.githubusercontent.com/nhost/nhost/main/assets/logo.png"/>
![Nhost](https://imgur.com/fGo6E4d.png)
<br />
<br />
<div align="center">
# Nhost
<a href="https://docs.nhost.io/get-started">Quickstart</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
@@ -20,9 +20,9 @@
<hr />
</div>
**Nhost is a serverless backend for web and mobile apps** built with the following things in mind:
**Nhost is a open-source GraphQL backend,** built with the following things in mind:
- Open Source
- Open-Source
- Developer Productivity
- SQL
- GraphQL
@@ -184,6 +184,13 @@ Here are some ways of contributing to making Nhost better:
<sub><b>Mrinal Wahal</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gdangelo">
<img src="https://avatars.githubusercontent.com/u/4352286?v=4" width="100;" alt="gdangelo"/>
<br />
<sub><b>Grégory D'Angelo</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/FuzzyReason">
<img src="https://avatars.githubusercontent.com/u/62517920?v=4" width="100;" alt="FuzzyReason"/>
@@ -204,15 +211,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Christopher Möller</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/jerryjappinen">
<img src="https://avatars.githubusercontent.com/u/1101002?v=4" width="100;" alt="jerryjappinen"/>
<br />
<sub><b>Jerry Jäppinen</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/mustafa-hanif">
<img src="https://avatars.githubusercontent.com/u/30019262?v=4" width="100;" alt="mustafa-hanif"/>
@@ -247,15 +254,15 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Colin Broderick</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/dohomi">
<img src="https://avatars.githubusercontent.com/u/489221?v=4" width="100;" alt="dohomi"/>
<br />
<sub><b>Dominic Garms</b></sub>
</a>
</td></tr>
<tr>
</td>
<td align="center">
<a href="https://github.com/alveshelio">
<img src="https://avatars.githubusercontent.com/u/8176422?v=4" width="100;" alt="alveshelio"/>
@@ -290,7 +297,8 @@ Here are some ways of contributing to making Nhost better:
<br />
<sub><b>Quentin Decré</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/komninoschat">
<img src="https://avatars.githubusercontent.com/u/29049104?v=4" width="100;" alt="komninoschat"/>

View File

@@ -409,10 +409,41 @@ const Component = () => {
## User data
<!-- TODO ellaborate -->
```js
const userData = useUserData()
const { id, email, displayName, avatarUrl, isAnonymous, locale, defaultRole, roles, metadata, createdAt } = useUserData()
```
| Name | Type | Default | Notes |
| ------------- | ------------- | ---------------- | ------------------------------------------------------ |
| `id` | string | | User's unique identifier (uuid) |
| `email` | string | | User's email address |
| `displayName` | string | `""` | User's display name |
| `avatarUrl` | string | `""` | The URL to the user's profile picture |
| `isAnonymous` | boolean | `false` | Whether or not the user is anonymous |
| `locale` | string | `"en"` | A two-characters locale |
| `defaultRole` | string | `"user"` | The default role of the user |
| `roles` | string[] | `["me", "user"]` | The roles assigned to the user |
| `metadata` | JSON object | `null` | Additional attributes used for user information |
| `createdAt` | string | | The date-time when the user has been created |
Example of an authenticated user:
```json
{
"avatarUrl": "https://s.gravatar.com/avatar/3020737ed9d932c6665111a5550454d2?r=g&default=blank",
"createdAt": "2022-04-11T16:33:14.780439+00:00",
"defaultRole": "user",
"displayName": "Grégory D'Angelo",
"email": "greg@nhost.io",
"id": "05e054c7-a722-42e7-90a6-3f77a2f118c8",
"isAnonymous": false,
"locale": "en",
"metadata": {
"lastName": "D'Angelo",
"firstName": "Grégory"
},
"roles": ["user", "me"]
}
```
### Avatar

View File

@@ -4,49 +4,67 @@ title: 'Protecting routes'
## React Router
You can protect routes by creating an `AuthGate` component when using `@nhost/react` with [React Router](https://reactrouter.com/web/guides/quick-start).
> This example uses the latest version of [React Router (v6)](https://reactrouter.com/docs/en/v6).
You can protect routes by creating a wrapper component, `ProtectedRoute`, to implement the authentication logic using `@nhost/react`.
```jsx
import { useAuthenticationStatus } from '@nhost/react'
import { Redirect } from 'react-router-dom'
// src/components/ProtectedRoute.js
export function AuthGate({ children }) {
const { isLoading, isAuthenticated } = useAuthenticationStatus()
import { useAuthenticationStatus } from '@nhost/react';
import { Navigate, Outlet, useLocation } from 'react-router-dom';
const ProtectedRoute = () => {
const { isAuthenticated, isLoading } = useAuthenticationStatus();
const location = useLocation();
if (isLoading) {
return <div>Loading...</div>
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <Redirect to="/login" />
return <Navigate to="/login" />;
}
return children
}
return <Outlet />;
};
export default ProtectedRoute;
```
Then, in your React Router, wrap the `AuthGate` component around the routes you want to protect:
So, if the user is not authenticated, we redirect him to the `/login` route using the [`Navigate`](https://reactrouter.com/docs/en/v6/api#navigate) component from React Router. Otherwise, we render the [`Outlet`](https://reactrouter.com/docs/en/v6/api#outlet) component, also provided by React Router, to render the `ProtectedRoute` child route elements.
Then, in your `App.js` file, you can use a [layout route](https://reactrouter.com/docs/en/v6/getting-started/concepts#layout-route) to wrap the `ProtectedRoute` component around the routes you want to protect:
```jsx
import { AuthGate } from 'components/AuthGate'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
// src/App.js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { NhostReactProvider } from '@nhost/react';
import ProtectedRoute from './components/ProtectedRoute';
import Home from './pages/Home';
import Login from './pages/Login';
import Dashboard from './pages/Dashboard';
import Profile from './pages/Profile';
import { nhost } from './lib/nhost';
export function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login">
<Login />
</Route>
<Route path="/" exact>
{/* Use AuthGate component like this */}
<AuthGate>
<div>My protected dashboard</div>
</AuthGate>
</Route>
</Routes>
</BrowserRouter>
)
<NhostReactProvider nhost={nhost}>
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<ProtectedRoute />}>
<Route index element={<Dashboard />} />
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
</BrowserRouter>
</NhostReactProvider>
);
}
```

View File

@@ -1,5 +1,13 @@
# @nhost/apollo
## 0.3.9
### Patch Changes
- Updated dependencies [63d6059]
- Updated dependencies [63d6059]
- @nhost/core@0.3.10
## 0.3.8
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/apollo",
"version": "0.3.8",
"version": "0.3.9",
"description": "Nhost Apollo Client library",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,14 @@
# @nhost/core
## 0.3.10
### Patch Changes
- 63d6059: Set onTokenChanged before the state interpreter started
Fixes [#384](https://github.com/nhost/nhost/issues/384), thanks [@noverby](https://github.com/noverby)
- 63d6059: Trigger onTokenChanged when token changes
Fixes [#373](https://github.com/nhost/nhost/issues/373), thanks [@yureckey](https://github.com/yureckey)
## 0.3.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/core",
"version": "0.3.9",
"version": "0.3.10",
"description": "Nhost core client library",
"license": "MIT",
"keywords": [

View File

@@ -401,7 +401,12 @@ export const createAuthMachine = ({
src: 'refreshToken',
id: 'refreshToken',
onDone: {
actions: ['saveSession', 'persist', 'resetTimer'],
actions: [
'saveSession',
'persist',
'resetTimer',
'reportTokenChanged'
],
target: 'pending'
},
onError: [

View File

@@ -32,6 +32,7 @@ export interface Typegen0 {
| 'done.invoke.authenticateAnonymously'
| 'done.invoke.signInMfaTotp'
| 'done.invoke.registerUser'
| 'done.invoke.refreshToken'
| 'done.invoke.authenticateWithToken'
saveRefreshToken: 'done.invoke.importRefreshToken'
saveInvalidEmail: 'SIGNIN_PASSWORD' | 'SIGNIN_PASSWORDLESS_EMAIL'

View File

@@ -1,5 +1,18 @@
# @nhost/hasura-auth-js
## 1.0.11
### Patch Changes
- 63d6059: Add TSDoc information about Nhost client options
- 63d6059: Set onTokenChanged before the state interpreter started
Fixes [#384](https://github.com/nhost/nhost/issues/384), thanks [@noverby](https://github.com/noverby)
- 63d6059: Trigger onTokenChanged when token changes
Fixes [#373](https://github.com/nhost/nhost/issues/373), thanks [@yureckey](https://github.com/yureckey)
- Updated dependencies [63d6059]
- Updated dependencies [63d6059]
- @nhost/core@0.3.10
## 1.0.10
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/hasura-auth-js",
"version": "1.0.10",
"version": "1.0.11",
"description": "Hasura-auth client",
"license": "MIT",
"keywords": [

View File

@@ -54,8 +54,6 @@ const EMAIL_NEEDS_VERIFICATION: ApiError = {
}
export class HasuraAuthClient {
private _client: AuthClient
private onTokenChangedSubscriptions: Set<AuthInterpreter> = new Set()
private onAuthStateChangedSubscriptions: Set<AuthInterpreter> = new Set()
constructor({
url,
@@ -414,17 +412,23 @@ export class HasuraAuthClient {
* @docs https://docs.nhost.io/TODO
*/
onTokenChanged(fn: OnTokenChangedFunction): Function {
if (this._client.interpreter)
this.onTokenChangedSubscriptions.add(
this._client.interpreter?.onTransition(({ event, context }) => {
if (event.type === 'TOKEN_CHANGED') fn(getSession(context))
})
)
else {
console.log('onTokenChanged: no interpreter is set yet', fn)
}
return () => {
this.onTokenChangedSubscriptions.forEach((subscription) => subscription.stop())
const listen = (interpreter: AuthInterpreter) =>
interpreter.onTransition(({ event, context }) => {
if (event.type === 'TOKEN_CHANGED') fn(getSession(context))
})
if (this._client.interpreter) {
const subscription = listen(this._client.interpreter)
return () => subscription.stop()
} else {
this._client.onStart((client) => {
listen(client.interpreter as AuthInterpreter)
})
return () => {
console.log(
'onTokenChanged was added before the interpreter started. Cannot unsubscribe listener.'
)
}
}
}
@@ -441,18 +445,23 @@ export class HasuraAuthClient {
* @docs https://docs.nhost.io/reference/sdk/authentication#nhost-auth-onauthstatechangedevent,-session
*/
onAuthStateChanged(fn: AuthChangedFunction): Function {
if (this._client.interpreter)
this.onAuthStateChangedSubscriptions.add(
this._client.interpreter?.onTransition(({ event, context }) => {
if (event.type === 'SIGNED_IN') fn('SIGNED_IN', getSession(context))
else if (event.type === 'SIGNED_OUT') fn('SIGNED_OUT', getSession(context))
})
)
else {
console.log('onAuthStateChanged: no interpreter is set yet', fn)
}
return () => {
this.onAuthStateChangedSubscriptions.forEach((subscription) => subscription.stop())
const listen = (interpreter: AuthInterpreter) =>
interpreter.onTransition(({ event, context }) => {
if (event.type === 'SIGNED_IN' || event.type === 'SIGNED_OUT')
fn(event.type, getSession(context))
})
if (this._client.interpreter) {
const subscription = listen(this._client.interpreter)
return () => subscription.stop()
} else {
this._client.onStart((client) => {
listen(client.interpreter as AuthInterpreter)
})
return () => {
console.log(
'onAuthStateChanged was added before the interpreter started. Cannot unsubscribe listener.'
)
}
}
}

View File

@@ -12,14 +12,19 @@ import {
export type { AuthClient, Provider, StorageGetter, StorageSetter, User }
export interface NhostAuthConstructorParams {
url: string
/** Time interval until token refreshes, in seconds */
refreshIntervalTime?: number
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
clientStorage?: ClientStorage
/** @deprecated Use clientStorageGetter and clientStorageSetter options instead */
clientStorageType?: ClientStorageType
/** Define a way to get information about the refresh token and its exipration date */
clientStorageGetter?: StorageGetter
/** Define a way to set information about the refresh token and its exipration date */
clientStorageSetter?: StorageSetter
/** When set to true, will automatically refresh token before it expires */
autoRefreshToken?: boolean
/** When set to true, will parse the url on startup to check if it contains a refresh token to start the session with */
autoLogin?: boolean
start?: boolean
Client?: typeof AuthClient

View File

@@ -1,5 +1,12 @@
# @nhost/nextjs
## 1.0.12
### Patch Changes
- @nhost/nhost-js@1.0.11
- @nhost/react@0.5.2
## 1.0.11
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/nextjs",
"version": "1.0.11",
"version": "1.0.12",
"description": "Nhost NextJS library",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,14 @@
# @nhost/nhost-js
## 1.0.11
### Patch Changes
- Updated dependencies [63d6059]
- Updated dependencies [63d6059]
- Updated dependencies [63d6059]
- @nhost/hasura-auth-js@1.0.11
## 1.0.10
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/nhost-js",
"version": "1.0.10",
"version": "1.0.11",
"description": "Nhost JavaScript SDK",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,12 @@
# @nhost/react-apollo
## 4.0.12
### Patch Changes
- @nhost/react@0.5.2
- @nhost/apollo@0.3.9
## 4.0.11
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/react-apollo",
"version": "4.0.11",
"version": "4.0.12",
"description": "Nhost React Apollo client",
"license": "MIT",
"keywords": [

View File

@@ -1,5 +1,11 @@
# @nhost/react
## 0.5.2
### Patch Changes
- @nhost/nhost-js@1.0.11
## 0.5.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@nhost/react",
"version": "0.5.1",
"version": "0.5.2",
"description": "Nhost React library",
"license": "MIT",
"keywords": [