auth & cache

This commit is contained in:
h z
2024-12-03 11:29:16 +00:00
parent b355b867a5
commit d035a781ae
9 changed files with 118 additions and 9 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
summerizer.py

4
Dockerfile Normal file
View File

@@ -0,0 +1,4 @@
FROM ubuntu:latest
LABEL authors="hzhang"
ENTRYPOINT ["top", "-b"]

20
package-lock.json generated
View File

@@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"oidc-client-ts": "^3.1.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^7.0.1" "react-router-dom": "^7.0.1"
@@ -4521,6 +4522,14 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"engines": {
"node": ">=18"
}
},
"node_modules/kind-of": { "node_modules/kind-of": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -4829,6 +4838,17 @@
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
"dev": true "dev": true
}, },
"node_modules/oidc-client-ts": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.1.0.tgz",
"integrity": "sha512-IDopEXjiwjkmJLYZo6BTlvwOtnlSniWZkKZoXforC/oLZHC9wkIxd25Kwtmo5yKFMMVcsp3JY6bhcNJqdYk8+g==",
"dependencies": {
"jwt-decode": "^4.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/on-finished": { "node_modules/on-finished": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",

View File

@@ -12,6 +12,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"oidc-client-ts": "^3.1.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^7.0.1" "react-router-dom": "^7.0.1"

30
src/AuthProvider.js Normal file
View File

@@ -0,0 +1,30 @@
import React, { createContext, useEffect, useState } from "react";
import { UserManager } from "oidc-client-ts";
import {oidcConfig} from "./oicdConfig";
export const AuthContext = createContext();
const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const userManager = new UserManager(oidcConfig);
useEffect(() => {
userManager.getUser().then((user) => {
if (user && !user.expired) {
setUser(user);
}
});
}, [userManager]);
const login = () => userManager.signinRedirect();
const logout = () => userManager.signoutRedirect();
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export default AuthProvider;

17
src/Callback.js Normal file
View File

@@ -0,0 +1,17 @@
import React, { useEffect } from "react";
import { UserManager } from "oidc-client-ts";
import {oidcConfig} from "./oicdConfig";
const Callback = () => {
useEffect(() => {
const userManager = new UserManager(oidcConfig);
userManager.signinRedirectCallback().then(() => {
window.location.href = "/";
});
}, []);
return <div>Logging in...</div>;
};
export default Callback;

View File

@@ -1,16 +1,28 @@
//src/components/MainNavigation.js //src/components/MainNavigation.js
import React from "react"; import React, {useContext} from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import "./MainNavigation.css"; import "./MainNavigation.css";
import {AuthContext} from "../AuthProvider";
const MainNavigation = () => { const MainNavigation = () => {
const { user, login, logout } = useContext(AuthContext);
return ( return (
<nav className="main-navigation"> <nav className="main-navigation">
<ul> <ul>
<li> <li>
<Link to="/">Home</Link> <Link to="/">Home</Link>
</li> </li>
{user ? (
<div>
<h1>{user.profile.name}</h1>
<button onClick={logout}>Logout</button>
</div>
) : (
<button onClick={login}>Login</button>
)
}
<li> <li>
<Link to="/login">Login</Link> <Link to="/login">Login</Link>
</li> </li>

8
src/oicdConfig.js Normal file
View File

@@ -0,0 +1,8 @@
export const oidcConfig = {
authority: "https://login.hangman-lab.top/auth/realms/myrealm",
client_id: "your-client-id",
redirect_uri: "http://localhost:3000/callback",
post_logout_redirect_uri: "http://localhost:3000",
response_type: "code",
scope: "openid profile email",
};

View File

@@ -1,4 +1,10 @@
const ongoingRequests = new Map();
export async function fetchWithCache(url, cacheKey = url, cacheExpiry = 60) { export async function fetchWithCache(url, cacheKey = url, cacheExpiry = 60) {
if (ongoingRequests.has(url)) {
return ongoingRequests.get(url);
}
const cachedData = localStorage.getItem(cacheKey); const cachedData = localStorage.getItem(cacheKey);
const now = Date.now(); const now = Date.now();
@@ -12,13 +18,23 @@ export async function fetchWithCache(url, cacheKey = url, cacheExpiry = 60) {
} }
} }
const response = await fetch(url); try {
if (!response.ok) { const fetchPromise = fetch(url)
throw new Error(`HTTP error! Status: ${response.status}`); .then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then((data) => {
localStorage.setItem(cacheKey, JSON.stringify({ data, timestamp: now }));
ongoingRequests.delete(url);
return data;
});
ongoingRequests.set(url, fetchPromise);
return await fetchPromise;
} catch (error) {
ongoingRequests.delete(url);
throw error;
} }
const data = await response.json();
localStorage.setItem(cacheKey, JSON.stringify({ data, timestamp: now }));
return data;
} }