Skip to content

Commit

Permalink
334 move info message to handbook (#345)
Browse files Browse the repository at this point in the history
This work unifies the overlay for the three main popups: welcome message, mission info, handbook.
  • Loading branch information
heatherlogan-scottlogic authored Oct 12, 2023
1 parent 291dbcf commit 98fc75b
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 105 deletions.
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 {
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;
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
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 {
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

0 comments on commit 98fc75b

Please sign in to comment.