Skip to content

Commit 2da171e

Browse files
committed
feat: implemente unlimited teams feature client-side
1 parent 9716335 commit 2da171e

4 files changed

Lines changed: 99 additions & 1 deletion

File tree

src/client/api/rest.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
GetFilesRequest,
1111
GetFilesResponse,
1212
IGenericResultRes,
13+
NewTeamResponse,
1314
StartActivityRequest,
1415
StartBroadcastRequest,
1516
StartExploitAppRequest,
@@ -122,6 +123,11 @@ class RESTManager {
122123
return res;
123124
}
124125

126+
async addNewTeam(): Promise<AxiosResponse<NewTeamResponse>> {
127+
const res = await http.post<NewTeamResponse>(E.NEW_TEAM);
128+
return res;
129+
}
130+
125131
async getAttackSurface(debugToken: string): Promise<AxiosResponse<CompanionAttackSurface>> {
126132
const res = await http.get<CompanionAttackSurface>(E.ATTACK_SURFACE, { headers: { Authorization: debugToken } });
127133
return res;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useEffect, useState } from "react";
2+
import toast from "react-hot-toast";
3+
import { RESTManagerInstance } from "@client/api/rest";
4+
5+
interface IModalProps {
6+
dialogRef: React.RefObject<HTMLDialogElement | null>;
7+
}
8+
9+
export const AddNewTeamModal: React.FC<IModalProps> = ({ dialogRef }) => {
10+
const [requestResult, setRequestResult] = useState<string>("");
11+
12+
useEffect(() => {
13+
const handleClose = () => {
14+
setRequestResult("");
15+
};
16+
17+
const dialog = dialogRef.current;
18+
if (dialog) {
19+
dialog.addEventListener("close", handleClose);
20+
}
21+
22+
return () => {
23+
if (dialog) {
24+
dialog.removeEventListener("close", handleClose);
25+
}
26+
};
27+
}, []);
28+
29+
const getTeamToken = async () => {
30+
try {
31+
const res = await RESTManagerInstance.addNewTeam();
32+
setRequestResult(`New Team Token generated: ${res.data.teamToken}`);
33+
} catch (e) {
34+
console.error(e);
35+
toast.error("Error while generating new Team Token.");
36+
}
37+
};
38+
39+
return (
40+
<dialog ref={dialogRef} className="modal">
41+
<div className="modal-box max-w-3xl">
42+
<h3 className="font-bold text-lg mb-4">Get Team Token</h3>
43+
<p className="mb-4">
44+
This will allow you to get a new Team Token which is <b>required</b> to install and run <i>exploit apps</i>{" "}
45+
and for the <i>Exploit Server</i> as well.
46+
</p>
47+
<div className="space-y-4">
48+
{/* Result */}
49+
{requestResult.length > 0 && (
50+
<div className="flex flex-col justify-between mb-4 gap-4">
51+
<span className="font-semibold">Output</span>
52+
<div className="mockup-code w-full hide-before max-h-96 overflow-y-auto p-4">
53+
<pre className="text-accent text-wrap wrap-break-word break-all">
54+
<code>{requestResult}</code>
55+
</pre>
56+
</div>
57+
</div>
58+
)}
59+
60+
{/* Submit */}
61+
<div className="flex justify-end">
62+
<input onClick={getTeamToken} className="btn btn-primary" value="Get Token" />
63+
</div>
64+
</div>
65+
</div>
66+
<form method="dialog" className="modal-backdrop">
67+
<button>close</button>
68+
</form>
69+
</dialog>
70+
);
71+
};

src/client/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export { StartBroadcastModal } from "@client/components/StartBroadcastModal";
44
export { StartServiceModal } from "@client/components/StartServiceModal";
55
export { InstallExploitAppModal } from "@client/components/InstallExploitAppModal";
66
export { StartExploitAppModal } from "@client/components/StartExploitAppModal";
7+
export { AddNewTeamModal } from "@client/components/AddNewTeamModal";

src/client/views/Overview.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MdSpaceDashboard } from "react-icons/md";
77
import { RESTManagerInstance } from "@client/api/rest";
88
import { BugreportzStatusResponse } from "@shared/api";
99
import { useAPI } from "@client/context/API";
10-
import { StartActivityModal, StartBroadcastModal, StartServiceModal } from "@client/components";
10+
import { AddNewTeamModal, StartActivityModal, StartBroadcastModal, StartServiceModal } from "@client/components";
1111

1212
export const Overview: React.FC = () => {
1313
const { featuresConfig, deviceInfo } = useAPI();
@@ -17,6 +17,7 @@ export const Overview: React.FC = () => {
1717
});
1818
const isPowerMenuEnabled = featuresConfig.shutdownEnabled || featuresConfig.rebootEnabled;
1919
// Dialogs
20+
const addNewTeamDialogRef = useRef<HTMLDialogElement | null>(null);
2021
const startActivityDialogRef = useRef<HTMLDialogElement | null>(null);
2122
const startBroadcastReceiverDialogRef = useRef<HTMLDialogElement | null>(null);
2223
const startServiceDialogRef = useRef<HTMLDialogElement | null>(null);
@@ -120,6 +121,9 @@ export const Overview: React.FC = () => {
120121
* Modals *
121122
***************/}
122123

124+
{/* New Team Modal */}
125+
<AddNewTeamModal dialogRef={addNewTeamDialogRef} />
126+
123127
{/* Start Activity Modal */}
124128
<StartActivityModal dialogRef={startActivityDialogRef} />
125129

@@ -202,6 +206,22 @@ export const Overview: React.FC = () => {
202206
</div>
203207
</div>
204208

209+
{featuresConfig.unlimitedTeams && (
210+
<div className="flex w-full justify-between items-center">
211+
<p>
212+
Get <b>Team Token</b>
213+
</p>
214+
<div className="join">
215+
<button
216+
className="btn btn-info join-item rounded-r-md"
217+
onClick={() => addNewTeamDialogRef.current?.showModal()}
218+
>
219+
Get
220+
</button>
221+
</div>
222+
</div>
223+
)}
224+
205225
{featuresConfig.startActivityEnabled && (
206226
<div className="flex w-full justify-between items-center">
207227
<p>

0 commit comments

Comments
 (0)