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

Implement a command bridge between servers and the API #106

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

benrobson
Copy link
Member

No description provided.

benrobson and others added 8 commits October 8, 2024 22:00
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99)

* Delete message after filtering prohibited content.

* Fix spacing in network log messages.

* Make usernames more presentable in logs.

* Remove deleted channel field from being mentioned twice.

* Fixed issue where filter errors after response is sent.

* Changed from HEX to Colour

* Add /poll command.

* Add page descriptions to headers.

* Added keywords and SEO option to configuration.

* Add documentation badges for list and editors.

* Push mobile view changes for session views.

* Resolved mobile styling issues with dashboard views.

* Added a staffChannel config option and a /staffhelp command

* Resolve issues with cookie banner not showing on /register

* Made urgent change to hasPermission, allowing non-logged in users to view admin panel.

* Reformat all project files using Prettier. (#90)

* Commit not found.

* Prettify all JS and JSON files.

* Resolve issue with logout crashing.

* Separate redirect route into own file, add config option for kb and added issue tracker route.

* Change node engine to support node 18. (#92)

* Implementation of a Ranks/donation page. (#91)

* Commence work on /ranks page and Tebex integration.

* Transitioning back to JSON file, using catagory and packages

* Finish rank page implementation.

* Update perks.

* Implement a call to action button style instead and make mobile friendly.

* Made the server name look to site config for /ranks

* Change rank page descriptor.

* Commit start of rego process.

* Add more routes

* Implement 2fa interactive form element.

* Install packages for email integration

* Implement email template draft and smtp credentials.

* Commence more work on controller and tests for emails.

* Working on pathing.

* Fix pathing on email template.

* Add email header and footer and fix up routes.

* Add a rough template draft of registration

* Change registration gateway to discord, commence working on Minecraft link.

* Add user verification via /verify

* Remove all old rego code and mentions to passwords, remove email views and partials.

* Add token code expiry and draft a expiry cron task.

* Refactor getUser() into UserGetter

* Push user verification service.

* Commence drafting profiles and finalising login gateway

* Add coming soon alerts on profile features.

* Commit more profile work and db profile changes.

* Applied permissions to profile.

* Add example.env and config files.

* Added Minecraft login and chat audits, also added website login.

* Added discord voice and message audit events.

* Filled in fields for audit to complete feature development.

* Start work on profile editor.

* Start implementing social connections into editor.

* Finalise design for profile editor.

* Implemented all of the base work for API routes and controllers.

* Start on profile/display in editor and fix issue with Gravatar.

* Finalise Social Connections in display and editor.

* Fix permission node of everyone able to see dashboard, and open new tab for social connections.

* Audit: If no data, then display no data instead of invalid date

* Added profile stats for total logins and playtime.

* Add latest session with online and offline indicators.

* Add support for  verification server in /server

* Resolved issues with Server types displaying all instead of their type.

* Create dbupgrade.sql

Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql

* Commence port to new schema.

* Fix result type return in user api and added 17 global images.

* Make unregistered failure link back to rego page.

* Set audit to skip for discord voice and chat if discord is not linked.

* Resolved issues with user api creation.

* Resolve issues with messages attempting to send to channels.

* Require the webhook package.

* Rollback to d70b343

* Changes to user route and troubleshooting discord login.

* Remove redirect returns.

* Add troubleshooting to callback.

* Push further troubleshooting.

* Add troubleshooting to isRegistered

* Add additional check and troubleshooting

* Commit

* Add a build command.

* Fix Discord oAuth (#98)

* Wrap in string for ID and secret.

* Add logging to callback.

* Add more logging.

* Add more testing

* got here marker.

* move marker.

* Move marker

* update marker

* marker 4, reveal session

* Add permission data log

* Fix issues with loading profile editor.

* On profile updates, redirect to profile.

* Add steam social and profanity filter to interests.

* Add ability for linked accounts to not trigger linking codes.

* Push profile command.

* Add ranks api to fetch by rank and user.

* Add debug for user permissions

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>

* Added rank permissions context into login sessions and clean up profile command. (#100)

* Start rank perms scope on user implementation

* Fix getUserPermissions to scope in rank permission nodes.

* Remove the zanderdev prefix from permissions lookup.

* Replace with amended getUserLastSession() to stop profiles from crashing.

* Refactor to stop nulls from crashing the API

* Removed all Craftatar discord side features due to traffic amplification attacks.

* Add ` in profile title username to keep formatting.

* Start work on report and locking behind login session.

* Added report support via in-game and web.

* Add discord /report command.

* Add feature blocks to apply, ranks and report. Fix staffhelp command.

* move reporting to true

* Get a timeout on db and refactor to CraftHead.

* Draft reports tab in profile.

* Finish reporting badge.

* Remove report log.

* Add safe server to features on home.

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99)

* Delete message after filtering prohibited content.

* Fix spacing in network log messages.

* Make usernames more presentable in logs.

* Remove deleted channel field from being mentioned twice.

* Fixed issue where filter errors after response is sent.

* Changed from HEX to Colour

* Add /poll command.

* Add page descriptions to headers.

* Added keywords and SEO option to configuration.

* Add documentation badges for list and editors.

* Push mobile view changes for session views.

* Resolved mobile styling issues with dashboard views.

* Added a staffChannel config option and a /staffhelp command

* Resolve issues with cookie banner not showing on /register

* Made urgent change to hasPermission, allowing non-logged in users to view admin panel.

* Reformat all project files using Prettier. (#90)

* Commit not found.

* Prettify all JS and JSON files.

* Resolve issue with logout crashing.

* Separate redirect route into own file, add config option for kb and added issue tracker route.

* Change node engine to support node 18. (#92)

* Implementation of a Ranks/donation page. (#91)

* Commence work on /ranks page and Tebex integration.

* Transitioning back to JSON file, using catagory and packages

* Finish rank page implementation.

* Update perks.

* Implement a call to action button style instead and make mobile friendly.

* Made the server name look to site config for /ranks

* Change rank page descriptor.

* Commit start of rego process.

* Add more routes

* Implement 2fa interactive form element.

* Install packages for email integration

* Implement email template draft and smtp credentials.

* Commence more work on controller and tests for emails.

* Working on pathing.

* Fix pathing on email template.

* Add email header and footer and fix up routes.

* Add a rough template draft of registration

* Change registration gateway to discord, commence working on Minecraft link.

* Add user verification via /verify

* Remove all old rego code and mentions to passwords, remove email views and partials.

* Add token code expiry and draft a expiry cron task.

* Refactor getUser() into UserGetter

* Push user verification service.

* Commence drafting profiles and finalising login gateway

* Add coming soon alerts on profile features.

* Commit more profile work and db profile changes.

* Applied permissions to profile.

* Add example.env and config files.

* Added Minecraft login and chat audits, also added website login.

* Added discord voice and message audit events.

* Filled in fields for audit to complete feature development.

* Start work on profile editor.

* Start implementing social connections into editor.

* Finalise design for profile editor.

* Implemented all of the base work for API routes and controllers.

* Start on profile/display in editor and fix issue with Gravatar.

* Finalise Social Connections in display and editor.

* Fix permission node of everyone able to see dashboard, and open new tab for social connections.

* Audit: If no data, then display no data instead of invalid date

* Added profile stats for total logins and playtime.

* Add latest session with online and offline indicators.

* Add support for  verification server in /server

* Resolved issues with Server types displaying all instead of their type.

* Create dbupgrade.sql

Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql

* Commence port to new schema.

* Fix result type return in user api and added 17 global images.

* Make unregistered failure link back to rego page.

* Set audit to skip for discord voice and chat if discord is not linked.

* Resolved issues with user api creation.

* Resolve issues with messages attempting to send to channels.

* Require the webhook package.

* Rollback to d70b343

* Changes to user route and troubleshooting discord login.

* Remove redirect returns.

* Add troubleshooting to callback.

* Push further troubleshooting.

* Add troubleshooting to isRegistered

* Add additional check and troubleshooting

* Commit

* Add a build command.

* Fix Discord oAuth (#98)

* Wrap in string for ID and secret.

* Add logging to callback.

* Add more logging.

* Add more testing

* got here marker.

* move marker.

* Move marker

* update marker

* marker 4, reveal session

* Add permission data log

* Fix issues with loading profile editor.

* On profile updates, redirect to profile.

* Add steam social and profanity filter to interests.

* Add ability for linked accounts to not trigger linking codes.

* Push profile command.

* Add ranks api to fetch by rank and user.

* Add debug for user permissions

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>

* Added rank permissions context into login sessions and clean up profile command. (#100)

* Start rank perms scope on user implementation

* Fix getUserPermissions to scope in rank permission nodes.

* Remove the zanderdev prefix from permissions lookup.

* Replace with amended getUserLastSession() to stop profiles from crashing.

* Refactor to stop nulls from crashing the API

* Removed all Craftatar discord side features due to traffic amplification attacks.

* Add ` in profile title username to keep formatting.

* Start work on report and locking behind login session.

* Added report support via in-game and web.

* Add discord /report command.

* Add feature blocks to apply, ranks and report. Fix staffhelp command.

* move reporting to true

* Add vault get/add/update/delete

* Add description and /vault command

* Fix edit query on vault

* Change from announcementSlug to announcementId

* Commit Application api change

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>
@benrobson benrobson requested a review from JaedanC as a code owner November 11, 2024 12:55

try {
function getBridge(dbQuery) {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.
This query string depends on a
user-provided value
.

Copilot Autofix AI 3 months ago

To fix the problem, we should use query parameters to safely embed user-provided data into the SQL query. This approach prevents SQL injection by ensuring that the user input is treated as a literal value rather than executable code.

  1. Modify the getBridge function to accept query parameters.
  2. Update the SQL query strings to use placeholders for the parameters.
  3. Pass the user-provided data as parameters to the db.query function.
Suggested changeset 1
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -11,4 +11,4 @@
     try {
-      function getBridge(dbQuery) {
-        db.query(dbQuery, function (error, results, fields) {
+      function getBridge(dbQuery, queryParams) {
+        db.query(dbQuery, queryParams, function (error, results, fields) {
           if (error) {
@@ -36,4 +36,4 @@
       if (bridgeId) {
-        let dbQuery = `SELECT * FROM bridge WHERE bridgeId=${bridgeId};`;
-        getBridge(dbQuery);
+        let dbQuery = `SELECT * FROM bridge WHERE bridgeId=?;`;
+        getBridge(dbQuery, [bridgeId]);
       }
@@ -42,4 +42,4 @@
       if (targetServer) {
-        let dbQuery = `SELECT * FROM bridge WHERE targetServer='${targetServer}' AND processed=0;`;
-        getBridge(dbQuery);
+        let dbQuery = `SELECT * FROM bridge WHERE targetServer=? AND processed=0;`;
+        getBridge(dbQuery, [targetServer]);
       }
@@ -48,3 +48,3 @@
       let dbQuery = `SELECT * FROM bridge;`;
-      getBridge(dbQuery);
+      getBridge(dbQuery, []);
     } catch (error) {
EOF
@@ -11,4 +11,4 @@
try {
function getBridge(dbQuery) {
db.query(dbQuery, function (error, results, fields) {
function getBridge(dbQuery, queryParams) {
db.query(dbQuery, queryParams, function (error, results, fields) {
if (error) {
@@ -36,4 +36,4 @@
if (bridgeId) {
let dbQuery = `SELECT * FROM bridge WHERE bridgeId=${bridgeId};`;
getBridge(dbQuery);
let dbQuery = `SELECT * FROM bridge WHERE bridgeId=?;`;
getBridge(dbQuery, [bridgeId]);
}
@@ -42,4 +42,4 @@
if (targetServer) {
let dbQuery = `SELECT * FROM bridge WHERE targetServer='${targetServer}' AND processed=0;`;
getBridge(dbQuery);
let dbQuery = `SELECT * FROM bridge WHERE targetServer=? AND processed=0;`;
getBridge(dbQuery, [targetServer]);
}
@@ -48,3 +48,3 @@
let dbQuery = `SELECT * FROM bridge;`;
getBridge(dbQuery);
getBridge(dbQuery, []);
} catch (error) {
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +60 to +92
app.post(baseEndpoint + "/command/add", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);

const command = required(req.body, "command", res);
const targetServer = required(req.body, "targetServer", res);

try {
db.query(
`INSERT INTO bridge (command, targetServer) VALUES (?, ?)`,
[command, targetServer],
function (error, results, fields) {
if (error) {
return res.send({
success: false,
message: `${error}`,
});
}

return res.send({
success: true,
message: `New Bridge command added for ${targetServer}: ${command}`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the route handlers that perform database access. The best way to achieve this is by using the express-rate-limit middleware. This middleware allows us to set a maximum number of requests a user can make within a specified time window. We will apply this middleware to the relevant routes to ensure they are protected against excessive requests.

We will:

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Set up a rate limiter with appropriate configuration.
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -1,4 +1,9 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
 export default function bridgeApiRoute(app, config, db, features, lang) {
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
   const baseEndpoint = "/api/bridge";
@@ -59,3 +64,3 @@
 
-  app.post(baseEndpoint + "/command/add", async function (req, res) {
+  app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@
 
-  app.post(baseEndpoint + "/clear", async function (req, res) {
+  app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@
 
-  app.get(baseEndpoint + "/server/get", async function (req, res) {
+  app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
EOF
@@ -1,4 +1,9 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

export default function bridgeApiRoute(app, config, db, features, lang) {
const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});
const baseEndpoint = "/api/bridge";
@@ -59,3 +64,3 @@

app.post(baseEndpoint + "/command/add", async function (req, res) {
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@

app.post(baseEndpoint + "/clear", async function (req, res) {
app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@

app.get(baseEndpoint + "/server/get", async function (req, res) {
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines 94 to 131
app.post(baseEndpoint + "/command/process", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);

const bridgeId = required(req.body, "bridgeId", res);

try {
const fetchURL = `${process.env.siteAddress}/api/bridge/get?id=${bridgeId}`;
const response = await fetch(fetchURL, {
headers: { "x-access-token": process.env.apiKey },
});
const bridgeApiData = await response.json();

db.query(
`UPDATE bridge SET processed=? WHERE bridgeId=?;`,
[1, bridgeId],
function (error, results, fields) {
if (error) {
return res.send({
success: false,
message: `${error}`,
});
}

return res.send({
success: true,
message: `Bridge ID ${bridgeId} has been executed.`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the Express application. The best way to do this is by using the express-rate-limit package, which allows us to easily set up and apply rate limiting to all routes or specific routes.

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the api/routes/bridge.js file.
  3. Set up a rate limiter with appropriate configuration (e.g., maximum number of requests per time window).
  4. Apply the rate limiter to the routes that perform database access operations.
Suggested changeset 2
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -1,2 +1,3 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
@@ -4,4 +5,8 @@
   const baseEndpoint = "/api/bridge";
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
 
-  app.get(baseEndpoint + "/get", async function (req, res) {
+  app.get(baseEndpoint + "/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +64,3 @@
 
-  app.post(baseEndpoint + "/command/add", async function (req, res) {
+  app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@
 
-  app.post(baseEndpoint + "/clear", async function (req, res) {
+  app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@
 
-  app.get(baseEndpoint + "/server/get", async function (req, res) {
+  app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -153,3 +158,3 @@
 
-  app.post(baseEndpoint + "/server/update", async function (req, res) {
+  app.post(baseEndpoint + "/server/update", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +192,3 @@
 
-  app.post(baseEndpoint + "/command/process", async function (req, res) {
+  app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
EOF
@@ -1,2 +1,3 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

@@ -4,4 +5,8 @@
const baseEndpoint = "/api/bridge";
const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

app.get(baseEndpoint + "/get", async function (req, res) {
app.get(baseEndpoint + "/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +64,3 @@

app.post(baseEndpoint + "/command/add", async function (req, res) {
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@

app.post(baseEndpoint + "/clear", async function (req, res) {
app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@

app.get(baseEndpoint + "/server/get", async function (req, res) {
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -153,3 +158,3 @@

app.post(baseEndpoint + "/server/update", async function (req, res) {
app.post(baseEndpoint + "/server/update", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +192,3 @@

app.post(baseEndpoint + "/command/process", async function (req, res) {
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +55 to +141
app.post(baseEndpoint + "/create", async function (req, res) {
isFeatureEnabled(features.report, res, lang);

const reporterUser = required(req.body, "reporterUser", res);
const reportedUser = required(req.body, "reportedUser", res);
const reportReason = required(req.body, "reportReason", res);
const reportReasonEvidence = optional(
req.body,
"reportReasonEvidence",
res
);
const reportPlatform = required(req.body, "reportPlatform", res);

try {
db.query(
`
INSERT INTO
reports
(
reporterId,
reportedUser,
reportReason,
reportReasonEvidence,
reportPlatform
) VALUES ((SELECT userId FROM users WHERE username=?), ?, ?, ?, ?)`,
[
reporterUser,
reportedUser,
reportReason,
reportReasonEvidence,
reportPlatform,
],
function (error, results, fields) {
console.log(req.body);

if (error) {
console.log(error);
console.log(results);

return res.send({
success: false,
message: `Report has failed, please try again later.`,
});
} else {
setBannerCookie("success", "Report has been sent.", res);

try {
const staffChannelHook = new Webhook(
config.discord.webhooks.staffChannel
);

const embed = new MessageBuilder()
.setTitle(`New Report: ${reportedUser}`)
.addField("Report Platform", reportPlatform, true)
.addField("Report By", reporterUser, true)
.addField("Report Reason", reportReason)
.setColor(Colors.Red)
.setTimestamp();

if (reportReasonEvidence) {
embed.addField("Report Evidence", reportReasonEvidence);
}

staffChannelHook.send(embed);
} catch (error) {
return res.send({
success: false,
message: `${error}`,
});
}

return res.send({
success: true,
message: `Thanks for your submission: ${reportedUser} for ${reportReason}.`,
});
}
}
);
} catch (error) {
return res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the route handlers that perform database access. The best way to achieve this is by using the express-rate-limit package, which allows us to easily set up and apply rate limiting middleware to our Express routes.

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Set up a rate limiter with appropriate configuration.
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/report.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/report.js b/api/routes/report.js
--- a/api/routes/report.js
+++ b/api/routes/report.js
@@ -3,2 +3,3 @@
 import { Colors } from "discord.js";
+import rateLimit from 'express-rate-limit';
 
@@ -7,4 +8,10 @@
 
+  // set up rate limiter: maximum of 100 requests per 15 minutes
+  const limiter = rateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
+
   // TODO: Update docs
-  app.get(baseEndpoint + "/get", async function (req, res) {
+  app.get(baseEndpoint + "/get", limiter, async function (req, res) {
     isFeatureEnabled(features.report, res, lang);
@@ -54,3 +61,3 @@
 
-  app.post(baseEndpoint + "/create", async function (req, res) {
+  app.post(baseEndpoint + "/create", limiter, async function (req, res) {
     isFeatureEnabled(features.report, res, lang);
EOF
@@ -3,2 +3,3 @@
import { Colors } from "discord.js";
import rateLimit from 'express-rate-limit';

@@ -7,4 +8,10 @@

// set up rate limiter: maximum of 100 requests per 15 minutes
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

// TODO: Update docs
app.get(baseEndpoint + "/get", async function (req, res) {
app.get(baseEndpoint + "/get", limiter, async function (req, res) {
isFeatureEnabled(features.report, res, lang);
@@ -54,3 +61,3 @@

app.post(baseEndpoint + "/create", async function (req, res) {
app.post(baseEndpoint + "/create", limiter, async function (req, res) {
isFeatureEnabled(features.report, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options

try {
function getVault(dbQuery) {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.

Copilot Autofix AI 3 months ago

To fix the problem, we should use parameterized queries to safely embed the user input into the SQL query string. This approach ensures that the user input is treated as a literal value and not as part of the SQL command, thus preventing SQL injection attacks.

  • Modify the getVault function to accept query parameters.
  • Use the query parameters in the SQL query instead of directly embedding the user input.
  • Update the db.query call to use the parameterized query.
Suggested changeset 1
api/routes/vault.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/vault.js b/api/routes/vault.js
--- a/api/routes/vault.js
+++ b/api/routes/vault.js
@@ -10,4 +10,4 @@
     try {
-      function getVault(dbQuery) {
-        db.query(dbQuery, function (error, results, fields) {
+      function getVault(dbQuery, queryParams) {
+        db.query(dbQuery, queryParams, function (error, results, fields) {
           console.log(results);
@@ -37,4 +37,4 @@
       if (vaultId) {
-        let dbQuery = `SELECT * FROM vault WHERE vaultId=${vaultId};`;
-        getVault(dbQuery);
+        let dbQuery = `SELECT * FROM vault WHERE vaultId=?;`;
+        getVault(dbQuery, [vaultId]);
       }
@@ -43,3 +43,3 @@
       let dbQuery = `SELECT * FROM vault ORDER BY position ASC;`;
-      getVault(dbQuery);
+      getVault(dbQuery, []);
     } catch (error) {
EOF
@@ -10,4 +10,4 @@
try {
function getVault(dbQuery) {
db.query(dbQuery, function (error, results, fields) {
function getVault(dbQuery, queryParams) {
db.query(dbQuery, queryParams, function (error, results, fields) {
console.log(results);
@@ -37,4 +37,4 @@
if (vaultId) {
let dbQuery = `SELECT * FROM vault WHERE vaultId=${vaultId};`;
getVault(dbQuery);
let dbQuery = `SELECT * FROM vault WHERE vaultId=?;`;
getVault(dbQuery, [vaultId]);
}
@@ -43,3 +43,3 @@
let dbQuery = `SELECT * FROM vault ORDER BY position ASC;`;
getVault(dbQuery);
getVault(dbQuery, []);
} catch (error) {
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +55 to +105
app.post(baseEndpoint + "/create", async function (req, res) {
isFeatureEnabled(features.vault, res, lang);

const actioningUser = required(req.body, "actioningUser", res);
const displayName = required(req.body, "displayName", res);
const description = required(req.body, "description", res);
const redirectUrl = required(req.body, "redirectUrl", res);
const position = required(req.body, "position", res);

try {
db.query(
`INSERT INTO vault
(displayName, description, redirectUrl, position)
VALUES (?, ?, ?, ?)`,
[
displayName,
description,
redirectUrl,
position
],
function (error, results, fields) {
if (error) {
return res.send({
success: false,
message: `${error}`,
});
}

generateLog(
actioningUser,
"SUCCESS",
"VAULT",
`Created ${displayName}`,
res
);

return res.send({
success: true,
message: `Created ${displayName} vault.`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we will use the express-rate-limit package to add rate limiting to the Express application. This will involve:

  1. Installing the express-rate-limit package.
  2. Importing the package in the api/routes/vault.js file.
  3. Setting up a rate limiter with appropriate configuration.
  4. Applying the rate limiter to the routes that perform database operations.
Suggested changeset 2
api/routes/vault.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/vault.js b/api/routes/vault.js
--- a/api/routes/vault.js
+++ b/api/routes/vault.js
@@ -1,2 +1,3 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
@@ -4,4 +5,8 @@
   const baseEndpoint = "/api/vault";
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
 
-  app.get(baseEndpoint + "/get", async function (req, res) {
+  app.get(baseEndpoint + "/get", limiter, async function (req, res) {
     isFeatureEnabled(features.vault, res, lang);
@@ -54,3 +59,3 @@
 
-  app.post(baseEndpoint + "/create", async function (req, res) {
+  app.post(baseEndpoint + "/create", limiter, async function (req, res) {
     isFeatureEnabled(features.vault, res, lang);
@@ -106,3 +111,3 @@
 
-  app.post(baseEndpoint + "/edit", async function (req, res) {
+  app.post(baseEndpoint + "/edit", limiter, async function (req, res) {
     isFeatureEnabled(features.vault, res, lang);
@@ -166,3 +171,3 @@
 
-  app.post(baseEndpoint + "/delete", async function (req, res) {
+  app.post(baseEndpoint + "/delete", limiter, async function (req, res) {
     isFeatureEnabled(features.vault, res, lang);
EOF
@@ -1,2 +1,3 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

@@ -4,4 +5,8 @@
const baseEndpoint = "/api/vault";
const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

app.get(baseEndpoint + "/get", async function (req, res) {
app.get(baseEndpoint + "/get", limiter, async function (req, res) {
isFeatureEnabled(features.vault, res, lang);
@@ -54,3 +59,3 @@

app.post(baseEndpoint + "/create", async function (req, res) {
app.post(baseEndpoint + "/create", limiter, async function (req, res) {
isFeatureEnabled(features.vault, res, lang);
@@ -106,3 +111,3 @@

app.post(baseEndpoint + "/edit", async function (req, res) {
app.post(baseEndpoint + "/edit", limiter, async function (req, res) {
isFeatureEnabled(features.vault, res, lang);
@@ -166,3 +171,3 @@

app.post(baseEndpoint + "/delete", async function (req, res) {
app.post(baseEndpoint + "/delete", limiter, async function (req, res) {
isFeatureEnabled(features.vault, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +107 to +165
app.post(baseEndpoint + "/edit", async function (req, res) {
isFeatureEnabled(features.vault, res, lang);

const actioningUser = required(req.body, "actioningUser", res);
const vaultId = required(req.body, "vaultId", res);
const displayName = required(req.body, "displayName", res);
const description = required(req.body, "description", res);
const redirectUrl = required(req.body, "redirectUrl", res);
const position = required(req.body, "position", res);

try {
db.query(
`
UPDATE
vault
SET
displayName=?,
description=?,
redirectUrl=?,
position=?
WHERE vaultId=?;`,
[
displayName,
description,
redirectUrl,
position,
vaultId,
],
function (error, results, fields) {
if (error) {
return res.send({
success: false,
message: `${error}`,
});
}

generateLog(
actioningUser,
"SUCCESS",
"VAULT",
`Edited ${displayName}`,
res
);

return res.send({
success: true,
message: `${displayName} has been edited.`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.
Comment on lines +167 to +207
app.post(baseEndpoint + "/delete", async function (req, res) {
isFeatureEnabled(features.vault, res, lang);

const actioningUser = required(req.body, "actioningUser", res);
const vaultId = required(req.body, "vaultId", res);

try {
db.query(
`DELETE FROM vault WHERE vaultId=?;`,
[vaultId],
function (error, results, fields) {
if (error) {
res.send({
success: false,
message: `${error}`,
});
}

generateLog(
actioningUser,
"WARNING",
"VAULT",
`Deleted ${vaultId}`,
res
);

return res.send({
success: true,
message: `Deletion of vault with the id ${vaultId} has been successful.`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we will introduce rate limiting to the Express application using the express-rate-limit package. This will ensure that the number of requests to the endpoints is controlled, preventing potential DoS attacks.

  1. Install the express-rate-limit package if it is not already installed.
  2. Import the express-rate-limit package in the api/routes/vault.js file.
  3. Set up a rate limiter with appropriate configuration (e.g., maximum of 100 requests per 15 minutes).
  4. Apply the rate limiter to the routes that perform database access operations.
Suggested changeset 2
api/routes/vault.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/vault.js b/api/routes/vault.js
--- a/api/routes/vault.js
+++ b/api/routes/vault.js
@@ -1,2 +1,3 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
@@ -5,2 +6,9 @@
 
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
+
+  app.use(limiter);
+
   app.get(baseEndpoint + "/get", async function (req, res) {
EOF
@@ -1,2 +1,3 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

@@ -5,2 +6,9 @@

const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

app.use(limiter);

app.get(baseEndpoint + "/get", async function (req, res) {
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +94 to +122
app.post(baseEndpoint + "/clear", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);

try {
db.query(
`TRUNCATE bridge;`,
function (error, results, fields) {
if (error) {
return res.send({
success: false,
message: `${error}`,
});
}

return res.send({
success: true,
message: `Bridge has now been cleared.`,
});
}
);
} catch (error) {
res.send({
success: false,
message: `${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the route handlers that perform database access operations. The best way to achieve this is by using the express-rate-limit middleware. This middleware allows us to set a maximum number of requests that can be made to the server within a specified time window. We will apply this middleware to the relevant routes to ensure that they are protected against denial-of-service attacks.

We will need to:

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Set up a rate limiter with appropriate configuration.
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -1,2 +1,3 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
@@ -4,4 +5,8 @@
   const baseEndpoint = "/api/bridge";
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
 
-  app.get(baseEndpoint + "/get", async function (req, res) {
+  app.get(baseEndpoint + "/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +64,3 @@
 
-  app.post(baseEndpoint + "/command/add", async function (req, res) {
+  app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@
 
-  app.post(baseEndpoint + "/clear", async function (req, res) {
+  app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@
 
-  app.get(baseEndpoint + "/server/get", async function (req, res) {
+  app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +192,3 @@
 
-  app.post(baseEndpoint + "/command/process", async function (req, res) {
+  app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
EOF
@@ -1,2 +1,3 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

@@ -4,4 +5,8 @@
const baseEndpoint = "/api/bridge";
const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

app.get(baseEndpoint + "/get", async function (req, res) {
app.get(baseEndpoint + "/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +64,3 @@

app.post(baseEndpoint + "/command/add", async function (req, res) {
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +98,3 @@

app.post(baseEndpoint + "/clear", async function (req, res) {
app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +128,3 @@

app.get(baseEndpoint + "/server/get", async function (req, res) {
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +192,3 @@

app.post(baseEndpoint + "/command/process", async function (req, res) {
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
benrobson and others added 3 commits November 15, 2024 23:26
* Implement Discord-based registration with Minecraft backed auth and user profiles. (#99)

* Delete message after filtering prohibited content.

* Fix spacing in network log messages.

* Make usernames more presentable in logs.

* Remove deleted channel field from being mentioned twice.

* Fixed issue where filter errors after response is sent.

* Changed from HEX to Colour

* Add /poll command.

* Add page descriptions to headers.

* Added keywords and SEO option to configuration.

* Add documentation badges for list and editors.

* Push mobile view changes for session views.

* Resolved mobile styling issues with dashboard views.

* Added a staffChannel config option and a /staffhelp command

* Resolve issues with cookie banner not showing on /register

* Made urgent change to hasPermission, allowing non-logged in users to view admin panel.

* Reformat all project files using Prettier. (#90)

* Commit not found.

* Prettify all JS and JSON files.

* Resolve issue with logout crashing.

* Separate redirect route into own file, add config option for kb and added issue tracker route.

* Change node engine to support node 18. (#92)

* Implementation of a Ranks/donation page. (#91)

* Commence work on /ranks page and Tebex integration.

* Transitioning back to JSON file, using catagory and packages

* Finish rank page implementation.

* Update perks.

* Implement a call to action button style instead and make mobile friendly.

* Made the server name look to site config for /ranks

* Change rank page descriptor.

* Commit start of rego process.

* Add more routes

* Implement 2fa interactive form element.

* Install packages for email integration

* Implement email template draft and smtp credentials.

* Commence more work on controller and tests for emails.

* Working on pathing.

* Fix pathing on email template.

* Add email header and footer and fix up routes.

* Add a rough template draft of registration

* Change registration gateway to discord, commence working on Minecraft link.

* Add user verification via /verify

* Remove all old rego code and mentions to passwords, remove email views and partials.

* Add token code expiry and draft a expiry cron task.

* Refactor getUser() into UserGetter

* Push user verification service.

* Commence drafting profiles and finalising login gateway

* Add coming soon alerts on profile features.

* Commit more profile work and db profile changes.

* Applied permissions to profile.

* Add example.env and config files.

* Added Minecraft login and chat audits, also added website login.

* Added discord voice and message audit events.

* Filled in fields for audit to complete feature development.

* Start work on profile editor.

* Start implementing social connections into editor.

* Finalise design for profile editor.

* Implemented all of the base work for API routes and controllers.

* Start on profile/display in editor and fix issue with Gravatar.

* Finalise Social Connections in display and editor.

* Fix permission node of everyone able to see dashboard, and open new tab for social connections.

* Audit: If no data, then display no data instead of invalid date

* Added profile stats for total logins and playtime.

* Add latest session with online and offline indicators.

* Add support for  verification server in /server

* Resolved issues with Server types displaying all instead of their type.

* Create dbupgrade.sql

Convert prior SCHEMA to the new schema. Use this script to upgrade from an already existing database. If creating a new database use the dbinit.sql

* Commence port to new schema.

* Fix result type return in user api and added 17 global images.

* Make unregistered failure link back to rego page.

* Set audit to skip for discord voice and chat if discord is not linked.

* Resolved issues with user api creation.

* Resolve issues with messages attempting to send to channels.

* Require the webhook package.

* Rollback to d70b343

* Changes to user route and troubleshooting discord login.

* Remove redirect returns.

* Add troubleshooting to callback.

* Push further troubleshooting.

* Add troubleshooting to isRegistered

* Add additional check and troubleshooting

* Commit

* Add a build command.

* Fix Discord oAuth (#98)

* Wrap in string for ID and secret.

* Add logging to callback.

* Add more logging.

* Add more testing

* got here marker.

* move marker.

* Move marker

* update marker

* marker 4, reveal session

* Add permission data log

* Fix issues with loading profile editor.

* On profile updates, redirect to profile.

* Add steam social and profanity filter to interests.

* Add ability for linked accounts to not trigger linking codes.

* Push profile command.

* Add ranks api to fetch by rank and user.

* Add debug for user permissions

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>

* Added rank permissions context into login sessions and clean up profile command. (#100)

* Start rank perms scope on user implementation

* Fix getUserPermissions to scope in rank permission nodes.

* Remove the zanderdev prefix from permissions lookup.

* Replace with amended getUserLastSession() to stop profiles from crashing.

* Refactor to stop nulls from crashing the API

* Removed all Craftatar discord side features due to traffic amplification attacks.

* Add ` in profile title username to keep formatting.

* Start work on report and locking behind login session.

* Added report support via in-game and web.

* Add discord /report command.

* Add feature blocks to apply, ranks and report. Fix staffhelp command.

* move reporting to true

* Get a timeout on db and refactor to CraftHead.

* Start draft implementation of shop directory

* Start the bridge draft.

* API routes and dashboard UI

* bridge api and dashboard implementation

* Have target server only execute non-processed tasks

* Add a clean up task and don't execute old tasks.

* Start work on shop directory api and website route.

* Implement shopdirectory page, add by userId in users api and add /shop/get

* Fix db merge issues

* Replaced with prod implementation.

* Push rate limiting on /shop/get

* JSON parsing troubleshooting

* Add ref to profile

* Added WIP shop command.

* defer response on shop

* Fix undefined fields.

* Prefer display name over item name.

* Fix embed formatting issue on new line.

* Fix up additional formatting in embed.

* Remove $ from amount.

* Remove $ form stock

---------

Co-authored-by: Aron Brown <[email protected]>
Co-authored-by: Ben Robson <[email protected]>
* Update dbinit.sql

Add query to create a punishments view that pulls data from litebans.

* Fix formatting in dbinit.sql
try {
function getReports(dbQuery) {
return new Promise((resolve, reject) => {
db.query(dbQuery, function (error, results, fields) {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.

Copilot Autofix AI 3 months ago

To fix the problem, we need to ensure that user input is safely embedded into the SQL query. The best way to achieve this is by using query parameters or prepared statements. This approach ensures that the user input is treated as a literal value and not as part of the SQL query itself.

In this specific case, we will modify the getReports function to use query parameters for the reportedId value. This will involve changing the SQL query string to use a placeholder for the reportedId and passing the actual value as a parameter to the db.query function.

Suggested changeset 1
api/routes/report.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/report.js b/api/routes/report.js
--- a/api/routes/report.js
+++ b/api/routes/report.js
@@ -13,5 +13,5 @@
     try {
-      function getReports(dbQuery) {
+      function getReports(dbQuery, params = []) {
         return new Promise((resolve, reject) => {
-          db.query(dbQuery, function (error, results, fields) {
+          db.query(dbQuery, params, function (error, results, fields) {
             if (error) {
@@ -39,4 +39,4 @@
       if (reportedId) {
-        let dbQuery = `SELECT * FROM reports WHERE reportedId=${reportedId};`;
-        await getReports(dbQuery);
+        let dbQuery = `SELECT * FROM reports WHERE reportedId=?;`;
+        await getReports(dbQuery, [reportedId]);
       }
EOF
@@ -13,5 +13,5 @@
try {
function getReports(dbQuery) {
function getReports(dbQuery, params = []) {
return new Promise((resolve, reject) => {
db.query(dbQuery, function (error, results, fields) {
db.query(dbQuery, params, function (error, results, fields) {
if (error) {
@@ -39,4 +39,4 @@
if (reportedId) {
let dbQuery = `SELECT * FROM reports WHERE reportedId=${reportedId};`;
await getReports(dbQuery);
let dbQuery = `SELECT * FROM reports WHERE reportedId=?;`;
await getReports(dbQuery, [reportedId]);
}
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
try {
async function getShops(dbQuery) {
return new Promise((resolve, reject) => {
db.query(dbQuery, async (error, results) => {

Check failure

Code scanning / CodeQL

Database query built from user-controlled sources High

This query string depends on a
user-provided value
.

Copilot Autofix AI 3 months ago

To fix the problem, we should use query parameters to safely embed the user input into the SQL query. This approach prevents SQL injection by ensuring that the user input is treated as a literal value rather than executable code.

  • Modify the construction of the dbQuery string to use parameterized queries.
  • Use the db.query method's parameterization feature to pass the user input as a parameter to the query.
  • Update the getShops function to accept query parameters and pass them to the db.query method.
Suggested changeset 1
api/routes/shopdirectory.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/shopdirectory.js b/api/routes/shopdirectory.js
--- a/api/routes/shopdirectory.js
+++ b/api/routes/shopdirectory.js
@@ -14,5 +14,5 @@
     try {
-      async function getShops(dbQuery) {
+      async function getShops(dbQuery, queryParams) {
         return new Promise((resolve, reject) => {
-          db.query(dbQuery, async (error, results) => {
+          db.query(dbQuery, queryParams, async (error, results) => {
             if (error) {
@@ -119,7 +119,8 @@
       const dbQuery = material
-        ? `SELECT * FROM shoppingDirectory WHERE item LIKE '%${material}%';`
+        ? `SELECT * FROM shoppingDirectory WHERE item LIKE $1;`
         : `SELECT * FROM shoppingDirectory;`;
+      const queryParams = material ? [`%${material}%`] : [];
 
       // Execute the query and process the shops
-      await getShops(dbQuery);
+      await getShops(dbQuery, queryParams);
     } catch (error) {
EOF
@@ -14,5 +14,5 @@
try {
async function getShops(dbQuery) {
async function getShops(dbQuery, queryParams) {
return new Promise((resolve, reject) => {
db.query(dbQuery, async (error, results) => {
db.query(dbQuery, queryParams, async (error, results) => {
if (error) {
@@ -119,7 +119,8 @@
const dbQuery = material
? `SELECT * FROM shoppingDirectory WHERE item LIKE '%${material}%';`
? `SELECT * FROM shoppingDirectory WHERE item LIKE $1;`
: `SELECT * FROM shoppingDirectory;`;
const queryParams = material ? [`%${material}%`] : [];

// Execute the query and process the shops
await getShops(dbQuery);
await getShops(dbQuery, queryParams);
} catch (error) {
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines 124 to 156
app.post(baseEndpoint + "/server/update", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);

const serverInfo = required(req.body, "serverInfo", res);
let lastUpdated = required(req.body, "lastUpdated", res);

try {
const serverInfoString = JSON.stringify(serverInfo);

db.query(
`UPDATE serverStatus SET statusInfo = ?, lastUpdated = ? WHERE serverStatusId = 1;`,
[serverInfoString, lastUpdated],
function (error, updateResults) {
if (error) {
return res.send({
success: false,
message: `Update failed: ${error}`,
});
}

return res.send({
success: true,
message: `Server status updated successfully.`,
});
}
);
} catch (error) {
return res.send({
success: false,
message: `Unexpected error: ${error}`,
});
}
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the Express application. The best way to do this is by using the express-rate-limit package, which allows us to easily set up and apply rate limiting to our routes. We will configure a rate limiter and apply it to the routes that perform database access operations.

  1. Install the express-rate-limit package.
  2. Import the express-rate-limit package in the file.
  3. Configure a rate limiter with appropriate settings (e.g., maximum number of requests per time window).
  4. Apply the rate limiter to the relevant routes.
Suggested changeset 2
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -1,2 +1,3 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import RateLimit from 'express-rate-limit';
 
@@ -5,3 +6,9 @@
 
-  app.get(baseEndpoint + "/get", async function (req, res) {
+  // set up rate limiter: maximum of 100 requests per 15 minutes
+  const limiter = RateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // max 100 requests per windowMs
+  });
+
+  app.get(baseEndpoint + "/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +66,3 @@
 
-  app.post(baseEndpoint + "/command/add", async function (req, res) {
+  app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +100,3 @@
 
-  app.post(baseEndpoint + "/clear", async function (req, res) {
+  app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +130,3 @@
 
-  app.get(baseEndpoint + "/server/get", async function (req, res) {
+  app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -153,3 +160,3 @@
 
-  app.post(baseEndpoint + "/server/update", async function (req, res) {
+  app.post(baseEndpoint + "/server/update", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +194,3 @@
 
-  app.post(baseEndpoint + "/command/process", async function (req, res) {
+  app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
     isFeatureEnabled(features.bridge, res, lang);
EOF
@@ -1,2 +1,3 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import RateLimit from 'express-rate-limit';

@@ -5,3 +6,9 @@

app.get(baseEndpoint + "/get", async function (req, res) {
// set up rate limiter: maximum of 100 requests per 15 minutes
const limiter = RateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // max 100 requests per windowMs
});

app.get(baseEndpoint + "/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -59,3 +66,3 @@

app.post(baseEndpoint + "/command/add", async function (req, res) {
app.post(baseEndpoint + "/command/add", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -93,3 +100,3 @@

app.post(baseEndpoint + "/clear", async function (req, res) {
app.post(baseEndpoint + "/clear", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -123,3 +130,3 @@

app.get(baseEndpoint + "/server/get", async function (req, res) {
app.get(baseEndpoint + "/server/get", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -153,3 +160,3 @@

app.post(baseEndpoint + "/server/update", async function (req, res) {
app.post(baseEndpoint + "/server/update", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
@@ -187,3 +194,3 @@

app.post(baseEndpoint + "/command/process", async function (req, res) {
app.post(baseEndpoint + "/command/process", limiter, async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Comment on lines +124 to +152
app.get(baseEndpoint + "/server/get", async function (req, res) {
isFeatureEnabled(features.bridge, res, lang);

try {
db.query(
`SELECT * FROM serverStatus;`,
function (error, results) {
if (error) {
return res.send({
success: false,
message: `Failed: ${error}`,
});
}

return res.send({
success: true,
data: results,
});
}
);
} catch (error) {
return res.send({
success: false,
message: `Unexpected error: ${error}`,
});
}

return res;
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a database access
, but is not rate-limited.

Copilot Autofix AI 3 months ago

To fix the problem, we need to introduce rate limiting to the route handlers in the bridgeApiRoute function. The best way to achieve this is by using the express-rate-limit middleware. This middleware allows us to set a maximum number of requests that can be made to the server within a specified time window. We will apply this middleware to all the routes defined in the bridgeApiRoute function.

  1. Install the express-rate-limit package if it is not already installed.
  2. Import the express-rate-limit package at the beginning of the file.
  3. Define a rate limiter with appropriate settings (e.g., maximum of 100 requests per 15 minutes).
  4. Apply the rate limiter to the routes in the bridgeApiRoute function.
Suggested changeset 2
api/routes/bridge.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/routes/bridge.js b/api/routes/bridge.js
--- a/api/routes/bridge.js
+++ b/api/routes/bridge.js
@@ -1,6 +1,13 @@
 import { isFeatureEnabled, required, optional, generateLog } from "../common";
+import rateLimit from 'express-rate-limit';
 
 export default function bridgeApiRoute(app, config, db, features, lang) {
+  const limiter = rateLimit({
+    windowMs: 15 * 60 * 1000, // 15 minutes
+    max: 100, // limit each IP to 100 requests per windowMs
+  });
   const baseEndpoint = "/api/bridge";
 
+  app.use(baseEndpoint, limiter);
+
   app.get(baseEndpoint + "/get", async function (req, res) {
EOF
@@ -1,6 +1,13 @@
import { isFeatureEnabled, required, optional, generateLog } from "../common";
import rateLimit from 'express-rate-limit';

export default function bridgeApiRoute(app, config, db, features, lang) {
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
});
const baseEndpoint = "/api/bridge";

app.use(baseEndpoint, limiter);

app.get(baseEndpoint + "/get", async function (req, res) {
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -51,3 +51,4 @@
     "querystring": "^0.2.1",
-    "zero-md": "^2.3.1"
+    "zero-md": "^2.3.1",
+    "express-rate-limit": "^7.4.1"
   }
EOF
@@ -51,3 +51,4 @@
"querystring": "^0.2.1",
"zero-md": "^2.3.1"
"zero-md": "^2.3.1",
"express-rate-limit": "^7.4.1"
}
This fix introduces these dependencies
Package Version Security advisories
express-rate-limit (npm) 7.4.1 None
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants