Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
A
ajs12_shop
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Egor Kremnev
ajs12_shop
Commits
7c08e9a7
Commit
7c08e9a7
authored
May 15, 2023
by
Egor Kremnev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add logout user
parent
4b9e320f
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
232 additions
and
51 deletions
+232
-51
fixtures.js
api_client/fixtures.js
+67
-0
User.js
api_client/models/User.js
+9
-2
package.json
api_client/package.json
+2
-1
users.js
api_client/routes/users.js
+16
-0
App.js
front_client/src/App.js
+0
-1
AppToolbar.jsx
front_client/src/components/UI/AppToolbar/AppToolbar.jsx
+6
-37
AnonymousMenu.jsx
...nents/UI/AppToolbar/Menus/AnonymousMenu/AnonymousMenu.jsx
+12
-0
UserMenu.jsx
.../src/components/UI/AppToolbar/Menus/UserMenu/UserMenu.jsx
+47
-0
index.js
front_client/src/index.js
+21
-1
usersActions.js
front_client/src/store/actions/usersActions.js
+25
-7
usersSlice.js
front_client/src/store/services/usersSlice.js
+27
-2
No files found.
api_client/fixtures.js
0 → 100644
View file @
7c08e9a7
const
mongoose
=
require
(
'mongoose'
);
const
config
=
require
(
'./config'
).
db
;
const
Category
=
require
(
'./models/Category'
);
const
Product
=
require
(
'./models/Product'
);
const
User
=
require
(
'./models/User'
);
mongoose
.
connect
(
config
.
host
+
'/'
+
config
.
database
);
const
db
=
mongoose
.
connection
;
db
.
once
(
'open'
,
async
()
=>
{
try
{
await
db
.
dropCollection
(
'categories'
);
await
db
.
dropCollection
(
'products'
);
await
db
.
dropCollection
(
'users'
);
}
catch
(
e
)
{
console
.
log
(
'Collections were not present, skipping drop...'
);
}
const
[
cpuCategory
,
hddCategory
,
monitorCategory
]
=
await
Category
.
create
([
{
title
:
"CPU's"
,
description
:
"Central processor units"
,
},
{
title
:
"HDDs"
,
description
:
"Hard disk drives"
,
},
{
title
:
"Monitors"
,
description
:
"Monitors for office and home"
,
}
]);
await
Product
.
create
([
{
title
:
"Ryzen 7"
,
category
:
cpuCategory
.
_id
,
price
:
300
},
{
title
:
"HDD seagate 1TB"
,
category
:
hddCategory
.
_id
,
price
:
200
},
{
title
:
"Lenovo Legion 7"
,
category
:
monitorCategory
.
_id
,
price
:
150
},
]);
await
User
.
create
([
{
username
:
"user"
,
password
:
"qwerty"
,
token
:
null
},
{
username
:
"admin"
,
password
:
"qwerty"
,
token
:
null
}
]);
db
.
close
();
});
api_client/models/User.js
View file @
7c08e9a7
...
...
@@ -12,7 +12,6 @@ const UserSchema = new Schema({
username
:
{
type
:
String
,
required
:
true
,
unique
:
true
,
validate
:
{
validator
:
async
function
(
username
)
{
const
user
=
await
User
.
findOne
({
username
});
...
...
@@ -24,7 +23,15 @@ const UserSchema = new Schema({
token
:
{
type
:
String
,
required
:
false
,
unique
:
true
validate
:
{
validator
:
async
function
(
token
)
{
if
(
!
token
)
return
true
;
const
user
=
await
User
.
findOne
({
token
});
return
!
user
||
user
.
_id
!==
this
.
_id
;
},
message
:
"Token duplicated"
}
}
});
...
...
api_client/package.json
View file @
7c08e9a7
...
...
@@ -6,7 +6,8 @@
"scripts"
:
{
"test"
:
"echo
\"
Error: no test specified
\"
&& exit 1"
,
"start"
:
"node index.js"
,
"dev"
:
"nodemon index.js"
"dev"
:
"nodemon index.js"
,
"fixture"
:
"node fixtures.js"
},
"keywords"
:
[],
"author"
:
""
,
...
...
api_client/routes/users.js
View file @
7c08e9a7
...
...
@@ -56,4 +56,20 @@ router.get('/profile', async (req, res) => {
});
});
router
.
delete
(
'/logout'
,
async
(
req
,
res
)
=>
{
const
token
=
req
.
get
(
'Authorization'
);
const
success
=
{
message
:
'Success'
};
if
(
!
token
)
return
res
.
send
(
success
);
const
user
=
await
User
.
findOne
({
token
});
if
(
!
user
)
return
res
.
send
(
success
);
user
.
token
=
null
;
user
.
save
();
res
.
send
(
success
);
});
module
.
exports
=
router
;
front_client/src/App.js
View file @
7c08e9a7
...
...
@@ -8,7 +8,6 @@ import Register from "./containers/Auth/Register/Register";
import
Login
from
"./containers/Auth/Login/Login"
;
import
{
useSelector
}
from
"react-redux"
;
import
ProtectedRoute
from
"./components/ProtectedRoute/ProtectedRoute"
;
import
axiosApi
from
"./api/axiosApi"
;
const
App
=
()
=>
{
const
user
=
useSelector
(({
usersState
})
=>
usersState
.
user
);
...
...
front_client/src/components/UI/AppToolbar/AppToolbar.jsx
View file @
7c08e9a7
import
{
AppBar
,
Box
,
Toolbar
,
Typography
,
Button
,
IconButton
,
Menu
,
MenuItem
}
from
'@mui/material'
;
import
{
AppBar
,
Box
,
Toolbar
,
Typography
,
IconButton
}
from
'@mui/material'
;
import
HomeIcon
from
'@mui/icons-material/Home'
;
import
{
NavLink
}
from
"react-router-dom"
;
import
{
MAIN
,
REGISTER
,
LOGIN
}
from
"../../../constants/routes"
;
import
{
MAIN
}
from
"../../../constants/routes"
;
import
{
useSelector
}
from
"react-redux"
;
import
{
useState
}
from
'react'
;
import
UserMenu
from
"./Menus/UserMenu/UserMenu"
;
import
AnonymousMenu
from
"./Menus/AnonymousMenu/AnonymousMenu"
;
const
AppToolbar
=
()
=>
{
const
user
=
useSelector
(({
usersState
})
=>
usersState
.
user
);
const
[
anchorEl
,
setAnchorEl
]
=
useState
(
null
);
const
handleClick
=
e
=>
{
setAnchorEl
(
e
.
currentTarget
);
};
const
handleClose
=
()
=>
{
setAnchorEl
(
null
);
};
return
(
<
Box
sx=
{
{
flexGrow
:
1
}
}
>
<
AppBar
position=
"static"
>
...
...
@@ -38,30 +29,8 @@ const AppToolbar = () => {
</
Typography
>
{
user
?
<>
<
Button
aria
-
controls=
"simple-menu"
aria
-
haspopup=
{
true
}
onClick=
{
handleClick
}
color=
"inherit"
>
Hello,
{
user
.
username
}
</
Button
>
<
Menu
open=
{
!!
anchorEl
}
anchorEl=
{
anchorEl
}
onClose=
{
handleClose
}
keepMounted
>
<
MenuItem
>
Profile
</
MenuItem
>
<
MenuItem
>
My account
</
MenuItem
>
<
MenuItem
>
Logout
</
MenuItem
>
</
Menu
>
</>
:
<>
<
Button
color=
"inherit"
component=
{
NavLink
}
to=
{
REGISTER
}
>
Sign up
</
Button
>
<
Button
color=
"inherit"
component=
{
NavLink
}
to=
{
LOGIN
}
>
Sign In
</
Button
>
</>
?
<
UserMenu
user=
{
user
}
/>
:
<
AnonymousMenu
/>
}
</
Toolbar
>
</
AppBar
>
...
...
front_client/src/components/UI/AppToolbar/Menus/AnonymousMenu/AnonymousMenu.jsx
0 → 100644
View file @
7c08e9a7
import
{
NavLink
}
from
"react-router-dom"
;
import
{
LOGIN
,
REGISTER
}
from
"../../../../../constants/routes"
;
import
{
Button
}
from
'@mui/material'
;
const
AnonymousMenu
=
()
=>
{
return
<>
<
Button
color=
"inherit"
component=
{
NavLink
}
to=
{
REGISTER
}
>
Sign up
</
Button
>
<
Button
color=
"inherit"
component=
{
NavLink
}
to=
{
LOGIN
}
>
Sign In
</
Button
>
</>;
};
export
default
AnonymousMenu
;
front_client/src/components/UI/AppToolbar/Menus/UserMenu/UserMenu.jsx
0 → 100644
View file @
7c08e9a7
import
{
useState
}
from
"react"
;
import
{
Button
,
Menu
,
MenuItem
}
from
'@mui/material'
;
import
{
useDispatch
}
from
"react-redux"
;
import
{
logoutUser
}
from
"../../../../../store/actions/usersActions"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
MAIN
}
from
"../../../../../constants/routes"
;
const
UserMenu
=
({
user
})
=>
{
const
navigate
=
useNavigate
();
const
dispatch
=
useDispatch
();
const
[
anchorEl
,
setAnchorEl
]
=
useState
(
null
);
const
handleClick
=
e
=>
{
setAnchorEl
(
e
.
currentTarget
);
};
const
handleClose
=
()
=>
{
setAnchorEl
(
null
);
};
return
<>
<
Button
aria
-
controls=
"simple-menu"
aria
-
haspopup=
{
true
}
onClick=
{
handleClick
}
color=
"inherit"
>
Hello,
{
user
.
username
}
</
Button
>
<
Menu
open=
{
!!
anchorEl
}
anchorEl=
{
anchorEl
}
onClose=
{
handleClose
}
keepMounted
>
<
MenuItem
>
Profile
</
MenuItem
>
<
MenuItem
>
My account
</
MenuItem
>
<
MenuItem
onClick=
{
()
=>
dispatch
(
logoutUser
({
callback
:
()
=>
navigate
(
MAIN
)}))
}
>
Logout
</
MenuItem
>
</
Menu
>
</>;
};
export
default
UserMenu
;
front_client/src/index.js
View file @
7c08e9a7
...
...
@@ -9,11 +9,31 @@ import productsReducer from './store/services/productsSlice';
import
usersReducer
from
'./store/services/usersSlice'
;
import
{
BrowserRouter
}
from
"react-router-dom"
;
const
localStorageMiddleware
=
({
getState
})
=>
next
=>
action
=>
{
const
result
=
next
(
action
);
localStorage
.
setItem
(
'user'
,
JSON
.
stringify
(
getState
().
usersState
.
user
));
return
result
;
};
const
reHydrateStore
=
()
=>
{
if
(
localStorage
.
getItem
(
'user'
)
!==
null
)
{
return
{
usersState
:
{
user
:
JSON
.
parse
(
localStorage
.
getItem
(
'user'
))
}
};
}
return
undefined
;
};
const
store
=
configureStore
({
reducer
:
{
usersState
:
usersReducer
,
productsState
:
productsReducer
}
},
preloadedState
:
reHydrateStore
(),
middleware
:
getDefaultMiddleware
=>
getDefaultMiddleware
().
concat
(
localStorageMiddleware
)
});
const
root
=
ReactDOM
.
createRoot
(
document
.
getElementById
(
'root'
));
...
...
front_client/src/store/actions/usersActions.js
View file @
7c08e9a7
import
{
createAsyncThunk
}
from
"@reduxjs/toolkit"
;
import
axiosApi
from
"../../api/axiosApi"
;
import
{
setLoginError
,
setRegisterError
,
setUser
}
from
"../services/usersSlice"
;
import
{
setLoginError
,
setRegisterError
,
setUser
,
setLogoutError
}
from
"../services/usersSlice"
;
export
const
registerUser
=
createAsyncThunk
(
'users/register'
,
async
(
payload
,
{
dispatch
})
=>
await
axiosApi
.
post
(
'/users'
,
payload
.
data
)
.
then
(
res
=>
payload
.
callback
())
async
(
{
data
,
callback
}
,
{
dispatch
})
=>
await
axiosApi
.
post
(
'/users'
,
data
)
.
then
(
res
=>
callback
())
.
catch
(
e
=>
{
if
(
e
?.
response
?.
data
)
dispatch
(
setRegisterError
(
e
.
response
.
data
));
else
dispatch
(
setRegisterError
(
e
));
...
...
@@ -16,11 +16,11 @@ export const registerUser = createAsyncThunk(
export
const
loginUser
=
createAsyncThunk
(
'users/login'
,
async
(
payload
,
{
dispatch
,
getState
})
=>
await
axiosApi
.
post
(
'/users/login'
,
payload
.
data
)
async
(
{
data
,
callback
}
,
{
dispatch
,
getState
})
=>
await
axiosApi
.
post
(
'/users/login'
,
data
)
.
then
(
res
=>
{
dispatch
(
setUser
(
res
.
data
));
payload
.
callback
();
callback
();
})
.
catch
(
e
=>
{
if
(
e
?.
response
?.
data
)
dispatch
(
setLoginError
(
e
.
response
.
data
));
...
...
@@ -28,3 +28,21 @@ export const loginUser = createAsyncThunk(
throw
e
;
})
);
export
const
logoutUser
=
createAsyncThunk
(
'users/logout'
,
async
(
payload
,
{
dispatch
,
getState
})
=>
await
axiosApi
.
delete
(
'/users/logout'
,
{
headers
:
{
Authorization
:
getState
().
usersState
.
user
.
token
}}
)
.
then
(
res
=>
{
dispatch
(
setUser
(
null
));
payload
.
callback
();
})
.
catch
(
e
=>
{
if
(
e
?.
response
?.
data
)
dispatch
(
setLogoutError
(
e
.
response
.
data
));
else
dispatch
(
setLogoutError
(
e
));
throw
e
;
})
);
front_client/src/store/services/usersSlice.js
View file @
7c08e9a7
import
{
createSlice
}
from
"@reduxjs/toolkit"
;
import
{
loginUser
,
registerUser
}
from
"../actions/usersActions"
;
import
{
loginUser
,
logoutUser
,
registerUser
}
from
"../actions/usersActions"
;
const
initialState
=
{
loginError
:
null
,
logoutError
:
null
,
registerError
:
null
,
loading
:
false
,
user
:
null
...
...
@@ -18,6 +19,9 @@ const usersSlice = createSlice({
setRegisterError
:
(
state
,
action
)
=>
{
state
.
registerError
=
action
.
payload
;
},
setLogoutError
:
(
state
,
action
)
=>
{
state
.
logoutError
=
action
.
payload
;
},
setUser
:
(
state
,
action
)
=>
{
state
.
user
=
action
.
payload
;
}
...
...
@@ -66,8 +70,29 @@ const usersSlice = createSlice({
state
.
loading
=
false
;
}
);
builder
.
addCase
(
logoutUser
.
pending
,
state
=>
{
state
.
logoutError
=
null
;
state
.
loading
=
true
;
}
)
.
addCase
(
logoutUser
.
rejected
,
state
=>
{
state
.
loading
=
false
;
}
)
.
addCase
(
logoutUser
.
fulfilled
,
state
=>
{
state
.
loading
=
false
;
}
);
}
});
export
const
{
setLoginError
,
setRegisterError
,
setUser
}
=
usersSlice
.
actions
;
export
const
{
setLoginError
,
setRegisterError
,
setUser
,
setLogoutError
}
=
usersSlice
.
actions
;
export
default
usersSlice
.
reducer
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment