Skip to content

Commit ad1e9d5

Browse files
authored
Merge pull request #32 from sw-yx/v0.2.2
V0.2.2
2 parents 2bbb51f + 1859df6 commit ad1e9d5

File tree

3 files changed

+60
-26
lines changed

3 files changed

+60
-26
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@ yarn add react-netlify-identity
5959
- `updateUser(fields: object)`: see [updateUser @ gotrue-js](https://github.com/netlify/gotrue-js#update-a-user)
6060
- `getFreshJWT()`
6161
- `authedFetch(endpoint: string, obj: RequestInit = {})` a thin axios-like wrapper over `fetch` that has the user's JWT attached, for convenience pinging Netlify Functions with Netlify Identity
62+
- `recoverAccount(remember?: boolean)`: verifies and consumes the recovery token caught by `runRoutes`, sets user on success
6263
- `param: TokenParam`
6364
- a token exposing Netlify tokens a dev has to implement the actions for; namely `invite`, `recovery`, `email_change` and `access_denied`
64-
- **Important:** tokens this package exposes no methods for are automatically handled and will not be passed down - see [runRoutes implementation](https://github.com/sw-yx/react-netlify-identity/master/src/runRoutes.tsx)
65+
- **important:** tokens this package exposes no methods for are automatically handled and will not be passed down - see [runRoutes implementation](https://github.com/sw-yx/react-netlify-identity/master/src/runRoutes.tsx)
6566
- if you don't want this behaviour (added [here](https://github.com/sw-yx/react-netlify-identity/issues/12) in v.0.1.8), pass `runRoutes={false}` to the exposed hook
6667
- for further reference, please check the [type definition](https://github.com/sw-yx/react-netlify-identity/tree/master/src/token.ts)
6768
- an example implementation for a Recovery process can be found below
68-
- `recoverAccount(remember?: boolean)`: verifies and consumes the recovery token caught by `runRoutes`, sets user on success
69+
- `verifyToken()`
70+
- consumes & verifies TokenParam based on the type and tries to retrieve a valid user object
71+
- devs duty to show password field to afterwards call `signupUser(user.email, newPassword)`
6972

7073
```tsx
7174
import React from 'react';

src/index.tsx

+46-21
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ const errors = {
4141
tokenMissingOrInvalid: 'either no token found or invalid for this purpose',
4242
};
4343

44-
type MaybeUserPromise = Promise<User | undefined>;
45-
4644
export type ReactNetlifyIdentityAPI = {
4745
user: User | undefined;
4846
/** not meant for normal use! you should mostly use one of the other exported methods to update the user instance */
@@ -54,29 +52,33 @@ export type ReactNetlifyIdentityAPI = {
5452
password: string,
5553
data: Object,
5654
directLogin: boolean
57-
) => MaybeUserPromise;
55+
) => Promise<User | undefined>;
5856
loginUser: (
5957
email: string,
6058
password: string,
6159
remember?: boolean
62-
) => MaybeUserPromise;
63-
logoutUser: () => MaybeUserPromise;
60+
) => Promise<User | undefined>;
61+
logoutUser: () => Promise<User | undefined>;
6462
requestPasswordRecovery: (email: string) => Promise<void>;
65-
recoverAccount: (remember?: boolean) => MaybeUserPromise;
66-
updateUser: (fields: object) => MaybeUserPromise;
67-
getFreshJWT: () => Promise<string>;
63+
recoverAccount: (remember?: boolean) => Promise<User | undefined>;
64+
updateUser: (fields: object) => Promise<User | undefined>;
65+
getFreshJWT: () => Promise<string> | undefined;
6866
authedFetch: {
69-
get: (endpoint: string, obj?: {}) => Promise<any>;
70-
post: (endpoint: string, obj?: {}) => Promise<any>;
71-
put: (endpoint: string, obj?: {}) => Promise<any>;
72-
delete: (endpoint: string, obj?: {}) => Promise<any>;
67+
get: (endpoint: string, obj?: RequestInit) => Promise<any>;
68+
post: (endpoint: string, obj?: RequestInit) => Promise<any>;
69+
put: (endpoint: string, obj?: RequestInit) => Promise<any>;
70+
delete: (endpoint: string, obj?: RequestInit) => Promise<any>;
7371
};
7472
_goTrueInstance: GoTrue;
7573
_url: string;
7674
loginProvider: (provider: Provider) => void;
77-
acceptInviteExternalUrl: (provider: Provider) => string;
75+
acceptInviteExternalUrl: (
76+
provider: Provider,
77+
autoRedirect: boolean
78+
) => string | undefined;
7879
settings: Settings;
7980
param: TokenParam;
81+
verifyToken: () => Promise<User | undefined>;
8082
};
8183

8284
const [_useIdentityContext, _IdentityCtxProvider] = createCtx<
@@ -179,20 +181,42 @@ export function useNetlifyIdentity(
179181
* @see https://github.com/netlify/gotrue-js/blob/master/src/index.js#L92
180182
*/
181183
const acceptInviteExternalUrl = useCallback(
182-
(provider: Provider) => {
184+
(provider: Provider, autoRedirect: boolean = true) => {
183185
if (!param.token || param.type !== 'invite') {
184-
throw new Error(errors.tokenMissingOrInvalid);
186+
console.error(errors.tokenMissingOrInvalid);
187+
return;
185188
}
186189

187190
const url = goTrueInstance.acceptInviteExternalUrl(provider, param.token);
188191
// clean up consumed token
189192
setParam(defaultParam);
190193

194+
if (autoRedirect) {
195+
window.location.href = url;
196+
return;
197+
}
198+
191199
return url;
192200
},
193201
[goTrueInstance, param]
194202
);
195203

204+
/**
205+
* @see https://github.com/netlify/gotrue-js/blob/master/src/index.js#L123
206+
*/
207+
const verifyToken = useCallback(() => {
208+
if (!param.type || !param.token) {
209+
return Promise.reject(errors.tokenMissingOrInvalid);
210+
}
211+
212+
return goTrueInstance.verify(param.type, param.token).then(user => {
213+
// cleanup consumed token
214+
setParam(defaultParam);
215+
216+
return user;
217+
});
218+
}, [goTrueInstance, param]);
219+
196220
/******* email auth */
197221
/**
198222
* @see https://github.com/netlify/gotrue-js/blob/master/src/index.js#L50
@@ -237,7 +261,7 @@ export function useNetlifyIdentity(
237261
const recoverAccount = useCallback(
238262
(remember?: boolean) => {
239263
if (!param.token || param.type !== 'recovery') {
240-
throw new Error(errors.tokenMissingOrInvalid);
264+
return Promise.reject(errors.tokenMissingOrInvalid);
241265
}
242266

243267
return goTrueInstance
@@ -259,7 +283,7 @@ export function useNetlifyIdentity(
259283
const updateUser = useCallback(
260284
(fields: object) => {
261285
if (!user) {
262-
throw new Error(errors.noUserFound);
286+
return Promise.reject(errors.noUserFound);
263287
}
264288

265289
return user!
@@ -274,7 +298,7 @@ export function useNetlifyIdentity(
274298
*/
275299
const getFreshJWT = useCallback(() => {
276300
if (!user) {
277-
throw new Error(errors.noUserFound);
301+
return Promise.reject(errors.noUserFound);
278302
}
279303

280304
return user.jwt();
@@ -285,18 +309,18 @@ export function useNetlifyIdentity(
285309
*/
286310
const logoutUser = useCallback(() => {
287311
if (!user) {
288-
throw new Error(errors.noUserFound);
312+
return Promise.reject(errors.noUserFound);
289313
}
290314

291315
return user.logout().then(() => _setUser(undefined));
292316
}, [user]);
293317

294-
const genericAuthedFetch = (method: string) => (
318+
const genericAuthedFetch = (method: RequestInit['method']) => (
295319
endpoint: string,
296320
options: RequestInit = {}
297321
) => {
298322
if (!user?.token?.access_token) {
299-
throw new Error(errors.noUserTokenFound);
323+
return Promise.reject(errors.noUserTokenFound);
300324
}
301325

302326
const defaultObj = {
@@ -341,6 +365,7 @@ export function useNetlifyIdentity(
341365
acceptInviteExternalUrl,
342366
settings,
343367
param,
368+
verifyToken,
344369
};
345370
}
346371

src/runRoutes.tsx

+9-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ export function runRoutes(
3232

3333
const hash = document.location.hash.replace(hashReplace, '');
3434

35-
// todo: maybe replace with history.replaceState to completely clear the url?
36-
// currently keeps #
37-
document.location.hash = '';
35+
try {
36+
history.pushState(
37+
'',
38+
document.title,
39+
window.location.pathname + window.location.search
40+
);
41+
} catch (_) {
42+
window.location.href.substr(0, window.location.href.indexOf('#'));
43+
}
3844

3945
// earliest possible bail on any match
4046
if (hash.match(errorRoute)) {

0 commit comments

Comments
 (0)