Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
I
initial_project
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
Нұрасыл Қайратұлы
initial_project
Commits
6dc7ef41
Commit
6dc7ef41
authored
Aug 26, 2024
by
Нұрасыл Қайратұлы
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix
parent
f54153c9
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
94 additions
and
20 deletions
+94
-20
NewProductForm.tsx
client/src/containers/NewProductForm.tsx
+8
-1
Products.tsx
client/src/containers/Products.tsx
+10
-5
productsSlice.ts
client/src/features/productsSlice.ts
+4
-2
usersSlice.ts
client/src/features/usersSlice.ts
+6
-0
user.controller.ts
server/src/controllers/user.controller.ts
+1
-1
main.seeds.ts
server/src/database/seeds/main.seeds.ts
+0
-1
user.entity.ts
server/src/entities/user.entity.ts
+4
-0
IRequest.interface.ts
server/src/interfaces/IRequest.interface.ts
+6
-0
IUser.interface.ts
server/src/interfaces/IUser.interface.ts
+6
-0
auth.middleware.ts
server/src/middlewares/auth.middleware.ts
+20
-0
checkRole.ts
server/src/middlewares/checkRole.ts
+14
-0
article.route.ts
server/src/routes/article.route.ts
+5
-3
category.route.ts
server/src/routes/category.route.ts
+5
-3
product.route.ts
server/src/routes/product.route.ts
+5
-3
user.route.ts
server/src/routes/user.route.ts
+0
-1
No files found.
client/src/containers/NewProductForm.tsx
View file @
6dc7ef41
import
{
ProductForm
}
from
"@/components/ProductForm"
;
import
{
ProductForm
}
from
"@/components/ProductForm"
;
import
{
createProduct
}
from
"@/features/productsSlice"
;
import
{
createProduct
}
from
"@/features/productsSlice"
;
import
{
useAppDispatch
}
from
"@/store/hook"
;
import
{
UserRoles
}
from
"@/features/usersSlice"
;
import
{
useAppDispatch
,
useAppSelector
}
from
"@/store/hook"
;
import
{
Typography
}
from
"@mui/material"
;
import
{
Typography
}
from
"@mui/material"
;
import
{
useEffect
}
from
"react"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
useNavigate
}
from
"react-router-dom"
;
export
function
NewProductForm
()
{
export
function
NewProductForm
()
{
const
dispatch
=
useAppDispatch
();
const
dispatch
=
useAppDispatch
();
const
navigate
=
useNavigate
();
const
navigate
=
useNavigate
();
const
{
user
}
=
useAppSelector
(
state
=>
state
.
users
)
const
onProductFormSubmit
=
async
(
product
:
Omit
<
FormData
,
"id"
>
)
=>
{
const
onProductFormSubmit
=
async
(
product
:
Omit
<
FormData
,
"id"
>
)
=>
{
await
dispatch
(
createProduct
(
product
));
await
dispatch
(
createProduct
(
product
));
navigate
(
"/"
);
navigate
(
"/"
);
}
}
// useEffect(() => {
// if(user?.role !== UserRoles.admin) navigate('/')
// }, [user])
return
<>
return
<>
<
Typography
variant=
"h4"
>
New product
</
Typography
>
<
Typography
variant=
"h4"
>
New product
</
Typography
>
<
ProductForm
onProductFormSubmit=
{
onProductFormSubmit
}
/>
<
ProductForm
onProductFormSubmit=
{
onProductFormSubmit
}
/>
...
...
client/src/containers/Products.tsx
View file @
6dc7ef41
...
@@ -4,9 +4,11 @@ import { Button, Grid, Typography } from '@mui/material';
...
@@ -4,9 +4,11 @@ import { Button, Grid, Typography } from '@mui/material';
import
{
useEffect
}
from
'react'
;
import
{
useEffect
}
from
'react'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
ProductItem
}
from
'./ProductItem'
;
import
{
ProductItem
}
from
'./ProductItem'
;
import
{
UserRoles
}
from
'@/features/usersSlice'
;
export
function
Products
()
{
export
function
Products
()
{
const
dispatch
=
useAppDispatch
();
const
dispatch
=
useAppDispatch
();
const
{
user
}
=
useAppSelector
((
state
)
=>
state
.
users
);
const
{
products
}
=
useAppSelector
((
state
)
=>
state
.
products
);
const
{
products
}
=
useAppSelector
((
state
)
=>
state
.
products
);
useEffect
(()
=>
{
useEffect
(()
=>
{
...
@@ -27,11 +29,14 @@ export function Products() {
...
@@ -27,11 +29,14 @@ export function Products() {
))
}
))
}
</
Grid
>
</
Grid
>
<
Grid
item
>
{
<
Button
color=
"primary"
component=
{
Link
}
to=
{
'/products/new'
}
>
user
?.
role
!==
UserRoles
.
admin
&&
Add product
<
Grid
item
>
</
Button
>
<
Button
color=
"primary"
component=
{
Link
}
to=
{
'/products/new'
}
>
</
Grid
>
Add product
</
Button
>
</
Grid
>
}
</
Grid
>
</
Grid
>
);
);
}
}
...
...
client/src/features/productsSlice.ts
View file @
6dc7ef41
...
@@ -25,12 +25,14 @@ const initialState: State = {
...
@@ -25,12 +25,14 @@ const initialState: State = {
};
};
export
const
fetchProducts
=
createAsyncThunk
(
'fetch/products'
,
async
()
=>
{
export
const
fetchProducts
=
createAsyncThunk
(
'fetch/products'
,
async
()
=>
{
return
await
axiosApiClient
.
get
<
IProductState
[]
>
(
'/products'
).
then
(
res
=>
res
.
data
);
const
token
=
localStorage
.
getItem
(
'token'
)
return
await
axiosApiClient
.
get
<
IProductState
[]
>
(
'/products'
,
{
headers
:
{
Authorization
:
token
}}).
then
(
res
=>
res
.
data
);
});
});
export
const
createProduct
=
createAsyncThunk
(
'create/product'
,
export
const
createProduct
=
createAsyncThunk
(
'create/product'
,
async
(
payload
:
Omit
<
FormData
,
"id"
>
)
=>
{
async
(
payload
:
Omit
<
FormData
,
"id"
>
)
=>
{
return
axiosApiClient
.
post
<
IProduct
>
(
"/products/create"
,
payload
)
const
token
=
localStorage
.
getItem
(
'token'
)
return
axiosApiClient
.
post
<
IProduct
>
(
"/products/create"
,
payload
,
{
headers
:
{
Authorization
:
token
}})
.
then
(
res
=>
res
.
data
);
.
then
(
res
=>
res
.
data
);
});
});
...
...
client/src/features/usersSlice.ts
View file @
6dc7ef41
...
@@ -13,6 +13,12 @@ export interface IUserState {
...
@@ -13,6 +13,12 @@ export interface IUserState {
username
:
string
;
username
:
string
;
displayName
:
string
;
displayName
:
string
;
token
:
string
;
token
:
string
;
role
:
UserRoles
}
export
enum
UserRoles
{
user
=
'user'
,
admin
=
'admin'
}
}
interface
State
{
interface
State
{
...
...
server/src/controllers/user.controller.ts
View file @
6dc7ef41
...
@@ -12,7 +12,7 @@ export class UserController {
...
@@ -12,7 +12,7 @@ export class UserController {
this
.
service
=
new
UserService
();
this
.
service
=
new
UserService
();
}
}
signIn
:
RequestHandler
=
async
(
req
,
res
):
Promise
<
void
>
=>
{
signIn
:
RequestHandler
=
async
(
req
,
res
):
Promise
<
void
>
=>
{
try
{
try
{
const
signInDto
=
plainToInstance
(
SignInUserDto
,
req
.
body
)
const
signInDto
=
plainToInstance
(
SignInUserDto
,
req
.
body
)
const
user
=
await
this
.
service
.
signIn
(
signInDto
)
const
user
=
await
this
.
service
.
signIn
(
signInDto
)
...
...
server/src/database/seeds/main.seeds.ts
View file @
6dc7ef41
...
@@ -4,7 +4,6 @@ import { Product } from "@/entities/product.entity";
...
@@ -4,7 +4,6 @@ import { Product } from "@/entities/product.entity";
import
{
DataSource
}
from
"typeorm"
;
import
{
DataSource
}
from
"typeorm"
;
import
{
faker
}
from
'@faker-js/faker'
;
import
{
faker
}
from
'@faker-js/faker'
;
import
{
Seeder
,
SeederFactoryManager
}
from
"typeorm-extension"
;
import
{
Seeder
,
SeederFactoryManager
}
from
"typeorm-extension"
;
export
default
class
MainSeeder
implements
Seeder
{
export
default
class
MainSeeder
implements
Seeder
{
public
async
run
(
dataSource
:
DataSource
,
factoryManager
:
SeederFactoryManager
):
Promise
<
any
>
{
public
async
run
(
dataSource
:
DataSource
,
factoryManager
:
SeederFactoryManager
):
Promise
<
any
>
{
const
userFactory
=
factoryManager
.
get
(
User
)
const
userFactory
=
factoryManager
.
get
(
User
)
...
...
server/src/entities/user.entity.ts
View file @
6dc7ef41
import
{
Entity
,
PrimaryGeneratedColumn
,
Column
,
Unique
}
from
"typeorm"
;
import
{
Entity
,
PrimaryGeneratedColumn
,
Column
,
Unique
}
from
"typeorm"
;
import
bcrypt
from
'bcrypt'
;
import
bcrypt
from
'bcrypt'
;
import
{
UserRoles
}
from
"@/interfaces/IUser.interface"
;
const
SALT_WORK_FACTOR
=
10
;
const
SALT_WORK_FACTOR
=
10
;
@
Entity
()
@
Entity
()
...
@@ -20,6 +21,9 @@ export class User {
...
@@ -20,6 +21,9 @@ export class User {
@
Column
({
nullable
:
true
})
@
Column
({
nullable
:
true
})
displayName
!
:
string
displayName
!
:
string
@
Column
({
default
:
UserRoles
.
user
})
role
!
:
string
async
comparePassword
(
password
:
string
):
Promise
<
boolean
>
{
async
comparePassword
(
password
:
string
):
Promise
<
boolean
>
{
return
await
bcrypt
.
compare
(
password
,
this
.
password
);
return
await
bcrypt
.
compare
(
password
,
this
.
password
);
}
}
...
...
server/src/interfaces/IRequest.interface.ts
0 → 100644
View file @
6dc7ef41
import
{
Request
}
from
'express'
;
import
{
IUser
}
from
'./IUser.interface'
;
export
interface
RequestWithUser
extends
Request
{
user
?:
IUser
;
}
\ No newline at end of file
server/src/interfaces/IUser.interface.ts
View file @
6dc7ef41
...
@@ -3,4 +3,10 @@ export interface IUser {
...
@@ -3,4 +3,10 @@ export interface IUser {
username
:
string
username
:
string
password
?:
string
password
?:
string
displayName
?:
string
displayName
?:
string
role
:
string
}
export
enum
UserRoles
{
user
=
'user'
,
admin
=
'admin'
}
}
\ No newline at end of file
server/src/middlewares/auth.middleware.ts
0 → 100644
View file @
6dc7ef41
import
{
RequestHandler
}
from
"express"
;
import
{
UserService
}
from
"@/services/user.service"
;
import
{
RequestWithUser
}
from
"@/interfaces/IRequest.interface"
;
const
userService
=
new
UserService
()
export
const
authValidate
:
RequestHandler
=
async
(
req
:
RequestWithUser
,
res
,
next
):
Promise
<
any
>
=>
{
try
{
const
token
=
req
.
header
(
'Authorization'
)
if
(
!
token
)
return
res
.
status
(
401
).
send
({
message
:
'Invalide Token'
})
const
user
=
await
userService
.
validateToken
(
token
)
if
(
!
user
)
return
res
.
status
(
401
).
send
({
message
:
'User Not Found'
})
req
.
user
=
user
next
()
}
catch
(
e
)
{
return
res
.
status
(
500
).
send
({
message
:
'Internal error'
})
}
}
\ No newline at end of file
server/src/middlewares/checkRole.ts
0 → 100644
View file @
6dc7ef41
import
{
RequestWithUser
}
from
"@/interfaces/IRequest.interface"
;
import
{
Response
,
NextFunction
}
from
"express"
;
export
function
checkRole
(...
allowedRoles
:
string
[])
{
return
(
req
:
RequestWithUser
,
res
:
Response
,
next
:
NextFunction
)
=>
{
const
user
=
req
.
user
if
(
user
&&
allowedRoles
.
includes
(
user
.
role
))
{
next
()
}
else
{
res
.
status
(
403
).
send
({
error
:
'Permission denied'
})
}
}
}
\ No newline at end of file
server/src/routes/article.route.ts
View file @
6dc7ef41
import
{
Router
}
from
'express'
;
import
{
Router
}
from
'express'
;
import
{
ArticleController
}
from
'../controllers/article.controller'
;
import
{
ArticleController
}
from
'../controllers/article.controller'
;
import
{
IRoute
}
from
'../interfaces/IRoute.interface'
;
import
{
IRoute
}
from
'../interfaces/IRoute.interface'
;
import
{
authValidate
}
from
'@/middlewares/auth.middleware'
;
import
{
checkRole
}
from
'@/middlewares/checkRole'
;
export
class
ArticleRoute
implements
IRoute
{
export
class
ArticleRoute
implements
IRoute
{
public
path
=
'/articles'
;
public
path
=
'/articles'
;
...
@@ -13,8 +15,8 @@ export class ArticleRoute implements IRoute {
...
@@ -13,8 +15,8 @@ export class ArticleRoute implements IRoute {
}
}
private
init
()
{
private
init
()
{
this
.
router
.
get
(
'/'
,
this
.
controller
.
getAllArticles
);
this
.
router
.
get
(
'/'
,
authValidate
,
this
.
controller
.
getAllArticles
);
this
.
router
.
get
(
'/:id'
,
this
.
controller
.
getArticle
);
this
.
router
.
get
(
'/:id'
,
authValidate
,
this
.
controller
.
getArticle
);
this
.
router
.
post
(
'/create'
,
this
.
controller
.
createArticle
);
this
.
router
.
post
(
'/create'
,
authValidate
,
checkRole
(
'admin'
),
this
.
controller
.
createArticle
);
}
}
}
}
server/src/routes/category.route.ts
View file @
6dc7ef41
import
{
CategoryController
}
from
'@/controllers/category.controller'
;
import
{
CategoryController
}
from
'@/controllers/category.controller'
;
import
{
authValidate
}
from
'@/middlewares/auth.middleware'
;
import
{
checkRole
}
from
'@/middlewares/checkRole'
;
import
{
Router
}
from
'express'
;
import
{
Router
}
from
'express'
;
export
class
CategoryRoute
{
export
class
CategoryRoute
{
...
@@ -12,8 +14,8 @@ export class CategoryRoute {
...
@@ -12,8 +14,8 @@ export class CategoryRoute {
}
}
private
init
()
{
private
init
()
{
this
.
router
.
get
(
'/'
,
this
.
controller
.
getAllCategories
);
this
.
router
.
get
(
'/'
,
authValidate
,
this
.
controller
.
getAllCategories
);
this
.
router
.
get
(
'/:id'
,
this
.
controller
.
getCategory
);
this
.
router
.
get
(
'/:id'
,
authValidate
,
this
.
controller
.
getCategory
);
this
.
router
.
post
(
'/create'
,
this
.
controller
.
createCategory
);
this
.
router
.
post
(
'/create'
,
authValidate
,
checkRole
(
'admin'
),
this
.
controller
.
createCategory
);
}
}
}
}
server/src/routes/product.route.ts
View file @
6dc7ef41
import
{
ProductController
}
from
'@/controllers/product.controller'
;
import
{
ProductController
}
from
'@/controllers/product.controller'
;
import
{
authValidate
}
from
'@/middlewares/auth.middleware'
;
import
{
checkRole
}
from
'@/middlewares/checkRole'
;
import
upload
from
'@/middlewares/storage'
;
import
upload
from
'@/middlewares/storage'
;
import
{
Router
}
from
'express'
;
import
{
Router
}
from
'express'
;
...
@@ -13,8 +15,8 @@ export class ProductRoute {
...
@@ -13,8 +15,8 @@ export class ProductRoute {
}
}
private
init
()
{
private
init
()
{
this
.
router
.
get
(
'/'
,
this
.
controller
.
getAllProducts
);
this
.
router
.
get
(
'/'
,
authValidate
,
this
.
controller
.
getAllProducts
);
this
.
router
.
get
(
'/:id'
,
this
.
controller
.
getProduct
);
this
.
router
.
get
(
'/:id'
,
authValidate
,
this
.
controller
.
getProduct
);
this
.
router
.
post
(
'/create'
,
upload
.
single
(
'image'
)
,
this
.
controller
.
createProduct
);
this
.
router
.
post
(
'/create'
,
authValidate
,
checkRole
(
'admin'
),
upload
.
single
(
'image'
)
,
this
.
controller
.
createProduct
);
}
}
}
}
server/src/routes/user.route.ts
View file @
6dc7ef41
import
{
Router
}
from
'express'
;
import
{
Router
}
from
'express'
;
import
{
IRoute
}
from
'../interfaces/IRoute.interface'
;
import
{
IRoute
}
from
'../interfaces/IRoute.interface'
;
import
{
UserController
}
from
'@/controllers/user.controller'
;
import
{
UserController
}
from
'@/controllers/user.controller'
;
export
class
UserRoute
implements
IRoute
{
export
class
UserRoute
implements
IRoute
{
public
path
=
'/user'
;
public
path
=
'/user'
;
public
router
=
Router
();
public
router
=
Router
();
...
...
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