Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remember defences between phase 2 and sandbox #236

Merged
merged 2 commits into from
Sep 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 101 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@ import { PHASE_NAMES } from "./models/phase";
import {
getChatHistory,
clearChat,
addMessageToChatHistory,
} from "./service/chatService";
import { EmailInfo } from "./models/email";
import { clearEmails, getSentEmails } from "./service/emailService";
import { CHAT_MESSAGE_TYPE, ChatMessage } from "./models/chat";
import { resetActiveDefences } from "./service/defenceService";
import {
activateDefence,
configureDefence,
deactivateDefence,
getDefences,
resetActiveDefences,
} from "./service/defenceService";
import { DEFENCE_DETAILS_ALL, DEFENCE_DETAILS_PHASE } from "./Defences";
import { DefenceInfo } from "./models/defence";
import { DefenceConfig, DefenceInfo } from "./models/defence";
import { getCompletedPhases } from "./service/phaseService";
import { PHASES } from "./Phases";

Expand Down Expand Up @@ -97,7 +104,95 @@ function App() {
newPhase === PHASE_NAMES.PHASE_2
? DEFENCE_DETAILS_PHASE
: DEFENCE_DETAILS_ALL;
setDefencesToShow(defences);
// fetch defences from backend
getDefences(newPhase).then((remoteDefences) => {
defences.map((localDefence) => {
const matchingRemoteDefence = remoteDefences.find((remoteDefence) => {
return localDefence.id === remoteDefence.id;
});
if (matchingRemoteDefence) {
localDefence.isActive = matchingRemoteDefence.isActive;
// set each config value
if (matchingRemoteDefence.config && localDefence.config) {
matchingRemoteDefence.config.forEach((configEntry) => {
// get the matching config in the local defence
const matchingConfig = localDefence.config.find((config) => {
return config.id === configEntry.id;
});
if (matchingConfig) {
matchingConfig.value = configEntry.value;
}
});
}
}
return localDefence;
});
setDefencesToShow(defences);
});
};

const addInfoMessage = (message: string) => {
addChatMessage({
message: message,
type: CHAT_MESSAGE_TYPE.INFO,
});
addMessageToChatHistory(message, CHAT_MESSAGE_TYPE.INFO, currentPhase);
};

const setDefenceActive = (defence: DefenceInfo) => {
activateDefence(defence.id, currentPhase).then(() => {
// update state
const newDefenceDetails = defencesToShow.map((defenceDetail) => {
if (defenceDetail.id === defence.id) {
defenceDetail.isActive = true;
defenceDetail.isTriggered = false;
const infoMessage = `${defence.name} defence activated`;
addInfoMessage(infoMessage.toLowerCase());
}
return defenceDetail;
});
setDefencesToShow(newDefenceDetails);
});
};

const setDefenceInactive = (defence: DefenceInfo) => {
deactivateDefence(defence.id, currentPhase).then(() => {
// update state
const newDefenceDetails = defencesToShow.map((defenceDetail) => {
if (defenceDetail.id === defence.id) {
defenceDetail.isActive = false;
defenceDetail.isTriggered = false;
const infoMessage = `${defence.name} defence deactivated`;
addInfoMessage(infoMessage.toLowerCase());
}
return defenceDetail;
});
setDefencesToShow(newDefenceDetails);
});
};

const setDefenceConfiguration = (
defenceId: string,
config: DefenceConfig[]
) => {
const configSuccess = configureDefence(
defenceId,
config,
currentPhase
).then((success) => {
if (success) {
// update state
const newDefences = defencesToShow.map((defence) => {
if (defence.id === defenceId) {
defence.config = config;
}
return defence;
});
setDefencesToShow(newDefences);
}
return success;
});
return configSuccess;
};

return (
Expand All @@ -117,6 +212,9 @@ function App() {
messages={messages}
addChatMessage={addChatMessage}
resetPhase={resetPhase}
setDefenceActive={setDefenceActive}
setDefenceInactive={setDefenceInactive}
setDefenceConfiguration={setDefenceConfiguration}
setEmails={setEmails}
setNumCompletedPhases={setNumCompletedPhases}
/>
Expand Down
112 changes: 10 additions & 102 deletions frontend/src/components/DefenceBox/DefenceBox.tsx
Original file line number Diff line number Diff line change
@@ -1,124 +1,32 @@
import { useEffect, useState } from "react";
import "../StrategyBox/StrategyBox.css";
import DefenceMechanism from "./DefenceMechanism";
import {
getDefences,
activateDefence,
deactivateDefence,
configureDefence,
} from "../../service/defenceService";
import { DefenceConfig, DefenceInfo } from "../../models/defence";

function DefenceBox({
currentPhase,
defences,
showConfigurations,
defenceActivated,
defenceDeactivated,
setDefenceActive,
setDefenceInactive,
setDefenceConfiguration,
}: {
currentPhase: number;
defences: DefenceInfo[];
showConfigurations: boolean;
defenceActivated: (defenceInfo: DefenceInfo) => void;
defenceDeactivated: (defenceInfo: DefenceInfo) => void;
}) {
// list of defence mechanisms
const [defenceDetails, setDefenceDetails] = useState(defences);

useEffect(() => {
setDefenceDetails(defences);
}, [defences]);

// called on mount & when defences are updated
useEffect(() => {
// fetch defences from backend
getDefences(currentPhase).then((remoteDefences) => {
defenceDetails.map((localDefence) => {
const matchingRemoteDefence = remoteDefences.find((remoteDefence) => {
return localDefence.id === remoteDefence.id;
});
if (matchingRemoteDefence) {
localDefence.isActive = matchingRemoteDefence.isActive;
// set each config value
if (matchingRemoteDefence.config && localDefence.config) {
matchingRemoteDefence.config.forEach((configEntry) => {
// get the matching config in the local defence
const matchingConfig = localDefence.config.find((config) => {
return config.id === configEntry.id;
});
if (matchingConfig) {
matchingConfig.value = configEntry.value;
}
});
}
}
return localDefence;
});
});
}, [defences]);

const setDefenceActive = (defenceType: string) => {
activateDefence(defenceType, currentPhase).then(() => {
// update state
const newDefenceDetails = defenceDetails.map((defenceDetail) => {
if (defenceDetail.id === defenceType) {
defenceDetail.isActive = true;
defenceDetail.isTriggered = false;
defenceActivated(defenceDetail);
}
return defenceDetail;
});
setDefenceDetails(newDefenceDetails);
});
};

const setDefenceInactive = (defenceType: string) => {
deactivateDefence(defenceType, currentPhase).then(() => {
// update state
const newDefenceDetails = defenceDetails.map((defenceDetail) => {
if (defenceDetail.id === defenceType) {
defenceDetail.isActive = false;
defenceDetail.isTriggered = false;
defenceDeactivated(defenceDetail);
}
return defenceDetail;
});
setDefenceDetails(newDefenceDetails);
});
};

const setDefenceConfiguration = (
setDefenceActive: (defence: DefenceInfo) => void;
setDefenceInactive: (defence: DefenceInfo) => void;
setDefenceConfiguration: (
defenceId: string,
config: DefenceConfig[]
) => {
const configSuccess = configureDefence(
defenceId,
config,
currentPhase
).then((success) => {
if (success) {
// update state
const newDefences = defenceDetails.map((defence) => {
if (defence.id === defenceId) {
defence.config = config;
}
return defence;
});
setDefenceDetails(newDefences);
}
return success;
});
return configSuccess;
};

) => Promise<boolean>;
}) {
return (
<div id="strategy-box">
<div className="side-bar-header">Defences</div>
{defenceDetails.map((defenceDetail, index) => {
{defences.map((defence, index) => {
return (
<DefenceMechanism
key={index}
defenceDetail={defenceDetail}
defenceDetail={defence}
showConfigurations={showConfigurations}
setDefenceActive={setDefenceActive}
setDefenceInactive={setDefenceInactive}
Expand Down
16 changes: 8 additions & 8 deletions frontend/src/components/DefenceBox/DefenceMechanism.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ function DefenceMechanism({
}: {
defenceDetail: DefenceInfo;
showConfigurations: boolean;
setDefenceActive: (defenceId: string) => void;
setDefenceInactive: (defenceId: string) => void;
setDefenceActive: (defence: DefenceInfo) => void;
setDefenceInactive: (defence: DefenceInfo) => void;
setDefenceConfiguration: (
defenceId: string,
config: DefenceConfig[]
Expand Down Expand Up @@ -68,14 +68,14 @@ function DefenceMechanism({
>
<div className="strategy-mechanism-header">
<span>{defenceDetail.name}</span>
<label className="switch" >
<input
type="checkbox"
placeholder="defence-toggle"
<label className="switch">
<input
type="checkbox"
placeholder="defence-toggle"
onChange={() => {
defenceDetail.isActive
? setDefenceInactive(defenceDetail.id)
: setDefenceActive(defenceDetail.id);
? setDefenceInactive(defenceDetail)
: setDefenceActive(defenceDetail);
}}
// set checked if defence is active
checked={defenceDetail.isActive}
Expand Down
38 changes: 14 additions & 24 deletions frontend/src/components/MainComponent/DemoBody.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./DemoBody.css";
import { ATTACKS_PHASE_1, ATTACKS_ALL } from "../../Attacks";
import { ChatMessage, CHAT_MESSAGE_TYPE } from "../../models/chat";
import { DefenceInfo } from "../../models/defence";
import { ChatMessage } from "../../models/chat";
import { DefenceConfig, DefenceInfo } from "../../models/defence";
import { PHASE_NAMES } from "../../models/phase";
import AttackBox from "../AttackBox/AttackBox";
import ChatBox from "../ChatBox/ChatBox";
Expand All @@ -10,7 +10,6 @@ import EmailBox from "../EmailBox/EmailBox";
import ExportPDFLink from "../ExportChat/ExportPDFLink";
import ModelSelectionBox from "../ModelSelectionBox/ModelSelectionBox";
import { EmailInfo } from "../../models/email";
import { addMessageToChatHistory } from "../../service/chatService";
import { useState } from "react";
import DocumentViewButton from "../DocumentViewer/DocumentViewButton";

Expand All @@ -21,6 +20,9 @@ function DemoBody({
messages,
addChatMessage,
resetPhase,
setDefenceActive,
setDefenceInactive,
setDefenceConfiguration,
setEmails,
setNumCompletedPhases,
}: {
Expand All @@ -30,6 +32,12 @@ function DemoBody({
messages: ChatMessage[];
addChatMessage: (message: ChatMessage) => void;
resetPhase: () => void;
setDefenceActive: (defence: DefenceInfo) => void;
setDefenceInactive: (defence: DefenceInfo) => void;
setDefenceConfiguration: (
defenceId: string,
config: DefenceConfig[]
) => Promise<boolean>;
setEmails: (emails: EmailInfo[]) => void;
setNumCompletedPhases: (numCompletedPhases: number) => void;
}) {
Expand All @@ -48,25 +56,6 @@ function DemoBody({
resetPhase();
}

const addInfoMessage = (message: string) => {
addChatMessage({
message: message,
type: CHAT_MESSAGE_TYPE.INFO,
});
addMessageToChatHistory(message, CHAT_MESSAGE_TYPE.INFO, currentPhase);
};

// methods to be called when defences are (de)activated
// this adds an info message to the chat
const defenceActivated = (defenceInfo: DefenceInfo) => {
const infoMessage = `${defenceInfo.name} defence activated`;
addInfoMessage(infoMessage.toLowerCase());
};
const defenceDeactivated = (defenceInfo: DefenceInfo) => {
const infoMessage = `${defenceInfo.name} defence deactivated`;
addInfoMessage(infoMessage.toLowerCase());
};

return (
<span id="main-area">
<div className="side-bar">
Expand All @@ -86,8 +75,9 @@ function DemoBody({
currentPhase={currentPhase}
defences={defences}
showConfigurations={currentPhase > 2 ? true : false}
defenceActivated={defenceActivated}
defenceDeactivated={defenceDeactivated}
setDefenceActive={setDefenceActive}
setDefenceInactive={setDefenceInactive}
setDefenceConfiguration={setDefenceConfiguration}
/>
)}
{/* hide model selection box on phases 0 and 1 */}
Expand Down