Skip to content
Snippets Groups Projects
Commit 9df28f7c authored by Nico Vermaas's avatar Nico Vermaas
Browse files

added ''isTokenValid' and 'loginAgain' functions to prevent cors errors

parent 8129e02a
No related branches found
No related tags found
1 merge request!54Dev nico
Pipeline #16786 skipped
import React, { useContext, useState } from "react";
import { useHistory } from "react-router-dom";
import { Button, Modal } from "react-bootstrap";
import { GlobalContext } from "../../contexts/GlobalContext";
import { BasketContext } from "../../contexts/BasketContext";
import { getTrashIcon, getOKIcon } from "../../utils/styling";
import { saveBasket } from "./SaveBasketButton"
export default function EmptyBasketButton(props) {
const { api_host, isAuthenticated } = useContext(GlobalContext);
const { api_host, isAuthenticated, isTokenValid, loginAgain } = useContext(GlobalContext);
const basketContext = useContext(BasketContext);
const { setHasChanged } = useContext(BasketContext);
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
function emptyBasket(){
let history = useHistory()
function emptyBasket(basketContext , api_host, isTokenValid, loginAgain, history){
basketContext.setDatasets([])
setHasChanged(true)
setShow(false)
saveBasket(basketContext , api_host, isTokenValid, loginAgain, history)
}
......@@ -39,7 +43,9 @@ export default function EmptyBasketButton(props) {
</Modal.Header>
<Modal.Body>Are you sure you want to empty the shopping basket?</Modal.Body>
<Modal.Footer>
<Button variant="success" onClick={emptyBasket}>
<Button variant="success"
onClick={() => emptyBasket(basketContext, api_host, isTokenValid, loginAgain, history)}
>
{getOKIcon()}{' '}OK
</Button>
<Button variant="warning" onClick={handleClose}>
......
......@@ -13,9 +13,8 @@ function ResponseToDatasets(response) {
let datasets = shopping_cart.map((item) => {
// make item_data an object instead of a string
console.log('itemdata = '+item.item_data)
//console.log('itemdata = '+item.item_data)
let o = JSON.parse(item.item_data)
//alert(o)
return o
//return item.item_data
......@@ -23,6 +22,8 @@ function ResponseToDatasets(response) {
return datasets
}
export function loadBasket(basketContext, api_host, isAuthenticated){
//alert('loadBasket: authenticated = '+isAuthenticated)
if (!isAuthenticated) {
......
import React, { useContext } from "react";
import { useHistory } from "react-router-dom";
import { Button } from "react-bootstrap";
import { GlobalContext } from "../../contexts/GlobalContext";
import { BasketContext } from "../../contexts/BasketContext";
import axios from "axios";
import { getShoppingIcon } from "../../utils/styling";
export default function SaveBasketButton(props) {
const { api_host, isAuthenticated } = useContext(GlobalContext);
const basketContext = useContext(BasketContext);
const { hasChanged, setHasChanged } = useContext(BasketContext);
function saveBasket(basketData){
const payload = {shopping_cart: basketData};
console.log(payload);
export function saveBasket(basketContext, api_host, isTokenValid, loginAgain, history){
const payload = {shopping_cart: basketContext.datasets};
console.log('saveBasket()')
const profileUrl = api_host + "accounts/user-profiles/";
// check if he token is still valid
let token_is_valid = isTokenValid()
console.log('token valid: '+token_is_valid)
// if the token is not valid, then refresh it by logging in again
if (token_is_valid < 0) {
console.log('token no longer valid, retrying login...')
loginAgain(history)
//saveBasket(basketContext, api_host, isTokenValid, history)
return
}
axios
.get(profileUrl, {
withCredentials: true,
//headers : {"Access-Control-Allow-Origin": "*"}
})
.then((response) => {
console.log(response.data)
const userProfileUrl = profileUrl + response.data.results[0].user_name + "/";
.get(profileUrl, {
withCredentials: true,
})
.then((response) => {
// build the userProfileUrl based on the user_name in the original id_token
console.log(response.data)
const userProfileUrl = profileUrl + response.data.results[0].user_name + "/";
axios
.patch(userProfileUrl, payload, {withCredentials: true})
.then((response) => {
console.log("patch", response);
basketContext.setHasChanged(false)
})
.catch((error) => {
// send the payload to the userProfile
axios
.patch(userProfileUrl, payload, {withCredentials: true})
.then((response) => {
console.log("patch", response);
basketContext.setHasChanged(false)
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
alert(error)
});
})
.catch((error) => {
console.log(error);
//alert(error)
});
}
});
}
export default function SaveBasketButton(props) {
const { api_host, isAuthenticated, isTokenValid, loginAgain } = useContext(GlobalContext);
const basketContext = useContext(BasketContext);
const { hasChanged, setHasChanged } = useContext(BasketContext);
// fake authentication when in 'development' mode.
//let authenticated = isAuthenticated || (process.env.NODE_ENV === "development")
let authenticated = isAuthenticated
let history = useHistory()
if (authenticated) {
// only show the 'save basket' button when a user is logged in and something in the basket has changed
if (isAuthenticated) {
if (hasChanged) {
return (
<Button
type="button"
variant="primary"
onClick={() => saveBasket(basketContext.datasets)}
onClick={() => saveBasket(basketContext , api_host, isTokenValid, loginAgain, history)}
{...props}>
{getShoppingIcon("save_cart")} Save Basket</Button>
)
......@@ -60,11 +74,7 @@ export default function SaveBasketButton(props) {
}
}
else{
return (<>
<Button variant="warning" disabled {...props}>
Log In to Enable Data Selection
</Button>
</>
);
return null
}
}
......@@ -11,8 +11,8 @@ function setProfileState(api_host,
setIdToken,
setAccessToken,
setTokenExpiration,
setSecondsLeft,
setIsAuthenticated){
const profileUrl = api_host + "accounts/user-profiles/";
axios
.get(profileUrl, {withCredentials: true})
......@@ -30,12 +30,13 @@ function setProfileState(api_host,
})
.catch((error) => {
alert('GlobalContext.setProfileState:' + error)
console.log('GlobalContext.setProfileState:' + error)
// when the token is no longer valid, .get with credentials will fail
// mark the user as being logged out
localStorage.removeItem('esap_logged_in')
setIsAuthenticated(false);
setLoggedInUserName("");
});
}
......@@ -53,32 +54,30 @@ export function GlobalContextProvider({ children }) {
const [idToken, setIdToken] = useState([]);
const [accessToken, setAccessToken] = useState([]);
const [tokenExpiration, setTokenExpiration] = useState([]);
const [secondsLeft, setSecondsLeft] = useState(undefined)
useEffect(() => {
axios
.get(api_host + "query/archives-uri")
.then((response) => setArchives(response.data.results));
}, [api_host]);
useEffect(() => {
axios
.get(api_host + "query/configuration?name=navbar")
.then((response) => {
console.log("navbar response", response.data.configuration);
setNavbar(response.data.configuration);
});
}, [api_host]);
axios
.get(api_host + "query/archives-uri")
.then((response) => setArchives(response.data.results));
}, [api_host]);
useEffect(() => {
axios
.get(api_host + "query/configuration?name=navbar")
.then((response) => {
console.log("navbar response", response.data.configuration);
setNavbar(response.data.configuration);
});
}, [api_host]);
// Zheng: "!!!!! Still need to look at sessionid and stuff"
const [sessionid, setSessionid] = useState(getCookie("sessionid"));
console.log("waah", sessionid, getCookie("sessionid"), document.cookie);
const [isAuthenticated, setIsAuthenticated] = useState(
sessionid ? true : false
);
const [isAuthenticated, setIsAuthenticated] = useState(sessionid ? true : false);
const handleLogin = ({ history }) => {
console.log('handleLogin()')
setIsAuthenticated(true);
setSessionid(getCookie("sessionid"));
history.replace("/");
......@@ -88,17 +87,29 @@ export function GlobalContextProvider({ children }) {
setIdToken,
setAccessToken,
setTokenExpiration,
setSecondsLeft,
setIsAuthenticated);
return null;
};
// used when token expiration is detected before or during an axios fetch
const loginAgain = (history) => {
console.log('loginAgain()')
const loginUrl = api_host + "oidc/authenticate"
console.log('history = '+history)
//history.replace("/login");
window.location = loginUrl
//alert('history push')
//history.push("/login");
}
const handleLogout = ({ history }) => {
setIsAuthenticated(false);
setSessionid(null);
history.replace("/");
setLoggedInUserName("");
localStorage.removeItem('esap_logged_in')
console.log('handleLogout()')
setIsAuthenticated(false);
setSessionid(null);
history.replace("/");
setLoggedInUserName("");
localStorage.removeItem('esap_logged_in')
return null;
};
......@@ -112,6 +123,15 @@ export function GlobalContextProvider({ children }) {
}
}
// compare the tokenExpiration timestamp with the current time
// to determine if the token is still valid.
const isTokenValid = () => {
let expiration = Date.parse(tokenExpiration)
let now = Date.parse(new Date())
let valid = (expiration - now) > 0
return (expiration - now)/1000
}
const handleError = (event) => {
setIsAuthenticated(false);
setSessionid(null);
......@@ -140,9 +160,9 @@ export function GlobalContextProvider({ children }) {
idToken,
accessToken,
tokenExpiration,
secondsLeft,
setSecondsLeft,
refreshLogin
refreshLogin,
isTokenValid,
loginAgain
}}
>
{children}
......
......@@ -16,7 +16,7 @@ export function QueryContextProvider({ children }) {
const [collection, setCollection] = useState();
const [config, setConfig] = useState();
const [configName, setConfigName] = useState(defaultConf);
const { api_host } = useContext(GlobalContext);
const { api_host, loginAgain } = useContext(GlobalContext);
const [preview, setPreview] = useState(false);
const [ds9, setDS9] = useState(false);
......@@ -61,6 +61,11 @@ export function QueryContextProvider({ children }) {
let description = ". Configuration not loaded. Is ESAP-API online? " + api_host
console.log(error.toString() + description)
//alert(description)
// frantic attempt to solve cors errors by trying to trigger a login
//const loginUrl = api_host + "oidc/authenticate"
//alert('(QueryContext) token expired, attempting login: '+loginUrl)
//window.location = loginUrl
loginAgain()
return false
});
......@@ -95,9 +100,13 @@ export function QueryContextProvider({ children }) {
setConfig(config);
})
.catch((error) => {
let description = ". Configuration not loaded. Is ESAP-API online? " + api_host
console.log(error.toString() + description)
//alert(description)
alert(description)
//const loginUrl = api_host + "oidc/authenticate"
// window.location = loginUrl
loginAgain()
});
return true
......
......@@ -87,7 +87,7 @@ export default function Routes() {
</Switch>
<footer><small>esap-gui version 23 aug 2021 - 15:00</small></footer>
<footer><small>esap-gui version 27 aug 2021 - 11:00</small></footer>
</Router>
);
}
import React, { useContext, useState, useRef, useEffect } from "react";
import { GlobalContext } from "../contexts/GlobalContext";
export function ShowTimeLeft() {
const { tokenExpiration } = useContext(GlobalContext);
const [timer, setTimer] = useState(undefined)
const [secondsLeft, setSecondsLeft] = useState(undefined)
useEffect(() => {
setTimer(setInterval(() => showTimeLeft(), 10000))
// this function is automatically called when the component unmounts
return function cleanup() {
clearInterval(timer);
}
},[]
);
function showTimeLeft() {
//console.log({tokenExpiration})
alert(tokenExpiration)
//let expiration = new Date(tokenExpiration)
setSecondsLeft(1)
}
alert('showtimeleft')
return (<h5>{secondsLeft}</h5>)
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment