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

334 move info message to handbook #345

Merged
merged 11 commits into from
Oct 12, 2023
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react": "^4.0.3",
"eslint": "^8.50.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"prettier": "2.8.8",
Expand Down
33 changes: 19 additions & 14 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import {
import { DEFENCE_DETAILS_ALL, DEFENCE_DETAILS_LEVEL } from "./Defences";
import { DEFENCE_TYPES, DefenceConfig, DefenceInfo } from "./models/defence";
import { getCompletedLevels } from "./service/levelService";
import { LEVELS } from "./Levels";
import HandbookOverlay from "./components/HandbookOverlay/HandbookOverlay";
import Overlay from "./components/Overlay/Overlay";
import { OVERLAY_TYPE } from "./models/overlay";

function App({ isNewUser }: { isNewUser: boolean }) {
Expand Down Expand Up @@ -75,14 +74,24 @@ function App({ isNewUser }: { isNewUser: boolean }) {
}, [currentLevel]);

function closeOverlay() {
setShowOverlay(false);
// open the mission info after welcome page for a new user
if (overlayType === OVERLAY_TYPE.WELCOME) {
openInformationOverlay();
} else {
setShowOverlay(false);
}
}

function openHandbook() {
setOverlayType(OVERLAY_TYPE.HANDBOOK);
setShowOverlay(true);
}

function openInformationOverlay() {
setOverlayType(OVERLAY_TYPE.INFORMATION);
setShowOverlay(true);
}

// methods to modify messages
function addChatMessage(message: ChatMessage) {
setMessages((messages: ChatMessage[]) => [...messages, message]);
Expand All @@ -94,11 +103,6 @@ function App({ isNewUser }: { isNewUser: boolean }) {

await clearChat(currentLevel);
setMessages([]);
// add preamble to start of chat
addChatMessage({
message: LEVELS[currentLevel].preamble,
type: CHAT_MESSAGE_TYPE.LEVEL_INFO,
});

await clearEmails(currentLevel);
setEmails([]);
Expand All @@ -119,6 +123,11 @@ function App({ isNewUser }: { isNewUser: boolean }) {
// for going switching level without clearing progress
async function setNewLevel(newLevel: LEVEL_NAMES) {
console.log(`changing level from ${currentLevel} to ${newLevel}`);

if (currentLevel !== newLevel) {
openInformationOverlay();
}

setMessages([]);
setCurrentLevel(newLevel);

Expand All @@ -128,11 +137,7 @@ function App({ isNewUser }: { isNewUser: boolean }) {

// get chat history for new level from the backend
const levelChatHistory = await getChatHistory(newLevel);
// add the preamble to the start of the chat history
levelChatHistory.unshift({
message: LEVELS[newLevel].preamble,
type: CHAT_MESSAGE_TYPE.LEVEL_INFO,
});

setMessages(levelChatHistory);

const defences =
Expand Down Expand Up @@ -224,7 +229,7 @@ function App({ isNewUser }: { isNewUser: boolean }) {
return (
<div id="app-content">
{showOverlay && (
<HandbookOverlay
<Overlay
currentLevel={currentLevel}
overlayType={overlayType}
closeOverlay={closeOverlay}
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/Levels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ const LEVELS: Level[] = [
{
id: LEVEL_NAMES.LEVEL_1,
name: "Level 1",
preamble:
missionInfo:
"The chatbot can answer some questions about the company and ongoing projects. " +
"Your first task is to ask for the name of the secret project, and then email it to [email protected].",
},
{
id: LEVEL_NAMES.LEVEL_2,
name: "Level 2",
preamble:
missionInfo:
"As the secret project was exposed, we have renamed it. " +
"You should now try and find out the product owner of the secret project. " +
"We've told the AI not to reveal information about this project, so you will have to trick the chatbot. " +
Expand All @@ -21,7 +21,7 @@ const LEVELS: Level[] = [
{
id: LEVEL_NAMES.LEVEL_3,
name: "Level 3",
preamble:
missionInfo:
"Since you compromised the secret project again, we have had to take drastic action and cut the project. " +
"Meanwhile, we have adopted a new unrelated secret project with a different name, brief, cost, team etc. " +
"We have also tightened up our security so the chatbot is much more strict about revealing sensitive information. " +
Expand All @@ -32,7 +32,7 @@ const LEVELS: Level[] = [
{
id: LEVEL_NAMES.SANDBOX,
name: "Sandbox",
preamble:
missionInfo:
"This is a sandbox environment. " +
"The bot can send emails and has access to documents with sensitive and non-sensitive information. " +
"Experiment with different attacks and defences while you try to get the bot to reveal sensitive information or perform actions it shouldn't. ",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/Theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

--overlay-hidden-colour: #0008;
--overlay-background-colour: #8ad5da;
--overlay-closed-tab-colour: #c7e8f4;
--overlay-attack-background-colour: #d6d6ff;
--overlay-text-colour: #313131;

Expand Down
54 changes: 1 addition & 53 deletions frontend/src/components/HandbookOverlay/HandbookOverlay.css
Original file line number Diff line number Diff line change
@@ -1,57 +1,5 @@
.handbook-overlay-screen {
background-color: var(--overlay-hidden-colour);

position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;

display: flex;
justify-content: center;
align-items: center;
}

.handbook-overlay {
position: relative;

background-color: var(--overlay-background-colour);
color: var(--overlay-text-colour);

display: flex;
justify-content: center;
align-items: center;
overflow-y: auto;

width: 50%;
height: 50%;
border-radius: 10px;
}

.handbook-overlay > .close-button {
position: absolute;
right: 16px;
top: 16px;
max-width: 2rem;
max-height: 2rem;
min-height: 1.6rem;
padding: 5px;

color: inherit;
font-size: 1.5rem;
font-weight: bold;
}

.handbook-overlay > .close-button:hover {
color: var(--main-button-hover-text-colour);
text-decoration: none;
cursor: pointer;
}

.handbook-overlay-content {
#handbook-overlay-content {
chriswilty marked this conversation as resolved.
Show resolved Hide resolved
height: 100%;
padding: 0 5%;

text-align: center;
overflow-y: auto;
Expand Down
53 changes: 27 additions & 26 deletions frontend/src/components/HandbookOverlay/HandbookOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,40 @@
import { useState } from "react";
import { LEVEL_NAMES } from "../../models/level";
import { OVERLAY_TYPE } from "../../models/overlay";
import MissionInformation from "../Overlay/MissionInformation";
import HandbookAttacks from "./HandbookAttacks";
import HandbookOverlayTabs from "./HandbookOverlayTabs";
import { HANDBOOK_PAGES } from "../../models/handbook";
import "./HandbookOverlay.css";
import HandbookWelcome from "./HandbookWelcome";

function HandbookOverlay({
currentLevel,
overlayType,
closeOverlay,
}: {
currentLevel: LEVEL_NAMES;
overlayType: OVERLAY_TYPE;
closeOverlay: () => void;
}) {
function showOverlayByType() {
switch (overlayType) {
case OVERLAY_TYPE.HANDBOOK:
function HandbookOverlay({ currentLevel }: { currentLevel: LEVEL_NAMES }) {
const [selectedPage, setSelectedPage] = useState<HANDBOOK_PAGES>(
HANDBOOK_PAGES.MISSION_INFO
);

function setPageContent(handbookPage: HANDBOOK_PAGES) {
switch (handbookPage) {
case HANDBOOK_PAGES.ATTACKS:
return <HandbookAttacks currentLevel={currentLevel} />;
case OVERLAY_TYPE.WELCOME:
case HANDBOOK_PAGES.TOOLS:
return (
<div>
<h2> Placeholder </h2>
</div>
);
case HANDBOOK_PAGES.MISSION_INFO:
default:
return <HandbookWelcome />;
return <MissionInformation currentLevel={currentLevel} />;
}
}

return (
<div className="handbook-overlay-screen">
<div className="handbook-overlay">
<button
className="prompt-injection-min-button close-button"
onClick={closeOverlay}
aria-label="close handbook overlay"
>
X
</button>
<div className="handbook-overlay-content">{showOverlayByType()}</div>
<div className="handbook-overlay">
<HandbookOverlayTabs
currentLevel={currentLevel}
setSelectedPage={setSelectedPage}
/>
<div className="handbook-overlay-content">
{setPageContent(selectedPage)}
</div>
</div>
);
Expand Down
57 changes: 57 additions & 0 deletions frontend/src/components/HandbookOverlay/HandbookOverlayTabs.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.handbook-tabs {
display: flex;
flex-wrap: wrap;
width: 100%;
position: absolute;
top: -50px; /* position above overlay */
left: 2rem;
z-index: -1;
}

.handbook-tabs label {
display: flex;
align-items: center;
justify-content: center;
padding: 1rem 2rem;
margin-right: 0.0625rem;
cursor: pointer;
background-color: var(--overlay-closed-tab-colour);
font-weight: 700;
transition: ease 0.1s;
border-radius: 10px 10px 0 0;
}

.handbook-tabs label:not(:first-child):not(:last-child) {
border-right: 2px solid #000;
}

.handbook-tabs [type="radio"] {
display: none;
}

.handbook-tabs [type="radio"]:checked + label {
background-color: var(--overlay-background-colour);
}

.handbook-tabs [type="radio"]:checked + label + .tab {
display: block;
}

@media (min-width: 768px) {
body {
font-size: 1.125rem;
}

.handbook-tabs-container {
padding: 4rem 4rem;
}

.handbook-tabs label {
order: 1;
chriswilty marked this conversation as resolved.
Show resolved Hide resolved
width: auto;
}

.handbook-tabs .tab {
order: 9;
}
}
46 changes: 46 additions & 0 deletions frontend/src/components/HandbookOverlay/HandbookOverlayTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { HANDBOOK_PAGES, handbookPageNames } from "../../models/handbook";
import { LEVEL_NAMES } from "../../models/level";
import "./HandbookOverlayTabs.css";

function HandbookOverlayTabs({
currentLevel,
setSelectedPage,
}: {
currentLevel: LEVEL_NAMES;
setSelectedPage: (page: HANDBOOK_PAGES) => void;
}) {
// the tabs that are shown depend on the current level
function getLevelTabs(currentLevel: LEVEL_NAMES) {
switch (currentLevel) {
case LEVEL_NAMES.LEVEL_1:
return [HANDBOOK_PAGES.MISSION_INFO];
default:
return [
HANDBOOK_PAGES.MISSION_INFO,
HANDBOOK_PAGES.ATTACKS,
HANDBOOK_PAGES.TOOLS,
];
}
}

return (
<div className="handbook-tabs">
{getLevelTabs(currentLevel).map((tab) => (
<div key={tab}>
<input
chriswilty marked this conversation as resolved.
Show resolved Hide resolved
type="radio"
name="handbook-tabs"
id={tab.toString()}
defaultChecked={tab === HANDBOOK_PAGES.MISSION_INFO}
onClick={() => {
setSelectedPage(tab);
}}
/>
<label htmlFor={tab.toString()}>{handbookPageNames[tab]}</label>
</div>
))}
</div>
);
}

export default HandbookOverlayTabs;
3 changes: 3 additions & 0 deletions frontend/src/components/Overlay/MissionInformation.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#mission-info p {
chriswilty marked this conversation as resolved.
Show resolved Hide resolved
font-size: 1.5rem;
}
17 changes: 17 additions & 0 deletions frontend/src/components/Overlay/MissionInformation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { LEVEL_NAMES } from "../../models/level";
import { LEVELS } from "../../Levels";

import "./MissionInformation.css";

function MissionInformation({ currentLevel }: { currentLevel: LEVEL_NAMES }) {
return (
<div>
<h2> Mission Information </h2>
<div id="mission-info">
<p>{LEVELS[currentLevel].missionInfo}</p>
</div>
</div>
);
}

export default MissionInformation;
Loading