mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-09-11 04:38:42 -06:00
feat: add login component and user config
This commit is contained in:
@@ -28,6 +28,7 @@ import WorkflowList from "./Workflow_List";
|
|||||||
import DeviceList from "./Device_List";
|
import DeviceList from "./Device_List";
|
||||||
import ScriptList from "./Script_List";
|
import ScriptList from "./Script_List";
|
||||||
import ScheduledJobsList from "./Scheduled_Jobs_List";
|
import ScheduledJobsList from "./Scheduled_Jobs_List";
|
||||||
|
import Login from "./Login.jsx";
|
||||||
|
|
||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
|
|
||||||
@@ -86,6 +87,31 @@ export default function App() {
|
|||||||
const [tabMenuAnchor, setTabMenuAnchor] = useState(null);
|
const [tabMenuAnchor, setTabMenuAnchor] = useState(null);
|
||||||
const [tabMenuTabId, setTabMenuTabId] = useState(null);
|
const [tabMenuTabId, setTabMenuTabId] = useState(null);
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const session = localStorage.getItem("borealis_session");
|
||||||
|
if (session) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(session);
|
||||||
|
if (Date.now() - data.timestamp < 3600 * 1000) {
|
||||||
|
setUser(data.username);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem("borealis_session");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
localStorage.removeItem("borealis_session");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleLoginSuccess = (username) => {
|
||||||
|
setUser(username);
|
||||||
|
localStorage.setItem(
|
||||||
|
"borealis_session",
|
||||||
|
JSON.stringify({ username, timestamp: Date.now() })
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
|
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
|
||||||
@@ -386,6 +412,14 @@ export default function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (!user) {
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={darkTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
<Login onLogin={handleLoginSuccess} />
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={darkTheme}>
|
<ThemeProvider theme={darkTheme}>
|
||||||
|
103
Data/Server/WebUI/src/Login.jsx
Normal file
103
Data/Server/WebUI/src/Login.jsx
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { Box, TextField, Button, Typography } from "@mui/material";
|
||||||
|
|
||||||
|
export default function Login({ onLogin }) {
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
const [username, setUsername] = useState("admin");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("/users.json")
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => setUsers(data.users || []))
|
||||||
|
.catch(() => setUsers([]));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const sha512 = async (text) => {
|
||||||
|
const encoder = new TextEncoder();
|
||||||
|
const data = encoder.encode(text);
|
||||||
|
const hashBuffer = await crypto.subtle.digest("SHA-512", data);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||||
|
return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const user = users.find((u) => u.username === username);
|
||||||
|
if (!user) {
|
||||||
|
setError("Invalid username or password");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const hash = await sha512(password);
|
||||||
|
if (hash === user.password) {
|
||||||
|
setError("");
|
||||||
|
onLogin(username);
|
||||||
|
} else {
|
||||||
|
setError("Invalid username or password");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "100vh",
|
||||||
|
backgroundColor: "#2b2b2b",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
width: 300,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/Borealis_Logo.png"
|
||||||
|
alt="Borealis Logo"
|
||||||
|
style={{ width: "120px", marginBottom: "16px" }}
|
||||||
|
/>
|
||||||
|
<Typography variant="h6" sx={{ mb: 3 }}>
|
||||||
|
Borealis - Automation Platform
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
label="Username"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Password"
|
||||||
|
type="password"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
margin="normal"
|
||||||
|
/>
|
||||||
|
{error && (
|
||||||
|
<Typography color="error" sx={{ mt: 1 }}>
|
||||||
|
{error}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
fullWidth
|
||||||
|
sx={{ mt: 2, bgcolor: "#58a6ff", "&:hover": { bgcolor: "#1d82d3" } }}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
9
users.json
Normal file
9
users.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"username": "admin",
|
||||||
|
"password": "18ec3210467c363a6cf96901261be4431bb4a75285ccd362b8cf8eae504ce6250ea4d64264a75486bf446051e3d4a6ac004410914ae706d29a01e96ba53f49a3"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user