From 360bd95304eb940ce9b5b3acf660e47dcafcfcd1 Mon Sep 17 00:00:00 2001 From: Ravi Sri Ram Chowdary Date: Sat, 26 Dec 2020 15:12:20 +0530 Subject: [PATCH 1/5] Installed redux-thunk and introduced action creators --- package-lock.json | 5 +++++ package.json | 3 ++- src/index.js | 5 +++-- src/store/actions/actionCreators.js | 1 + src/store/{actions.js => actions/actionTypes.js} | 2 -- src/store/actions/theme.js | 10 ++++++++++ src/store/reducer.js | 2 +- src/views/About.js | 4 ++-- 8 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 src/store/actions/actionCreators.js rename src/store/{actions.js => actions/actionTypes.js} (72%) create mode 100644 src/store/actions/theme.js 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/store/actions/actionCreators.js b/src/store/actions/actionCreators.js new file mode 100644 index 0000000..f494b80 --- /dev/null +++ b/src/store/actions/actionCreators.js @@ -0,0 +1 @@ +export { setTheme } from './theme'; diff --git a/src/store/actions.js b/src/store/actions/actionTypes.js similarity index 72% rename from src/store/actions.js rename to src/store/actions/actionTypes.js index 8c4c173..4f81b6a 100644 --- a/src/store/actions.js +++ b/src/store/actions/actionTypes.js @@ -1,4 +1,2 @@ -// Methods or Actions - // Theme related actions export const SET_THEME = 'SET_THEME' 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..9fbf373 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: { 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)) } } From 1208ba5a8ec052ef4378b92e46854bd17f08739f Mon Sep 17 00:00:00 2001 From: Ravi Sri Ram Chowdary Date: Sat, 26 Dec 2020 18:41:20 +0530 Subject: [PATCH 2/5] Moved authentication related HTTP requests to store --- src/main/ForgotPassword.js | 55 ++++----- src/main/ResendEmail.js | 54 ++++---- src/main/SignIn.js | 60 ++++----- src/main/SignUp.js | 65 ++++------ src/store/actions/actionCreators.js | 6 + src/store/actions/actionTypes.js | 6 + src/store/actions/auth.js | 185 ++++++++++++++++++++++++++++ src/store/reducer.js | 38 +++++- 8 files changed, 319 insertions(+), 150 deletions(-) create mode 100644 src/store/actions/auth.js 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..4bc1c5b 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(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/actionCreators.js b/src/store/actions/actionCreators.js index f494b80..0b462b9 100644 --- a/src/store/actions/actionCreators.js +++ b/src/store/actions/actionCreators.js @@ -1 +1,7 @@ export { setTheme } from './theme'; +export { + signUp, + signIn, + submitForgotPass, + resendEmail +} from './auth'; diff --git a/src/store/actions/actionTypes.js b/src/store/actions/actionTypes.js index 4f81b6a..7fff4cf 100644 --- a/src/store/actions/actionTypes.js +++ b/src/store/actions/actionTypes.js @@ -1,2 +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..1a68e64 --- /dev/null +++ b/src/store/actions/auth.js @@ -0,0 +1,185 @@ +import axios from 'axios'; +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.", '')); + } + }) + } +} diff --git a/src/store/reducer.js b/src/store/reducer.js index 9fbf373..166a929 100644 --- a/src/store/reducer.js +++ b/src/store/reducer.js @@ -80,23 +80,55 @@ 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, Theme: { ...themeDictionary[timeSlot] } } - else + else return { ...initialState, Theme: { ...themeDictionary[action.payload.theme] } } + case actionTypes.SET_SIGNUP_MESSAGE: + return { + ...initialState, + signUpMessage: action.payload.message, + signUpFollowLink: action.payload.link + } + case actionTypes.SET_SIGNIN_MESSAGE: + return { + ...initialState, + signInMessage: action.payload.message, + signInFollowLink: action.payload.link + } + case actionTypes.SET_FORGOTPASS_MESSAGE: + return { + ...initialState, + forgotPassMessage: action.payload.message, + forgotPassFollowLink: action.payload.link + } + case actionTypes.SET_RESEND_EMAIL_MESSAGE: + return { + ...initialState, + resendEmailMessage: action.payload.message, + resendEmailFollowLink: action.payload.link + } default: return { ...state From 80887771d435be2d87caaab879a73a8c435dcfea Mon Sep 17 00:00:00 2001 From: Ravi Sri Ram Chowdary Date: Sat, 26 Dec 2020 18:49:12 +0530 Subject: [PATCH 3/5] Fixed small bugs and corrected 'initialState' where it has to be 'state' in reducer --- src/main/ResendEmail.js | 2 +- src/store/reducer.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/ResendEmail.js b/src/main/ResendEmail.js index 4bc1c5b..a1109ee 100644 --- a/src/main/ResendEmail.js +++ b/src/main/ResendEmail.js @@ -110,7 +110,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return{ - resendEmail : email => dispatch(actionCreators(email)) + resendEmail : email => dispatch(actionCreators.resendEmail(email)) } } diff --git a/src/store/reducer.js b/src/store/reducer.js index 166a929..2cb9774 100644 --- a/src/store/reducer.js +++ b/src/store/reducer.js @@ -97,35 +97,35 @@ function reducer(state = initialState, action) { localStorage.setItem("themeSet", JSON.stringify(action.payload.theme)) if (action.payload.theme === "Auto-change") return { - ...initialState, + ...state, Theme: { ...themeDictionary[timeSlot] } } else return { - ...initialState, + ...state, Theme: { ...themeDictionary[action.payload.theme] } } case actionTypes.SET_SIGNUP_MESSAGE: return { - ...initialState, + ...state, signUpMessage: action.payload.message, signUpFollowLink: action.payload.link } case actionTypes.SET_SIGNIN_MESSAGE: return { - ...initialState, + ...state, signInMessage: action.payload.message, signInFollowLink: action.payload.link } - case actionTypes.SET_FORGOTPASS_MESSAGE: + case actionTypes.SET_FORGOT_PASS_MESSAGE: return { - ...initialState, + ...state, forgotPassMessage: action.payload.message, forgotPassFollowLink: action.payload.link } case actionTypes.SET_RESEND_EMAIL_MESSAGE: return { - ...initialState, + ...state, resendEmailMessage: action.payload.message, resendEmailFollowLink: action.payload.link } From e5f032e5c43c034cd01fb7e7c930781a08275e8e Mon Sep 17 00:00:00 2001 From: Ravi Sri Ram Chowdary Date: Sun, 27 Dec 2020 12:26:57 +0530 Subject: [PATCH 4/5] Moved logic for logout and refreshing token to redux --- src/store/actions/actionCreators.js | 6 ++- src/store/actions/auth.js | 52 +++++++++++++++++++- src/store/reducer.js | 12 +++++ src/views/CreatePost.js | 48 ++++++++---------- src/views/Movie.js | 51 ++++++++------------ src/views/Post.js | 63 +++++++++--------------- src/views/Profile.js | 75 ++++++++--------------------- 7 files changed, 150 insertions(+), 157 deletions(-) diff --git a/src/store/actions/actionCreators.js b/src/store/actions/actionCreators.js index 0b462b9..09a9e3f 100644 --- a/src/store/actions/actionCreators.js +++ b/src/store/actions/actionCreators.js @@ -1,7 +1,9 @@ export { setTheme } from './theme'; -export { +export { signUp, signIn, submitForgotPass, - resendEmail + resendEmail, + registerRefreshToken, + logout } from './auth'; diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js index 1a68e64..aed27ec 100644 --- a/src/store/actions/auth.js +++ b/src/store/actions/auth.js @@ -1,4 +1,5 @@ import axios from 'axios'; +import createAuthRefreshInterceptor from 'axios-auth-refresh'; import * as actionTypes from './actionTypes'; // Synchronous action creator for setting sign up message @@ -158,7 +159,7 @@ export const setResendEmailMessage = (message, 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`, @@ -183,3 +184,52 @@ export const resendEmail = email => { }) } } + +// 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/reducer.js b/src/store/reducer.js index 2cb9774..97e92b9 100644 --- a/src/store/reducer.js +++ b/src/store/reducer.js @@ -79,20 +79,27 @@ else { // Initial State const initialState = { + Theme: { ...presetTheme }, 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") @@ -105,30 +112,35 @@ function reducer(state = initialState, action) { ...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/CreatePost.js b/src/views/CreatePost.js index 50c74da..fb0a43f 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..8f1bfb0 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..695ed6d 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); From b7fe6b381eb786bfad25215af65a28bb006b8725 Mon Sep 17 00:00:00 2001 From: Ravi Sri Ram Chowdary Date: Wed, 30 Dec 2020 14:27:39 +0530 Subject: [PATCH 5/5] Removed unnecessary parantheses --- src/store/actions/auth.js | 2 +- src/views/CreatePost.js | 2 +- src/views/Movie.js | 2 +- src/views/Post.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/store/actions/auth.js b/src/store/actions/auth.js index aed27ec..b532033 100644 --- a/src/store/actions/auth.js +++ b/src/store/actions/auth.js @@ -186,7 +186,7 @@ export const resendEmail = email => { } // Asynchronous action creator for registering to refresh auth-token -export const registerRefreshToken = (axiosInstance) => { +export const registerRefreshToken = axiosInstance => { const refreshOptions = { 'method': 'POST', diff --git a/src/views/CreatePost.js b/src/views/CreatePost.js index fb0a43f..206dc34 100644 --- a/src/views/CreatePost.js +++ b/src/views/CreatePost.js @@ -248,7 +248,7 @@ const mapStateToProps = null/*state => { const mapDispatchToProps = dispatch => { return { - registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) } } diff --git a/src/views/Movie.js b/src/views/Movie.js index 8f1bfb0..a978fe0 100644 --- a/src/views/Movie.js +++ b/src/views/Movie.js @@ -253,7 +253,7 @@ const mapStateToProps = null/*state => { const mapDispatchToProps = dispatch => { return { - registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) } } diff --git a/src/views/Post.js b/src/views/Post.js index 695ed6d..e234ed3 100644 --- a/src/views/Post.js +++ b/src/views/Post.js @@ -379,7 +379,7 @@ const mapStateToProps = null/*state => { const mapDispatchToProps = dispatch => { return { - registerRefreshToken: (axiosInstance) => dispatch(actionCreators.registerRefreshToken(axiosInstance)) + registerRefreshToken: axiosInstance => dispatch(actionCreators.registerRefreshToken(axiosInstance)) } }