diff --git a/package-lock.json b/package-lock.json index 3aec10b..5cddcc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11424,6 +11424,11 @@ "symbol-observable": "^1.2.0" } }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", diff --git a/package.json b/package.json index ab17ba8..7623ecb 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "react-router-dom": "^5.1.2", "react-scripts": "3.4.1", "react-uwp": "^1.3.1", - "redux": "^4.0.5" + "redux": "^4.0.5", + "redux-thunk": "^2.3.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/index.js b/src/index.js index 6a43f52..607ba3e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; -import { createStore } from 'redux'; +import { createStore, applyMiddleware } from 'redux'; +import thunk from 'redux-thunk'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import reducer from './store/reducer'; -const store = createStore(reducer); +const store = createStore(reducer, applyMiddleware(thunk)); ReactDOM.render( diff --git a/src/main/ForgotPassword.js b/src/main/ForgotPassword.js index 8744e87..9496978 100644 --- a/src/main/ForgotPassword.js +++ b/src/main/ForgotPassword.js @@ -1,47 +1,21 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import { NavLink } from "react-router-dom"; -import axios from 'axios'; - +import { connect } from "react-redux"; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; +import * as actionCreators from '../store/actions/actionCreators'; - -export default class ForgotPassword extends React.Component { +class ForgotPassword extends React.Component { constructor(props) { super(props); - this.state = { email: '', errMessage: '' }; + this.state = { email: '' }; this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { - - const axiosOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/reset/request`, - 'data': { - 'email': this.state.email, - } - } - - axios(axiosOptions) - .then(response => { - this.setState({ errMessage: "Ah, Dementia. Reset mail sent!" }); - }) - .catch(error => { - let status = error.response.status - - if (status === 401) { - this.setState({ - errMessage: "User is not registered. Please sign up first.", - errHref: "/signup" - }); - } - else { - this.setState({ errMessage: "It's not you, it's us. Try again later." }) - } - }) + this.props.submitForgotPass(this.state.email); } componentDidMount() { @@ -111,7 +85,7 @@ export default class ForgotPassword extends React.Component { />
- {this.state.errMessage} + {this.props.message} } @@ -124,4 +98,19 @@ export default class ForgotPassword extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = state => { + return { + message: state.forgotPassMessage, + followLink: state.forgotPassFollowLink + } +} + +const mapDispatchToProps = dispatch => { + return { + submitForgotPass: email => dispatch(actionCreators.submitForgotPass(email)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ForgotPassword); diff --git a/src/main/ResendEmail.js b/src/main/ResendEmail.js index c664c4f..a1109ee 100644 --- a/src/main/ResendEmail.js +++ b/src/main/ResendEmail.js @@ -1,47 +1,22 @@ import * as React from "react"; import * as PropTypes from "prop-types"; -import axios from 'axios' - import { NavLink } from "react-router-dom"; +import { connect } from "react-redux"; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; +import * as actionCreators from '../store/actions/actionCreators'; -export default class ResendEmail extends React.Component { +class ResendEmail extends React.Component { constructor(props) { super(props); - this.state = { email: '', errMessage: '' }; + this.state = { email: ''}; this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { - - const axiosOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/resendVerificationEmail`, - 'data': { - 'email': this.state.email, - } - } - - axios(axiosOptions) - .then(response => { - this.setState({ errMessage: "Verification mail sent!" }); - }) - .catch(error => { - let status = error.response.status - - if (status === 401) { - this.setState({ - errMessage: "User is not registered. Please sign up first.", - errHref: "/signup" - }); - } - else { - this.setState({ errMessage: "It's not you, it's us. Try again later." }) - } - }) + this.props.resendEmail(this.state.email); } componentDidMount() { @@ -111,7 +86,7 @@ export default class ResendEmail extends React.Component { />
- {this.state.errMessage} + {this.props.message} } @@ -124,4 +99,19 @@ export default class ResendEmail extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = state => { + return{ + message : state.resendEmailMessage, + followLink: state.resendEmailFollowLink + } +} + +const mapDispatchToProps = dispatch => { + return{ + resendEmail : email => dispatch(actionCreators.resendEmail(email)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(ResendEmail); diff --git a/src/main/SignIn.js b/src/main/SignIn.js index 8139f9f..5eae26a 100644 --- a/src/main/SignIn.js +++ b/src/main/SignIn.js @@ -1,17 +1,17 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import { NavLink, Link } from "react-router-dom"; -import axios from 'axios'; - +import { connect } from "react-redux"; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; import PasswordBox from "react-uwp/PasswordBox"; +import * as actionCreators from '../store/actions/actionCreators'; -export default class SignIn extends React.Component { +class SignIn extends React.Component { constructor(props) { super(props); - this.state = { username: '', password: '', errMessage: '', errHref: '', remember: 'false' }; + this.state = { username: '', password: '', remember: 'false' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } @@ -27,40 +27,7 @@ export default class SignIn extends React.Component { } handleSubmit(event) { - - const axiosOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/login`, - 'data': { - 'username': this.state.username, - 'password': this.state.password, - 'remember': this.state.remember - } - } - - axios(axiosOptions) - .then(response => { - localStorage.setItem('access_token', response.data.access_token); - localStorage.setItem('refresh_token', response.data.refresh_token); - localStorage.setItem('userID', response.data.id); - localStorage.setItem('username', response.data.username); - window.location.pathname = "/profile"; - }) - .catch(error => { - let status = error.response.status; - if (status === 401) { - this.setState({ errMessage: "Couldn't verify. Please check credentials!" }); - } - - if (status === 402) { - this.setState({ errMessage: "Please verify your email before signing in. ", errHref: "/resendVerification" }); - } - - if (status === 403) { - this.setState({ errMessage: "Account not found. ", errHref: "/signup" }); - } - }) - + this.props.signIn(this.state.username, this.state.password, this.state.remember); } componentDidMount() { @@ -159,7 +126,7 @@ export default class SignIn extends React.Component {

- {this.state.errMessage} + {this.props.message} { + return { + message: state.signInMessage, + followLink: state.signInFollowLink + } +} + +const mapDispatchToProps = dispatch => { + return { + signIn: (username, password, remember) => dispatch(actionCreators.signIn(username, password, remember)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(SignIn); diff --git a/src/main/SignUp.js b/src/main/SignUp.js index a0102eb..38e0443 100644 --- a/src/main/SignUp.js +++ b/src/main/SignUp.js @@ -1,18 +1,17 @@ import * as React from "react"; import * as PropTypes from "prop-types"; -import axios from 'axios'; - import { NavLink, Link } from "react-router-dom"; +import { connect } from 'react-redux'; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; import PasswordBox from "react-uwp/PasswordBox"; +import * as actionCreators from '../store/actions/actionCreators'; - -export default class SignUp extends React.Component { +class SignUp extends React.Component { constructor(props) { super(props); - this.state = { email: '', username: '', bio: '', password: '', confPassword: '', errMessage: '', errHref: '' }; + this.state = { email: '', username: '', bio: '', password: '', confPassword: '' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } @@ -28,42 +27,7 @@ export default class SignUp extends React.Component { } handleSubmit(event) { - - if (this.state.confPassword !== this.state.password) { - this.setState({ errMessage: "Passwords don't match" }) - } - else { - const axiosOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/signup`, - 'data': { - 'email': this.state.email, - 'username': this.state.username, - 'password': this.state.password, - 'bio': this.state.bio - } - } - - axios(axiosOptions) - .then(response => { - this.setState({ errMessage: "Signed Up! Please verify your email!" }); - }) - .catch(error => { - let status = error.response.status - //console.log(error.response); - - if (status === 402) { - this.setState({ errMessage: "Username is taken" }); - } - - else if (status === 401) { - this.setState({ errMessage: "This email is registered with another account." }); - } - else { - this.setState({ errMessage: "It's not you, it's us. Try again later." }) - } - }) - } + this.props.signUp(this.state.email, this.state.username, this.state.password, this.state.bio, this.state.confPassword); } componentDidMount() { @@ -183,7 +147,7 @@ export default class SignUp extends React.Component {

- {this.state.errMessage} + {this.props.message} } @@ -198,4 +162,19 @@ export default class SignUp extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = state => { + return { + message: state.signUpMessage, + followLink: state.signUpFollowLink + } +} + +const mapDispatchToProps = dispatch => { + return { + signUp: (email, username, password, bio, confPassword) => dispatch(actionCreators.signUp(email, username, password, bio, confPassword)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(SignUp); diff --git a/src/store/actions.js b/src/store/actions.js deleted file mode 100644 index 8c4c173..0000000 --- a/src/store/actions.js +++ /dev/null @@ -1,4 +0,0 @@ -// Methods or Actions - -// Theme related actions -export const SET_THEME = 'SET_THEME' diff --git a/src/store/actions/actionCreators.js b/src/store/actions/actionCreators.js new file mode 100644 index 0000000..09a9e3f --- /dev/null +++ b/src/store/actions/actionCreators.js @@ -0,0 +1,9 @@ +export { setTheme } from './theme'; +export { + signUp, + signIn, + submitForgotPass, + resendEmail, + registerRefreshToken, + logout +} from './auth'; diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js new file mode 100644 index 0000000..7fff4cf --- /dev/null +++ b/src/store/actions/actionTypes.js @@ -0,0 +1,8 @@ +// Theme related actions +export const SET_THEME = 'SET_THEME' + +// Authentication related actions +export const SET_SIGNUP_MESSAGE = 'SET_SIGNUP_MESSAGE' +export const SET_SIGNIN_MESSAGE = 'SET_SIGNIN_MESSAGE' +export const SET_FORGOT_PASS_MESSAGE = 'SET_FORGOT_PASS_MESSAGE' +export const SET_RESEND_EMAIL_MESSAGE = 'SET_RESEND_EMAIL_MESSAGE' diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js new file mode 100644 index 0000000..b532033 --- /dev/null +++ b/src/store/actions/auth.js @@ -0,0 +1,235 @@ +import axios from 'axios'; +import createAuthRefreshInterceptor from 'axios-auth-refresh'; +import * as actionTypes from './actionTypes'; + +// Synchronous action creator for setting sign up message +export const setSignupMessage = (message, link) => { + return { + type: actionTypes.SET_SIGNUP_MESSAGE, + payload: { + message: message, + link: link + } + } +} + +// Asynchronous action Creator for sign Up +export const signUp = (email, username, password, bio, confPassword) => { + return dispatch => { + + if (confPassword !== password) { + dispatch(setSignupMessage("Passwords don't match", '')) + } + else { + const axiosOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/signup`, + 'data': { + 'email': email, + 'username': username, + 'password': password, + 'bio': bio + } + } + + axios(axiosOptions) + .then(response => { + dispatch(setSignupMessage("Signed Up! Please verify your email!", '')) + }) + .catch(error => { + let status = error.response.status + //console.log(error.response); + + if (status === 402) { + dispatch(setSignupMessage("Username is taken", '')) + } + else if (status === 401) { + dispatch(setSignupMessage("This email is registered with another account.", '')) + } + else { + dispatch(setSignupMessage("It's not you, it's us. Try again later.", '')) + } + }) + } + } +} + +// Synchronous action creator for setting sign in message +export const setSignInMessage = (message, link) => { + return { + type: actionTypes.SET_SIGNIN_MESSAGE, + payload: { + message: message, + link: link + } + } +} + +// Asynchronous action creator for sign In +export const signIn = (username, password, remember) => { + return dispatch => { + + const axiosOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/login`, + 'data': { + 'username': username, + 'password': password, + 'remember': remember + } + } + + axios(axiosOptions) + .then(response => { + localStorage.setItem('access_token', response.data.access_token); + localStorage.setItem('refresh_token', response.data.refresh_token); + localStorage.setItem('userID', response.data.id); + localStorage.setItem('username', response.data.username); + window.location.pathname = "/profile"; + }) + .catch(error => { + let status = error.response.status; + if (status === 401) { + dispatch(setSignInMessage("Couldn't verify. Please check credentials!", '')); + } + + if (status === 402) { + dispatch(setSignInMessage("Please verify your email before signing in. ", '/resendVerification')); + } + + if (status === 403) { + dispatch(setSignInMessage("Account not found. ", '/signup')); + } + }) + + } +} + +// Synchronous action creator for setting Forgot pass message +export const setForgotPassMessage = (message, link) => { + return { + type: actionTypes.SET_FORGOT_PASS_MESSAGE, + payload: { + message: message, + link: link + } + } +} + +// Asynchronous action creator for forgot pass handler +export const submitForgotPass = email => { + return dispatch => { + + const axiosOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/reset/request`, + 'data': { + 'email': email, + } + } + + axios(axiosOptions) + .then(response => { + dispatch(setForgotPassMessage("Ah, Dementia. Reset mail sent!", '')); + }) + .catch(error => { + let status = error.response.status + + if (status === 401) { + dispatch(setForgotPassMessage("User is not registered. Please sign up first.", "/signup")); + } + else { + dispatch(setForgotPassMessage("It's not you, it's us. Try again later.", '')); + } + }) + } +} + +// Synchronous action creator for setting resend email message +export const setResendEmailMessage = (message, link) => { + return { + type: actionTypes.SET_RESEND_EMAIL_MESSAGE, + payload: { + message: message, + link: link + } + } +} + +// Asynchronous action creator for resend email handler +export const resendEmail = email => { + return dispatch => { + + const axiosOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/resendVerificationEmail`, + 'data': { + 'email': email, + } + } + + axios(axiosOptions) + .then(response => { + dispatch(setResendEmailMessage("Verification mail sent!")); + }) + .catch(error => { + let status = error.response.status + + if (status === 401) { + dispatch(setResendEmailMessage("User is not registered. Please sign up first.", "/signup")); + } + else { + dispatch(setResendEmailMessage("It's not you, it's us. Try again later.", '')); + } + }) + } +} + +// Asynchronous action creator for registering to refresh auth-token +export const registerRefreshToken = axiosInstance => { + + const refreshOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`, + 'headers': { + 'Authorization': localStorage.getItem("refresh_token") + } + } + + const refreshAuthLogic = failedRequest => axios(refreshOptions) + .then(tokenRefreshResponse => { + localStorage.setItem('access_token', tokenRefreshResponse.data.access_token); + localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token); + failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token; + return Promise.resolve(); + }); + + // return refreshAuthLogic; + createAuthRefreshInterceptor(axiosInstance, refreshAuthLogic); +} + +// Asynchronous action creator for logout +export const logout = () => { + + const axiosOptions = { + 'method': 'POST', + 'url': `${process.env.REACT_APP_DB_HOST}/auth/logout`, + headers: { + 'Authorization': localStorage.getItem("access_token") + } + } + + registerRefreshToken(axios); + + axios(axiosOptions) + .then(response => { + //console.log(response.data); + localStorage.removeItem("username"); + localStorage.removeItem("userID"); + localStorage.removeItem("access_token"); + localStorage.removeItem("refresh_token"); + // localStorage.clear(); Else it removes the saved theme also + window.location.pathname = "/"; + }) + .catch(error => { /* console.log(error) */ }) +} diff --git a/src/store/actions/theme.js b/src/store/actions/theme.js new file mode 100644 index 0000000..25c665a --- /dev/null +++ b/src/store/actions/theme.js @@ -0,0 +1,10 @@ +import * as actionTypes from './actionTypes'; + +export const setTheme = theme => { + return { + type: actionTypes.SET_THEME, + payload: { + theme: theme + } + } +} diff --git a/src/store/reducer.js b/src/store/reducer.js index 1f426c6..97e92b9 100644 --- a/src/store/reducer.js +++ b/src/store/reducer.js @@ -1,4 +1,4 @@ -import * as actionTypes from './actions' +import * as actionTypes from './actions/actionTypes' const themeDictionary = { Midnight: { @@ -79,24 +79,68 @@ else { // Initial State const initialState = { + Theme: { ...presetTheme }, - themeDict: themeDictionary + themeDict: themeDictionary, + + signUpMessage: '', + signUpFollowLink: '', + + signInMessage: '', + signInFollowLink: '', + + forgotPassMessage: '', + forgotPassFollowLink: '', + + resendEmailMessage: '', + resendEmailFollowLink: '' + } function reducer(state = initialState, action) { switch (action.type) { + case actionTypes.SET_THEME: localStorage.setItem("themeSet", JSON.stringify(action.payload.theme)) - if (action.payload.theme === "Auto-change") + if (action.payload.theme === "Auto-change") return { - ...initialState, + ...state, Theme: { ...themeDictionary[timeSlot] } } - else + else return { - ...initialState, + ...state, Theme: { ...themeDictionary[action.payload.theme] } } + + case actionTypes.SET_SIGNUP_MESSAGE: + return { + ...state, + signUpMessage: action.payload.message, + signUpFollowLink: action.payload.link + } + + case actionTypes.SET_SIGNIN_MESSAGE: + return { + ...state, + signInMessage: action.payload.message, + signInFollowLink: action.payload.link + } + + case actionTypes.SET_FORGOT_PASS_MESSAGE: + return { + ...state, + forgotPassMessage: action.payload.message, + forgotPassFollowLink: action.payload.link + } + + case actionTypes.SET_RESEND_EMAIL_MESSAGE: + return { + ...state, + resendEmailMessage: action.payload.message, + resendEmailFollowLink: action.payload.link + } + default: return { ...state diff --git a/src/views/About.js b/src/views/About.js index b2a34e3..10283cc 100644 --- a/src/views/About.js +++ b/src/views/About.js @@ -5,7 +5,7 @@ import { getTheme } from "react-uwp/Theme"; import HyperLink from "react-uwp/HyperLink"; import DropDownMenu from "react-uwp/DropDownMenu"; import AppBarButton from "react-uwp/AppBarButton"; -import * as actionTypes from '../store/actions' +import * as actionCreators from '../store/actions/actionCreators' class About extends React.Component { @@ -120,7 +120,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - setTheme: (theme) => dispatch({ type: actionTypes.SET_THEME, payload: { theme: theme } }) + setTheme: (theme) => dispatch(actionCreators.setTheme(theme)) } } diff --git a/src/views/CreatePost.js b/src/views/CreatePost.js index 50c74da..206dc34 100644 --- a/src/views/CreatePost.js +++ b/src/views/CreatePost.js @@ -1,11 +1,12 @@ import * as React from "react"; import * as PropTypes from "prop-types"; +import axios from "axios"; +import { connect } from 'react-redux'; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; -import axios from "axios"; -import createAuthRefreshInterceptor from 'axios-auth-refresh'; +import * as actionCreators from '../store/actions/actionCreators'; -export default class CreatePost extends React.Component { +class CreatePost extends React.Component { constructor(props) { super(props); @@ -25,27 +26,6 @@ export default class CreatePost extends React.Component { }; this.handleMovieSearch = this.handleMovieSearch.bind(this); this.handleSubmit = this.handleSubmit.bind(this); - this.refreshToken = this.refreshToken.bind(this); - } - - refreshToken() { - const refreshOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`, - 'headers': { - 'Authorization': localStorage.getItem("refresh_token") - } - } - - const refreshAuthLogic = failedRequest => axios(refreshOptions) - .then(tokenRefreshResponse => { - localStorage.setItem('access_token', tokenRefreshResponse.data.access_token); - localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token); - failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token; - return Promise.resolve(); - }); - - return refreshAuthLogic; } handleMovieSearch(event) { @@ -95,9 +75,7 @@ export default class CreatePost extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(axios); axios(axiosOptions) .then(response => { @@ -260,4 +238,18 @@ export default class CreatePost extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = null/*state => { + return { + + } +}*/ + +const mapDispatchToProps = dispatch => { + return { + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(CreatePost); diff --git a/src/views/Movie.js b/src/views/Movie.js index 6c518a7..a978fe0 100644 --- a/src/views/Movie.js +++ b/src/views/Movie.js @@ -1,12 +1,12 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import axios from 'axios'; -import createAuthRefreshInterceptor from 'axios-auth-refresh'; - +import { connect } from "react-redux"; import AppBarButton from "react-uwp/AppBarButton"; import Button from "react-uwp/Button"; +import * as actionCreators from '../store/actions/actionCreators'; -export default class Movie extends React.Component { +class Movie extends React.Component { constructor(props) { super(props); @@ -34,27 +34,6 @@ export default class Movie extends React.Component { this.getData = this.getData.bind(this); this.handleAddSeen = this.handleAddSeen.bind(this); this.handleAddBucket = this.handleAddBucket.bind(this); - this.refreshToken = this.refreshToken.bind(this); - } - - refreshToken() { - const refreshOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`, - 'headers': { - 'Authorization': localStorage.getItem("refresh_token") - } - } - - const refreshAuthLogic = failedRequest => axios(refreshOptions) - .then(tokenRefreshResponse => { - localStorage.setItem('access_token', tokenRefreshResponse.data.access_token); - localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token); - failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token; - return Promise.resolve(); - }); - - return refreshAuthLogic; } getData() { @@ -123,9 +102,7 @@ export default class Movie extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(axios); axios(axiosOptions) .then(response => { @@ -156,9 +133,7 @@ export default class Movie extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(axios); axios(axiosOptions) .then(response => { @@ -268,4 +243,18 @@ export default class Movie extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = null/*state => { + return { + + } +}*/ + +const mapDispatchToProps = dispatch => { + return { + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Movie); diff --git a/src/views/Post.js b/src/views/Post.js index fab5687..e234ed3 100644 --- a/src/views/Post.js +++ b/src/views/Post.js @@ -1,14 +1,14 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import axios from 'axios'; -import createAuthRefreshInterceptor from 'axios-auth-refresh'; import { Link } from "react-router-dom"; - +import { connect } from 'react-redux'; import TextBox from "react-uwp/TextBox"; import AppBarButton from "react-uwp/AppBarButton"; import MarkdownRender from "react-uwp/MarkdownRender"; +import * as actionCreators from '../store/actions/actionCreators'; -export default class Post extends React.Component { +class Post extends React.Component { constructor(props) { super(props); @@ -42,27 +42,6 @@ export default class Post extends React.Component { this.handleCreateComment = this.handleCreateComment.bind(this); this.handleCommentUpvote = this.handleCommentUpvote.bind(this); this.handleCommentDownvote = this.handleCommentDownvote.bind(this); - this.refreshToken = this.refreshToken.bind(this); - } - - refreshToken() { - const refreshOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`, - 'headers': { - 'Authorization': localStorage.getItem("refresh_token") - } - } - - const refreshAuthLogic = failedRequest => axios(refreshOptions) - .then(tokenRefreshResponse => { - localStorage.setItem('access_token', tokenRefreshResponse.data.access_token); - localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token); - failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token; - return Promise.resolve(); - }); - - return refreshAuthLogic; } getData() { @@ -141,9 +120,7 @@ export default class Post extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(); axios(axiosOptions) .then(response => { @@ -171,9 +148,7 @@ export default class Post extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(); axios(axiosOptions) .then(response => { @@ -203,9 +178,7 @@ export default class Post extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(); axios(axiosOptions) @@ -230,9 +203,7 @@ export default class Post extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(); axios(axiosOptions) .then(response => { @@ -258,9 +229,7 @@ export default class Post extends React.Component { } } - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); + this.props.registerRefreshToken(); axios(axiosOptions) .then(response => { @@ -400,4 +369,18 @@ export default class Post extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = null/*state => { + return { + + } +}*/ + +const mapDispatchToProps = dispatch => { + return { + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Post); diff --git a/src/views/Profile.js b/src/views/Profile.js index 4f7311f..e0f8c67 100644 --- a/src/views/Profile.js +++ b/src/views/Profile.js @@ -1,15 +1,15 @@ import * as React from "react"; import * as PropTypes from "prop-types"; import { Link } from "react-router-dom"; -import axios from 'axios' -import createAuthRefreshInterceptor from 'axios-auth-refresh'; - +import axios from 'axios'; +import { connect } from "react-redux"; import AppBarButton from "react-uwp/AppBarButton"; import Button from "react-uwp/Button"; import ContentDialog from "react-uwp/ContentDialog"; +import * as actionCreators from '../store/actions/actionCreators'; -export default class Profile extends React.Component { +class Profile extends React.Component { constructor(props) { super(props); @@ -35,31 +35,8 @@ export default class Profile extends React.Component { this.getPostList = this.getPostList.bind(this); this.handleDeleteDialog = this.handleDeleteDialog.bind(this); this.handleDeletePost = this.handleDeletePost.bind(this); - this.handleLogOut = this.handleLogOut.bind(this); - this.refreshToken = this.refreshToken.bind(this); - } - - refreshToken() { - const refreshOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/refreshToken`, - 'headers': { - 'Authorization': localStorage.getItem("refresh_token") - } - } - - const refreshAuthLogic = failedRequest => axios(refreshOptions) - .then(tokenRefreshResponse => { - localStorage.setItem('access_token', tokenRefreshResponse.data.access_token); - localStorage.setItem('refresh_token', tokenRefreshResponse.data.refresh_token); - failedRequest.response.config.headers['Authorization'] = tokenRefreshResponse.data.access_token; - return Promise.resolve(); - }); - - return refreshAuthLogic; } - getData() { let username = localStorage.getItem("username"); let url = `${process.env.REACT_APP_DB_HOST}/user/` + username; @@ -192,32 +169,6 @@ export default class Profile extends React.Component { .catch(error => { /* console.log(error) */ }) } - handleLogOut() { - const axiosOptions = { - 'method': 'POST', - 'url': `${process.env.REACT_APP_DB_HOST}/auth/logout`, - headers: { - 'Authorization': localStorage.getItem("access_token") - } - } - - const refreshAuthLogic = this.refreshToken(); - - createAuthRefreshInterceptor(axios, refreshAuthLogic); - - axios(axiosOptions) - .then(response => { - //console.log(response.data); - localStorage.removeItem("username"); - localStorage.removeItem("userID"); - localStorage.removeItem("access_token"); - localStorage.removeItem("refresh_token"); - localStorage.clear(); - window.location.pathname = "/"; - }) - .catch(error => { /* console.log(error) */ }) - } - componentDidMount() { this.getData(); this.getSeenData(); @@ -267,7 +218,7 @@ export default class Profile extends React.Component { icon={} label="Sign Out" labelPosition="right" - onClick={this.handleLogOut} + onClick={() => this.props.logout()} />

@@ -373,4 +324,18 @@ export default class Profile extends React.Component { ); } -} \ No newline at end of file +} + +const mapStateToProps = null/*state => { + return { + + } +}*/ + +const mapDispatchToProps = dispatch => { + return { + logout: () => dispatch(actionCreators.logout()) + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(Profile);