Skip to content

Commit 276c470

Browse files
committed
0.8.5
- Fixed a bug with normal code blocks - Delete many challenges/users/announcements at once - Edit visibility of multiple challenges at once - Pagination preservation in admin panel
1 parent 2866026 commit 276c470

File tree

7 files changed

+402
-276
lines changed

7 files changed

+402
-276
lines changed

api/api.js

Lines changed: 115 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,10 @@ MongoDB.MongoClient.connect('mongodb://localhost:27017', {
248248
const username = signer.unsign(req.headers.authorization);
249249
if (await checkPermissions(username) === false) throw new Error('BadToken');
250250
let userToDelete = username;
251-
if (req.body.username) {
251+
if (req.body.users) {
252+
if (!Array.isArray(req.body.users)) throw new Error('Validation');
253+
const usersToDelete = req.body.users;
254+
if (usersToDelete.includes(username)) return res.send({ success: false, error: 'delete_self'})
252255
if (checkPermissions(username) < 2) {
253256
res.status(403);
254257
res.send({
@@ -257,34 +260,64 @@ MongoDB.MongoClient.connect('mongodb://localhost:27017', {
257260
});
258261
return;
259262
}
260-
userToDelete = req.body.username;
261-
}
262-
if ((await collections.users.deleteOne({ username: userToDelete.toLowerCase() })).deletedCount == 0) {
263-
res.status(400);
264-
res.send({
265-
success: false,
266-
error: 'not_found'
263+
264+
if ((await collections.users.deleteMany({ username: {$in: usersToDelete} })).deletedCount == 0) {
265+
res.status(400);
266+
res.send({
267+
success: false,
268+
error: 'not_found'
269+
});
270+
return;
271+
}
272+
await collections.challs.updateMany({}, {
273+
$pull: {
274+
solves: {$in: usersToDelete}
275+
}
267276
});
268-
return;
277+
await collections.challs.updateMany({
278+
hints: {
279+
$exists: true
280+
}
281+
}, {
282+
$pull: {
283+
'hints.$[].purchased': {$in: usersToDelete}
284+
}
285+
});
286+
await collections.challs.deleteMany({ author: {$in: usersToDelete} });
287+
await collections.transactions.deleteMany({ author: {$in: usersToDelete} });
288+
usersToDelete.forEach(username => {if (permissions.includes(username)) delete permissions[username]})
289+
290+
res.send({ success: true });
269291
}
270-
await collections.challs.updateMany({}, {
271-
$pull: {
272-
solves: userToDelete
273-
}
274-
});
275-
await collections.challs.updateMany({
276-
hints: {
277-
$exists: true
278-
}
279-
}, {
280-
$pull: {
281-
'hints.$[].purchased': userToDelete
292+
else {
293+
if ((await collections.users.deleteOne({ username: userToDelete.toLowerCase() })).deletedCount == 0) {
294+
res.status(400);
295+
res.send({
296+
success: false,
297+
error: 'not_found'
298+
});
299+
return;
282300
}
283-
});
284-
await collections.challs.deleteMany({ author: userToDelete });
285-
await collections.transactions.deleteMany({ author: userToDelete });
286-
if (permissions.includes(username)) delete permissions[username];
287-
res.send({ success: true });
301+
await collections.challs.updateMany({}, {
302+
$pull: {
303+
solves: userToDelete
304+
}
305+
});
306+
await collections.challs.updateMany({
307+
hints: {
308+
$exists: true
309+
}
310+
}, {
311+
$pull: {
312+
'hints.$[].purchased': userToDelete
313+
}
314+
});
315+
await collections.challs.deleteMany({ author: userToDelete });
316+
await collections.transactions.deleteMany({ author: userToDelete });
317+
if (permissions.includes(username)) delete permissions[username];
318+
res.send({ success: true });
319+
}
320+
288321
}
289322
catch (err) {
290323
errors(err, res);
@@ -468,7 +501,9 @@ MongoDB.MongoClient.connect('mongodb://localhost:27017', {
468501
if (req.headers.authorization == undefined) throw new Error('MissingToken');
469502
const username = signer.unsign(req.headers.authorization);
470503
if (await checkPermissions(username) < 2) throw new Error('Permissions');
471-
const delReq = await collections.announcements.deleteOne({ _id: MongoDB.ObjectID(req.body.id) });
504+
if (!Array.isArray(req.body.ids)) throw new Error('Validation');
505+
let ids = req.body.ids.map((id) => {return MongoDB.ObjectID(id)})
506+
const delReq = await collections.announcements.deleteMany({ _id: {$in: ids}});
472507
if (!delReq.result.ok) throw new Error('Unknown');
473508
if (delReq.deletedCount === 0) throw new Error('NotFound');
474509
res.send({
@@ -973,6 +1008,32 @@ MongoDB.MongoClient.connect('mongodb://localhost:27017', {
9731008
errors(err, res);
9741009
}
9751010
});
1011+
app.post('/v1/challenge/edit/visibility', async (req, res) => {
1012+
try {
1013+
if (req.headers.authorization == undefined) throw new Error('MissingToken');
1014+
const username = signer.unsign(req.headers.authorization);
1015+
if (await checkPermissions(username) < 2) throw new Error('Permissions');
1016+
if (!Array.isArray(req.body.challenges)) throw new Error('Validation');
1017+
if ((await collections.challs.updateMany({
1018+
name: {
1019+
$in: req.body.challenges
1020+
}
1021+
}, {
1022+
$set: { visibility: req.body.visibility }
1023+
})).matchedCount > 0) res.send({ success: true });
1024+
else throw new Error('NotFound');
1025+
}
1026+
catch (err) {
1027+
if (err.message == 'MissingHintCost') {
1028+
res.status(400);
1029+
res.send({
1030+
success: false,
1031+
error: 'validation'
1032+
});
1033+
}
1034+
errors(err, res);
1035+
}
1036+
});
9761037
app.post('/v1/challenge/edit/category', async (req, res) => {
9771038
try {
9781039
if (req.headers.authorization == undefined) throw new Error('MissingToken');
@@ -1005,32 +1066,35 @@ MongoDB.MongoClient.connect('mongodb://localhost:27017', {
10051066
if (req.headers.authorization == undefined) throw new Error('MissingToken');
10061067
const username = signer.unsign(req.headers.authorization);
10071068
if (await checkPermissions(username) < 2) throw new Error('Permissions');
1008-
const delReq = await collections.challs.findOneAndDelete({
1009-
name: req.body.chall
1010-
}, {
1011-
solves: 1,
1012-
points: 1,
1013-
hints: 1,
1014-
_id: 0
1015-
});
1016-
if (!delReq.ok) throw new Error('Unknown');
1017-
if (delReq.value === null) throw new Error('NotFound');
1018-
const timestamp = new Date();
1019-
await collections.transactions.deleteMany({ challenge: req.body.chall });
1020-
await collections.users.updateMany({
1021-
username: { $in: delReq.value.solves }
1022-
}, {
1023-
$inc: { score: -delReq.value.points }
1024-
});
1025-
if (delReq.value.hints) {
1026-
for (hint of delReq.value.hints) {
1027-
await collections.users.updateMany({
1028-
username: { $in: hint.purchased }
1029-
}, {
1030-
$inc: { score: hint.cost }
1031-
});
1069+
for (let i = 0; i < req.body.chall.length; i++) {
1070+
const delReq = await collections.challs.findOneAndDelete({
1071+
name: req.body.chall[i]
1072+
}, {
1073+
solves: 1,
1074+
points: 1,
1075+
hints: 1,
1076+
_id: 0
1077+
});
1078+
if (!delReq.ok) throw new Error('Unknown');
1079+
if (delReq.value === null) throw new Error('NotFound');
1080+
const timestamp = new Date();
1081+
await collections.transactions.deleteMany({ challenge: req.body.chall });
1082+
await collections.users.updateMany({
1083+
username: { $in: delReq.value.solves }
1084+
}, {
1085+
$inc: { score: -delReq.value.points }
1086+
});
1087+
if (delReq.value.hints) {
1088+
for (hint of delReq.value.hints) {
1089+
await collections.users.updateMany({
1090+
username: { $in: hint.purchased }
1091+
}, {
1092+
$inc: { score: hint.cost }
1093+
});
1094+
}
10321095
}
10331096
}
1097+
10341098
res.send({
10351099
success: true
10361100
});

client/src/App.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const Login = lazy(() => import("./login.js"));
3030
const Admin = lazy(() => import("./admin.js"));
3131
const Oops = lazy(() => import("./oops.js"));
3232

33+
var ctfxVersion = "0.8.5"
34+
3335

3436
class App extends React.Component {
3537
constructor(props) {
@@ -264,7 +266,7 @@ class App extends React.Component {
264266

265267
</Menu>
266268
<div style={{ textAlign: "center", marginTop: "3ch", color: "#8c8c8c" }}>
267-
<p>Sieberrsec CTF Platform 0.8.1 <a href="https://github.com/IRS-Cybersec/ctf_platform" target="_blank">Contribute <GithubOutlined /></a></p>
269+
<p>Sieberrsec CTF Platform {ctfxVersion} <a href="https://github.com/IRS-Cybersec/ctf_platform" target="_blank">Contribute <GithubOutlined /></a></p>
268270
</div>
269271
</Sider>
270272

client/src/MarkdownRenderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function MarkdownRender(props) {
1515
return !inline && match ? (
1616
<SyntaxHighlighter style={{ ...atomDark }} language={match[1]} PreTag="div" children={String(children).replace(/\n$/, '')} {...props} />
1717
) : (
18-
<code className={className} {...props} />
18+
<code className={className} {...props} children={String(children)} />
1919
)
2020
}
2121
}

0 commit comments

Comments
 (0)