summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Shetye2025-03-26 12:19:11 +0530
committerSunil Shetye2025-04-07 15:38:16 +0530
commit8c46c646e2ef2447173f4ed8b7549b72d6c960ed (patch)
tree551bfd95fad39719922005a34b1c38daeceb35c0
parent1f54ee754a9dad21831cac97f80979e7c2a845e1 (diff)
downloadCommon-Interface-Project-8c46c646e2ef2447173f4ed8b7549b72d6c960ed.tar.gz
Common-Interface-Project-8c46c646e2ef2447173f4ed8b7549b72d6c960ed.tar.bz2
Common-Interface-Project-8c46c646e2ef2447173f4ed8b7549b72d6c960ed.zip
convert auth action/reducer to slice
-rw-r--r--blocks/eda-frontend/src/App.js10
-rw-r--r--blocks/eda-frontend/src/components/Dashboard/DashboardHome.js4
-rw-r--r--blocks/eda-frontend/src/components/Dashboard/DashboardSidebar.js2
-rw-r--r--blocks/eda-frontend/src/components/Dashboard/SchematicsList.js2
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/Header.js7
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js2
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js4
-rw-r--r--blocks/eda-frontend/src/components/Shared/Navbar.js6
-rw-r--r--blocks/eda-frontend/src/pages/Login.js16
-rw-r--r--blocks/eda-frontend/src/pages/signUp.js26
-rw-r--r--blocks/eda-frontend/src/redux/actions/actions.js12
-rw-r--r--blocks/eda-frontend/src/redux/actions/authActions.js275
-rw-r--r--blocks/eda-frontend/src/redux/actions/dashboardActions.js4
-rw-r--r--blocks/eda-frontend/src/redux/actions/index.js1
-rw-r--r--blocks/eda-frontend/src/redux/actions/saveSchematicActions.js6
-rw-r--r--blocks/eda-frontend/src/redux/authSlice.js298
-rw-r--r--blocks/eda-frontend/src/redux/reducers/authReducer.js92
-rw-r--r--blocks/eda-frontend/src/redux/reducers/index.js2
-rw-r--r--blocks/eda-frontend/src/redux/store.js2
19 files changed, 346 insertions, 425 deletions
diff --git a/blocks/eda-frontend/src/App.js b/blocks/eda-frontend/src/App.js
index 9d72db82..79b9088a 100644
--- a/blocks/eda-frontend/src/App.js
+++ b/blocks/eda-frontend/src/App.js
@@ -14,13 +14,13 @@ import Dashboard from './pages/Dashboard'
import SignUp from './pages/signUp'
import { useSelector, useDispatch } from 'react-redux'
-import { loadUser } from './redux/actions/index'
+import { loadUser } from './redux/authSlice'
// Controls Private routes, this are accessible for authenticated users. [ e.g : dashboard ]
// and restricted routes disabled for authenticated users. [ e.g : login , signup ]
const PrivateRoute = ({ component: Component, ...rest }) => {
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
- const isLoading = useSelector(state => state.authReducer.isLoading)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
+ const isLoading = useSelector(state => state.auth.isLoading)
const dispatch = useDispatch()
useEffect(() => dispatch(loadUser()), [])
@@ -46,8 +46,8 @@ PrivateRoute.propTypes = {
// Public routes accessible to all users. [ e.g. editor, gallery ]
const PublicRoute = ({ component: Component, restricted, nav, ...rest }) => {
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
- const isLoading = useSelector(state => state.authReducer.isLoading)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
+ const isLoading = useSelector(state => state.auth.isLoading)
const dispatch = useDispatch()
useEffect(() => dispatch(loadUser()), [])
diff --git a/blocks/eda-frontend/src/components/Dashboard/DashboardHome.js b/blocks/eda-frontend/src/components/Dashboard/DashboardHome.js
index e3858ea0..c4c087fb 100644
--- a/blocks/eda-frontend/src/components/Dashboard/DashboardHome.js
+++ b/blocks/eda-frontend/src/components/Dashboard/DashboardHome.js
@@ -21,7 +21,7 @@ const useStyles = makeStyles((theme) => ({
// Card displaying user dashboard home page header.
function MainCard () {
const classes = useStyles()
- const user = useSelector(state => state.authReducer.user)
+ const user = useSelector(state => state.auth.user)
const dashboard = process.env.REACT_APP_NAME
const button = 'My ' + process.env.REACT_APP_DIAGRAMS_NAME
@@ -51,7 +51,7 @@ function MainCard () {
export default function DashboardHome () {
const classes = useStyles()
- const user = useSelector(state => state.authReducer.user)
+ const user = useSelector(state => state.auth.user)
const typography = 'Track your ' + process.env.REACT_APP_SMALL_DIAGRAMS_NAME + ' status here...'
return (
diff --git a/blocks/eda-frontend/src/components/Dashboard/DashboardSidebar.js b/blocks/eda-frontend/src/components/Dashboard/DashboardSidebar.js
index 2327ef79..a0bc92e9 100644
--- a/blocks/eda-frontend/src/components/Dashboard/DashboardSidebar.js
+++ b/blocks/eda-frontend/src/components/Dashboard/DashboardSidebar.js
@@ -39,7 +39,7 @@ const useStyles = makeStyles((theme) => ({
// Vertical Navbar for user dashboard
export default function DashSidebar (props) {
const classes = useStyles()
- const user = useSelector(state => state.authReducer.user)
+ const user = useSelector(state => state.auth.user)
const schematics = useSelector(state => state.dashboardReducer.schematics)
const dispatch = useDispatch()
diff --git a/blocks/eda-frontend/src/components/Dashboard/SchematicsList.js b/blocks/eda-frontend/src/components/Dashboard/SchematicsList.js
index 8d8cb712..75562afb 100644
--- a/blocks/eda-frontend/src/components/Dashboard/SchematicsList.js
+++ b/blocks/eda-frontend/src/components/Dashboard/SchematicsList.js
@@ -55,7 +55,7 @@ function MainCard () {
export default function SchematicsList () {
const classes = useStyles()
- const user = useSelector(state => state.authReducer.user)
+ const user = useSelector(state => state.auth.user)
const schematics = useSelector(state => state.dashboardReducer.schematics)
const dispatch = useDispatch()
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/Header.js b/blocks/eda-frontend/src/components/SchematicEditor/Header.js
index d0153b9f..b40987aa 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/Header.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/Header.js
@@ -30,7 +30,8 @@ import { makeStyles } from '@material-ui/core/styles'
import { deepPurple } from '@material-ui/core/colors'
import logo from '../../static/favicon.ico'
-import { setTitle, logout, setSchTitle, setSchShared } from '../../redux/actions/index'
+import { setTitle, setSchTitle, setSchShared } from '../../redux/actions/index'
+import { logout } from '../../redux/authSlice'
import { getDateTime as getDate, getUppercaseInitial } from '../../utils/GalleryUtils'
const useStyles = makeStyles((theme) => ({
@@ -101,8 +102,8 @@ SimpleSnackbar.propTypes = {
function Header () {
const history = useHistory()
const classes = useStyles()
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
- const user = useSelector(state => state.authReducer.user)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
+ const user = useSelector(state => state.auth.user)
const details = useSelector(state => state.saveSchematicReducer.details)
const isSaved = useSelector(state => state.saveSchematicReducer.isSaved)
const isShared = useSelector(state => state.saveSchematicReducer.isShared)
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js b/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
index c4f78c03..1d36dd61 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
@@ -95,7 +95,7 @@ SimpleSnackbar.propTypes = {
export default function SchematicToolbar ({ mobileClose, gridRef }) {
const classes = useStyles()
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
const description = useSelector(state => state.saveSchematicReducer.description)
const title2 = useSelector(state => state.saveSchematicReducer.title)
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js b/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
index b629f76c..bcf7b567 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
@@ -522,8 +522,8 @@ export function OpenSchDialog (props) {
const [isLocal, setisLocal] = useState(true)
const [isGallery, setisGallery] = useState(false)
const details = useSelector(state => state.saveSchematicReducer.details)
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
- const user = useSelector(state => state.authReducer.user)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
+ const user = useSelector(state => state.auth.user)
const schematics = useSelector(state => state.dashboardReducer.schematics)
const GallerySchSample = useSelector(state => state.dashboardReducer.gallery)
diff --git a/blocks/eda-frontend/src/components/Shared/Navbar.js b/blocks/eda-frontend/src/components/Shared/Navbar.js
index 8303cfbf..3b75f5cf 100644
--- a/blocks/eda-frontend/src/components/Shared/Navbar.js
+++ b/blocks/eda-frontend/src/components/Shared/Navbar.js
@@ -6,7 +6,7 @@ import { makeStyles } from '@material-ui/core/styles'
import { deepPurple } from '@material-ui/core/colors'
import { Link as RouterLink, useHistory } from 'react-router-dom'
import logo from '../../static/favicon.ico'
-import { logout } from '../../redux/actions/index'
+import { logout } from '../../redux/authSlice'
import { getUppercaseInitial } from '../../utils/GalleryUtils'
const useStyles = makeStyles((theme) => ({
@@ -43,8 +43,8 @@ export function Header () {
const history = useHistory()
const classes = useStyles()
const [anchorEl, setAnchorEl] = useState(null)
- const isAuthenticated = useSelector(state => state.authReducer.isAuthenticated)
- const user = useSelector(state => state.authReducer.user)
+ const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
+ const user = useSelector(state => state.auth.user)
const dispatch = useDispatch()
diff --git a/blocks/eda-frontend/src/pages/Login.js b/blocks/eda-frontend/src/pages/Login.js
index 2af2fc1f..f2f8c4cb 100644
--- a/blocks/eda-frontend/src/pages/Login.js
+++ b/blocks/eda-frontend/src/pages/Login.js
@@ -22,7 +22,7 @@ import Visibility from '@material-ui/icons/Visibility'
import VisibilityOff from '@material-ui/icons/VisibilityOff'
import { Link as RouterLink } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
-import { login, authDefault, googleLogin, githubLogin } from '../redux/actions/index'
+import { login, authDefault, googleLogin, githubLogin } from '../redux/authSlice'
import google from '../static/google.png'
import github from '../static/github-mark.png'
@@ -51,13 +51,12 @@ let url = ''
export default function SignIn (props) {
const classes = useStyles()
- const errors = useSelector(state => state.authReducer.errors)
+ const errors = useSelector(state => state.auth.errors)
const dispatch = useDispatch()
const homeURL = `${window.location.protocol}\\\\${window.location.host}/`
useEffect(() => {
- dispatch(authDefault())
document.title = 'Login - ' + process.env.REACT_APP_NAME
if (props.location.search !== '') {
const query = new URLSearchParams(props.location.search)
@@ -66,6 +65,10 @@ export default function SignIn (props) {
} else {
url = ''
}
+
+ return () => {
+ dispatch(authDefault())
+ }
}, [props.location.search])
const [username, setUsername] = useState('')
@@ -76,20 +79,19 @@ export default function SignIn (props) {
// Function call for normal user login.
const handleLogin = () => {
- dispatch(login(username, password, url))
+ dispatch(login({ email: username, password, toUrl: url }))
}
// Function call for google oAuth login.
const handleGoogleLogin = () => {
- const host = window.location.protocol + '//' + window.location.host
+ const host = window.location.origin
dispatch(googleLogin(host))
}
// Function call for github login.
const handleGithubLogin = () => {
const host = window.location.origin
- const toUrl = '' // Add any redirect URL logic if needed
- dispatch(githubLogin(host, toUrl))
+ dispatch(githubLogin(host))
}
return (
diff --git a/blocks/eda-frontend/src/pages/signUp.js b/blocks/eda-frontend/src/pages/signUp.js
index bce4873e..17e1ecef 100644
--- a/blocks/eda-frontend/src/pages/signUp.js
+++ b/blocks/eda-frontend/src/pages/signUp.js
@@ -18,9 +18,9 @@ import { makeStyles } from '@material-ui/core/styles'
import LockOutlinedIcon from '@material-ui/icons/LockOutlined'
import Visibility from '@material-ui/icons/Visibility'
import VisibilityOff from '@material-ui/icons/VisibilityOff'
-import { Link as RouterLink, useHistory } from 'react-router-dom'
+import { Link as RouterLink } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
-import { signUp, authDefault, googleLogin, githubLogin } from '../redux/actions/index'
+import { signUp, authDefault, googleLogin, githubLogin } from '../redux/authSlice'
import google from '../static/google.png'
import github from '../static/github-mark.png'
@@ -48,18 +48,19 @@ const useStyles = makeStyles((theme) => ({
export default function SignUp () {
const classes = useStyles()
- const isRegistered = useSelector(state => state.authReducer.isRegistered)
- const regErrors = useSelector(state => state.authReducer.regErrors)
+ const isRegistered = useSelector(state => state.auth.isRegistered)
+ const regErrors = useSelector(state => state.auth.regErrors)
const dispatch = useDispatch()
const homeURL = `${window.location.protocol}\\\\${window.location.host}/`
useEffect(() => {
- dispatch(authDefault())
document.title = 'Sign Up - ' + process.env.REACT_APP_NAME
- }, [])
- const history = useHistory()
+ return () => {
+ dispatch(authDefault())
+ }
+ }, [])
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
@@ -74,15 +75,14 @@ export default function SignUp () {
// Function call for google oAuth sign up.
const handleGoogleSignup = () => {
- const host = window.location.protocol + '//' + window.location.host
+ const host = window.location.origin
dispatch(googleLogin(host))
}
// Function call for github sign up.
- const handleGithubLogin = () => {
+ const handleGithubSignup = () => {
const host = window.location.origin
- const toUrl = '' // Add any redirect URL logic if needed
- dispatch(githubLogin(host, toUrl))
+ dispatch(githubLogin(host))
}
return (
@@ -178,7 +178,7 @@ export default function SignUp () {
fullWidth
variant='contained'
color='primary'
- onClick={() => dispatch(signUp(email, password, reenterPassword, history))}
+ onClick={() => dispatch(signUp({ email, password, reenterPassword }))}
className={classes.submit}
disabled={!accept}
>
@@ -201,7 +201,7 @@ export default function SignUp () {
fullWidth
variant='outlined'
color='primary'
- onClick={handleGithubLogin}
+ onClick={handleGithubSignup}
className={classes.submit}
>
<img alt='GitHub' src={github} height='20' />&emsp; Sign Up With GitHub
diff --git a/blocks/eda-frontend/src/redux/actions/actions.js b/blocks/eda-frontend/src/redux/actions/actions.js
index 3dc9f29b..85bc061e 100644
--- a/blocks/eda-frontend/src/redux/actions/actions.js
+++ b/blocks/eda-frontend/src/redux/actions/actions.js
@@ -17,18 +17,6 @@ export const SET_NETLIST = 'SET_NETLIST'
export const SET_TITLE = 'SET_TITLE'
export const SET_MODEL = 'SET_MODEL'
-// Actions for handling user authentication and registration
-export const USER_LOADING = 'USER_LOADING'
-export const USER_LOADED = 'USER_LOADED'
-export const LOGIN_SUCCESSFUL = 'LOGIN_SUCCESSFUL'
-export const AUTHENTICATION_ERROR = 'AUTHENTICATION_ERROR'
-export const LOGIN_FAILED = 'LOGIN_FAILED'
-export const LOGOUT_SUCCESSFUL = 'LOGOUT_SUCCESSFUL'
-export const LOADING_FAILED = 'LOADING_FAILED'
-export const SIGNUP_SUCCESSFUL = 'SIGNUP_SUCCESSFUL'
-export const SIGNUP_FAILED = 'SIGNUP_FAILED'
-export const DEFAULT_STORE = 'DEFAULT_STORE'
-
// Actions for saving scheamtics and loading saved, gallery and local schematics.
export const LOADING_DIAGRAM = 'LOADING_DIAGRAM'
export const SAVE_SCHEMATICS = 'SAVE_SCHEMATICS'
diff --git a/blocks/eda-frontend/src/redux/actions/authActions.js b/blocks/eda-frontend/src/redux/actions/authActions.js
deleted file mode 100644
index 19e22808..00000000
--- a/blocks/eda-frontend/src/redux/actions/authActions.js
+++ /dev/null
@@ -1,275 +0,0 @@
-import * as actions from './actions'
-import api from '../../utils/Api'
-
-// Api call for maintaining user login state throughout the application
-export const loadUser = () => (dispatch, getState) => {
- // User Loading
- dispatch({ type: actions.USER_LOADING })
-
- // Get token from localstorage
- const token = getState().authReducer.token
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
-
- // If token available add to headers
- if (token) {
- config.headers.Authorization = `Token ${token}`
- } else {
- dispatch({ type: actions.LOADING_FAILED })
- return
- }
-
- api.get('auth/users/me/', config)
- .then(
- (res) => {
- if (res.status === 200) {
- dispatch({
- type: actions.USER_LOADED,
- payload: {
- user: res.data
- }
- })
- } else if (res.status >= 400 && res.status < 500) {
- dispatch(loginFailed(res.data))
- }
- }
- )
- .catch((err) => {
- console.error(err)
- dispatch(loginFailed({}))
- })
-}
-
-// Handle api call for user login
-export const login = (email, password, toUrl) => {
- const body = {
- email,
- password
- }
-
- return function (dispatch) {
- const allowedUrls = [
- '/editor'
- ]
- api.post('auth/token/login/', body)
- .then((res) => {
- if (res.status === 200) {
- dispatch({
- type: actions.LOGIN_SUCCESSFUL,
- payload: {
- data: res.data
- }
- })
- if (toUrl === '') {
- dispatch(loadUser())
- } else if (!allowedUrls.includes(toUrl)) {
- console.log('Not redirecting to', toUrl)
- dispatch(loadUser())
- } else {
- window.open(toUrl, '_self')
- }
- } else if (res.status === 400 || res.status === 403 || res.status === 401) {
- const data = res.data
- if (data.email !== undefined) {
- dispatch(loginError(data.email[0]))
- } else if (data.password !== undefined) {
- dispatch(loginError(data.password[0]))
- } else if (data.non_field_errors !== undefined) {
- dispatch(loginError(data.non_field_errors[0]))
- } else {
- dispatch(loginError('Incorrect Username or Password.'))
- }
- } else {
- dispatch(loginFailed('Something went wrong! Login Failed'))
- }
- })
- .catch((err) => {
- const res = err.response
- if (res.status === 400 || res.status === 403 || res.status === 401) {
- const data = res.data
- if (data.email !== undefined) {
- dispatch(loginError(data.email[0]))
- } else if (data.password !== undefined) {
- dispatch(loginError(data.password[0]))
- } else if (data.non_field_errors !== undefined) {
- dispatch(loginError(data.non_field_errors[0]))
- } else {
- dispatch(loginError('Incorrect Username or Password.'))
- }
- } else {
- dispatch(loginError('Something went wrong! Login Failed'))
- }
- })
- }
-}
-
-// Handle api call for user sign up
-export const signUp = (email, password, reenterPassword) => (dispatch) => {
- const body = {
- email,
- username: email,
- password,
- re_password: reenterPassword
- }
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
-
- api.post('auth/users/', body, config)
- .then((res) => {
- if (res.status === 200 || res.status === 201) {
- dispatch({
- type: actions.SIGNUP_SUCCESSFUL,
- payload: {
- data: 'Successfully Signed Up! A verification link has been sent to your email account.'
- }
- })
- }
- })
- .catch((err) => {
- const res = err.response
- if (res.status === 400 || res.status === 403 || res.status === 401) {
- const data = res.data
- if (data.email !== undefined) {
- dispatch(signUpError(data.email[0]))
- } else if (data.username !== undefined) {
- dispatch(signUpError(data.username[0]))
- } else if (data.password !== undefined) {
- dispatch(signUpError(data.password[0]))
- } else if (data.re_password !== undefined) {
- dispatch(signUpError(data.re_password[0]))
- } else if (data.non_field_errors !== undefined) {
- dispatch(signUpError(data.non_field_errors[0]))
- } else {
- dispatch(signUpError('Enter valid credentials.'))
- }
- } else {
- dispatch(signUpError('Something went wrong! Registration Failed'))
- }
- })
-}
-
-// Handle api call for user logout
-export const logout = (history) => (dispatch, getState) => {
- // Get token from localstorage
- const token = getState().authReducer.token
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
-
- // If token available add to headers
- if (token) {
- config.headers.Authorization = `Token ${token}`
- }
-
- api.post('auth/token/logout/', {}, config)
- .then(
- (res) => {
- if (res.status === 200 || res.status === 204) {
- dispatch({
- type: actions.LOGOUT_SUCCESSFUL,
- payload: {
- user: res.data
- }
- })
- history.push('/login')
- }
- }
- )
- .catch((err) => { console.error(err) })
-}
-
-// Redux action for default auth store
-export const authDefault = () => (dispatch) => {
- dispatch({ type: actions.DEFAULT_STORE })
-}
-
-// Redux action for display login error
-const loginError = (message) => (dispatch) => {
- dispatch({
- type: actions.AUTHENTICATION_ERROR,
- payload: {
- data: message
- }
- })
-}
-
-// Redux action for display login error
-const loginFailed = (message) => (dispatch) => {
- dispatch({
- type: actions.LOGIN_FAILED,
- payload: {
- data: message
- }
- })
-}
-
-// Redux action for display sign up error
-const signUpError = (message) => (dispatch) => {
- dispatch({
- type: actions.SIGNUP_FAILED,
- payload: {
- data: message
- }
- })
-}
-
-// Api call for Google oAuth login or sign up
-export const googleLogin = (host) => {
- return function (dispatch) {
- api.get('auth/o/google-oauth2/?redirect_uri=' + host + '/api/auth/google-callback')
- .then((res) => {
- if (res.status === 200) {
- // Open google login page
- window.open(res.data.authorization_url, '_self')
- } else {
- dispatch(loginFailed('Something went wrong! Login Failed'))
- }
- })
- .then((res) => { console.log(res) })
- .catch((err) => {
- const res = err.response
- if (res.status === 400 || res.status === 403 || res.status === 401) {
- dispatch(loginError('Incorrect Username or Password.'))
- } else {
- dispatch(loginError('Something went wrong! Login Failed'))
- }
- })
- }
-}
-
-// Api call for GitHub OAuth login or sign up
-export const githubLogin = (host) => {
- return function (dispatch) {
- api.get('auth/o/github/?redirect_uri=' + host + '/api/auth/github-callback')
- .then((res) => {
- if (res.status === 200) {
- // Open GitHub login page
- window.open(res.data.authorization_url, '_self')
- } else {
- dispatch(loginFailed('Something went wrong! Login Failed'))
- }
- })
- .catch((err) => {
- const res = err.response
- if (res && (res.status === 400 || res.status === 403 || res.status === 401)) {
- dispatch(loginError('Incorrect Username or Password.'))
- } else {
- dispatch(loginError('Something went wrong! Login Failed'))
- }
- })
- }
-}
diff --git a/blocks/eda-frontend/src/redux/actions/dashboardActions.js b/blocks/eda-frontend/src/redux/actions/dashboardActions.js
index 210c1a74..9d47b289 100644
--- a/blocks/eda-frontend/src/redux/actions/dashboardActions.js
+++ b/blocks/eda-frontend/src/redux/actions/dashboardActions.js
@@ -3,7 +3,7 @@ import * as actions from './actions'
// Api call for listing saved schematic to display on dashboard
export const fetchSchematics = () => (dispatch, getState) => {
- const token = getState().authReducer.token
+ const token = getState().auth.token
const config = {
headers: {
@@ -42,7 +42,7 @@ export const fetchGallery = () => (dispatch) => {
// Api call for deleting saved schematic
export const deleteSchematic = (saveId) => (dispatch, getState) => {
- const token = getState().authReducer.token
+ const token = getState().auth.token
const config = {
headers: {
diff --git a/blocks/eda-frontend/src/redux/actions/index.js b/blocks/eda-frontend/src/redux/actions/index.js
index dcbfcaf5..7fbee38a 100644
--- a/blocks/eda-frontend/src/redux/actions/index.js
+++ b/blocks/eda-frontend/src/redux/actions/index.js
@@ -2,6 +2,5 @@
export * from './schematicEditorActions'
export * from './componentPropertiesActions'
export * from './netlistActions'
-export * from './authActions'
export * from './saveSchematicActions'
export * from './dashboardActions'
diff --git a/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js b/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js
index c3b3bab6..b4ae9466 100644
--- a/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js
+++ b/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js
@@ -61,7 +61,7 @@ export const saveSchematic = (title, description, xml, base64, scriptDump) => (d
}
// Get token from localstorage
- const token = getState().authReducer.token
+ const token = getState().auth.token
const details = getState().saveSchematicReducer.details
const isSaved = getState().saveSchematicReducer.isSaved
@@ -107,7 +107,7 @@ export const saveSchematic = (title, description, xml, base64, scriptDump) => (d
// Action for Loading on-cloud saved schematics
export const fetchSchematic = (saveId) => (dispatch, getState) => {
// Get token from localstorage
- const token = getState().authReducer.token
+ const token = getState().auth.token
// add headers
const config = {
@@ -150,7 +150,7 @@ export const fetchDiagram = (saveId) => (dispatch) => {
export const setSchShared = (share) => (dispatch, getState) => {
// Get token from localstorage
- const token = getState().authReducer.token
+ const token = getState().auth.token
const details = getState().saveSchematicReducer.details
// add headers
diff --git a/blocks/eda-frontend/src/redux/authSlice.js b/blocks/eda-frontend/src/redux/authSlice.js
new file mode 100644
index 00000000..9af1fac6
--- /dev/null
+++ b/blocks/eda-frontend/src/redux/authSlice.js
@@ -0,0 +1,298 @@
+import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
+
+import api from '../utils/Api'
+
+const tokenKey = process.env.REACT_APP_NAME + '_token'
+
+const initialState = {
+ token: localStorage.getItem(tokenKey),
+ isAuthenticated: false,
+ isRegistered: false,
+ isLoading: false,
+ user: null,
+ errors: '',
+ regErrors: ''
+}
+
+// Api call for maintaining user login state throughout the application
+export const loadUser = createAsyncThunk(
+ 'auth/loadUser',
+ async (_, { getState, rejectWithValue }) => {
+ // Get token from localstorage
+ const token = getState().auth.token
+ if (!token) return rejectWithValue('No token found')
+
+ // add headers
+ const config = {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${token}`
+ }
+ }
+
+ try {
+ const res = await api.get('auth/users/me/', config)
+ if (res.status === 200) {
+ return res.data
+ }
+ return rejectWithValue(res.data || 'Failed to load user')
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return rejectWithValue(res?.data || 'Failed to load user')
+ }
+ })
+
+const loginError = (res, rejectWithValue) => {
+ if ([400, 401, 403].includes(res.status)) {
+ const data = res.data
+ const error = data.email?.[0] ??
+ data.password?.[0] ??
+ data.non_field_errors?.[0] ??
+ 'Incorrect Username or Password.'
+ return rejectWithValue(error)
+ }
+
+ console.error(res)
+ return rejectWithValue('Something went wrong! Login Failed')
+}
+
+// Handle api call for user login
+export const login = createAsyncThunk(
+ 'auth/login',
+ async ({ email, password, toUrl }, { dispatch, rejectWithValue }) => {
+ try {
+ const allowedUrls = [
+ '/editor'
+ ]
+ const res = await api.post('auth/token/login/', {
+ email,
+ password
+ })
+ if (res.status === 200) {
+ localStorage.setItem(tokenKey, res.data.auth_token)
+ if (toUrl === '') {
+ dispatch(loadUser())
+ } else if (!allowedUrls.includes(toUrl)) {
+ console.log('Not redirecting to', toUrl)
+ dispatch(loadUser())
+ } else {
+ window.open(toUrl, '_self')
+ }
+ return res.data.auth_token
+ }
+
+ return loginError(res, rejectWithValue)
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return loginError(res, rejectWithValue)
+ }
+ })
+
+const signupError = (res, rejectWithValue) => {
+ if ([400, 401, 403].includes(res.status)) {
+ const data = res.data
+ const error = data.email?.[0] ??
+ data.username?.[0] ??
+ data.password?.[0] ??
+ data.re_password?.[0] ??
+ data.non_field_errors?.[0] ??
+ 'Enter valid credentials.'
+ return rejectWithValue(error)
+ }
+
+ console.error(res)
+ return rejectWithValue('Something went wrong! Registration Failed')
+}
+
+// Handle api call for user sign up
+export const signUp = createAsyncThunk(
+ 'auth/signUp',
+ async ({ email, password, reenterPassword }, { rejectWithValue }) => {
+ try {
+ const res = await api.post('auth/users/', {
+ email,
+ username: email,
+ password,
+ re_password: reenterPassword
+ })
+ if (res.status === 200) {
+ return 'Successfully Signed Up! A verification link has been sent to your email account.'
+ }
+
+ return signupError(res, rejectWithValue)
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return signupError(res, rejectWithValue)
+ }
+ })
+
+// Handle api call for user logout
+export const logout = createAsyncThunk(
+ 'auth/logout',
+ async (history, { getState }) => {
+ try {
+ // Get token from localstorage
+ const token = getState().auth.token
+
+ // add headers
+ const config = {
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ }
+
+ // If token available add to headers
+ if (token) {
+ config.headers.Authorization = `Token ${token}`
+ }
+
+ await api.post('auth/token/logout/', {}, config)
+ localStorage.removeItem(tokenKey)
+ history.push('/login')
+ return 'Logout successful'
+ } catch (err) {
+ console.log(err)
+ return 'Logout successful'
+ }
+ })
+
+// Api call for Google oAuth login or sign up
+export const googleLogin = createAsyncThunk(
+ 'auth/googleLogin',
+ async (host, { rejectWithValue }) => {
+ try {
+ const res = await api.get('auth/o/google-oauth2/?redirect_uri=' + host + '/api/auth/google-callback')
+ if (res.status === 200) {
+ // Open google login page
+ window.open(res.data.authorization_url, '_self')
+ return res.data.authorization_url
+ }
+
+ return loginError(res, rejectWithValue)
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return loginError(res, rejectWithValue)
+ }
+ })
+
+// Api call for GitHub OAuth login or sign up
+export const githubLogin = createAsyncThunk(
+ 'auth/githubLogin',
+ async (host, { rejectWithValue }) => {
+ try {
+ const res = await api.get('auth/o/github/?redirect_uri=' + host + '/api/auth/github-callback')
+ if (res.status === 200) {
+ // Open GitHub login page
+ window.open(res.data.authorization_url, '_self')
+ return res.data.authorization_url
+ }
+
+ return loginError(res, rejectWithValue)
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return loginError(res, rejectWithValue)
+ }
+ })
+
+const authSlice = createSlice({
+ name: 'auth',
+ initialState,
+ reducers: {
+ authDefault: (state) => {
+ state.errors = ''
+ state.regErrors = ''
+ }
+ },
+ extraReducers: (builder) => {
+ builder
+ .addCase(loadUser.pending, (state) => {
+ state.isLoading = true
+ state.isAuthenticated = false
+ })
+ .addCase(loadUser.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.isAuthenticated = true
+ state.user = action.payload
+ })
+ .addCase(loadUser.rejected, (state) => {
+ state.isLoading = false
+ state.isAuthenticated = false
+ })
+ .addCase(login.pending, (state) => {
+ state.isLoading = true
+ state.isAuthenticated = false
+ })
+ .addCase(login.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.token = action.payload
+ state.errors = ''
+ })
+ .addCase(login.rejected, (state, action) => {
+ state.isLoading = false
+ state.token = null
+ state.user = null
+ state.isAuthenticated = false
+ state.errors = action.payload || 'Incorrect username or password.'
+ })
+ .addCase(googleLogin.pending, (state) => {
+ state.isLoading = true
+ state.isAuthenticated = false
+ })
+ .addCase(googleLogin.fulfilled, (state) => {
+ state.isLoading = false
+ })
+ .addCase(googleLogin.rejected, (state, action) => {
+ state.isLoading = false
+ state.token = null
+ state.user = null
+ state.isAuthenticated = false
+ state.errors = action.payload || 'Incorrect username or password.'
+ })
+ .addCase(githubLogin.pending, (state) => {
+ state.isLoading = true
+ state.isAuthenticated = false
+ })
+ .addCase(githubLogin.fulfilled, (state) => {
+ state.isLoading = false
+ })
+ .addCase(githubLogin.rejected, (state, action) => {
+ state.isLoading = false
+ state.token = null
+ state.user = null
+ state.isAuthenticated = false
+ state.errors = action.payload || 'Incorrect username or password.'
+ })
+ .addCase(signUp.pending, (state) => {
+ state.isLoading = true
+ state.isAuthenticated = false
+ })
+ .addCase(signUp.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.isRegistered = true
+ state.regErrors = action.payload
+ })
+ .addCase(signUp.rejected, (state, action) => {
+ state.isLoading = false
+ state.isRegistered = false
+ state.regErrors = action.payload
+ })
+ .addCase(logout.fulfilled, (state) => {
+ state.isLoading = false
+ state.token = null
+ state.user = null
+ state.isAuthenticated = false
+ state.errors = ''
+ })
+ }
+})
+
+export const {
+ authDefault
+} = authSlice.actions
+
+export default authSlice.reducer
diff --git a/blocks/eda-frontend/src/redux/reducers/authReducer.js b/blocks/eda-frontend/src/redux/reducers/authReducer.js
deleted file mode 100644
index 7c470617..00000000
--- a/blocks/eda-frontend/src/redux/reducers/authReducer.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import * as actions from '../actions/actions'
-
-const token = process.env.REACT_APP_NAME + '_token'
-const initialState = {
- token: localStorage.getItem(token),
- isAuthenticated: null,
- isRegistered: null,
- isLoading: false,
- user: null,
- errors: '',
- regErrors: ''
-}
-
-export default function authReducer (state = initialState, action) {
- switch (action.type) {
- case actions.USER_LOADING: {
- return {
- ...state,
- isLoading: true
- }
- }
-
- case actions.DEFAULT_STORE: {
- return {
- ...state,
- errors: '',
- regErrors: ''
- }
- }
-
- case actions.SIGNUP_SUCCESSFUL: {
- return {
- ...state,
- isRegistered: true,
- regErrors: action.payload.data
- }
- }
-
- case actions.SIGNUP_FAILED: {
- return {
- ...state,
- isRegistered: false,
- regErrors: action.payload.data
- }
- }
-
- case actions.USER_LOADED: {
- return {
- ...state,
- isAuthenticated: true,
- isLoading: false,
- user: action.payload.user
- }
- }
-
- case actions.LOGIN_SUCCESSFUL: {
- localStorage.setItem(token, action.payload.data.auth_token)
- return {
- ...state,
- token: action.payload.data.auth_token,
- // ...action.payload.data,
- // isAuthenticated: true,
- // isLoading: false,
- errors: ''
- }
- }
-
- case actions.LOADING_FAILED: {
- return {
- ...state,
- isLoading: false
- }
- }
-
- case actions.AUTHENTICATION_ERROR:
- case actions.LOGIN_FAILED:
- case actions.LOGOUT_SUCCESSFUL: {
- localStorage.removeItem(token)
- return {
- ...state,
- errors: action.payload.data,
- token: null,
- user: null,
- isAuthenticated: false,
- isLoading: false
- }
- }
-
- default:
- return state
- }
-}
diff --git a/blocks/eda-frontend/src/redux/reducers/index.js b/blocks/eda-frontend/src/redux/reducers/index.js
index 5827bdec..660caf78 100644
--- a/blocks/eda-frontend/src/redux/reducers/index.js
+++ b/blocks/eda-frontend/src/redux/reducers/index.js
@@ -2,14 +2,12 @@ import { combineReducers } from 'redux'
import schematicEditorReducer from './schematicEditorReducer'
import componentPropertiesReducer from './componentPropertiesReducer'
import netlistReducer from './netlistReducer'
-import authReducer from './authReducer'
import saveSchematicReducer from './saveSchematicReducer'
import dashboardReducer from './dashboardReducer'
export default combineReducers({
schematicEditorReducer,
componentPropertiesReducer,
netlistReducer,
- authReducer,
saveSchematicReducer,
dashboardReducer
})
diff --git a/blocks/eda-frontend/src/redux/store.js b/blocks/eda-frontend/src/redux/store.js
index 9e280bba..d2c2c9c8 100644
--- a/blocks/eda-frontend/src/redux/store.js
+++ b/blocks/eda-frontend/src/redux/store.js
@@ -1,8 +1,10 @@
import { configureStore } from '@reduxjs/toolkit'
+import authReducer from './authSlice'
import simulationReducer from './simulationSlice'
const store = configureStore({
reducer: {
+ auth: authReducer,
simulation: simulationReducer
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware()