simple login/checkauth/main app components
This commit is contained in:
83
src/App.jsx
83
src/App.jsx
@@ -1,38 +1,63 @@
|
|||||||
import { useState } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import reactLogo from './assets/react.svg'
|
import reactLogo from './assets/react.svg'
|
||||||
import viteLogo from '/vite.svg'
|
import viteLogo from '/vite.svg'
|
||||||
import './App.css'
|
import './App.css'
|
||||||
|
|
||||||
import Login from './components/login.jsx'
|
import Login from './components/login.jsx'
|
||||||
|
import MainApp from './components/MainApp.jsx'
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
const [loading, setLoading] = useState(true); // true while checking auth
|
||||||
|
const [loggedIn, setLoggedIn] = useState(false);
|
||||||
|
|
||||||
function App() {
|
useEffect(() => {
|
||||||
const [count, setCount] = useState(0)
|
async function checkAuth() {
|
||||||
|
try {
|
||||||
|
// This endpoint should validate the refresh token cookie and return an access token
|
||||||
|
const res = await fetch("http://localhost:7080/auth/login_refresh_token", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"User-Agent": "react-app",
|
||||||
|
},
|
||||||
|
credentials: "include", // send cookies automatically
|
||||||
|
body: JSON.stringify({
|
||||||
|
device_id : "147ac10b-58cc-4372-a567-0e02b2c3d479", // or persistent device ID
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
console.log("sent checkAuth request")
|
||||||
|
if (!res.ok) {
|
||||||
|
console.log(res)
|
||||||
|
console.log("checkAuth request not ok")
|
||||||
|
// No valid refresh token → user must log in
|
||||||
|
setLoggedIn(false);
|
||||||
|
} else {
|
||||||
|
// Got short-lived access token
|
||||||
|
console.log("Got short-lived access token")
|
||||||
|
const data = await res.json();
|
||||||
|
console.log(data)
|
||||||
|
localStorage.setItem("access_tokens", JSON.stringify(data.tokens)); // store for API calls
|
||||||
|
setLoggedIn(true);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Auth check failed:", err);
|
||||||
|
setLoggedIn(false);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
checkAuth();
|
||||||
<>
|
}, []);
|
||||||
<div>
|
|
||||||
<a href="https://vite.dev" target="_blank">
|
if (loading) return <p>Loading...</p>; // can show a spinner
|
||||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
|
||||||
</a>
|
// Show main app if logged in, otherwise show login
|
||||||
<a href="https://react.dev" target="_blank">
|
return loggedIn ? (
|
||||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
<MainApp />
|
||||||
</a>
|
) : (
|
||||||
</div>
|
<Login onLogin={() => setLoggedIn(true)} />
|
||||||
<h1>Vite + React</h1>
|
);
|
||||||
<div className="card">
|
|
||||||
<button onClick={() => setCount((count) => count + 1)}>
|
|
||||||
count is {count}
|
|
||||||
</button>
|
|
||||||
<p>
|
|
||||||
Edit <code>src/App.jsx</code> and save to test HMR
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<p className="read-the-docs">
|
|
||||||
Click on the Vite and React logos to learn more
|
|
||||||
</p>
|
|
||||||
<Login />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
//export default App
|
||||||
|
|||||||
24
src/components/MainApp.jsx
Normal file
24
src/components/MainApp.jsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default function MainApp() {
|
||||||
|
// You could fetch your short-lived access token from localStorage
|
||||||
|
const accessToken = localStorage.getItem("access_tokens");
|
||||||
|
console.log("the accesToken in Mainapp is :" + accessToken);
|
||||||
|
return (
|
||||||
|
<div style={{ padding: "2rem" }}>
|
||||||
|
<h1>Welcome to MyHotel!</h1>
|
||||||
|
<p>Your access token (short-lived) is:</p>
|
||||||
|
<pre>{accessToken}</pre>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>Dashboard</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Rooms</li>
|
||||||
|
<li>Bookings</li>
|
||||||
|
<li>Guests</li>
|
||||||
|
<li>Reports</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Login from ".components/Login";
|
import Login from "./components/Login";
|
||||||
import MainApp from "./MainApp";
|
import MainApp from "./MainApp";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
@@ -29,7 +29,7 @@ export default function App() {
|
|||||||
|
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
// store short-lived token somewhere accessible
|
// store short-lived token somewhere accessible
|
||||||
localStorage.setItem("access_token", data.access_token);
|
localStorage.setItem("access_token", JSON.stringify(data.tokens));
|
||||||
setLoggedIn(true);
|
setLoggedIn(true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Auth check failed:", err);
|
console.error("Auth check failed:", err);
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login({ onLogin }) {
|
||||||
const [username, setUsername] = useState("")
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("")
|
const [password, setPassword] = useState("");
|
||||||
const [error, setError] = useState("")
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
async function handleSubmit(e) {
|
async function handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
const device_id = crypto.randomUUID(); // browser-native UUID
|
const device_id = "147ac10b-58cc-4372-a567-0e02b2c3d479" ;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("http://localhost:7080/auth/create_refresh", {
|
const res = await fetch("http://localhost:7080/auth/create_refresh", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"User-Agent": "react-app" // optional
|
"User-Agent": "react-app",
|
||||||
},
|
},
|
||||||
credentials: "include", // lets cookies like PHPSESSID flow if server sets them
|
credentials: "include",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({ username, password, device_id }),
|
||||||
username,
|
|
||||||
password,
|
|
||||||
device_id
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -31,34 +27,33 @@ export default function Login() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.text();
|
//const data = await res.json(); // server returns short-lived token
|
||||||
console.log("Login success:", data);
|
//localStorage.setItem("access_token", data.access_token);
|
||||||
// store tokens/responses where you want (context/localStorage/etc.)
|
|
||||||
|
if (onLogin) onLogin(); // notify App to show MainApp
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
setError("Network error.");
|
setError("Network error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column", width: "200px" }}>
|
<form onSubmit={handleSubmit}>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Username"
|
placeholder="Username"
|
||||||
value={username}
|
value={username}
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button type="submit">Login</button>
|
<button type="submit">Login</button>
|
||||||
|
|
||||||
{error && <p style={{ color: "red" }}>{error}</p>}
|
{error && <p style={{ color: "red" }}>{error}</p>}
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user