redux-auth-wrapper
Advanced tools
Comparing version
@@ -1,3 +0,6 @@ | ||
## [HEAD](https://github.com/mjrussell/redux-auth-wrapper/compare/v0.9.0...master) | ||
## [HEAD](https://github.com/mjrussell/redux-auth-wrapper/compare/v0.10.0...master) | ||
## [0.10.0](https://github.com/mjrussell/redux-auth-wrapper/compare/v0.9.0...v0.10.0) | ||
- **Feature:** `allowRedirectBack` can also take a selector function that returns a bool instead of a bool. [#93](https://github.com/mjrussell/redux-auth-wrapper/pull/93) | ||
## [0.9.0](https://github.com/mjrussell/redux-auth-wrapper/compare/v0.8.0...v0.9.0) | ||
@@ -4,0 +7,0 @@ - **Bugfix:** Don't pass down auth wrapper props besides authData [#81](https://github.com/mjrussell/redux-auth-wrapper/issues/81) |
@@ -84,3 +84,5 @@ 'use strict'; | ||
var query = void 0; | ||
if (allowRedirectBack) { | ||
var canRedirect = typeof allowRedirectBack === 'function' ? allowRedirectBack(location, redirectPath) : allowRedirectBack; | ||
if (canRedirect) { | ||
query = _defineProperty({}, redirectQueryParamName, '' + location.pathname + location.search); | ||
@@ -87,0 +89,0 @@ } else { |
{ | ||
"name": "redux-auth-wrapper", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"description": "A utility library for handling authentication and authorization for redux and react-router", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -34,3 +34,3 @@ # redux-auth-wrapper | ||
`onEnter` is great, and useful in certain situations. However, here are some common authentication and authorization problems `onEnter` does not solve: | ||
* Decide authentication/authorization from redux store data (there are some [workarounds](https://github.com/CrocoDillon/universal-react-redux-boilerplate/blob/master/src/routes.jsx#L8)) | ||
* Decide authentication/authorization from redux store data (there are some [workarounds](https://github.com/CrocoDillon/universal-react-redux-boilerplate/blob/master/src/routes.js#L8)) | ||
* Recheck authentication/authorization if the store updates (but not the current route) | ||
@@ -142,5 +142,4 @@ * Recheck authentication/authorization if a child route changes underneath the protected route (React Router 2.0 now supports this with `onChange`) | ||
If it evaluates to false the browser will be redirected to `failureRedirectPath`, otherwise `DecoratedComponent` will be rendered. By default, it returns false if `authData` is {} or null. | ||
* `[allowRedirectBack]` \(*Bool*): Optional bool on whether to pass a `redirect` query parameter to the `failureRedirectPath`. Defaults to `true`. | ||
* `[propMapper]` \(*Function*): Optional function that takes the props passed into the wrapped component and returns those props to pass to the | ||
DecoratedComponent, The LoadingComponent, and the FailureComponent. | ||
* `[allowRedirectBack]` \(*Bool | (location, redirectPath): Bool* ): Optional bool on whether to pass a `redirect` query parameter to the `failureRedirectPath`. Can also be a function of location and the computed `failureRedirectPath` passed above, that must return a boolean value. Defaults to `true`. | ||
* `[propMapper]` \(*Function*): Optional function that takes the props passed into the wrapped component and returns those props to pass to the DecoratedComponent, The LoadingComponent, and the FailureComponent. | ||
@@ -186,3 +185,3 @@ #### Returns | ||
// Now to secure the component: | ||
// Now to secure the component: first check if the user is authenticated, and then check if the user is an admin | ||
<Route path="foo" component={UserIsAuthenticated(UserIsAdmin(Admin))}/> | ||
@@ -317,4 +316,6 @@ ``` | ||
## Server Side Rendering | ||
In order to perform authentication and authorization checks for Server Side Rendering, you may need to use the `onEnter` property | ||
of a `<Route>`. During onEnter, selectors such as `authSelector`, `authenticatingSelector`, and `failureRedirectPath` (if you are using) | ||
If your `UserAuthWrapper` uses redirection, then you may need to use the `onEnter` property | ||
of a `<Route>` to perform authentication and authorization checks for Server Side Rendering. (Note: If you are only using `FailureComponent` and not redirecting in your `UserAuthWrapper`, then you do not need to use `onEnter` option described below.) | ||
During onEnter, selectors such as `authSelector`, `authenticatingSelector`, and `failureRedirectPath` (if you are using) | ||
the function variation, will receive react-router's `nextState` as their second argument instead of the component props. | ||
@@ -346,2 +347,57 @@ | ||
#### Server Side Rendering (SSR) with nested auth wrappers | ||
To implement SSR with nested wrappers, you will have to provide a function to chain `onEnter` functions of each wrapper. To illustrate this, we can modify the example provided in the [Authorization & Advanced Usage](#authorization--advanced-usage) section above, wherein `UserIsAuthenticated` is the parent wrapper and `UserIsAdmin` is the child wrapper. | ||
```js | ||
import { UserAuthWrapper } from 'redux-auth-wrapper'; | ||
const UserIsAuthenticated = UserAuthWrapper({ | ||
authSelector: state => state.user, | ||
redirectAction: routerActions.replace, | ||
wrapperDisplayName: 'UserIsAuthenticated' | ||
}) | ||
// Admin Authorization, redirects non-admins to /app and don't send a redirect param | ||
const UserIsAdmin = UserAuthWrapper({ | ||
authSelector: state => state.user, | ||
redirectAction: routerActions.replace, | ||
failureRedirectPath: '/app', | ||
wrapperDisplayName: 'UserIsAdmin', | ||
predicate: user => user.isAdmin, | ||
allowRedirectBack: false | ||
}) | ||
const getRoutes = (store) => { | ||
const connect = (fn) => (nextState, replaceState) => fn(store, nextState, replaceState); | ||
//This executes the parent onEnter first, going from left to right. | ||
// `replace` has to be wrapped because we want to stop executing `onEnter` hooks | ||
// after the first call to `replace`. | ||
const onEnterChain = (...listOfOnEnters) => (store, nextState, replace) => { | ||
let redirected = false; | ||
const wrappedReplace = (...args) => { | ||
replace(...args); | ||
redirected = true; | ||
}; | ||
listOfOnEnters.forEach((onEnter) => { | ||
if (!redirected) { | ||
onEnter(store, nextState, wrappedReplace); | ||
} | ||
}); | ||
}; | ||
return ( | ||
<Route> | ||
<Route path="/" component={App}> | ||
<Route path="login" component={Login}/> | ||
<Route path="foo" | ||
component={UserIsAuthenticated(UserIsAdmin(Admin))} | ||
onEnter={connect(onEnterChain(UserIsAuthenticated.onEnter, UserIsAdmin.onEnter))} /> | ||
</Route> | ||
</Route> | ||
); | ||
}; | ||
``` | ||
## React Native | ||
@@ -348,0 +404,0 @@ |
@@ -29,3 +29,5 @@ import React, { Component, PropTypes } from 'react' | ||
let query | ||
if (allowRedirectBack) { | ||
const canRedirect = typeof allowRedirectBack === 'function' ? allowRedirectBack(location, redirectPath) : allowRedirectBack | ||
if (canRedirect) { | ||
query = { [redirectQueryParamName]: `${location.pathname}${location.search}` } | ||
@@ -32,0 +34,0 @@ } else { |
43233
7.24%327
0.62%410
15.82%