From 5e04f56e1b7c826819ccf01dba4114bb7a7f428f Mon Sep 17 00:00:00 2001 From: alea Date: Sat, 10 Oct 2026 22:59:34 +0200 Subject: [PATCH] Koble techniques frontend til GraphQL backend --- .../src/repositories/techniqueRepository.ts | 2 + docs/referat/meeting-29-09-26.txt | 8 ++ frontend/package.json | 2 + frontend/src/apollo/client.ts | 13 +++ .../TechniqueCard/TechniqueCard.tsx | 10 +- .../TechniqueGrid/TechniqueGrid.tsx | 8 +- .../src/graphql/queries/techniqueQueries.ts | 11 ++ frontend/src/main.tsx | 7 +- frontend/src/pages/Techniques/Techniques.tsx | 64 +++++----- pnpm-lock.yaml | 110 ++++++++++++++++++ 10 files changed, 191 insertions(+), 44 deletions(-) create mode 100644 docs/referat/meeting-29-09-26.txt create mode 100644 frontend/src/apollo/client.ts create mode 100644 frontend/src/graphql/queries/techniqueQueries.ts diff --git a/backend/src/repositories/techniqueRepository.ts b/backend/src/repositories/techniqueRepository.ts index 2cb9733..52d62f6 100644 --- a/backend/src/repositories/techniqueRepository.ts +++ b/backend/src/repositories/techniqueRepository.ts @@ -29,6 +29,8 @@ export async function getAllTechniques() { mitreId: technique.mitre_id, name: technique.name, description: technique.description, + /*tactic: technique.tactic, + platform: technique.platform,*/ }) .from(technique); } diff --git a/docs/referat/meeting-29-09-26.txt b/docs/referat/meeting-29-09-26.txt new file mode 100644 index 0000000..e615a7d --- /dev/null +++ b/docs/referat/meeting-29-09-26.txt @@ -0,0 +1,8 @@ +Oppsummering + +- Vi har alle begynt på hver våre sider (som vi fordelte forrige møte) +- Vi skal begynne å skrive KI kommentarer i PR +- Jobbe med readME til neste møte (fredag) +- Se om vi kan implementere globale: card, grid og toolbar +- Legge layout til «left» istedenfor «center» +- Tenke på ideer for å oppfylle «utvidet bruker-funksjonalitet» \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 39a2208..9994474 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@apollo/client": "^4.3.3", + "graphql": "16.11.0", "lucide-react": "^1.48.0", "react": "^19.2.8", "react-country-flag": "^3.1.0", diff --git a/frontend/src/apollo/client.ts b/frontend/src/apollo/client.ts new file mode 100644 index 0000000..853885a --- /dev/null +++ b/frontend/src/apollo/client.ts @@ -0,0 +1,13 @@ +import { + ApolloClient, + InMemoryCache, + HttpLink, +} from "@apollo/client"; + +export const apolloClient = + new ApolloClient({ + link: new HttpLink({ + uri: "http://localhost:3001", + }), + cache: new InMemoryCache(), + }); \ No newline at end of file diff --git a/frontend/src/components/techniques/allTechniques/TechniqueCard/TechniqueCard.tsx b/frontend/src/components/techniques/allTechniques/TechniqueCard/TechniqueCard.tsx index 3fe287f..f501ed2 100644 --- a/frontend/src/components/techniques/allTechniques/TechniqueCard/TechniqueCard.tsx +++ b/frontend/src/components/techniques/allTechniques/TechniqueCard/TechniqueCard.tsx @@ -8,8 +8,8 @@ type TechniqueCardProps = { mitreId: string; name: string; description: string; - tactic: string; - platform: string; + tactic?: string; + platform?: string; }; function TechniqueCard({ @@ -44,16 +44,16 @@ function TechniqueCard({
- {tactic} + {tactic ?? "Unknown"} - {platform} + {platform ?? "Unknown"}
Open profile diff --git a/frontend/src/components/techniques/allTechniques/TechniqueGrid/TechniqueGrid.tsx b/frontend/src/components/techniques/allTechniques/TechniqueGrid/TechniqueGrid.tsx index f7473a7..c578097 100644 --- a/frontend/src/components/techniques/allTechniques/TechniqueGrid/TechniqueGrid.tsx +++ b/frontend/src/components/techniques/allTechniques/TechniqueGrid/TechniqueGrid.tsx @@ -5,8 +5,8 @@ type Technique = { mitreId: string; name: string; description: string; - tactic: string; - platform: string; + tactic?: string; + platform?: string; }; type TechniqueGridProps = { @@ -24,8 +24,8 @@ function TechniqueGrid({ mitreId={technique.mitreId} name={technique.name} description={technique.description} - tactic={technique.tactic} - platform={technique.platform} + tactic={technique.tactic ?? "Unknown"} + platform={technique.platform ?? "Unknown"} /> ))} diff --git a/frontend/src/graphql/queries/techniqueQueries.ts b/frontend/src/graphql/queries/techniqueQueries.ts new file mode 100644 index 0000000..d47a990 --- /dev/null +++ b/frontend/src/graphql/queries/techniqueQueries.ts @@ -0,0 +1,11 @@ +import { gql } from "@apollo/client"; + +export const GET_TECHNIQUES = gql` + query GetTechniques { + allTechniques { + mitreId + name + description + } + } +`; \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index eff7ccc..63432b1 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,10 +1,15 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; +import { ApolloProvider } from "@apollo/client/react"; + import "./index.css"; import App from "./App.tsx"; +import { apolloClient } from "./apollo/client"; createRoot(document.getElementById("root")!).render( - + + + , ); diff --git a/frontend/src/pages/Techniques/Techniques.tsx b/frontend/src/pages/Techniques/Techniques.tsx index f8499ca..5eda3af 100644 --- a/frontend/src/pages/Techniques/Techniques.tsx +++ b/frontend/src/pages/Techniques/Techniques.tsx @@ -2,42 +2,38 @@ import TechniqueGrid from "../../components/techniques/allTechniques/TechniqueGr import TechniqueToolbar from "../../components/techniques/allTechniques/TechniqueToolbar/TechniqueToolbar"; import "./Techniques.css"; +import { useQuery } from "@apollo/client/react"; +import { GET_TECHNIQUES } from "../../graphql/queries/techniqueQueries"; + +interface Technique { + mitreId: string; + name: string; + description: string; + tactic?: string; + platform?: string; +} + +interface GetTechniquesData { + allTechniques: Technique[]; +} + function Techniques() { - const techniques = [ - { - mitreId: "T1566", - name: "Phishing", - description: - "Send deceptive messages to induce victims to reveal information.", - tactic: "Initial Access", - platform: "Windows", - }, - { - mitreId: "T1059", - name: "Command and Scripting Interpreter", - description: - "Execute commands and scripts through supported interpreters.", - tactic: "Execution", - platform: "Linux", - }, - { - mitreId: "T1003", - name: "OS Credential Dumping", - description: - "Obtain account login and credential material from operating systems.", - tactic: "Credential Access", - platform: "Windows", - }, - { - mitreId: "T1027", - name: "Obfuscated Files or Information", - description: - "Hide artifacts to make detection and analysis more difficult.", - tactic: "Defense Evasion", - platform: "Cross Platform", - }, - ]; + const { + data, + loading, + error, + } = useQuery( + GET_TECHNIQUES, + ); + console.log(data); + console.log(error); + console.log(loading); + + if (loading) return

Loading...

; + if (error) return

Error: {error.message}

; + + const techniques = data?.allTechniques || []; return (
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf688a1..eb20a68 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,6 +52,12 @@ importers: frontend: dependencies: + '@apollo/client': + specifier: ^4.3.3 + version: 4.3.3(graphql@16.11.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(rxjs@7.8.2) + graphql: + specifier: 16.11.0 + version: 16.11.0 lucide-react: specifier: ^1.48.0 version: 1.48.0(react@19.3.0) @@ -124,6 +130,25 @@ packages: peerDependencies: graphql: 14.x || 15.x || 16.x + '@apollo/client@4.3.3': + resolution: {integrity: sha512-wMfOUaFKLgNsu0OMCg50gfhEHTV9/GyO7DxQvut7iSBUoePy0kvll3oWeY8KVPRfnVhYEzcwPJ/Jwz4uSe3fQA==} + peerDependencies: + graphql: ^16.0.0 || ^17.0.0 + graphql-ws: ^5.5.5 || ^6.0.3 + react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc + react-dom: ^17.0.0 || ^18.0.0 || >=19.0.0-rc + rxjs: ^7.3.0 + subscriptions-transport-ws: ^0.9.0 || ^0.11.0 + peerDependenciesMeta: + graphql-ws: + optional: true + react: + optional: true + react-dom: + optional: true + subscriptions-transport-ws: + optional: true + '@apollo/protobufjs@1.2.8': resolution: {integrity: sha512-r7xNeUqZX+eBBEmyvaPw0/cSz6zgf5jdH8mjUz8ynKpNs/GU7vi2T7sNcZINk2ZID7wwjG91FCgdpCrQuJ8rzA==} hasBin: true @@ -1243,6 +1268,22 @@ packages: resolution: {integrity: sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==} engines: {node: '>=16.0.0'} + '@wry/caches@1.0.1': + resolution: {integrity: sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==} + engines: {node: '>=8'} + + '@wry/context@0.7.4': + resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} + engines: {node: '>=8'} + + '@wry/equality@0.5.7': + resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} + engines: {node: '>=8'} + + '@wry/trie@0.5.0': + resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} + engines: {node: '>=8'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1670,6 +1711,16 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graphql-tag@2.12.7: + resolution: {integrity: sha512-xnE/NFzy+0eIesvAsREJZ284zTl/wYuBAvpsFSDhRGRdRHdnE90M21Q3xAWyYInb0J756c6x0pIQ62+vtvOs1Q==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + graphql@16.11.0: + resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + graphql@17.0.2: resolution: {integrity: sha512-FRWbddMxfkjiB7z+aQDWIR+E34xo9I8c9mtK2RPv8PmMzKRvrdsreHL/Ui/TmwHJfhHChEtsFPyMHKI+xuarQQ==} engines: {node: ^22.0.0 || ^24.0.0 || ^25.0.0 || >=26.0.0} @@ -1954,6 +2005,9 @@ packages: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} + optimism@0.18.1: + resolution: {integrity: sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2062,6 +2116,9 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -2361,6 +2418,21 @@ snapshots: dependencies: graphql: 17.0.2 + '@apollo/client@4.3.3(graphql@16.11.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(rxjs@7.8.2)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.11.0 + graphql-tag: 2.12.7(graphql@16.11.0) + optimism: 0.18.1 + rxjs: 7.8.2 + tslib: 2.8.1 + optionalDependencies: + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + '@apollo/protobufjs@1.2.8': dependencies: '@protobufjs/aspromise': 1.1.2 @@ -2864,6 +2936,10 @@ snapshots: graphql: 17.0.2 tslib: 2.8.1 + '@graphql-typed-document-node/core@3.2.0(graphql@16.11.0)': + dependencies: + graphql: 16.11.0 + '@graphql-typed-document-node/core@3.2.0(graphql@17.0.2)': dependencies: graphql: 17.0.2 @@ -3216,6 +3292,22 @@ snapshots: dependencies: tslib: 2.8.1 + '@wry/caches@1.0.1': + dependencies: + tslib: 2.8.1 + + '@wry/context@0.7.4': + dependencies: + tslib: 2.8.1 + + '@wry/equality@0.5.7': + dependencies: + tslib: 2.8.1 + + '@wry/trie@0.5.0': + dependencies: + tslib: 2.8.1 + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: acorn: 8.18.0 @@ -3639,6 +3731,13 @@ snapshots: gopd@1.2.0: {} + graphql-tag@2.12.7(graphql@16.11.0): + dependencies: + graphql: 16.11.0 + tslib: 2.8.1 + + graphql@16.11.0: {} + graphql@17.0.2: {} has-property-descriptors@1.0.2: @@ -3854,6 +3953,13 @@ snapshots: dependencies: ee-first: 1.1.1 + optimism@0.18.1: + dependencies: + '@wry/caches': 1.0.1 + '@wry/context': 0.7.4 + '@wry/trie': 0.5.0 + tslib: 2.8.1 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -3961,6 +4067,10 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.10 '@rolldown/binding-win32-x64-msvc': 1.2.10 + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {}