-
Notifications
You must be signed in to change notification settings - Fork 1
Redux for Auth #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Redux for Auth #12
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
f700e13
redux starter. overcomplicated
5557250
Merge branch 'master' into JB.redux-start
c6c09a8
audit fix
afce06d
Merge branch 'master' into JB.redux-start
8977142
work please
569ba54
Merge branch 'master' into JB.redux-start
8db5482
redo all the things
dec7dfb
prettier
47937aa
something is wrong with prettier. extra rules on CI
1aae224
tests for reducer and thunk
c786288
adjust signup interface
651487b
add asyncRequest file, logout thunk
ba820c2
implement asyncRequest
e64123c
prettier
59942eb
for real, for real, this time...
21a20b8
type check
97b1de0
prettier :cry:
0bf4941
auth client tests
338b96c
lint
6e16799
lint
2cbfc80
compile error
71d16e3
move tokens into storage, add selector for privilegeLevel
c4cbe03
prettier lied to me locally
280b7be
add selector test
2753d5a
thunk error case tests
f34006b
remove unused axios func to improve test coverage
287557a
update axios to apply token using store.listener
0bef07d
Merge branch 'master' into JB.redux-start
7f7e457
delete axios test
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { | ||
| TokenPayload, | ||
| LoginRequest, | ||
| SignupRequest, | ||
| RefreshTokenResponse, | ||
| } from './ducks/types'; | ||
| import axios, { AxiosInstance } from 'axios'; | ||
|
|
||
| export interface AuthClient { | ||
| login: (user: LoginRequest) => Promise<TokenPayload>; | ||
| signup: (user: SignupRequest) => Promise<TokenPayload>; | ||
| logout: (refreshToken: string) => Promise<void>; | ||
| refresh: (refreshToken: string) => Promise<RefreshTokenResponse>; | ||
| } | ||
|
|
||
| export enum API_ROUTE { | ||
| LOGIN = '/api/v1/user/login/', | ||
| SIGNUP = '/api/v1/user/signup/', | ||
| REFRESH = '/api/v1/user/login/refresh/', | ||
| } | ||
|
|
||
| const AuthAxiosInstance: AxiosInstance = axios.create({ | ||
| baseURL: process.env.REACT_APP_API_DOMAIN, | ||
| timeout: 10000, | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }); | ||
|
|
||
| const login: (user: LoginRequest) => Promise<TokenPayload> = ( | ||
| user: LoginRequest, | ||
| ) => | ||
| AuthAxiosInstance.post(API_ROUTE.LOGIN, user).then( | ||
| (response) => response.data, | ||
| ); | ||
|
|
||
| const signup: (user: SignupRequest) => Promise<TokenPayload> = ( | ||
| user: SignupRequest, | ||
| ) => | ||
| AuthAxiosInstance.post(API_ROUTE.SIGNUP, user).then( | ||
| (response) => response.data, | ||
| ); | ||
|
|
||
| const logout: (refreshToken: string) => Promise<void> = ( | ||
| refreshToken: string, | ||
| ) => | ||
| AuthAxiosInstance.delete(API_ROUTE.LOGIN, { | ||
| headers: { | ||
| 'X-Refresh-Token': refreshToken, | ||
| }, | ||
| // eslint-disable-next-line | ||
| }).then(() => {}); | ||
|
|
||
| const refresh: (refreshToken: string) => Promise<RefreshTokenResponse> = ( | ||
| refreshToken: string, | ||
| ) => | ||
| AuthAxiosInstance.post(API_ROUTE.REFRESH, null, { | ||
| headers: { | ||
| 'X-Refresh-Token': refreshToken, | ||
| }, | ||
| }).then((response) => response.data); | ||
|
|
||
| const Client: AuthClient = Object.freeze({ | ||
| login, | ||
| signup, | ||
| logout, | ||
| refresh, | ||
| }); | ||
|
|
||
| export default Client; |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import axios, { AxiosInstance } from 'axios'; | ||
| import store, { C4CState } from '../store'; | ||
| import { AsyncRequestKinds } from '../utils/asyncRequest'; | ||
|
|
||
| const AppAxiosInstance: AxiosInstance = axios.create({ | ||
| baseURL: process.env.REACT_APP_API_DOMAIN, | ||
| timeout: 10000, | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| }); | ||
|
|
||
| const listener = () => { | ||
| const state: C4CState = store.getState(); | ||
| if (state.authenticationState.tokens.kind === AsyncRequestKinds.Completed) { | ||
| AppAxiosInstance.defaults.headers['X-Access-Token'] = | ||
| state.authenticationState.tokens.result.accessToken; | ||
| } | ||
| }; | ||
|
|
||
| store.subscribe(listener); | ||
|
|
||
| // const responseErrorInterceptor: (error: AxiosError) => void = (error) => { | ||
| // // const originalRequest = error.config; | ||
| // if ( | ||
| // error.code === '401' && | ||
| // error.message === INVALID_ACCESS_TOKEN && | ||
| // tokenService.isRefreshTokenValid() | ||
| // ) { | ||
| // // return refresh().then(() => { | ||
| // // Instance.defaults.headers[ | ||
| // // 'X-Access-Token' | ||
| // // ] = tokenService.getAccessToken(); | ||
| // // return Instance(originalRequest); | ||
| // // }); | ||
| // } | ||
| // if ( | ||
| // error.code === '401' && | ||
| // error.message === INVALID_ACCESS_TOKEN && | ||
| // !tokenService.isRefreshTokenValid() | ||
| // ) { | ||
| // // logout(); | ||
| // } | ||
| // return Promise.reject(error); | ||
| // }; | ||
|
|
||
| export default AppAxiosInstance; |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { genericAsyncActions } from '../../utils/asyncRequest'; | ||
| import { TokenPayload } from './types'; | ||
|
|
||
| export const authenticateUser = genericAsyncActions<TokenPayload, any>(); | ||
|
|
||
| export const logoutUser = genericAsyncActions<void, void>(); | ||
|
|
||
| export type UserAuthenticationActions = | ||
| | ReturnType<typeof authenticateUser.loading> | ||
| | ReturnType<typeof authenticateUser.loaded> | ||
| | ReturnType<typeof authenticateUser.failed> | ||
| | ReturnType<typeof logoutUser.loading> | ||
| | ReturnType<typeof logoutUser.loaded> | ||
| | ReturnType<typeof logoutUser.failed>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import { TokenPayload, UserAuthenticationReducerState } from './types'; | ||
| import { authenticateUser } from './actions'; | ||
| import { C4CAction } from '../../store'; | ||
| import { | ||
| ASYNC_REQUEST_FAILED_ACTION, | ||
| ASYNC_REQUEST_LOADED_ACTION, | ||
| ASYNC_REQUEST_LOADING_ACTION, | ||
| AsyncRequestNotStarted, | ||
| generateAsyncRequestReducer, | ||
| } from '../../utils/asyncRequest'; | ||
|
|
||
| export const initialUserState: UserAuthenticationReducerState = { | ||
| tokens: AsyncRequestNotStarted<TokenPayload, any>(), | ||
| }; | ||
|
|
||
| const userAuthenticationRequestReducer = generateAsyncRequestReducer< | ||
| UserAuthenticationReducerState, | ||
| TokenPayload, | ||
| void | ||
| >(authenticateUser.key); | ||
|
|
||
| const reducers = ( | ||
| state: UserAuthenticationReducerState = initialUserState, | ||
| action: C4CAction, | ||
| ): UserAuthenticationReducerState => { | ||
| switch (action.type) { | ||
| case ASYNC_REQUEST_LOADING_ACTION: | ||
| case ASYNC_REQUEST_LOADED_ACTION: | ||
| case ASYNC_REQUEST_FAILED_ACTION: | ||
| return { | ||
| ...state, | ||
| tokens: userAuthenticationRequestReducer(state.tokens, action), | ||
| }; | ||
| default: | ||
| return state; | ||
| } | ||
| }; | ||
|
|
||
| export default reducers; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { PrivilegeLevel, TokenPayload } from './types'; | ||
| import { AsyncRequest, AsyncRequestKinds } from '../../utils/asyncRequest'; | ||
|
|
||
| export const getPrivilegeLevel = ( | ||
| tokens: AsyncRequest<TokenPayload, any>, | ||
| ): PrivilegeLevel => { | ||
| if (tokens.kind === AsyncRequestKinds.Completed) { | ||
| const payload = JSON.parse(atob(tokens.result.accessToken.split('.')[1])); | ||
| return payload.privilegeLevel; | ||
| } | ||
| return PrivilegeLevel.NONE; | ||
| }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the top level reducer? If so, would all API calls that get data have to be included in this down the line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything in this
auth/ducks/folder will be solely for authentication-related data and actions. Each container typically will have its own ducks. The reducers, along with the action types, are combined instore.ts.