From 3e5bba85f0a5d371e112584d98914c9f07588345 Mon Sep 17 00:00:00 2001 From: Vallari Date: Tue, 15 Aug 2023 02:23:33 +0530 Subject: [PATCH 1/8] install react-cookie Signed-off-by: Vallari --- package-lock.json | 45 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index ae77754..cfa94b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "json-to-pretty-yaml": "^1.2.2", "mdi-material-ui": "^7.7.0", "react": "^18.2.0", + "react-cookie": "^5.0.0", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", "react-router-dom": "^6.14.1", @@ -2756,11 +2757,25 @@ "version": "5.0.1", "license": "MIT" }, + "node_modules/@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, "node_modules/@types/history": { "version": "4.7.11", "dev": true, "license": "MIT" }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -4296,6 +4311,14 @@ "version": "1.9.0", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/copy-anything": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", @@ -6800,6 +6823,19 @@ "node": ">=0.10.0" } }, + "node_modules/react-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-5.0.0.tgz", + "integrity": "sha512-IAO8ff0SP5QN7NZwiPNMr5P0vuCTE2Zm9ailckJqZOfokMddyZTXwCEHreHQGunj5G+EWhHTzTRl0IHmL04hmg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "hoist-non-react-statics": "^3.3.2", + "universal-cookie": "^4.0.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -7705,6 +7741,15 @@ "node": ">=4" } }, + "node_modules/universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "dependencies": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.11", "dev": true, diff --git a/package.json b/package.json index d6973dd..f50d84d 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "json-to-pretty-yaml": "^1.2.2", "mdi-material-ui": "^7.7.0", "react": "^18.2.0", + "react-cookie": "^5.0.0", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", "react-router-dom": "^6.14.1", @@ -71,4 +72,4 @@ "typescript": "^5.1.6", "vite": "^4.4.1" } -} \ No newline at end of file +} From eea851dc09cfaa1acfcdc769cbd52c403d565799 Mon Sep 17 00:00:00 2001 From: Vallari Date: Tue, 15 Aug 2023 02:24:24 +0530 Subject: [PATCH 2/8] add lib/teuthologyAPI.ts and login with github 1. redirect to teuthology API's login 2. AppBar uses cookie data to show username Signed-off-by: Vallari --- src/components/AppBar/index.jsx | 48 ++++++++++++++++++++++++++++++++- src/index.tsx | 21 ++++++++------- src/lib/teuthologyAPI.ts | 12 +++++++++ 3 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 src/lib/teuthologyAPI.ts diff --git a/src/components/AppBar/index.jsx b/src/components/AppBar/index.jsx index 13a403e..56e8216 100644 --- a/src/components/AppBar/index.jsx +++ b/src/components/AppBar/index.jsx @@ -8,13 +8,19 @@ import Brightness7Icon from "@mui/icons-material/Brightness7"; import MuiAppBar from "@mui/material/AppBar"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; +import Button from "@mui/material/Button"; +import { useCookies } from "react-cookie"; + +import { githubLogin } from "../../lib/teuthologyAPI" + const PREFIX = 'index'; const classes = { appBar: `${PREFIX}-appBar`, title: `${PREFIX}-title`, - toolbarIcon: `${PREFIX}-toolbarIcon` + toolbarIcon: `${PREFIX}-toolbarIcon`, + loginButton: `${PREFIX}-loginButton`, }; const StyledMuiAppBar = styled(MuiAppBar)(( @@ -40,11 +46,43 @@ const StyledMuiAppBar = styled(MuiAppBar)(( alignItems: "center", justifyContent: "flex-end", padding: "0 8px", + }, + + [`& .${classes.loginButton}`]: { + // TODO: add theme + marginLeft: "12px", } + })); export default function AppBar(props) { const theme = useTheme(); + const [cookies, setCookie, removeCookie] = useCookies(["pulpitosession"]); + + + const getCookieData = () => { + // ISO-8859-1 octal string -> char string + const authcookies = (cookies["pulpitosession"].replace(/\\073/g, ';')) + + if (authcookies){ + let cookie_dict = {} + let cookies_ = authcookies.split(";") + cookies_.map((cookie) => { + let [key, value] = cookie.split("="); + cookie_dict[key.trim()] = value.trim(); + }) + return cookie_dict + } + } + + const getUsername = () => { + const cookieData = getCookieData(); + return cookieData["username"]; + } + + const login = () => { + githubLogin(); + } return ( @@ -78,6 +116,14 @@ export default function AppBar(props) { Pulpito +
+ { cookies["pulpitosession"] + ? + Hey, {getUsername()} ! + + : + } +
{props.darkMode ? : } diff --git a/src/index.tsx b/src/index.tsx index 359b55b..c777a0c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -4,6 +4,7 @@ import { BrowserRouter as Router } from "react-router-dom"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryParamProvider } from "use-query-params"; import { ReactRouter6Adapter } from "use-query-params/adapters/react-router-6"; +import { CookiesProvider } from "react-cookie"; import axios from "axios"; import CssBaseline from "@mui/material/CssBaseline"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; @@ -78,15 +79,17 @@ export default function Root() { - - - - - - - - - + + + + + + + + + + + diff --git a/src/lib/teuthologyAPI.ts b/src/lib/teuthologyAPI.ts new file mode 100644 index 0000000..04aee3f --- /dev/null +++ b/src/lib/teuthologyAPI.ts @@ -0,0 +1,12 @@ +import { useQuery } from "@tanstack/react-query"; + +const TEUTHOLOGY_API_SERVER = + import.meta.env.VITE_TEUTHOLOGY_API || ""; + +function githubLogin() { + window.location.replace(`${TEUTHOLOGY_API_SERVER}/login`); +} + +export { + githubLogin, +} \ No newline at end of file From 0c3b8942cd1fc9423db53e0b340406337a8227c0 Mon Sep 17 00:00:00 2001 From: Vallari Date: Wed, 16 Aug 2023 21:10:44 +0530 Subject: [PATCH 3/8] Make new 'Login' component Signed-off-by: Vallari --- src/components/AppBar/index.jsx | 46 +++---------------------------- src/components/Login/index.jsx | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 43 deletions(-) create mode 100644 src/components/Login/index.jsx diff --git a/src/components/AppBar/index.jsx b/src/components/AppBar/index.jsx index 56e8216..f1abd8e 100644 --- a/src/components/AppBar/index.jsx +++ b/src/components/AppBar/index.jsx @@ -8,10 +8,8 @@ import Brightness7Icon from "@mui/icons-material/Brightness7"; import MuiAppBar from "@mui/material/AppBar"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; -import Button from "@mui/material/Button"; -import { useCookies } from "react-cookie"; -import { githubLogin } from "../../lib/teuthologyAPI" +import Login from "../Login"; const PREFIX = 'index'; @@ -19,8 +17,7 @@ const PREFIX = 'index'; const classes = { appBar: `${PREFIX}-appBar`, title: `${PREFIX}-title`, - toolbarIcon: `${PREFIX}-toolbarIcon`, - loginButton: `${PREFIX}-loginButton`, + toolbarIcon: `${PREFIX}-toolbarIcon` }; const StyledMuiAppBar = styled(MuiAppBar)(( @@ -46,43 +43,11 @@ const StyledMuiAppBar = styled(MuiAppBar)(( alignItems: "center", justifyContent: "flex-end", padding: "0 8px", - }, - - [`& .${classes.loginButton}`]: { - // TODO: add theme - marginLeft: "12px", } - })); export default function AppBar(props) { const theme = useTheme(); - const [cookies, setCookie, removeCookie] = useCookies(["pulpitosession"]); - - - const getCookieData = () => { - // ISO-8859-1 octal string -> char string - const authcookies = (cookies["pulpitosession"].replace(/\\073/g, ';')) - - if (authcookies){ - let cookie_dict = {} - let cookies_ = authcookies.split(";") - cookies_.map((cookie) => { - let [key, value] = cookie.split("="); - cookie_dict[key.trim()] = value.trim(); - }) - return cookie_dict - } - } - - const getUsername = () => { - const cookieData = getCookieData(); - return cookieData["username"]; - } - - const login = () => { - githubLogin(); - } return ( @@ -117,12 +82,7 @@ export default function AppBar(props) {
- { cookies["pulpitosession"] - ? - Hey, {getUsername()} ! - - : - } +
{props.darkMode ? : } diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx new file mode 100644 index 0000000..a5e10ca --- /dev/null +++ b/src/components/Login/index.jsx @@ -0,0 +1,48 @@ +import { useCookies } from "react-cookie"; +import Typography from "@mui/material/Typography"; +import Button from "@mui/material/Button"; + +import { githubLogin } from "../../lib/teuthologyAPI"; + + +const GH_USER_COOKIE = "GH_USER"; + + +export default function Login() { + const [cookies, setCookie, removeCookie] = useCookies([GH_USER_COOKIE]); + + const getCookieData = () => { + // ISO-8859-1 octal string -> char string + const authcookies = (cookies[GH_USER_COOKIE].replace(/\\073/g, ';')); + + if (authcookies) { + let cookie_dict = {}; + let cookies_ = authcookies.split(";"); + cookies_.map((cookie) => { + let [key, value] = cookie.split("="); + cookie_dict[key.trim()] = value.trim(); + }) + return cookie_dict; + } + } + + const getUsername = () => { + const cookieData = getCookieData(); + return cookieData["username"] || ""; + } + + const login = () => { + githubLogin(); + } + + return ( +
+ {cookies[GH_USER_COOKIE] + ? + Hey, {getUsername()} ! + + : + } +
+ ); +} From 3c968f1ae9b7f7389d99bd29adb9fe1ca67e2f40 Mon Sep 17 00:00:00 2001 From: Vallari Date: Thu, 17 Aug 2023 13:04:33 +0530 Subject: [PATCH 4/8] githubLogin: Use URL() to build url Signed-off-by: Vallari --- src/lib/teuthologyAPI.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/teuthologyAPI.ts b/src/lib/teuthologyAPI.ts index 04aee3f..8f41ee2 100644 --- a/src/lib/teuthologyAPI.ts +++ b/src/lib/teuthologyAPI.ts @@ -1,10 +1,10 @@ -import { useQuery } from "@tanstack/react-query"; const TEUTHOLOGY_API_SERVER = import.meta.env.VITE_TEUTHOLOGY_API || ""; function githubLogin() { - window.location.replace(`${TEUTHOLOGY_API_SERVER}/login`); + const url = new URL("/login/", TEUTHOLOGY_API_SERVER).href; + window.location.replace(url); } export { From 75cd849131f5a2864fc65e8c22eda50b6c6b7410 Mon Sep 17 00:00:00 2001 From: Vallari Date: Thu, 17 Aug 2023 18:00:10 +0530 Subject: [PATCH 5/8] add logout button and profile avatar Signed-off-by: Vallari --- src/components/Login/index.jsx | 47 ++++++++++++++++++++++++++-------- src/lib/teuthologyAPI.ts | 10 ++++++-- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx index a5e10ca..b0f10a8 100644 --- a/src/components/Login/index.jsx +++ b/src/components/Login/index.jsx @@ -1,8 +1,12 @@ +import { useState } from "react"; import { useCookies } from "react-cookie"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; +import Avatar from '@mui/material/Avatar'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; -import { githubLogin } from "../../lib/teuthologyAPI"; +import { login, logout } from "../../lib/teuthologyAPI"; const GH_USER_COOKIE = "GH_USER"; @@ -10,6 +14,14 @@ const GH_USER_COOKIE = "GH_USER"; export default function Login() { const [cookies, setCookie, removeCookie] = useCookies([GH_USER_COOKIE]); + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; const getCookieData = () => { // ISO-8859-1 octal string -> char string @@ -26,21 +38,34 @@ export default function Login() { } } - const getUsername = () => { - const cookieData = getCookieData(); - return cookieData["username"] || ""; - } - - const login = () => { - githubLogin(); + const githubLogout = () => { + removeCookie(GH_USER_COOKIE); + logout(); } return (
{cookies[GH_USER_COOKIE] - ? - Hey, {getUsername()} ! - + ?
+ + + Logout + +
: }
diff --git a/src/lib/teuthologyAPI.ts b/src/lib/teuthologyAPI.ts index 8f41ee2..5de8138 100644 --- a/src/lib/teuthologyAPI.ts +++ b/src/lib/teuthologyAPI.ts @@ -2,11 +2,17 @@ const TEUTHOLOGY_API_SERVER = import.meta.env.VITE_TEUTHOLOGY_API || ""; -function githubLogin() { +function login() { const url = new URL("/login/", TEUTHOLOGY_API_SERVER).href; window.location.replace(url); } +function logout() { + const url = new URL("/logout/", TEUTHOLOGY_API_SERVER).href; + window.location.replace(url); +} + export { - githubLogin, + login, + logout, } \ No newline at end of file From 1d1be3d03879ae4b6d808d652e161b33433428f6 Mon Sep 17 00:00:00 2001 From: Vallari Date: Fri, 18 Aug 2023 14:36:16 +0530 Subject: [PATCH 6/8] use window.location.href instead of replace() This preserves the browser's history stack. Also, add github icon to login button. Signed-off-by: Vallari --- src/components/Login/index.jsx | 13 ++++++++++--- src/lib/teuthologyAPI.ts | 12 ++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx index b0f10a8..9befc5b 100644 --- a/src/components/Login/index.jsx +++ b/src/components/Login/index.jsx @@ -5,8 +5,9 @@ import Button from "@mui/material/Button"; import Avatar from '@mui/material/Avatar'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; +import GitHubIcon from '@mui/icons-material/GitHub'; -import { login, logout } from "../../lib/teuthologyAPI"; +import { useLogin, useLogout } from "../../lib/teuthologyAPI"; const GH_USER_COOKIE = "GH_USER"; @@ -40,7 +41,7 @@ export default function Login() { const githubLogout = () => { removeCookie(GH_USER_COOKIE); - logout(); + useLogout(); } return ( @@ -66,7 +67,13 @@ export default function Login() { Logout - : + : } ); diff --git a/src/lib/teuthologyAPI.ts b/src/lib/teuthologyAPI.ts index 5de8138..68a83d2 100644 --- a/src/lib/teuthologyAPI.ts +++ b/src/lib/teuthologyAPI.ts @@ -2,17 +2,17 @@ const TEUTHOLOGY_API_SERVER = import.meta.env.VITE_TEUTHOLOGY_API || ""; -function login() { +function useLogin() { const url = new URL("/login/", TEUTHOLOGY_API_SERVER).href; - window.location.replace(url); + window.location.href = url; } -function logout() { +function useLogout() { const url = new URL("/logout/", TEUTHOLOGY_API_SERVER).href; - window.location.replace(url); + window.location.href = url; } export { - login, - logout, + useLogin, + useLogout, } \ No newline at end of file From c9760ae7c89a2ef062f53e1ea1450b66301ca969 Mon Sep 17 00:00:00 2001 From: Vallari Date: Fri, 18 Aug 2023 17:25:17 +0530 Subject: [PATCH 7/8] add useSession hook to ping and check if user is logged in Signed-off-by: Vallari --- src/components/Login/index.jsx | 7 +++++-- src/lib/teuthologyAPI.ts | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx index 9befc5b..9ef5aa1 100644 --- a/src/components/Login/index.jsx +++ b/src/components/Login/index.jsx @@ -7,13 +7,16 @@ import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import GitHubIcon from '@mui/icons-material/GitHub'; -import { useLogin, useLogout } from "../../lib/teuthologyAPI"; +import { useLogin, useLogout, useSession } from "../../lib/teuthologyAPI"; const GH_USER_COOKIE = "GH_USER"; export default function Login() { + const sessionQuery = useSession(); + if (sessionQuery.isError) return null; + const [cookies, setCookie, removeCookie] = useCookies([GH_USER_COOKIE]); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); @@ -46,7 +49,7 @@ export default function Login() { return (
- {cookies[GH_USER_COOKIE] + {sessionQuery.data?.session ?
( + axios.get(url, { + withCredentials: true + }).then((resp) => resp.data) + ), + }); + return query; +} + export { useLogin, useLogout, + useSession, } \ No newline at end of file From 237c06104bfda0e4c50a0e1e2f455d4033a24931 Mon Sep 17 00:00:00 2001 From: Vallari Date: Fri, 18 Aug 2023 18:25:18 +0530 Subject: [PATCH 8/8] add useUserData() hook Extract cookie related code from Login component to lib/teuthologyAPi.ts Signed-off-by: Vallari --- src/components/Login/index.jsx | 39 ++++++---------------------------- src/lib/teuthologyAPI.ts | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/components/Login/index.jsx b/src/components/Login/index.jsx index 9ef5aa1..48f902d 100644 --- a/src/components/Login/index.jsx +++ b/src/components/Login/index.jsx @@ -1,23 +1,16 @@ import { useState } from "react"; -import { useCookies } from "react-cookie"; -import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Avatar from '@mui/material/Avatar'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import GitHubIcon from '@mui/icons-material/GitHub'; -import { useLogin, useLogout, useSession } from "../../lib/teuthologyAPI"; - - -const GH_USER_COOKIE = "GH_USER"; +import { useLogin, useLogout, useSession, useUserData } from "../../lib/teuthologyAPI"; export default function Login() { const sessionQuery = useSession(); - if (sessionQuery.isError) return null; - - const [cookies, setCookie, removeCookie] = useCookies([GH_USER_COOKIE]); + const userData = useUserData(); const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); const handleClick = (event) => { @@ -27,33 +20,15 @@ export default function Login() { setAnchorEl(null); }; - const getCookieData = () => { - // ISO-8859-1 octal string -> char string - const authcookies = (cookies[GH_USER_COOKIE].replace(/\\073/g, ';')); - - if (authcookies) { - let cookie_dict = {}; - let cookies_ = authcookies.split(";"); - cookies_.map((cookie) => { - let [key, value] = cookie.split("="); - cookie_dict[key.trim()] = value.trim(); - }) - return cookie_dict; - } - } - - const githubLogout = () => { - removeCookie(GH_USER_COOKIE); - useLogout(); - } + if (sessionQuery.isError) return null; return (
{sessionQuery.data?.session ?
- - Logout + Logout
: