Skip to content

Commit 507c803

Browse files
refactor: move all auth to context
1 parent 4a08975 commit 507c803

File tree

13 files changed

+264
-117
lines changed

13 files changed

+264
-117
lines changed

examples/playground/src/Root.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import { SpinningCircles } from "react-loading-icons"
12
import { Route, Routes } from "react-router-dom"
3+
import NavigraphLogo from "./components/NavigraphLogo"
24
import SideBar from "./components/SideBar"
3-
import useAppConfigLoader from "./hooks/useAppConfigLoader"
4-
import useUserUpdater from "./hooks/useUserUpdater"
5+
import { useNavigraphAuth } from "./hooks/useNavigraphAuth"
56
import MainWindow from "./MainWindow"
67
import Amdb from "./pages/Amdb"
78
import App from "./pages/App"
@@ -11,8 +12,16 @@ import Packages from "./pages/Packages"
1112
import Tiles from "./pages/Tiles"
1213

1314
export default function Root() {
14-
useAppConfigLoader()
15-
useUserUpdater()
15+
const { isInitialized } = useNavigraphAuth()
16+
17+
if (!isInitialized) {
18+
return (
19+
<div className="h-screen flex items-center justify-center flex-col">
20+
<NavigraphLogo />
21+
<SpinningCircles />
22+
</div>
23+
)
24+
}
1625

1726
return (
1827
<main className="flex flex-row h-screen">
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import * as React from "react"
2+
3+
function NavigraphLogo({ size = 42 }) {
4+
return (
5+
<svg width={size * (179 / 42)} height={size} viewBox="0 0 179 42" fill="none">
6+
<path d="M107.583 14.5131H104.263V28.5841H107.583V14.5131Z" fill="white" />
7+
<path
8+
fillRule="evenodd"
9+
clipRule="evenodd"
10+
d="M86.9888 14.5131H90.4998L94.5822 24.7465L98.5831 14.5131H102.121L96.1608 28.5841H93.0309L86.9888 14.5131Z"
11+
fill="white"
12+
/>
13+
<path
14+
fillRule="evenodd"
15+
clipRule="evenodd"
16+
d="M157.777 14.2037C159.002 14.2037 160.118 14.5031 161.098 15.1291C162.077 15.7551 162.839 16.626 163.411 17.7419C163.955 18.8577 164.227 20.1369 164.227 21.5522C164.227 22.9674 163.955 24.2466 163.411 25.3625C162.839 26.4784 162.077 27.3493 161.098 27.9753C160.118 28.6285 159.002 28.9279 157.777 28.9279C156.743 28.9279 155.818 28.7101 154.974 28.2475C154.13 27.812 153.45 27.186 152.878 26.3695V33.2825H149.558V14.5303H151.79L152.878 16.7621C153.45 15.9456 154.13 15.3196 154.974 14.8569C155.818 14.4215 156.743 14.2037 157.777 14.2037ZM157.151 26.0973C158.321 26.0973 159.301 25.6619 160.063 24.8182C160.825 23.9745 161.206 22.8858 161.206 21.5522C161.206 20.2186 160.825 19.1571 160.063 18.2862C159.301 17.4697 158.321 17.0342 157.151 17.0342C155.981 17.0342 155.028 17.4697 154.293 18.2862C153.531 19.1571 153.178 20.2186 153.178 21.5522C153.178 22.8858 153.531 23.9745 154.293 24.8182C155.028 25.6619 155.981 26.0973 157.151 26.0973Z"
17+
fill="white"
18+
/>
19+
<path
20+
fillRule="evenodd"
21+
clipRule="evenodd"
22+
d="M141.392 14.2037C143.243 14.2037 144.713 14.7481 145.801 15.8095C146.89 16.8982 147.434 18.3406 147.434 20.1369V28.6013H145.039L144.195 26.9138C143.678 27.5398 143.025 28.0297 142.236 28.3835C141.419 28.7646 140.603 28.9279 139.759 28.9279C138.752 28.9279 137.854 28.7374 137.065 28.3563C136.275 28.0025 135.649 27.4582 135.187 26.7778C134.724 26.0973 134.506 25.3353 134.506 24.4371C134.506 23.539 134.779 22.7225 135.296 22.0149C135.813 21.3072 136.493 20.7629 137.364 20.3547C138.235 19.9464 139.188 19.7559 140.249 19.7559C141.555 19.7559 142.862 20.0008 144.195 20.518V20.1369C144.195 19.2388 143.923 18.4767 143.379 17.8507C142.807 17.2248 141.936 16.9254 140.739 16.9254C139.623 16.9254 138.344 17.2792 136.929 17.9868V15.6734C137.827 14.8297 139.65 14.2037 141.392 14.2037ZM140.494 26.5056C141.338 26.5056 142.127 26.2879 142.862 25.8796C143.569 25.4714 144.005 24.8998 144.195 24.1922V22.6136C143.134 22.2598 141.991 22.0693 140.739 22.0693C139.895 22.0693 139.188 22.287 138.616 22.6953C138.045 23.1307 137.745 23.6751 137.745 24.3283C137.745 24.9815 137.99 25.4986 138.534 25.9068C139.052 26.3151 139.705 26.5056 140.494 26.5056Z"
23+
fill="white"
24+
/>
25+
<path
26+
fillRule="evenodd"
27+
clipRule="evenodd"
28+
d="M129.794 17.2389C130.255 16.2904 130.906 15.5587 131.8 15.0167C132.667 14.4747 133.67 14.2037 134.808 14.2037V17.0221C133.317 17.0221 132.098 17.4286 131.177 18.2416C130.255 19.0546 129.794 20.1385 129.794 21.4664V28.5394H126.488V14.5289H128.494L129.794 17.2389Z"
29+
fill="white"
30+
/>
31+
<path
32+
fillRule="evenodd"
33+
clipRule="evenodd"
34+
d="M124.172 14.5303V27.1044C124.172 28.3019 123.872 29.3633 123.246 30.3159C122.62 31.2413 121.75 31.9761 120.634 32.4932C119.518 33.0103 118.239 33.2825 116.823 33.2825C115.653 33.2825 114.537 33.1192 113.476 32.7654C112.387 32.4116 111.516 31.9761 110.781 31.4046L111.979 28.9823C112.469 29.445 113.122 29.7988 113.911 30.071C114.7 30.3159 115.49 30.452 116.333 30.452C117.721 30.452 118.81 30.1526 119.627 29.5266C120.443 28.9007 120.851 28.0569 120.851 26.9955V25.172C120.28 25.934 119.599 26.5328 118.783 26.9411C117.939 27.3493 117.041 27.567 116.034 27.567C114.837 27.567 113.748 27.2677 112.795 26.6961C111.815 26.1246 111.053 25.3353 110.509 24.3283C109.965 23.3213 109.693 22.1509 109.693 20.8718C109.693 19.5926 109.965 18.4223 110.509 17.4153C111.053 16.4083 111.815 15.619 112.795 15.0474C113.748 14.4759 114.837 14.2037 116.034 14.2037C117.041 14.2037 117.966 14.4215 118.81 14.8569C119.654 15.2924 120.334 15.8911 120.851 16.626L121.886 14.5303H124.172ZM116.551 24.7365C117.667 24.7365 118.592 24.3827 119.327 23.6479C120.035 22.913 120.416 21.9876 120.416 20.8718C120.416 19.7559 120.035 18.8305 119.327 18.0957C118.592 17.3881 117.667 17.0342 116.551 17.0342C115.435 17.0342 114.51 17.3881 113.802 18.0957C113.067 18.8305 112.714 19.7559 112.714 20.8718C112.714 21.9876 113.067 22.913 113.775 23.6479C114.483 24.3827 115.408 24.7365 116.551 24.7365Z"
35+
fill="white"
36+
/>
37+
<path
38+
fillRule="evenodd"
39+
clipRule="evenodd"
40+
d="M80.4268 14.2037C82.2775 14.2037 83.7472 14.7481 84.8359 15.8095C85.9245 16.8982 86.4689 18.3406 86.4689 20.1369V28.6013H84.0738L83.2301 26.9138C82.713 27.5398 82.0598 28.0297 81.2705 28.3835C80.454 28.7646 79.6375 28.9279 78.7938 28.9279C77.7868 28.9279 76.8886 28.7374 76.0994 28.3563C75.3101 28.0025 74.6841 27.4582 74.2214 26.7778C73.7587 26.0973 73.541 25.3353 73.541 24.4371C73.541 23.539 73.8132 22.7225 74.3303 22.0149C74.8474 21.3072 75.5278 20.7629 76.3988 20.3547C77.2697 19.9464 78.2223 19.7559 79.2837 19.7559C80.5901 19.7559 81.8965 20.0008 83.2301 20.518V20.1369C83.2301 19.2388 82.9579 18.4767 82.4136 17.8507C81.8421 17.2248 80.9711 16.9254 79.7736 16.9254C78.6577 16.9254 77.3785 17.2792 75.9633 17.9868V15.6734C76.8614 14.8297 78.6849 14.2037 80.4268 14.2037ZM79.5287 26.5056C80.3724 26.5056 81.1616 26.2879 81.8965 25.8796C82.6041 25.4714 83.0396 24.8998 83.2301 24.1922V22.6136C82.1687 22.2598 81.0256 22.0693 79.7736 22.0693C78.9299 22.0693 78.2223 22.287 77.6507 22.6953C77.0792 23.1307 76.7798 23.6751 76.7798 24.3283C76.7798 24.9815 77.0247 25.4986 77.5691 25.9068C78.0862 26.3151 78.7394 26.5056 79.5287 26.5056Z"
41+
fill="white"
42+
/>
43+
<path
44+
fillRule="evenodd"
45+
clipRule="evenodd"
46+
d="M55.2823 9.90042H58.6844L68.0469 23.046V9.90042H71.4218V28.5982H68.0469L58.6844 15.4526V28.5982H55.2823V9.90042Z"
47+
fill="white"
48+
/>
49+
<path
50+
fillRule="evenodd"
51+
clipRule="evenodd"
52+
d="M173.774 14.1897C174.781 14.1897 175.707 14.4075 176.496 14.8701C177.285 15.3328 177.884 15.986 178.347 16.8025C178.782 17.6462 179 18.5716 179 19.633V28.5873H175.788V20.2862C175.788 19.3336 175.516 18.5444 174.972 17.9184C174.4 17.3196 173.693 17.0202 172.822 17.0202C171.869 17.0202 171.08 17.3196 170.4 17.9184C169.719 18.5172 169.393 19.2248 169.393 20.0685V28.5873H166.072V9.56291H169.393V16.4487C169.828 15.7683 170.427 15.1967 171.216 14.7885C172.005 14.3802 172.849 14.1897 173.774 14.1897Z"
53+
fill="white"
54+
/>
55+
<path
56+
d="M105.923 12.2361C106.84 12.2361 107.583 11.4928 107.583 10.576C107.583 9.65922 106.84 8.916 105.923 8.916C105.006 8.916 104.263 9.65922 104.263 10.576C104.263 11.4928 105.006 12.2361 105.923 12.2361Z"
57+
fill="white"
58+
/>
59+
<path
60+
fillRule="evenodd"
61+
clipRule="evenodd"
62+
d="M21.0352 19.4971C21.4548 19.4963 27.0103 14.0407 27.0103 13.5222C27.0103 12.576 22.0809 0 21.0352 0C19.9417 6.49475 19.7202 12.993 21.0352 19.4971Z"
63+
fill="#DF362C"
64+
/>
65+
<path
66+
fillRule="evenodd"
67+
clipRule="evenodd"
68+
d="M21.035 0C20.1574 0 16.4699 8.85944 15.3076 12.2658C15.085 12.9179 14.9551 13.3701 14.9551 13.5222C14.9551 14.0413 20.6153 19.4978 21.035 19.4971V0Z"
69+
fill="#A6302B"
70+
/>
71+
<path
72+
fillRule="evenodd"
73+
clipRule="evenodd"
74+
d="M22.5023 21.0416C22.5031 21.4612 27.9589 27.0167 28.4774 27.0167C29.4236 27.0167 42 22.0873 42 21.0416C35.5051 19.9481 29.0066 19.7266 22.5023 21.0416Z"
75+
fill="#9BA2AA"
76+
/>
77+
<path
78+
fillRule="evenodd"
79+
clipRule="evenodd"
80+
d="M42 21.041C42 20.1634 33.1403 16.4758 29.7339 15.3135C29.0817 15.091 28.6295 14.9611 28.4774 14.9611C27.9582 14.9611 22.5016 20.6213 22.5023 21.041H42Z"
81+
fill="#D7DADF"
82+
/>
83+
<path
84+
fillRule="evenodd"
85+
clipRule="evenodd"
86+
d="M20.9578 22.5029C20.5382 22.5037 14.9827 27.9593 14.9827 28.4778C14.9827 29.424 19.9121 42 20.9578 42C22.0512 35.5053 22.2728 29.007 20.9578 22.5029Z"
87+
fill="#9BA2AA"
88+
/>
89+
<path
90+
fillRule="evenodd"
91+
clipRule="evenodd"
92+
d="M20.9579 42C21.8355 42 25.5231 33.1406 26.6854 29.7342C26.9079 29.0821 27.0378 28.6299 27.0378 28.4778C27.0378 27.9587 21.3776 22.5022 20.9579 22.5029L20.9579 42Z"
93+
fill="#D7DADF"
94+
/>
95+
<path
96+
fillRule="evenodd"
97+
clipRule="evenodd"
98+
d="M19.4977 20.9635C19.4969 20.5439 14.0411 14.9884 13.5226 14.9884C12.5764 14.9884 0 19.9178 0 20.9635C6.49494 22.057 12.9934 22.2785 19.4977 20.9635Z"
99+
fill="#D7DADF"
100+
/>
101+
<path
102+
fillRule="evenodd"
103+
clipRule="evenodd"
104+
d="M0 20.9641C0 21.8418 8.85971 25.5293 12.2661 26.6916C12.9183 26.9142 13.3705 27.0441 13.5226 27.0441C14.0418 27.0441 19.4984 21.3838 19.4977 20.9641H0Z"
105+
fill="#9BA2AA"
106+
/>
107+
</svg>
108+
)
109+
}
110+
111+
export default React.memo(NavigraphLogo)

examples/playground/src/components/SideBar.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import { IconType } from "react-icons"
44
import { FaDatabase, FaDownload, FaGlobe, FaMap, FaUser } from "react-icons/fa"
55
import { MdOutlineSettings } from "react-icons/md"
66
import { NavLink } from "react-router-dom"
7-
import { useRecoilValue } from "recoil"
8-
import { appState } from "../state/app"
9-
import { userState } from "../state/user"
7+
import { useNavigraphAuth } from "../hooks/useNavigraphAuth"
108

119
interface SideBarLinkProps {
1210
path: string
@@ -41,16 +39,14 @@ function SideBarLink({ path, children, icon: Icon, disabled }: SideBarLinkProps)
4139
}
4240

4341
export default function SideBar() {
44-
const app = useRecoilValue(appState)
45-
46-
const user = useRecoilValue(userState)
42+
const { user, auth } = useNavigraphAuth()
4743

4844
return (
4945
<div className="flex flex-col w-20 p-3 gap-5">
5046
<SideBarLink path="/app" icon={MdOutlineSettings}>
5147
App
5248
</SideBarLink>
53-
<SideBarLink path="/auth" icon={FaUser} disabled={!app}>
49+
<SideBarLink path="/auth" icon={FaUser} disabled={!auth}>
5450
Auth
5551
</SideBarLink>
5652
<SideBarLink path="/tiles" icon={FaGlobe} disabled={!user?.scope.includes(Scope.TILES)}>

examples/playground/src/components/map/index.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ import { LatLngBounds, Map } from "leaflet"
55
import { useEffect, useMemo, useRef } from "react"
66
import { ImageOverlay, MapContainer, TileLayer, useMap } from "react-leaflet"
77
import { useRecoilState, useRecoilValue } from "recoil"
8-
import { appState } from "../../state/app"
9-
import { userState } from "../../state/user"
108
import "leaflet/dist/leaflet.css"
119
import { calculateChartBounds, getChartsAPI } from "@navigraph/charts"
1210
import { useQuery } from "@tanstack/react-query"
1311
import { TbCircleX } from "react-icons/tb"
12+
import { useNavigraphAuth } from "../../hooks/useNavigraphAuth"
1413
import { chartOverlayOpacityState, chartOverlayState } from "../../state/chartOverlay"
1514
import {
1615
mapCenterState,
@@ -151,8 +150,7 @@ export default function MapPane() {
151150
}
152151
}, [mapCenter])
153152

154-
const app = useRecoilValue(appState)
155-
const user = useRecoilValue(userState)
153+
const { auth, user } = useNavigraphAuth()
156154

157155
const [mapVisible, setMapVisible] = useRecoilState(mapVisibleState)
158156

@@ -170,8 +168,8 @@ export default function MapPane() {
170168
setInterval(() => mapRef.current?.invalidateSize(), 1000)
171169
}}>
172170
{mapVisible &&
173-
(app && user?.scope.includes(Scope.TILES) ? (
174-
<NavigraphTiles auth={app.auth} />
171+
(auth && user?.scope.includes(Scope.TILES) ? (
172+
<NavigraphTiles auth={auth} />
175173
) : (
176174
<TileLayer
177175
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'

examples/playground/src/components/protectedPage.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import { getChartsAPI } from "@navigraph/charts"
55
import { getPackagesAPI } from "@navigraph/packages"
66
import { ReactNode } from "react"
77
import { useNavigate } from "react-router-dom"
8-
import { useRecoilValue } from "recoil"
9-
import { appState } from "../state/app"
10-
import { userState } from "../state/user"
8+
import { useNavigraphAuth } from "../hooks/useNavigraphAuth"
119

1210
interface PropsStruct {
1311
[Scope.AMDB]: ReturnType<typeof getAmdbAPI>
@@ -24,11 +22,9 @@ export function protectedPage<P extends object, S extends Scope[]>(
2422
return (props: P) => {
2523
const navigate = useNavigate()
2624

27-
const app = useRecoilValue(appState)
25+
const { auth, user } = useNavigraphAuth()
2826

29-
const user = useRecoilValue(userState)
30-
31-
if (!app || !user || !requiredScopes.every(scope => user.scope.includes(scope))) {
27+
if (!auth || !user || !requiredScopes.every(scope => user.scope.includes(scope))) {
3228
navigate("/")
3329
return null
3430
}
@@ -40,7 +36,7 @@ export function protectedPage<P extends object, S extends Scope[]>(
4036
return (
4137
<Component
4238
user={user}
43-
auth={app.auth}
39+
auth={auth}
4440
amdb={amdb}
4541
charts={charts}
4642
fmsdata={fmsdata}

examples/playground/src/hooks/useAppConfigLoader.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { initializeApp, NavigraphApp } from "@navigraph/app"
2+
import { getAuth, NavigraphAuth, User } from "navigraph/auth"
3+
import React, { createContext, useContext, useEffect, useMemo, useState } from "react"
4+
5+
interface NavigraphAuthContext {
6+
isInitialized: boolean
7+
user: User | null
8+
app: NavigraphApp | null
9+
setApp: (app: NavigraphApp | null) => void
10+
auth?: NavigraphAuth
11+
}
12+
13+
const authContext = createContext<NavigraphAuthContext>({
14+
isInitialized: false,
15+
user: null,
16+
app: null,
17+
setApp: () => {
18+
throw new Error("Not initialized")
19+
},
20+
})
21+
22+
/**
23+
* Provides authentication and app config state, along with handling loading of credentials from local storage and providing user object
24+
*
25+
* Please do not use this code as an example, app configuration should not be dynamic, it is just for ease of use in the running playground
26+
*
27+
* ! This is NOT how app configuration and auth should be handled in your application. App Configuration should be done with an environment config and the app should be initialised near the entry
28+
* ! point of your application and only happen ONCE.
29+
*/
30+
export function NavigraphAuthProvider({ children }: { children: React.ReactNode }) {
31+
const [app, setApp] = useState<NavigraphApp | null>(null)
32+
const [user, setUser] = useState<User | null>(null)
33+
const [isInitialized, setIsInitialized] = useState(false)
34+
35+
const auth = useMemo(() => {
36+
if (app) {
37+
return getAuth()
38+
} else {
39+
// Absolutely do not do this in a real app, this is just for faking the time usually taken for loading a refresh token when the app hasn been already initialised for consistency, so that theres always a navigraph loading screen
40+
setTimeout(() => {
41+
setIsInitialized(true)
42+
}, 500)
43+
}
44+
}, [app])
45+
46+
// Subscribe to user changes on mount
47+
// Whenever a user is signed in or out, this hook will respond to the change.
48+
useEffect(() => {
49+
const unsubscribe = auth?.onAuthStateChanged(u => {
50+
setUser(u)
51+
setIsInitialized(true)
52+
})
53+
54+
// Cleanup subscription on unmount
55+
return () => unsubscribe?.()
56+
}, [auth])
57+
58+
// Handle loading client credentials from Config
59+
useEffect(() => {
60+
if (app) return
61+
62+
const data = localStorage.getItem("NG_CONFIG")
63+
64+
if (!data) return
65+
66+
const config = JSON.parse(data) as NavigraphApp
67+
68+
initializeApp(config)
69+
setApp(config)
70+
}, [app, setApp])
71+
72+
return (
73+
<authContext.Provider
74+
value={{
75+
user,
76+
isInitialized,
77+
app,
78+
setApp: app => {
79+
if (app) {
80+
initializeApp(app)
81+
82+
localStorage.setItem("NG_CONFIG", JSON.stringify(app))
83+
} else {
84+
void auth?.signOut()
85+
86+
localStorage.removeItem("NG_CONFIG")
87+
}
88+
setApp(app)
89+
},
90+
auth,
91+
}}>
92+
{children}
93+
</authContext.Provider>
94+
)
95+
}
96+
97+
// Hook for child components to access the authentication state
98+
export const useNavigraphAuth = () => useContext(authContext)

examples/playground/src/hooks/useUserUpdater.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)