diff --git a/config.json b/config.json index df122f6..8228f04 100644 --- a/config.json +++ b/config.json @@ -41,10 +41,19 @@ ] }, "redeems": { + "redeem_crushhisskull": { + "id": "redeem_crushhisskull", + "title": "MODS", + "description": "Crush His Skull", + "args": [], + "image": "https://vedalai.github.io/swarm-control/Erm.png", + "price": 1, + "sku": "bits1" + }, "redeem_addsignal": { "id": "redeem_addsignal", "title": "Add Beacon", - "description": "Adds a beacon ping to the map. (This one has a chance to fail on purpose)", + "description": "Adds a beacon ping to the map.", "args": [ { "type": 4, @@ -246,4 +255,4 @@ "hidden": true } } -} \ No newline at end of file +} diff --git a/ebs/src/util/db.ts b/ebs/src/util/db.ts index a898b73..aced376 100644 --- a/ebs/src/util/db.ts +++ b/ebs/src/util/db.ts @@ -33,7 +33,7 @@ export async function setupDb() { receipt VARCHAR(255) PRIMARY KEY, token VARCHAR(255) NOT NULL, userId VARCHAR(255) NOT NULL - ) + ); `); await db.query(` @@ -41,13 +41,24 @@ export async function setupDb() { token VARCHAR(255) PRIMARY KEY, cart JSON NOT NULL, userId VARCHAR(255) NOT NULL - ) + ); `); await db.query(` CREATE TABLE IF NOT EXISTS bans ( userId VARCHAR(255) PRIMARY KEY - ) + ); + `); + + await db.query(` + CREATE TABLE IF NOT EXISTS logs ( + id INT PRIMARY KEY AUTO_INCREMENT, + userId VARCHAR(255) NOT NULL, + transactionToken VARCHAR(255) NOT NULL, + data TEXT NOT NULL, + fromBackend BOOLEAN NOT NULL, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); `); } diff --git a/logger/src/modules/endpoints.ts b/logger/src/modules/endpoints.ts index edeb0f4..9598b7c 100644 --- a/logger/src/modules/endpoints.ts +++ b/logger/src/modules/endpoints.ts @@ -1,15 +1,14 @@ import { app } from "../index"; -import { LogBuilder } from "../util/discord"; +import { logToDiscord } from "../util/discord"; import { LogMessage } from "common/types"; -import { canLog, getUserIdFromTransactionToken, isUserBanned } from "../util/db"; +import { canLog, getUserIdFromTransactionToken, isUserBanned, logToDatabase } from "../util/db"; app.post("/log", async (req, res) => { try { const logMessage = req.body as LogMessage & { backendToken?: string }; + const isBackendRequest = process.env.PRIVATE_LOGGER_TOKEN == logMessage.backendToken; - if (process.env.PRIVATE_LOGGER_TOKEN! == logMessage.backendToken) { - // This is a log comin from the backend, we should let it through - } else { + if (!isBackendRequest) { const validTransactionToken = await canLog(logMessage.transactionToken); if (!validTransactionToken) { res.status(403).send("Invalid transaction token."); @@ -20,22 +19,37 @@ app.post("/log", async (req, res) => { // In the eventuality that this happens, we also check for extension bans here. const userId = await getUserIdFromTransactionToken(logMessage.transactionToken!); + if (userId && (await isUserBanned(userId))) { res.status(403).send("User is banned."); return; } - } - const builder = new LogBuilder(); + if (userId != logMessage.userIdInsecure) { + const warningMessage: LogMessage = { + transactionToken: logMessage.transactionToken, + userIdInsecure: userId, + important: true, + fields: [ + { + header: "Someone tried to bamboozle the logger user id check", + content: "Received user id: " + logMessage.userIdInsecure, + }, + ], + }; + logToDiscord(warningMessage, true); + logToDatabase(warningMessage, true).then(); + res.status(403).send("Invalid user id."); + return; + } + } - // TODO: add transaction token and user id to the log message + await logToDatabase(logMessage, isBackendRequest); - for (const field of logMessage.fields) { - builder.addField(field.header, field.content); + if (logMessage.important) { + logToDiscord(logMessage, isBackendRequest); } - builder.send(logMessage.important); - res.sendStatus(200); } catch (e: any) { console.error("Failed to log"); diff --git a/logger/src/util/db.ts b/logger/src/util/db.ts index 6fe45c1..d1ca2bc 100644 --- a/logger/src/util/db.ts +++ b/logger/src/util/db.ts @@ -1,5 +1,8 @@ import { db } from "../index"; import { RowDataPacket } from "mysql2"; +import { LogMessage } from "common/types"; +import { stringify } from "./stringify"; +import { logToDiscord } from "./discord"; export async function canLog(token: string | null): Promise { try { @@ -45,3 +48,19 @@ export async function isUserBanned(userId: string): Promise { return false; } } + +export async function logToDatabase(logMessage: LogMessage, isFromBackend: boolean) { + try { + await db.query("INSERT INTO logs (userId, transactionToken, data, fromBackend) VALUES (?, ?, ?, ?)", [ + logMessage.userIdInsecure, + logMessage.transactionToken, + stringify(logMessage, isFromBackend), + isFromBackend, + ]); + } catch (e: any) { + console.error("Database query failed (logToDatabase)"); + console.error(e); + + if (!logMessage.important) logToDiscord(logMessage, isFromBackend); + } +} diff --git a/logger/src/util/discord.ts b/logger/src/util/discord.ts index aedf550..036d311 100644 --- a/logger/src/util/discord.ts +++ b/logger/src/util/discord.ts @@ -1,36 +1,16 @@ import { Webhook } from "@vermaysha/discord-webhook"; +import { LogMessage } from "common/types"; +import { stringify } from "./stringify"; const hook = new Webhook(process.env.DISCORD_WEBHOOK!); hook.setUsername("Swarm Control"); -export function log(message: string) { +function log(message: string) { console.error(message); hook.setContent(message); hook.send().then(); } -export function logImportant(message: string) { - log(`<@183249892712513536>\n${message}`); -} - -export class LogBuilder { - public constructor() {} - - private data = ""; - - public send(important: boolean) { - if (!important) log(this.data); - else logImportant(this.data); - } - - public addField(header: string, content?: any): LogBuilder { - if (content) { - let contentStr = content.toString(); - if (contentStr == "[object Object]") contentStr = JSON.stringify(content, null, 4); - this.data += `### ${header}\n\`\`\`${contentStr}\`\`\`\n`; - } else { - this.data += `### ${header}\n`; - } - return this; - } +export function logToDiscord(logMessage: LogMessage, isFromBackend: boolean) { + log(stringify(logMessage, isFromBackend)); } diff --git a/logger/src/util/stringify.ts b/logger/src/util/stringify.ts new file mode 100644 index 0000000..be8c971 --- /dev/null +++ b/logger/src/util/stringify.ts @@ -0,0 +1,21 @@ +import { LogMessage } from "common/types"; + +export function stringify(logMessage: LogMessage, isFromBackend: boolean) { + let data = ""; + + if (logMessage.important) data += "<@183249892712513536>\n"; + + data += `${logMessage.userIdInsecure} | ${logMessage.transactionToken} | ${isFromBackend ? "Backend" : "Extension"}`; + + for (const field of logMessage.fields) { + if (field.content) { + let contentStr = field.content.toString(); + if (contentStr == "[object Object]") contentStr = JSON.stringify(field.content, null, 4); + data += `### ${field.header}\n\`\`\`${contentStr}\`\`\`\n`; + } else { + data += `### ${field.header}\n`; + } + } + + return data; +}