Skip to content

Commit 737da69

Browse files
authored
Merge pull request #1633 from solita-topip/feature/session-expired-logout
Add session expired dialog
2 parents a6778bd + e6e8836 commit 737da69

File tree

9 files changed

+85
-2
lines changed

9 files changed

+85
-2
lines changed

src/auth/auth.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ vi.mock("react-oidc-context", async () => {
2121
},
2222
signoutRedirect: () => Promise.resolve(),
2323
signinRedirect: () => Promise.resolve(),
24+
events: {
25+
addAccessTokenExpired: () => {},
26+
},
2427
}),
2528
};
2629
});
@@ -79,4 +82,11 @@ describe("useAuth", () => {
7982
result.current.logout({ returnTo: "/" }),
8083
).resolves.not.toThrowError();
8184
});
85+
86+
test("addAccessTokenExpiredCb", async () => {
87+
const { result } = testHook();
88+
expect(
89+
typeof result.current.addAccessTokenExpiredCallback === "function",
90+
).toBeTruthy();
91+
});
8292
});

src/auth/auth.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,22 @@ export interface Auth {
1818
getAccessToken: () => Promise<string>;
1919
logout: ({ returnTo }: { returnTo?: string }) => Promise<void>;
2020
login: (redirectUri?: string) => Promise<void>;
21+
addAccessTokenExpiredCallback: (cb: () => void) => () => void;
2122
}
2223

2324
/**
2425
* Wraps the useAuth hook from react-oidc-context and returns a facade for
2526
* the auth state.
2627
*/
2728
export const useAuth = (): Auth => {
28-
const { isLoading, isAuthenticated, user, signoutRedirect, signinRedirect } =
29-
useOidcAuth();
29+
const {
30+
isLoading,
31+
isAuthenticated,
32+
user,
33+
signoutRedirect,
34+
signinRedirect,
35+
events,
36+
} = useOidcAuth();
3037

3138
const { claimsNamespace, preferredNameNamespace } = useConfig();
3239

@@ -66,6 +73,7 @@ export const useAuth = (): Auth => {
6673
getAccessToken,
6774
logout,
6875
login,
76+
addAccessTokenExpiredCallback: events.addAccessTokenExpired.bind(events),
6977
};
7078
};
7179

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Button from "@mui/material/Button";
2+
import ButtonGroup from "@mui/material/ButtonGroup";
3+
import Dialog from "@mui/material/Dialog";
4+
import DialogActions from "@mui/material/DialogActions";
5+
import DialogContent from "@mui/material/DialogContent";
6+
import DialogTitle from "@mui/material/DialogTitle";
7+
import { useEffect, useState } from "react";
8+
import { injectIntl, IntlShape } from "react-intl";
9+
import { useAuth } from "../../auth/auth";
10+
11+
interface SessionExpiredDialogProps {
12+
intl: IntlShape;
13+
}
14+
15+
const SessionExpiredDialog = ({ intl }: SessionExpiredDialogProps) => {
16+
const { login, logout, addAccessTokenExpiredCallback } = useAuth();
17+
const { formatMessage } = intl;
18+
const [showSessionExpiredDialog, setShowSessionExpiredDialog] =
19+
useState(false);
20+
21+
useEffect(() => {
22+
return addAccessTokenExpiredCallback(() =>
23+
setShowSessionExpiredDialog(true),
24+
);
25+
}, [setShowSessionExpiredDialog, addAccessTokenExpiredCallback]);
26+
27+
return (
28+
<Dialog open={showSessionExpiredDialog}>
29+
<DialogTitle>
30+
{formatMessage({ id: "session_expired_title" })}
31+
</DialogTitle>
32+
<DialogContent>
33+
{formatMessage({ id: "session_expired_body" })}
34+
</DialogContent>
35+
<DialogActions>
36+
<ButtonGroup fullWidth sx={{ justifyContent: "space-between", gap: 2 }}>
37+
<Button
38+
variant="text"
39+
onClick={() => logout({ returnTo: window.location.origin })}
40+
color="secondary"
41+
>
42+
{formatMessage({ id: "log_out" })}
43+
</Button>
44+
<Button variant="text" onClick={() => login()} color="primary">
45+
{formatMessage({ id: "log_in" })}
46+
</Button>
47+
</ButtonGroup>
48+
</DialogActions>
49+
</Dialog>
50+
);
51+
};
52+
53+
export default injectIntl(SessionExpiredDialog);

src/containers/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { useDispatch } from "react-redux";
2525
import { StopPlaceActions, UserActions } from "../actions";
2626
import { fetchUserPermissions, updateAuth } from "../actions/UserActions";
2727
import { useAuth } from "../auth/auth";
28+
import SessionExpiredDialog from "../components/Dialogs/SessionExpiredDialog";
2829
import Header from "../components/Header/Header";
2930
import { OPEN_STREET_MAP } from "../components/Map/mapDefaults";
3031
import SnackbarWrapper from "../components/SnackbarWrapper";
@@ -125,6 +126,7 @@ const App = ({ children }) => {
125126
<Header config={config} />
126127
{children}
127128
<SnackbarWrapper />
129+
<SessionExpiredDialog />
128130
</div>
129131
</ComponentToggle>
130132
</StyledEngineProvider>

src/static/lang/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@
401401
"seconds": "seconds",
402402
"set_centroid": "Change coordinates",
403403
"set_coordinates_prompt": "Set coordinates for stop",
404+
"session_expired_title": "Session expired",
405+
"session_expired_body": "Please log in again to continue using the service",
404406
"settings": "Settings",
405407
"show_compass_bearing": "Show compass bearing",
406408
"show_expired_stops": "Show expired stop places",

src/static/lang/fi.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@
399399
"search_result_future": "Voimassa tulevaisuudessa",
400400
"second": "sekunti",
401401
"seconds": "sekuntia",
402+
"session_expired_title": "Sessio on vanhentunut",
403+
"session_expired_body": "Kirjaudu uudelleen sisään jatkaaksesi palvelun käyttöä",
402404
"set_centroid": "Vaihda koordinaatit",
403405
"set_coordinates_prompt": "Aseta pysäkin koordinaatit",
404406
"settings": "Asetukset",

src/static/lang/fr.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@
399399
"search_result_permanently_terminated": "Désactivé de manière définitive",
400400
"second": "seconde",
401401
"seconds": "secondes",
402+
"session_expired_title": "Session expirée",
403+
"session_expired_body": "Veuillez vous reconnecter pour continuer à utiliser le service",
402404
"set_centroid": "Modifier les coordonnées",
403405
"set_coordinates_prompt": "Définir les coordonnées pour ce point",
404406
"settings": "Paramètres",

src/static/lang/nb.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@
399399
"search_result_permanently_terminated": "Nedlagt",
400400
"second": "sekund",
401401
"seconds": "sekunder",
402+
"session_expired_title": "Innloggingsøkten har utløpt",
403+
"session_expired_body": "Logg inn på nytt for å fortsette å bruke tjenesten",
402404
"set_centroid": "Sett koordinater",
403405
"set_coordinates_prompt": "Sett koordinater for stopp",
404406
"settings": "Innstillinger",

src/static/lang/sv.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@
399399
"search_result_permanently_terminated": "Nedlagd",
400400
"second": "sekund",
401401
"seconds": "sekunder",
402+
"session_expired_title": "Sessionen har löpt ut",
403+
"session_expired_body": "Logga in igen för att fortsätta använda tjänsten",
402404
"set_centroid": "Ändra koordinater",
403405
"set_coordinates_prompt": "Ändra koordinater för hållplats",
404406
"settings": "Inställningar",

0 commit comments

Comments
 (0)