diff --git a/package-lock.json b/package-lock.json index 2eeab23..df946d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "zwd-frontend", "version": "0.0.1", "dependencies": { - "@amsterdam/design-system-react": "^0.10.0", + "@amsterdam/design-system-react": "^0.11.0", "@types/lodash.get": "^4.4.9", "@types/qs": "^6.9.15", "@types/react": "^18.3.3", @@ -27,7 +27,7 @@ "styled-components": "^6.1.11", "ts-node": "^10.9.2", "typescript": "^5.5.4", - "vite": "^5.3.1" + "vite": "^5.3.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^7.13.1", @@ -48,29 +48,32 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/@amsterdam/design-system-assets/-/design-system-assets-0.2.1.tgz", "integrity": "sha512-byLLmmF1cv2niZMXETV30nprypZY8bAFpNKKuRlmYlIREA6blz9kVIJsQeH3IldmClW1mNa8ccJN4EKJglnuRw==", + "license": "SEE LICENSE IN LICENSE.md", "peer": true }, "node_modules/@amsterdam/design-system-css": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@amsterdam/design-system-css/-/design-system-css-0.10.0.tgz", - "integrity": "sha512-cj0FV9tek1IvjjWjF1VugsQQc2Newv0M58+brvFcMVLi39yyNUMi/82SDrRG2JTmC0zhd2ocvBjZ6iIe3QMK0w==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@amsterdam/design-system-css/-/design-system-css-0.11.0.tgz", + "integrity": "sha512-f7HIkxmvkg6O75AaK1AnsPMsCMulCGHk847TrhRY3xFN+IXBaQUQyJiqLdFYa4GVhgA5vVXZO9WgNUSc7lnDQA==", + "license": "EUPL-1.2", "peer": true, "peerDependencies": { "@amsterdam/design-system-assets": "0.2.1", - "@amsterdam/design-system-tokens": "0.10.0" + "@amsterdam/design-system-tokens": "0.11.0" } }, "node_modules/@amsterdam/design-system-react": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@amsterdam/design-system-react/-/design-system-react-0.10.0.tgz", - "integrity": "sha512-Qnh56pambks8mzqE3alkyknTD4NRHwR8IOjK7+Ckr+9+RvezCTygDZDCrEb5kbmbnbtyJRYpHbOQxzeXKlm1fA==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@amsterdam/design-system-react/-/design-system-react-0.11.0.tgz", + "integrity": "sha512-LXZMajnhScYqZ1f+Di4Ta9+xXESsBqjVscrw95X49W/SaMr+K8L2CzbhLhAVmTUeqhM7JACcB5Fz+iXe/S8Rbw==", + "license": "EUPL-1.2", "dependencies": { "@amsterdam/design-system-react-icons": "0.1.12", - "@babel/runtime": "7.24.7", + "@babel/runtime": "7.24.8", "clsx": "2.1.1" }, "peerDependencies": { - "@amsterdam/design-system-css": "0.10.0", + "@amsterdam/design-system-css": "0.11.0", "react": "16 - 18", "react-dom": "16 - 18" } @@ -85,15 +88,17 @@ } }, "node_modules/@amsterdam/design-system-tokens": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@amsterdam/design-system-tokens/-/design-system-tokens-0.10.0.tgz", - "integrity": "sha512-QAyqmsZQXF21tbw8gVoe7zaUzIKh/GJYGCEqY8k63g35LH7qGiMZbqffLv1XCSDI+Abd7dW81T1sg/LZNkMaaw==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@amsterdam/design-system-tokens/-/design-system-tokens-0.11.0.tgz", + "integrity": "sha512-LgF8u5EDhNpjdhF4doaojoPV/cLJYWJR0ZPcJpJjjkkfKRsesEtO8cTZIQBCDMpXwvRUIuw7henmipdueLtsww==", + "license": "SEE LICENSE IN LICENSE.md", "peer": true }, "node_modules/@babel/runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -4359,7 +4364,8 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", @@ -5117,9 +5123,9 @@ "license": "MIT" }, "node_modules/vite": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", - "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", + "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.39", diff --git a/package.json b/package.json index c204491..f6b5868 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "preview": "vite preview" }, "dependencies": { - "@amsterdam/design-system-react": "^0.10.0", + "@amsterdam/design-system-react": "^0.11.0", "@types/lodash.get": "^4.4.9", "@types/qs": "^6.9.15", "@types/react": "^18.3.3", @@ -36,7 +36,7 @@ "styled-components": "^6.1.11", "ts-node": "^10.9.2", "typescript": "^5.5.4", - "vite": "^5.3.1" + "vite": "^5.3.5" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^7.13.1", diff --git a/src/app/state/rest/cases.ts b/src/app/state/rest/cases.ts index fd09214..e1f9883 100644 --- a/src/app/state/rest/cases.ts +++ b/src/app/state/rest/cases.ts @@ -9,6 +9,7 @@ export const useCases = (options?: Options) => { ...options, url: `${ makeApiUrl("cases") }`, groupName: "cases", - handleError + handleError, + isProtected: true }) } diff --git a/src/app/state/rest/hooks/useApiRequest.ts b/src/app/state/rest/hooks/useApiRequest.ts index 9a97266..af029f5 100644 --- a/src/app/state/rest/hooks/useApiRequest.ts +++ b/src/app/state/rest/hooks/useApiRequest.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useContext } from "react" import { ApiContext } from "../provider/ApiProvider" import { ApiGroup } from "../index" -import useRequest, { RequestError } from "./useRequest" +import useRequestWrapper, { RequestError } from "./useRequestWrapper" type GetOptions = { method: "get" @@ -33,7 +33,7 @@ type Config = { handleError?: (error: RequestError) => void } -const useApiRequest = >({ url, groupName, handleError, lazy, keepUsingInvalidCache }: Config) => { +const useApiRequest = >({ url, groupName, isProtected, handleError, lazy, keepUsingInvalidCache }: Config) => { const { getCacheItem, setCacheItem, @@ -44,7 +44,7 @@ const useApiRequest = >({ url, groupName, hand isRequestPendingInQueue } = useContext(ApiContext)[groupName] - const request = useRequest() + const request = useRequestWrapper(isProtected) /** * Executes an API request diff --git a/src/app/state/rest/hooks/useProtectedRequest.ts b/src/app/state/rest/hooks/useProtectedRequest.ts new file mode 100644 index 0000000..b466569 --- /dev/null +++ b/src/app/state/rest/hooks/useProtectedRequest.ts @@ -0,0 +1,39 @@ +import { useCallback } from "react" +import { useAuth } from "react-oidc-context" +import useRequest, { Method } from "./useRequest" + + +const useProtectedRequest = () => { + const request = useRequest() + const auth = useAuth() + const token = auth.user?.access_token + + return useCallback( + async (method: Method, url: string, data?: unknown, additionalHeaders = {}) => { + try { + // TODO: What if token expires? + const headers = { + Authorization: `Bearer ${ token }`, + ...additionalHeaders + } + const response = await request( + method, + url, + data, + headers + ) + return response + } catch (error) { + console.log("Error protected request:", error) + // switch ((error as RequestError)?.response?.status) { + // case 401: keycloak.logout(); break + // case 403: navigateTo("/auth"); break + // } + if (error !== undefined) throw error + } + }, + [token, request] + ) +} + +export default useProtectedRequest diff --git a/src/app/state/rest/hooks/useRequest.ts b/src/app/state/rest/hooks/useRequest.ts index 7bdcac4..112c59a 100644 --- a/src/app/state/rest/hooks/useRequest.ts +++ b/src/app/state/rest/hooks/useRequest.ts @@ -4,7 +4,7 @@ import axios, { Method, AxiosError } from "axios" export type { Method } from "axios" export type RequestError = AxiosError -export default () => useCallback( +export const useRequest = () => useCallback( async (method: Method, url: string, data?: unknown, headers = {}) => await axios.request({ method, @@ -14,3 +14,5 @@ export default () => useCallback( }), [] ) + +export default useRequest diff --git a/src/app/state/rest/hooks/useRequestWrapper.ts b/src/app/state/rest/hooks/useRequestWrapper.ts new file mode 100644 index 0000000..5cb89aa --- /dev/null +++ b/src/app/state/rest/hooks/useRequestWrapper.ts @@ -0,0 +1,11 @@ + +import useRequest from "./useRequest" +import useProtectedRequest from "./useProtectedRequest" +export type { RequestError, Method } from "./useRequest" + +export default (isProtected?: boolean) => { + const request = useRequest() + const protectedRequest = useProtectedRequest() + + return isProtected ? protectedRequest : request +}