fixed login

This commit is contained in:
SnippetsX 2024-11-01 23:35:01 +03:00
parent 03690424c5
commit a77f2ed598
12 changed files with 1347 additions and 3398 deletions

4424
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,11 +10,12 @@
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"codegen": "^0.1.0",
"eslint-plugin-react": "^7.37.1", "eslint-plugin-react": "^7.37.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.27.0", "react-router-dom": "^6.27.0",
"react-scripts": "5.0.1", "react-scripts": "^5.0.1",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
@ -40,5 +41,10 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"devDependencies": {
"ajv": "^8.17.1",
"cors": "^2.8.5",
"express": "^4.21.1"
} }
} }

View File

@ -4,6 +4,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />

13
server.js Normal file
View File

@ -0,0 +1,13 @@
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.use('/login', (req, res) =>{
res.send({
token: 'snippetsx'
})
})
app.listen(8080, () => console.log('API Running on localhost:8080'))

View File

@ -1,45 +1,3 @@
.board-row { body {
align-items: center; overflow-x: hidden; /* Hide horizontal scrollbar */
display: flex;
justify-content: center;
min-width: 210px;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.square {
background-color: #6b3b3b;
border: 1px solid #999;
float: left;
font-size: 23px;
font-weight: bold;
line-height: 10px;
height: 64px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
.square:focus {
outline: none;
}
.square:hover {
background-color: #00a2ff;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
min-width: 180px;
} }

View File

@ -1,35 +1,24 @@
import React, { useState, useEffect } from 'react'; import React, { useState} from 'react';
import Login from './Login/LoginPage'; import Login from './Login/LoginPage';
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom'; import { BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import { checkAuthCookie } from './Login/CookieCreating'; import Preferences from './Preferences/Preferences'
import Dashboard from './Dashboard/DashboardMain' import Dashboard from './Dashboard/DashboardMain'
import './App.css'
function App() { function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false); const [token, setToken] = useState();
useEffect(() => { if(!token){
const token = checkAuthCookie(); return <Login setToken={setToken} />
setIsAuthenticated(!!token); }
}, []);
return ( return (
<Router> <Router>
<Routes> <Routes>
<Route <Route path="/dashboard" element={<Dashboard/>} />
path="/login" <Route path="/preferences" element={<Preferences/>} />
element={isAuthenticated ? <Navigate to="/dashboard" /> : <Login />}
/>
<Route
path="/dashboard"
element={isAuthenticated ? <Dashboard /> : <Navigate to="/login" />}
/>
<Route
path="/"
element={<Navigate to={isAuthenticated ? "/dashboard" : "/login"} />}
/>
</Routes> </Routes>
</Router> </Router>
); );
} }
export default App; export default App;

View File

@ -9,7 +9,8 @@ import {
ListItemText, ListItemText,
List, List,
Drawer, Drawer,
IconButton IconButton,
Divider
} from '@mui/material'; } from '@mui/material';
import ListItemIcon from '@mui/icons-material/List' import ListItemIcon from '@mui/icons-material/List'
import PeopleIcon from'@mui/icons-material/People' import PeopleIcon from'@mui/icons-material/People'

View File

@ -1,34 +0,0 @@
export const createAuthCookie = (token) => {
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 7); // Set expiration to 7 days from now
const cookieValue = encodeURIComponent(token);
document.cookie = `authToken=${cookieValue}; expires=${expirationDate.toUTCString()}; path=/; SameSite=Strict; Secure`;
console.log(document.cookie);
};
export const checkAuthCookie = () => {
const cookies = document.cookie.split(';');
const authCookie = cookies.find(cookie => cookie.trim().startsWith('authToken='));
if (!authCookie) {
return null; // Cookie not found
}
const [, token] = authCookie.split('=');
const decodedToken = decodeURIComponent(token);
// Check if the cookie has expired
const expirationMatch = document.cookie.match(/expires=([^;]+)/);
if (!expirationMatch) {
return null; // Expiration date not found
}
const expirationDate = new Date(expirationMatch[1]);
if (expirationDate < new Date()) {
return null; // Cookie has expired
}
return decodedToken;
};

View File

@ -1,10 +0,0 @@
@keyframes shake {
0% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
20%, 40%, 60%, 80% { transform: translateX(10px); }
100% { transform: translateX(0); }
}
.shake-animation {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
}

View File

@ -1,66 +1,43 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { import PropTypes from 'prop-types';
Container, import { Button, Container, TextField, Typography, Box } from '@mui/material';
TextField,
Button,
Typography,
Box,
} from '@mui/material';
import { ThemeProvider } from '@mui/material/styles'; import { ThemeProvider } from '@mui/material/styles';
import theme from '../theme'; import theme from '../theme';
import './LoginPage.css' import {loginUser} from './LoginServerSend'
import { useNavigate } from 'react-router-dom';
import { createAuthCookie } from './CookieCreating';
export default function Login({ setToken }) {
const LoginPageWithTheme = () => ( const [username, setUserName] = useState('');
<ThemeProvider theme={theme}>
<LoginPage />
</ThemeProvider>
);
const LoginPage = () => {
const [username, setusername] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [msg, setMsg] = useState('');
const navigate = useNavigate();
const handleSubmit = (event) => { const handleSubmit = async e => {
event.preventDefault(); e.preventDefault();
console.log('Login attempt with:', username, password); const token = await loginUser({
if (username === 'snippetsx' && password === '2371') username,
{ password
createAuthCookie(username); });
navigate('/dashboard'); setToken(token);
}
else
{
setMsg(true)
} }
}; return(
<ThemeProvider theme={theme}>
return (
<>
<Box <Box
sx={{ sx={{
width: '100%', width: '100%',
backgroundColor: '#4e00ba', backgroundColor: '#4e00ba',
color: 'white', color: 'white',
padding: 2, padding: 2,
textAlign: 'bottom', textAlign: 'center',
}} }}
> >
<Typography variant="h6"> <Typography variant="h6">
Admin Dashboard Admin Dashboard
</Typography> </Typography>
</Box> </Box>
<Container component="main" maxWidth="xs">
<Container maxWidth="xs">
<Box <Box
sx={{ sx={{
marginTop: 5, marginTop: 8,
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
@ -68,10 +45,11 @@ const LoginPage = () => {
> >
<Typography component="h1" variant="h5"> <Typography component="h1" variant="h5">
Sign in to Admin Panel Please Log In
</Typography> </Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}> <Box component="form" onSubmit={handleSubmit} sx={{ mt: 1 }}>
<TextField <TextField
variant="outlined"
margin="normal" margin="normal"
required required
fullWidth fullWidth
@ -80,10 +58,10 @@ const LoginPage = () => {
name="username" name="username"
autoComplete="username" autoComplete="username"
autoFocus autoFocus
value={username} onChange={e => setUserName(e.target.value)}
onChange={(e) => setusername(e.target.value)}
/> />
<TextField <TextField
variant="outlined"
margin="normal" margin="normal"
required required
fullWidth fullWidth
@ -92,40 +70,24 @@ const LoginPage = () => {
type="password" type="password"
id="password" id="password"
autoComplete="current-password" autoComplete="current-password"
value={password} onChange={e => setPassword(e.target.value)}
onChange={(e) => setPassword(e.target.value)}
error={msg}
helperText={msg ? "Incorrect password" : ""}
className={msg ? 'shake-animation' : ''}
/> />
<Button <Button
type="submit" type="submit"
fullWidth fullWidth
variant="contained" variant="contained"
color="primary"
sx={{ mt: 3, mb: 2 }} sx={{ mt: 3, mb: 2 }}
> >
Sign In Submit
</Button> </Button>
</Box> </Box>
</Box> </Box>
</Container> </Container>
<Box sx={{ </ThemeProvider>
position: 'fixed', )
bottom: 0, }
left: 0,
right: 0, Login.propTypes = {
textAlign: 'center', setToken: PropTypes.func.isRequired
padding: '10px',
backgroundColor: 'background.paper'
}}>
<Typography variant="body2" color="text.secondary">
© {new Date().getFullYear()} LCSA and SnippetsX. Все права защищены.
</Typography>
</Box>
</>
);
}; };
export default LoginPageWithTheme;

View File

@ -1,17 +1,10 @@
import axios from 'axios'; export async function loginUser(credentials) {
return fetch('http://localhost:8080/login', {
const API_BASE_URL = 'https://api.admin.lcsa.ru'; // Replace with your actual API base URL method: 'POST',
headers: {
export const sendLoginCredentials = async (username, password) => { 'Content-Type': 'application/json'
/*try { },
const response = await axios.post(`${API_BASE_URL}/login`, { body: JSON.stringify(credentials)
username, })
password .then(data => data.json())
}); }
return response.data;
} catch (error) {
console.error('Login error:', error);
throw error;
}*/
return false
};

View File

@ -0,0 +1,40 @@
import React, { useState } from 'react';
import {
Container,
TextField,
Button,
Typography,
Box,
} from '@mui/material';
import { ThemeProvider } from '@mui/material/styles';
import theme from '../theme';
const PreferencesPageWithTheme = () => (
<ThemeProvider theme={theme}>
<PreferencesPage />
</ThemeProvider>
);
const PreferencesPage = () => {
return (
<>
<Box
sx={{
width: '100%',
backgroundColor: '#4e00ba',
color: 'white',
padding: 2,
textAlign: 'bottom',
}}
>
<Typography variant="h6">
Admin Dashboard
</Typography>
</Box>
</>
)
}
export default PreferencesPageWithTheme;