-
Notifications
You must be signed in to change notification settings - Fork 92
/
Provider.js
91 lines (82 loc) · 2.53 KB
/
Provider.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { fromJS } from 'immutable'
import PT from 'prop-types'
import * as React from 'react'
import * as RC from 'recompose'
import { useDispatch } from 'redux-react-hook'
import { push as notify } from 'containers/Notifications/actions'
import { useIntl } from 'containers/LanguageProvider'
import { useReducer } from 'utils/ReducerInjector'
import { useSaga } from 'utils/SagaInjector'
import * as RT from 'utils/reactTools'
import { withInitialState } from 'utils/reduxTools'
import { REDUX_KEY } from './constants'
import msg from './messages'
import reducer from './reducer'
import saga from './saga'
const ActionPattern = PT.oneOfType([PT.string, PT.func])
const StorageShape = PT.shape({
set: PT.func.isRequired,
remove: PT.func.isRequired,
load: PT.func.isRequired,
})
const useStorageHandlers = (storage) =>
React.useMemo(
() => ({
storeTokens: (tokens) => storage.set('tokens', tokens),
forgetTokens: () => storage.remove('tokens'),
storeUser: (user) => storage.set('user', user),
forgetUser: () => storage.remove('user'),
storeCredentials: (credentials) => storage.set('credentials', credentials),
forgetCredentials: () => storage.remove('credentials'),
}),
[storage],
)
const useNotificationHandlers = () => {
const intl = useIntl()
const dispatch = useDispatch()
return React.useMemo(
() => ({
onAuthLost: () => {
dispatch(notify(intl.formatMessage(msg.notificationAuthLost)))
},
}),
[intl, dispatch],
)
}
/**
* Provider component for the authentication system.
*/
export default RT.composeComponent(
'Auth.Provider',
RC.setPropTypes({
/**
* Determines on which actions to fire the check logic.
*/
checkOn: PT.oneOfType([ActionPattern, PT.arrayOf(ActionPattern)]),
/**
* Storage instance used to persist tokens and user data.
*/
storage: StorageShape.isRequired,
/**
* Expected API latency in seconds.
*/
latency: PT.number,
}),
({ children, checkOn, storage, latency = 20 }) => {
const reducerWithInit = React.useMemo(() => {
const init = fromJS(storage.load())
.filter(Boolean)
.update((s) =>
s.set('state', s.getIn(['user', 'current_user']) ? 'SIGNED_IN' : 'SIGNED_OUT'),
)
return withInitialState(init, reducer)
}, [])
useReducer(REDUX_KEY, reducerWithInit)
const handlers = {
...useStorageHandlers(storage),
...useNotificationHandlers(),
}
useSaga(saga, { ...handlers, checkOn, latency })
return children
},
)