Skip to content

Commit 6c9654d

Browse files
committed
0.6.5
- Fixed a bug where an error message will show when loading challenges via direct link - Minor CSS fixes to the Tables in admin panel - Refresh function for admin panels - Copy challenge link to clipboard in challenge page
1 parent eeec218 commit 6c9654d

9 files changed

+305
-215
lines changed

client/src/App.css

+4
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,8 @@
8888

8989
.ant-table {
9090
background:rgba(0, 0, 0, 0.5) !important;
91+
}
92+
93+
.ant-table-container {
94+
overflow: auto;
9195
}

client/src/App.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class App extends React.Component {
6868
previousPage = page
6969
}
7070

71+
message.config({maxCount: 2})
72+
7173
// Handles "remember me" logins
7274
if (!this.state.token) {
7375
const token = localStorage.getItem("IRSCTF-token")
@@ -263,7 +265,7 @@ class App extends React.Component {
263265

264266
</Menu>
265267
<div style={{ textAlign: "center", marginTop: "3ch", color: "#8c8c8c" }}>
266-
<p>Sieberrsec CTF Platform 0.6.1 <a href="https://github.com/IRS-Cybersec/ctf_platform" target="_blank">Contribute <GithubOutlined /></a></p>
268+
<p>Sieberrsec CTF Platform 0.6.5 <a href="https://github.com/IRS-Cybersec/ctf_platform" target="_blank">Contribute <GithubOutlined /></a></p>
267269
</div>
268270
</Sider>
269271

client/src/adminChallenges.js

+85-84
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
EditOutlined,
99
FileUnknownTwoTone,
1010
EyeOutlined,
11-
EyeInvisibleOutlined
11+
EyeInvisibleOutlined,
12+
RedoOutlined
1213
} from '@ant-design/icons';
1314
import './App.css';
1415
import AdminChallengeCreate from "./adminChallengeCreate.js";
@@ -36,19 +37,20 @@ class AdminChallenges extends React.Component {
3637
selectedKeys: [],
3738
targetKeys: [],
3839
allCat: [],
39-
transferDisabled: false
40+
transferDisabled: false,
41+
refreshLoading: false
4042
}
4143
}
4244

43-
componentDidUpdate(prevProps) {
44-
// Handle any page changes
45-
if (this.state.editChallenge && this.props.location.pathname !== "/Admin/Challenges/Edit") {
46-
this.setState({ editChallenge: false })
47-
}
48-
else if (this.state.challengeCreate && this.props.location.pathname !== "/Admin/Challenges/Create") {
49-
this.setState({ challengeCreate: false })
45+
componentDidUpdate(prevProps) {
46+
// Handle any page changes
47+
if (this.state.editChallenge && this.props.location.pathname !== "/Admin/Challenges/Edit") {
48+
this.setState({ editChallenge: false })
49+
}
50+
else if (this.state.challengeCreate && this.props.location.pathname !== "/Admin/Challenges/Create") {
51+
this.setState({ challengeCreate: false })
52+
}
5053
}
51-
}
5254

5355

5456
componentDidMount = async () => {
@@ -60,38 +62,36 @@ class AdminChallenges extends React.Component {
6062
message.warn("Please select a challenge from the table to edit")
6163
await this.props.history.push("/Admin/Challenges")
6264
}
63-
this.fillTableData()
64-
this.handleCategoryData()
65+
this.handleRefresh()
6566
}
6667

6768

68-
handleCategoryData() {
69+
handleCategoryData = async () => {
6970
this.setState({ transferDisabled: true })
7071
let visibleCat = []
7172
let allCat = []
7273

73-
const getInfo = async () => {
74-
fetch(window.ipAddress + "/v1/challenge/list_categories", {
75-
method: 'get',
76-
headers: { 'Content-Type': 'application/json', "Authorization": localStorage.getItem("IRSCTF-token") },
77-
}).then((results) => {
78-
return results.json(); //return data in JSON (since its JSON data)
79-
}).then((data) => {
74+
await Promise.all([fetch(window.ipAddress + "/v1/challenge/list_categories", {
75+
method: 'get',
76+
headers: { 'Content-Type': 'application/json', "Authorization": localStorage.getItem("IRSCTF-token") },
77+
}).then((results) => {
78+
return results.json(); //return data in JSON (since its JSON data)
79+
}).then((data) => {
8080

81-
if (data.success === true) {
82-
visibleCat = data.categories
83-
}
84-
else {
85-
message.error({ content: "Oops. Unknown error" })
86-
}
81+
if (data.success === true) {
82+
visibleCat = data.categories
83+
}
84+
else {
85+
message.error({ content: "Oops. Unknown error" })
86+
}
8787

8888

89-
}).catch((error) => {
90-
console.log(error)
91-
message.error({ content: "Oops. There was an issue connecting with the server" });
92-
})
89+
}).catch((error) => {
90+
console.log(error)
91+
message.error({ content: "Oops. There was an issue connecting with the server" });
92+
})
9393

94-
await fetch(window.ipAddress + "/v1/challenge/list_all_categories", {
94+
, fetch(window.ipAddress + "/v1/challenge/list_all_categories", {
9595
method: 'get',
9696
headers: { 'Content-Type': 'application/json', "Authorization": localStorage.getItem("IRSCTF-token") },
9797
}).then((results) => {
@@ -110,22 +110,17 @@ class AdminChallenges extends React.Component {
110110
console.log(error)
111111
message.error({ content: "Oops. There was an issue connecting with the server" });
112112
})
113+
])
113114

115+
let invisible = difference(allCat, visibleCat)
116+
/*console.log(invisible)
117+
console.log(allCat)
118+
console.log(visibleCat)*/
114119

120+
for (let i = 0; i < allCat.length; i++) {
121+
allCat[i] = { "key": allCat[i] }
115122
}
116-
117-
(async () => {
118-
await getInfo()
119-
let invisible = difference(allCat, visibleCat)
120-
/*console.log(invisible)
121-
console.log(allCat)
122-
console.log(visibleCat)*/
123-
124-
for (let i = 0; i < allCat.length; i++) {
125-
allCat[i] = { "key": allCat[i] }
126-
}
127-
this.setState({ targetKeys: invisible, allCat: allCat, transferDisabled: false })
128-
})()
123+
this.setState({ targetKeys: invisible, allCat: allCat, transferDisabled: false })
129124
}
130125

131126
handleChange = (nextTargetKeys, direction, moveKeys) => {
@@ -172,9 +167,9 @@ class AdminChallenges extends React.Component {
172167
})
173168
}
174169

175-
fillTableData = () => {
170+
fillTableData = async () => {
176171
this.setState({ loading: true })
177-
fetch(window.ipAddress + "/v1/challenge/list_all", {
172+
await fetch(window.ipAddress + "/v1/challenge/list_all", {
178173
method: 'get',
179174
headers: { 'Content-Type': 'application/json', "Authorization": localStorage.getItem("IRSCTF-token") },
180175
}).then((results) => {
@@ -191,6 +186,7 @@ class AdminChallenges extends React.Component {
191186
}
192187
}
193188
this.setState({ dataSource: data.challenges, loading: false })
189+
194190
}
195191
else {
196192
message.error({ content: "Oops. Unknown error" })
@@ -217,8 +213,7 @@ class AdminChallenges extends React.Component {
217213
//console.log(data)
218214
if (data.success === true) {
219215
message.success({ content: "Deleted challenge \"" + challengeName + "\" successfully" })
220-
this.fillTableData()
221-
this.handleCategoryData()
216+
this.handleRefresh()
222217

223218
}
224219
else {
@@ -249,15 +244,17 @@ class AdminChallenges extends React.Component {
249244
handleCreateBack() {
250245
this.props.history.push("/Admin/Challenges")
251246
this.setState({ challengeCreate: false })
252-
this.fillTableData()
253-
this.handleCategoryData()
247+
this.handleRefresh()
254248
}
255249

256250
handleEditChallBack() {
257251
this.props.history.push("/Admin/Challenges")
258252
this.setState({ editChallenge: false })
259-
this.fillTableData()
260-
this.handleCategoryData()
253+
this.handleRefresh()
254+
}
255+
256+
handleRefresh = async () => {
257+
await Promise.all([this.fillTableData(), this.handleCategoryData()])
261258
}
262259

263260

@@ -269,24 +266,26 @@ class AdminChallenges extends React.Component {
269266

270267
<Layout style={{ height: "100%", width: "100%", backgroundColor: "rgba(0, 0, 0, 0)" }}>
271268

272-
{this.state.loading && (
273-
<div style={{ position: "absolute", left: "55%", transform: "translate(-55%, 0%)", zIndex: 10 }}>
274-
<Ellipsis color="#177ddc" size={120} ></Ellipsis>
275-
</div>
276-
)}
277-
{!this.state.loading && (
278-
<div>
279-
280-
{!this.state.challengeCreate && !this.state.editChallenge && (
281-
<div>
282269

283-
<Button type="primary" style={{ marginBottom: "2vh", maxWidth: "25ch" }} icon={<FlagOutlined />} onClick={() => { this.setState({ challengeCreate: true }, this.props.history.push("/Admin/Challenges/Create")) }}>Create New Challenge</Button>
284270

271+
{!this.state.challengeCreate && !this.state.editChallenge && (
272+
<div>
273+
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
274+
<Button type="primary" style={{ marginBottom: "2vh", maxWidth: "25ch" }} icon={<FlagOutlined />} onClick={() => { this.setState({ challengeCreate: true }, this.props.history.push("/Admin/Challenges/Create")) }}>Create New Challenge</Button>
275+
<Button loading={this.state.loading} type="primary" shape="circle" size="large" style={{ marginBottom: "2vh", maxWidth: "25ch" }} icon={<RedoOutlined />} onClick={async () => { await this.handleRefresh(); message.success("Challenge list refreshed.") }} />
276+
</div>
277+
{this.state.loading && (
278+
<div style={{ display: "flex", justifyContent: "center", alignItems: "center" }}>
279+
<Ellipsis color="#177ddc" size={120} ></Ellipsis>
280+
</div>
281+
)}
282+
{!this.state.loading && (
283+
<div>
285284
<Table style={{ overflow: "auto" }} dataSource={this.state.dataSource} locale={{
286285
emptyText: (
287286
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", marginTop: "10vh" }}>
288287
<FileUnknownTwoTone style={{ color: "#177ddc", fontSize: "400%", zIndex: 1 }} />
289-
<h1 style={{ fontSize: "200%" }}>There are no challenges created.</h1>
288+
<h1 style={{ fontSize: "200%" }}>No Challenges Have Been Created.</h1>
290289
</div>
291290
)
292291
}}>
@@ -329,35 +328,37 @@ class AdminChallenges extends React.Component {
329328
)}
330329
/>
331330
</Table>
332-
<Divider />
333-
<h1 style={{ fontSize: "150%" }}>Category Management {this.state.transferDisabled && (<LoadingOutlined style={{ color: "#177ddc" }} />)}</h1>
334-
335-
<Transfer
336-
dataSource={this.state.allCat}
337-
titles={['Visible Categories', 'Hidden Categories']}
338-
targetKeys={this.state.targetKeys}
339-
selectedKeys={this.state.selectedKeys}
340-
onChange={this.handleChange}
341-
onSelectChange={this.handleSelectChange}
342-
render={item => item.key}
343-
pagination
344-
disabled={this.state.transferDisabled}
345-
/>
346-
347-
<Divider />
348331
</div>
349332
)}
350-
<Switch>
351-
<Route exact path='/Admin/Challenges/Create' render={(props) => <AdminChallengeCreate {...props} handleBack={this.handleBack.bind(this)} handleCreateBack={this.handleCreateBack.bind(this)} allCat={this.state.allCat} />} />
352-
<Route exact path='/Admin/Challenges/Edit' render={(props) => <AdminChallengeEdit {...props} allCat={this.state.allCat} challengeName={this.state.challengeName} handleEditBack={this.handleEditBack.bind(this)} handleEditChallBack={this.handleEditChallBack.bind(this)} />} />
333+
<Divider />
334+
<h1 style={{ fontSize: "150%" }}>Category Management {this.state.transferDisabled && (<LoadingOutlined style={{ color: "#177ddc" }} />)}</h1>
335+
336+
<Transfer
337+
dataSource={this.state.allCat}
338+
titles={['Visible Categories', 'Hidden Categories']}
339+
targetKeys={this.state.targetKeys}
340+
selectedKeys={this.state.selectedKeys}
341+
onChange={this.handleChange}
342+
onSelectChange={this.handleSelectChange}
343+
render={item => item.key}
344+
pagination
345+
disabled={this.state.transferDisabled}
346+
/>
353347

354-
</Switch>
348+
<Divider />
355349

356350

357351

358352
</div>
359353
)}
360354

355+
356+
<Switch>
357+
<Route exact path='/Admin/Challenges/Create' render={(props) => <AdminChallengeCreate {...props} handleBack={this.handleBack.bind(this)} handleCreateBack={this.handleCreateBack.bind(this)} allCat={this.state.allCat} />} />
358+
<Route exact path='/Admin/Challenges/Edit' render={(props) => <AdminChallengeEdit {...props} allCat={this.state.allCat} challengeName={this.state.challengeName} handleEditBack={this.handleEditBack.bind(this)} handleEditChallBack={this.handleEditChallBack.bind(this)} />} />
359+
360+
</Switch>
361+
361362
</Layout>
362363
);
363364
}

client/src/adminSubmissions.js

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from 'react';
2-
import { Layout, Table, message } from 'antd';
2+
import { Layout, Table, message, Button } from 'antd';
33
import {
44
FileUnknownTwoTone,
5+
RedoOutlined
56
} from '@ant-design/icons';
67
import { orderBy } from "lodash";
78
import { Ellipsis } from 'react-spinners-css';
@@ -25,9 +26,9 @@ class AdminSubmissions extends React.Component {
2526
this.fillTableData()
2627
}
2728

28-
fillTableData = () => {
29+
fillTableData = async () => {
2930
this.setState({ loading: true })
30-
fetch(window.ipAddress + "/v1/submissions", {
31+
await fetch(window.ipAddress + "/v1/submissions", {
3132
method: 'get',
3233
headers: { 'Content-Type': 'application/json', "Authorization": localStorage.getItem("IRSCTF-token") },
3334
}).then((results) => {
@@ -69,6 +70,10 @@ class AdminSubmissions extends React.Component {
6970

7071
<Layout style={{ height: "100%", width: "100%", backgroundColor: "rgba(0, 0, 0, 0)" }}>
7172

73+
<div style={{ display: "flex", justifyContent: "flex-end", alignItems: "center" }}>
74+
<Button loading={this.state.loading} type="primary" shape="circle" size="large" style={{ marginBottom: "2vh", maxWidth: "25ch" }} icon={<RedoOutlined />} onClick={async () => { await this.fillTableData(); message.success("Submissions list refreshed.") }} />
75+
</div>
76+
7277
{this.state.loading && (
7378
<div style={{ position: "absolute", left: "55%", transform: "translate(-55%, 0%)", zIndex: 10 }}>
7479
<Ellipsis color="#177ddc" size={120} ></Ellipsis>
@@ -95,7 +100,7 @@ class AdminSubmissions extends React.Component {
95100
<Column title="Correct" dataIndex="correct" key="correct" />
96101
</Table>
97102
)}
98-
</Layout>
103+
</Layout >
99104
);
100105
}
101106
}

0 commit comments

Comments
 (0)