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: {}