diff --git a/package-lock.json b/package-lock.json
index 10d1bc6..d98ebc9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -27,11 +27,13 @@
"@types/react": "^18.0.18",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
+ "axios": "^1.3.4",
"craco": "^0.0.3",
"dayjs": "^1.11.5",
"formik": "^2.2.9",
"moment": "^2.29.4",
"nanoid": "^4.0.1",
+ "notistack": "^3.0.1",
"numeral": "^2.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
@@ -6217,6 +6219,29 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
+ "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+ "dependencies": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/axios/node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -11767,6 +11792,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/goober": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.12.tgz",
+ "integrity": "sha512-yXHAvO08FU1JgTXX6Zn6sYCUFfB/OJSX8HHjDSgerZHZmFKAb08cykp5LBw5QnmyMcZyPRMqkdyHUSSzge788Q==",
+ "peerDependencies": {
+ "csstype": "^3.0.10"
+ }
+ },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -15225,6 +15258,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/notistack": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.1.tgz",
+ "integrity": "sha512-ntVZXXgSQH5WYfyU+3HfcXuKaapzAJ8fBLQ/G618rn3yvSzEbnOB8ZSOwhX+dAORy/lw+GC2N061JA0+gYWTVA==",
+ "dependencies": {
+ "clsx": "^1.1.0",
+ "goober": "^2.0.33"
+ },
+ "engines": {
+ "node": ">=12.0.0",
+ "npm": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/notistack"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -17482,6 +17536,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
@@ -26416,6 +26475,28 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz",
"integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg=="
},
+ "axios": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
+ "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
+ "requires": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ },
+ "dependencies": {
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
+ }
+ },
"axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -30511,6 +30592,12 @@
"slash": "^3.0.0"
}
},
+ "goober": {
+ "version": "2.1.12",
+ "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.12.tgz",
+ "integrity": "sha512-yXHAvO08FU1JgTXX6Zn6sYCUFfB/OJSX8HHjDSgerZHZmFKAb08cykp5LBw5QnmyMcZyPRMqkdyHUSSzge788Q==",
+ "requires": {}
+ },
"gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -32979,6 +33066,15 @@
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="
},
+ "notistack": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.1.tgz",
+ "integrity": "sha512-ntVZXXgSQH5WYfyU+3HfcXuKaapzAJ8fBLQ/G618rn3yvSzEbnOB8ZSOwhX+dAORy/lw+GC2N061JA0+gYWTVA==",
+ "requires": {
+ "clsx": "^1.1.0",
+ "goober": "^2.0.33"
+ }
+ },
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -34351,6 +34447,11 @@
}
}
},
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"prr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
diff --git a/package.json b/package.json
index 31a1361..cf77475 100644
--- a/package.json
+++ b/package.json
@@ -22,11 +22,13 @@
"@types/react": "^18.0.18",
"@types/react-dom": "^18.0.6",
"@types/react-router-dom": "^5.3.3",
+ "axios": "^1.3.4",
"craco": "^0.0.3",
"dayjs": "^1.11.5",
"formik": "^2.2.9",
"moment": "^2.29.4",
"nanoid": "^4.0.1",
+ "notistack": "^3.0.1",
"numeral": "^2.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/src/index.tsx b/src/index.tsx
index bd406da..6efa6e9 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,8 +1,9 @@
import * as React from "react";
import CssBaseline from "@mui/material/CssBaseline";
+import { SnackbarProvider } from 'notistack';
import { ThemeProvider } from '@mui/material/styles';
import { createRoot } from 'react-dom/client';
-import { BrowserRouter, Routes, Route } from "react-router-dom";
+import { BrowserRouter, Routes, Route, Outlet, Navigate } from "react-router-dom";
import theme from "./theme";
import PublicRoute from "@kitUI/publicRoute";
import PrivateRoute from "@kitUI/privateRoute";
@@ -10,7 +11,7 @@ import Signin from "@pages/Authorization/signin";
import Signup from "@pages/Authorization/signup";
import Restore from "@pages/Authorization/restore";
import Sections from "@pages/Sections";
-import LoggedIn from "@pages/dashboard";
+import Dashboard from "@pages/dashboard";
import Error404 from "@pages/Error404";
import Users from "@pages/dashboard/Content/Users";
import Entities from "@pages/dashboard/Content/Entities";
@@ -34,23 +35,27 @@ root.render(
-
-
- } />
- } />
- } />
- } />
- } />
- {componentsArray.map((e:any, i) => (
- {e[1]} } />
- ))}
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ }>
+ {componentsArray.map((e:any, i) => (
+
+ ))}
+
- }
- />
-
-
+ }
+ />
+
+
+
);
\ No newline at end of file
diff --git a/src/kitUI/makeRequest.ts b/src/kitUI/makeRequest.ts
new file mode 100644
index 0000000..bc9742d
--- /dev/null
+++ b/src/kitUI/makeRequest.ts
@@ -0,0 +1,65 @@
+import axios from 'axios'
+
+interface MakeRequest {
+ method?: string
+ url: string
+ body?: unknown
+ useToken?: boolean
+ contentType?: boolean
+}
+
+export default (props: MakeRequest) => {
+ return (
+ new Promise(async (resolve, reject) => {
+ await makeRequest(props)
+ .then(r => resolve(r))
+ .catch(r => reject(r))
+ })
+ )
+}
+
+function makeRequest({
+ method = "post",
+ url,
+ body,
+ useToken = true,
+ contentType = false
+}: MakeRequest) {
+ //В случае 401 рефреш должен попробовать вызваться 1 раз
+ let counterRefresh = true
+ let headers: any = {}
+ if (useToken) headers["Authorization"] = localStorage.getItem('AT')
+ if (contentType) headers["Content-Type"] = "application/json"
+ return axios({
+ url: url,
+ method: method,
+ headers: headers,
+ data: body
+ })
+ .then(response => {
+ if (response.data && response.data.accessToken) {
+ localStorage.setItem('AT', response.data.accessToken)
+ }
+ return response
+ })
+ .catch(error => {
+ if (error.response.status == 401 && counterRefresh) {
+ refresh().then(response => {
+ if (response.data && response.data.accessToken) localStorage.setItem('AT', response.data.accessToken)
+ counterRefresh = false
+ })
+ } else {
+ throw error
+ }
+ throw error
+ })
+}
+
+function refresh() {
+ return axios("https://hub.pena.digital/auth/refresh", {
+ headers: {
+ "Authorization": localStorage.getItem('AT'),
+ "Content-Type": "application/json"
+ }
+ })
+}
\ No newline at end of file
diff --git a/src/kitUI/privateRoute.tsx b/src/kitUI/privateRoute.tsx
index 45f9975..2a64373 100644
--- a/src/kitUI/privateRoute.tsx
+++ b/src/kitUI/privateRoute.tsx
@@ -2,13 +2,11 @@ import * as React from "react";
import { useLocation, Navigate } from 'react-router-dom'
export default ({ children }: any) => {
- console.log("проверяю")
- const auth = true
const location = useLocation()
-
- if (!auth) {
+//Если пользователь авторизован, перенаправляем его на нужный путь. Иначе выкидываем в регистрацию
+ if (localStorage.getItem('AT')) {
return children
}
- return
+ return
}
diff --git a/src/kitUI/publicRoute.tsx b/src/kitUI/publicRoute.tsx
index d0240cb..377b655 100644
--- a/src/kitUI/publicRoute.tsx
+++ b/src/kitUI/publicRoute.tsx
@@ -2,13 +2,11 @@ import * as React from "react";
import { useLocation, Navigate } from 'react-router-dom'
export default ({ children }: any) => {
- console.log("проверяю")
- const auth = true
const location = useLocation()
-
- if (!auth) {
- return
+//Если пользователь авторизован, перенаправляем его в приложение. Иначе пускаем куда хотел
+ if (localStorage.getItem('AT')) {
+ return
}
-
return children
+
}
diff --git a/src/pages/Authorization/restore.tsx b/src/pages/Authorization/restore.tsx
index 17042f9..884bcb8 100644
--- a/src/pages/Authorization/restore.tsx
+++ b/src/pages/Authorization/restore.tsx
@@ -1,16 +1,19 @@
import * as React from "react";
+import { useNavigate } from "react-router-dom";
import { Formik, Field, Form } from 'formik';
import {useTheme} from "@mui/material/styles";
import { Link } from "react-router-dom"
-import {Box, Button, Checkbox, TextField, Typography} from "@mui/material";
+import {Box, Typography} from "@mui/material";
import Logo from "@pages/Logo";
import CleverButton from "@kitUI/cleverButton"
+import MakeRequest from "@kitUI/makeRequest";
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import OutlinedInput from "@kitUI/outlinedInput";
export default () => {
const theme = useTheme()
+ const navigate = useNavigate();
const [restore, setRestore] = React.useState(true)
const [isReady, setIsReady] = React.useState(true)
if (restore) {
diff --git a/src/pages/Authorization/signin.tsx b/src/pages/Authorization/signin.tsx
index 5783989..e80aef5 100644
--- a/src/pages/Authorization/signin.tsx
+++ b/src/pages/Authorization/signin.tsx
@@ -1,4 +1,6 @@
import * as React from "react"
+import { useNavigate } from "react-router-dom";
+import { enqueueSnackbar } from 'notistack';
import {useTheme} from "@mui/material/styles"
import { Formik, Field, Form } from 'formik'
import { Link } from "react-router-dom"
@@ -6,21 +8,56 @@ import { Box, Checkbox, TextField, Typography, FormControlLabel} from "@mui/mate
import Logo from "@pages/Logo"
import CleverButton from "@kitUI/cleverButton"
import OutlinedInput from "@kitUI/outlinedInput"
+import makeRequest from "@kitUI/makeRequest";
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
import LockOutlinedIcon from "@mui/icons-material/LockOutlined"
+interface Values {
+ email: string;
+ password: string;
+}
+
+function validate(values: Values) {
+ const errors = {} as any;
+ if (!values.email) {
+ errors.email = "Required";
+ }
+ if (!values.password) {
+ errors.password = "Required";
+ } else if (!/^[\w-]{8,25}$/i.test(values.password)) {
+ errors.password = "Invalid password";
+ }
+ return errors;
+}
export default () => {
const theme = useTheme()
+ const navigate = useNavigate();
const [isReady, setIsReady] = React.useState(true)
return(
{
-
+ makeRequest({
+ url: "https://hub.pena.admin/auth/login",
+ body: {
+ "email": values.email,
+ "password": values.password
+ },
+ useToken: false
+ })
+ .then((e) => {
+ console.log(e)
+ navigate("/users")
+ })
+ .catch((e) => {
+ console.log(e)
+ enqueueSnackbar(e.message ? e.message : `Unknown error`)
+ })
}}
>