summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/api')
-rw-r--r--src/api/Server.ts3
-rw-r--r--src/api/middlewares/ErrorHandler.ts9
-rw-r--r--src/api/middlewares/RateLimit.ts2
-rw-r--r--src/api/middlewares/TestClient.ts9
-rw-r--r--src/api/routes/applications/#id/entitlements.ts2
-rw-r--r--src/api/routes/channels/#channel_id/followers.ts2
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts2
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts27
-rw-r--r--src/api/routes/channels/#channel_id/recipients.ts4
-rw-r--r--src/api/routes/discoverable-guilds.ts7
-rw-r--r--src/api/routes/discovery.ts3
-rw-r--r--src/api/routes/experiments.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/discovery-requirements.ts5
-rw-r--r--src/api/routes/guilds/#guild_id/premium.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/regions.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/templates.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/widget.json.ts4
-rw-r--r--src/api/routes/guilds/index.ts5
-rw-r--r--src/api/routes/guilds/templates/index.ts7
-rw-r--r--src/api/routes/outbound-promotions.ts2
-rw-r--r--src/api/routes/partners/#guild_id/requirements.ts5
-rw-r--r--src/api/routes/ping.ts2
-rw-r--r--src/api/routes/science.ts2
-rw-r--r--src/api/routes/track.ts2
-rw-r--r--src/api/routes/users/@me/activities/statistics/applications.ts2
-rw-r--r--src/api/routes/users/@me/affinities/guilds.ts2
-rw-r--r--src/api/routes/users/@me/affinities/users.ts2
-rw-r--r--src/api/routes/users/@me/billing/payment-sources.ts2
-rw-r--r--src/api/routes/users/@me/delete.ts7
-rw-r--r--src/api/routes/users/@me/devices.ts2
-rw-r--r--src/api/routes/users/@me/disable.ts1
-rw-r--r--src/api/routes/users/@me/email-settings.ts2
-rw-r--r--src/api/routes/users/@me/entitlements.ts2
-rw-r--r--src/api/routes/users/@me/guilds/premium/subscription-slots.ts4
-rw-r--r--src/api/routes/users/@me/index.ts1
-rw-r--r--src/api/routes/users/@me/library.ts2
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts3
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts1
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts1
-rw-r--r--src/api/routes/users/@me/relationships.ts6
-rw-r--r--src/api/routes/voice/regions.ts2
-rw-r--r--src/api/util/handlers/Message.ts21
-rw-r--r--src/api/util/handlers/Voice.ts4
-rw-r--r--src/api/util/index.ts8
-rw-r--r--src/api/util/utility/Base64.ts47
-rw-r--r--src/api/util/utility/RandomInviteID.ts31
-rw-r--r--src/api/util/utility/String.ts18
-rw-r--r--src/api/util/utility/ipAddress.ts99
-rw-r--r--src/api/util/utility/passwordStrength.ts59
49 files changed, 100 insertions, 343 deletions
diff --git a/src/api/Server.ts b/src/api/Server.ts

index a3e6f23b..03c68af1 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts
@@ -4,6 +4,7 @@ import { Server, ServerOptions } from "lambert-server"; import morgan from "morgan"; import path from "path"; import { red } from "picocolors"; +import { PluginConfig } from "../util"; import { Authentication, CORS } from "./middlewares/"; import { BodyParser } from "./middlewares/BodyParser"; import { ErrorHandler } from "./middlewares/ErrorHandler"; @@ -40,7 +41,7 @@ export class FosscordServer extends Server { await initEvent(); await initInstance(); - let logRequests = process.env["LOG_REQUESTS"] != undefined; + let logRequests = "LOG_REQUESTS" in process.env; if (logRequests) { this.app.use( morgan("combined", { diff --git a/src/api/middlewares/ErrorHandler.ts b/src/api/middlewares/ErrorHandler.ts
index a3333be5..3ce1137e 100644 --- a/src/api/middlewares/ErrorHandler.ts +++ b/src/api/middlewares/ErrorHandler.ts
@@ -9,14 +9,13 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne let code = 400; let httpcode = code; let message = error?.toString(); - let errors = undefined; - let data = undefined; + let errors = null; + let data = null; if (error instanceof HTTPError && error.code) { code = httpcode = error.code; - if(error.data) data = error.data; - } - else if (error instanceof ApiError) { + if (error.data) data = error.data; + } else if (error instanceof ApiError) { code = error.code; message = error.message; httpcode = error.httpStatus; diff --git a/src/api/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index dc93dcef..6d4b08b0 100644 --- a/src/api/middlewares/RateLimit.ts +++ b/src/api/middlewares/RateLimit.ts
@@ -1,6 +1,6 @@ -import { getIpAdress } from "@fosscord/api"; import { Config, getRights, listenEvent } from "@fosscord/util"; import { NextFunction, Request, Response, Router } from "express"; +import { getIpAdress } from ".."; import { API_PREFIX_TRAILING_SLASH } from "./Authentication"; // Docs: https://discord.com/developers/docs/topics/rate-limits diff --git a/src/api/middlewares/TestClient.ts b/src/api/middlewares/TestClient.ts
index 9090840e..e4daaf25 100644 --- a/src/api/middlewares/TestClient.ts +++ b/src/api/middlewares/TestClient.ts
@@ -10,6 +10,7 @@ import { patchFile } from ".."; const prettier = require("prettier"); const AssetsPath = path.join(__dirname, "..", "..", "..", "assets"); +const cfg = Config.get(); export default function TestClient(app: Application) { const agent = new ProxyAgent(); @@ -81,22 +82,22 @@ export default function TestClient(app: Application) { return res.send(fs.readFileSync(assetCacheItem.FilePath)); }); app.get("/developers*", (_req: Request, res: Response) => { - const { useTestClient } = Config.get().client; res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24); res.set("content-type", "text/html"); - if (!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance."); + if (!cfg.client.useTestClient) + return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance."); res.send(fs.readFileSync(path.join(__dirname, "..", "..", "..", "assets", "developers.html"), { encoding: "utf8" })); }); app.get("*", (req: Request, res: Response) => { - const { useTestClient } = Config.get().client; res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24); res.set("content-type", "text/html"); if (req.url.startsWith("/api") || req.url.startsWith("/__development")) return; - if (!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance."); + if (!cfg.client.useTestClient) + return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance."); if (req.url.startsWith("/invite")) return res.send(html.replace("9b2b7f0632acd0c5e781", "9f24f709a3de09b67c49")); res.send(html); diff --git a/src/api/routes/applications/#id/entitlements.ts b/src/api/routes/applications/#id/entitlements.ts
index 26054eb0..07b9219d 100644 --- a/src/api/routes/applications/#id/entitlements.ts +++ b/src/api/routes/applications/#id/entitlements.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route //const { exclude_consumed } = req.query; res.status(200).send([]); }); diff --git a/src/api/routes/channels/#channel_id/followers.ts b/src/api/routes/channels/#channel_id/followers.ts
index c06db61b..d91f4b84 100644 --- a/src/api/routes/channels/#channel_id/followers.ts +++ b/src/api/routes/channels/#channel_id/followers.ts
@@ -1,6 +1,6 @@ import { Router } from "express"; const router: Router = Router(); -// TODO: +// TODO: implement route export default router; diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
index fbbc65f0..5cdb2ba1 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.post("/", route({ permission: "MANAGE_MESSAGES" }), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json({ id: "", type: 0, diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index d542ea0f..00008ed4 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -12,12 +12,10 @@ import { Message, MessageCreateEvent, MessageCreateSchema, - Snowflake, - uploadFile, - Member, - MessageCreateSchema, PluginEventHandler, - PreMessageEventArgs + PreMessageEventArgs, + Snowflake, + uploadFile } from "@fosscord/util"; import { Request, Response, Router } from "express"; import multer from "multer"; @@ -210,8 +208,8 @@ router.post( }) ); } - - //Defining member fields + + //Defining member fields var member = await Member.findOneOrFail({ where: { id: req.user_id }, relations: ["roles", "user"] }); // TODO: This doesn't work either // member.roles = member.roles.filter((role) => { @@ -224,10 +222,17 @@ router.post( // delete message.member.last_message_id; // delete message.member.index; - let blocks = (await PluginEventHandler.preMessageEvent({ - message - } as PreMessageEventArgs)).filter(x=>x.cancel); - if(blocks.length > 0) throw new HTTPError("Message denied.", 400, blocks.filter(x=>x.blockReason).map(x=>x.blockReason)); + let blocks = ( + await PluginEventHandler.preMessageEvent({ + message + } as PreMessageEventArgs) + ).filter((x) => x.cancel); + if (blocks.length > 0) + throw new HTTPError( + "Message denied.", + 400, + blocks.filter((x) => x.blockReason).map((x) => x.blockReason) + ); await Promise.all([ message.save(), diff --git a/src/api/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts
index 276a0eda..fc6b6b4f 100644 --- a/src/api/routes/channels/#channel_id/recipients.ts +++ b/src/api/routes/channels/#channel_id/recipients.ts
@@ -26,7 +26,7 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => { return res.status(201).json(new_channel); } else { if (channel.recipients!.map((r) => r.user_id).includes(user_id)) { - throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? + throw DiscordApiErrors.INVALID_RECIPIENT; //TODO: is this the right error? } channel.recipients!.push(OrmUtils.mergeDeep(new Recipient(), { channel_id, user_id: user_id })); @@ -57,7 +57,7 @@ router.delete("/:user_id", route({}), async (req: Request, res: Response) => { throw DiscordApiErrors.MISSING_PERMISSIONS; if (!channel.recipients!.map((r) => r.user_id).includes(user_id)) { - throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error? + throw DiscordApiErrors.INVALID_RECIPIENT; //TODO: is this the right error? } await Channel.removeRecipientFromChannel(channel, user_id); diff --git a/src/api/routes/discoverable-guilds.ts b/src/api/routes/discoverable-guilds.ts
index 2bf49287..3516efd1 100644 --- a/src/api/routes/discoverable-guilds.ts +++ b/src/api/routes/discoverable-guilds.ts
@@ -7,9 +7,10 @@ import { route } from ".."; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { + let cfg = Config.get(); const { offset, limit, categories } = req.query; - let showAllGuilds = Config.get().guild.discovery.showAllGuilds; - let configLimit = Config.get().guild.discovery.limit; + let showAllGuilds = cfg.guild.discovery.showAllGuilds; + let configLimit = cfg.guild.discovery.limit; // ! this only works using SQL querys // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) }); let guilds; @@ -31,7 +32,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { res.send({ total: total, guilds: guilds, - offset: Number(offset || Config.get().guild.discovery.offset), + offset: Number(offset || cfg.guild.discovery.offset), limit: Number(limit || configLimit) }); }); diff --git a/src/api/routes/discovery.ts b/src/api/routes/discovery.ts
index 7b9edd48..dce29ef6 100644 --- a/src/api/routes/discovery.ts +++ b/src/api/routes/discovery.ts
@@ -5,8 +5,7 @@ import { route } from ".."; const router = Router(); router.get("/categories", route({}), async (req: Request, res: Response) => { - // TODO: - // Get locale instead + // TODO: Get locale instead const { locale, primary_only } = req.query; diff --git a/src/api/routes/experiments.ts b/src/api/routes/experiments.ts
index 0355c631..356d674f 100644 --- a/src/api/routes/experiments.ts +++ b/src/api/routes/experiments.ts
@@ -4,7 +4,7 @@ import { route } from ".."; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.send({ fingerprint: "", assignments: [], guild_experiments: [] }); }); diff --git a/src/api/routes/guilds/#guild_id/discovery-requirements.ts b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
index c0260fe7..b8fdd060 100644 --- a/src/api/routes/guilds/#guild_id/discovery-requirements.ts +++ b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
@@ -5,9 +5,8 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; - // TODO: - // Load from database - // Admin control, but for now it allows anyone to be discoverable + // TODO: Load from database + // TODO: Admin control, but for now it allows anyone to be discoverable res.send({ guild_id: guild_id, diff --git a/src/api/routes/guilds/#guild_id/premium.ts b/src/api/routes/guilds/#guild_id/premium.ts
index b7716378..920811b0 100644 --- a/src/api/routes/guilds/#guild_id/premium.ts +++ b/src/api/routes/guilds/#guild_id/premium.ts
@@ -3,7 +3,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/subscriptions", route({}), async (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json([]); }); diff --git a/src/api/routes/guilds/#guild_id/regions.ts b/src/api/routes/guilds/#guild_id/regions.ts
index aa57ec65..5064ace5 100644 --- a/src/api/routes/guilds/#guild_id/regions.ts +++ b/src/api/routes/guilds/#guild_id/regions.ts
@@ -7,7 +7,7 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ where: { id: guild_id } }); - //TODO we should use an enum for guild's features and not hardcoded strings + //TODO: we should use an enum for guild's features and not hardcoded strings return res.json(await getVoiceRegions(getIpAdress(req), guild.features.includes("VIP_REGIONS"))); }); diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index 448ee033..af116760 100644 --- a/src/api/routes/guilds/#guild_id/templates.ts +++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -1,5 +1,5 @@ -import { generateCode, route } from "@fosscord/api"; -import { Guild, HTTPError, OrmUtils, Template } from "@fosscord/util"; +import { route } from "@fosscord/api"; +import { generateCode, Guild, HTTPError, OrmUtils, Template } from "@fosscord/util"; import { Request, Response, Router } from "express"; const router: Router = Router(); diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index 368fe46e..66cc456f 100644 --- a/src/api/routes/guilds/#guild_id/widget.json.ts +++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -1,5 +1,5 @@ -import { random, route } from "@fosscord/api"; -import { Channel, Guild, HTTPError, Invite, Member, OrmUtils, Permissions } from "@fosscord/util"; +import { route } from "@fosscord/api"; +import { Channel, Guild, HTTPError, Invite, Member, OrmUtils, Permissions, random } from "@fosscord/util"; import { Request, Response, Router } from "express"; const router: Router = Router(); diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 6946e2f7..3d433232 100644 --- a/src/api/routes/guilds/index.ts +++ b/src/api/routes/guilds/index.ts
@@ -7,9 +7,10 @@ const router: Router = Router(); //TODO: create default channel router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => { + let cfg = Config.get(); const body = req.body as GuildCreateSchema; - const { maxGuilds } = Config.get().limits.user; + const { maxGuilds } = cfg.limits.user; const guild_count = await Member.count({ where: { id: req.user_id } }); const rights = await getRights(req.user_id); if (guild_count >= maxGuilds && !rights.has("MANAGE_GUILDS")) { @@ -18,7 +19,7 @@ router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), a const guild = await Guild.createGuild({ ...body, owner_id: req.user_id }); - const { autoJoin } = Config.get().guild; + const { autoJoin } = cfg.guild; if (autoJoin.enabled && !autoJoin.guilds?.length) { // @ts-ignore await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } }); diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index 467186a3..bef10d6c 100644 --- a/src/api/routes/guilds/templates/index.ts +++ b/src/api/routes/guilds/templates/index.ts
@@ -4,8 +4,9 @@ import { Request, Response, Router } from "express"; import fetch from "node-fetch"; const router: Router = Router(); +let cfg = Config.get(); router.get("/:code", route({}), async (req: Request, res: Response) => { - const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates; + const { allowDiscordTemplates, allowRaws, enabled } = cfg.templates; if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403); const { code } = req.params; @@ -33,14 +34,14 @@ router.get("/:code", route({}), async (req: Request, res: Response) => { }); router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req: Request, res: Response) => { - const { enabled, allowTemplateCreation, allowDiscordTemplates, allowRaws } = Config.get().templates; + const { enabled, allowTemplateCreation, allowDiscordTemplates, allowRaws } = cfg.templates; if (!enabled) return res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403); if (!allowTemplateCreation) return res.json({ code: 403, message: "Template creation is disabled on this instance." }).sendStatus(403); const { code } = req.params; const body = req.body as GuildTemplateCreateSchema; - const { maxGuilds } = Config.get().limits.user; + const { maxGuilds } = cfg.limits.user; const guild_count = await Member.count({ where: { id: req.user_id } }); if (guild_count >= maxGuilds) { diff --git a/src/api/routes/outbound-promotions.ts b/src/api/routes/outbound-promotions.ts
index 8e407184..42378bb2 100644 --- a/src/api/routes/outbound-promotions.ts +++ b/src/api/routes/outbound-promotions.ts
@@ -1,5 +1,5 @@ -import { route } from "@fosscord/api"; import { Request, Response, Router } from "express"; +import { route } from ".."; const router: Router = Router(); diff --git a/src/api/routes/partners/#guild_id/requirements.ts b/src/api/routes/partners/#guild_id/requirements.ts
index c0260fe7..b8fdd060 100644 --- a/src/api/routes/partners/#guild_id/requirements.ts +++ b/src/api/routes/partners/#guild_id/requirements.ts
@@ -5,9 +5,8 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; - // TODO: - // Load from database - // Admin control, but for now it allows anyone to be discoverable + // TODO: Load from database + // TODO: Admin control, but for now it allows anyone to be discoverable res.send({ guild_id: guild_id, diff --git a/src/api/routes/ping.ts b/src/api/routes/ping.ts
index 5f1b0174..e8b25442 100644 --- a/src/api/routes/ping.ts +++ b/src/api/routes/ping.ts
@@ -1,6 +1,6 @@ -import { route } from "@fosscord/api"; import { Config } from "@fosscord/util"; import { Request, Response, Router } from "express"; +import { route } from ".."; const router = Router(); diff --git a/src/api/routes/science.ts b/src/api/routes/science.ts
index cb01e576..a25fc958 100644 --- a/src/api/routes/science.ts +++ b/src/api/routes/science.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.post("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route? res.sendStatus(204); }); diff --git a/src/api/routes/track.ts b/src/api/routes/track.ts
index cb01e576..a25fc958 100644 --- a/src/api/routes/track.ts +++ b/src/api/routes/track.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.post("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route? res.sendStatus(204); }); diff --git a/src/api/routes/users/@me/activities/statistics/applications.ts b/src/api/routes/users/@me/activities/statistics/applications.ts
index ba359b47..1a3b9906 100644 --- a/src/api/routes/users/@me/activities/statistics/applications.ts +++ b/src/api/routes/users/@me/activities/statistics/applications.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json([]).status(200); }); diff --git a/src/api/routes/users/@me/affinities/guilds.ts b/src/api/routes/users/@me/affinities/guilds.ts
index e733910f..7e1a76c2 100644 --- a/src/api/routes/users/@me/affinities/guilds.ts +++ b/src/api/routes/users/@me/affinities/guilds.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.status(200).send({ guild_affinities: [] }); }); diff --git a/src/api/routes/users/@me/affinities/users.ts b/src/api/routes/users/@me/affinities/users.ts
index 758bedc3..ead5c564 100644 --- a/src/api/routes/users/@me/affinities/users.ts +++ b/src/api/routes/users/@me/affinities/users.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.status(200).send({ user_affinities: [], inverse_user_affinities: [] }); }); diff --git a/src/api/routes/users/@me/billing/payment-sources.ts b/src/api/routes/users/@me/billing/payment-sources.ts
index ba359b47..1a3b9906 100644 --- a/src/api/routes/users/@me/billing/payment-sources.ts +++ b/src/api/routes/users/@me/billing/payment-sources.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json([]).status(200); }); diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index dfc6131b..c3caf327 100644 --- a/src/api/routes/users/@me/delete.ts +++ b/src/api/routes/users/@me/delete.ts
@@ -1,5 +1,6 @@ import { route } from "@fosscord/api"; import { HTTPError, Member, User } from "@fosscord/util"; +import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; let bcrypt: any; @@ -24,7 +25,11 @@ router.post("/", route({}), async (req: Request, res: Response) => { } } - // TODO: decrement guild member count + (await Member.find({ where: { id: req.user_id }, relations: ["guild"] })).forEach((x) => { + let g = x.guild; + if (g.member_count) g.member_count--; + g.save(); + }); if (correctpass) { await Promise.all([User.delete({ id: req.user_id }), Member.delete({ id: req.user_id })]); diff --git a/src/api/routes/users/@me/devices.ts b/src/api/routes/users/@me/devices.ts
index cb01e576..7c0fd034 100644 --- a/src/api/routes/users/@me/devices.ts +++ b/src/api/routes/users/@me/devices.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.post("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.sendStatus(204); }); diff --git a/src/api/routes/users/@me/disable.ts b/src/api/routes/users/@me/disable.ts
index 05976908..e47ace91 100644 --- a/src/api/routes/users/@me/disable.ts +++ b/src/api/routes/users/@me/disable.ts
@@ -1,5 +1,6 @@ import { route } from "@fosscord/api"; import { User } from "@fosscord/util"; +import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; let bcrypt: any; diff --git a/src/api/routes/users/@me/email-settings.ts b/src/api/routes/users/@me/email-settings.ts
index 28d0864a..fc248283 100644 --- a/src/api/routes/users/@me/email-settings.ts +++ b/src/api/routes/users/@me/email-settings.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json({ categories: { social: true, diff --git a/src/api/routes/users/@me/entitlements.ts b/src/api/routes/users/@me/entitlements.ts
index 7aaa5d7c..2848755a 100644 --- a/src/api/routes/users/@me/entitlements.ts +++ b/src/api/routes/users/@me/entitlements.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/gifts", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json([]).status(200); }); diff --git a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
index ba359b47..3ce7ac1a 100644 --- a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts +++ b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
@@ -1,10 +1,10 @@ -import { route } from "@fosscord/api"; import { Request, Response, Router } from "express"; +import { route } from "../../../../.."; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: implement route res.json([]).status(200); }); diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 563300dc..7ee0a178 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts
@@ -12,6 +12,7 @@ import { UserModifySchema, UserUpdateEvent } from "@fosscord/util"; +import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; let bcrypt: any; diff --git a/src/api/routes/users/@me/library.ts b/src/api/routes/users/@me/library.ts
index 0aea02a0..b1a5a53e 100644 --- a/src/api/routes/users/@me/library.ts +++ b/src/api/routes/users/@me/library.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express"; const router = Router(); router.get("/", route({}), (req: Request, res: Response) => { - // TODO: + // TODO: Add library route res.status(200).send([]); }); diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index c62581cc..956ac2ae 100644 --- a/src/api/routes/users/@me/mfa/codes.ts +++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -1,6 +1,7 @@ -import { route } from "@fosscord/api"; import { BackupCode, Config, FieldErrors, generateMfaBackupCodes, MfaCodesSchema, User } from "@fosscord/util"; +import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; +import { route } from "../../../.."; let bcrypt: any; try { diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index a53fa816..22f34e06 100644 --- a/src/api/routes/users/@me/mfa/totp/disable.ts +++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -2,6 +2,7 @@ import { route } from "@fosscord/api"; import { BackupCode, generateToken, HTTPError, TotpDisableSchema, User } from "@fosscord/util"; import { Request, Response, Router } from "express"; import { verifyToken } from "node-2fa"; +import { route } from "../../../../.."; const router = Router(); diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index 0bf1a188..15b2764b 100644 --- a/src/api/routes/users/@me/mfa/totp/enable.ts +++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -2,6 +2,7 @@ import { route } from "@fosscord/api"; import { BackupCode, Config, generateMfaBackupCodes, generateToken, HTTPError, TotpEnableSchema, User } from "@fosscord/util"; import { Request, Response, Router } from "express"; import { verifyToken } from "node-2fa"; +import { route } from "../../../../.."; let bcrypt: any; try { diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index 8267c142..1ff6c452 100644 --- a/src/api/routes/users/@me/relationships.ts +++ b/src/api/routes/users/@me/relationships.ts
@@ -25,7 +25,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { select: ["relationships"] }); - //TODO DTO + //TODO: DTO const related_users = user.relationships.map((r) => { return { id: r.to.id, @@ -181,7 +181,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you"); if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); // accept friend request - incoming_relationship = friendRequest as any; //TODO: checkme, any cast + incoming_relationship = friendRequest; incoming_relationship.type = RelationshipType.friends; } @@ -189,7 +189,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request"); if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request"); if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); - outgoing_relationship = relationship as any; //TODO: checkme, any cast + outgoing_relationship = relationship; outgoing_relationship.type = RelationshipType.friends; } diff --git a/src/api/routes/voice/regions.ts b/src/api/routes/voice/regions.ts
index eacdcf11..9745bbe4 100644 --- a/src/api/routes/voice/regions.ts +++ b/src/api/routes/voice/regions.ts
@@ -1,5 +1,5 @@ -import { getIpAdress, getVoiceRegions, route } from "@fosscord/api"; import { Request, Response, Router } from "express"; +import { getIpAdress, getVoiceRegions, route } from "../.."; const router: Router = Router(); diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 07ed11ad..5237b26a 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts
@@ -18,16 +18,11 @@ import { MessageType, MessageUpdateEvent, OrmUtils, + PluginEventHandler, + PreMessageEventArgs, Role, ROLE_MENTION, User, - Application, - Webhook, - Attachment, - Config, - MessageCreateSchema, - PluginEventHandler, - PreMessageEventArgs, USER_MENTION, Webhook } from "@fosscord/util"; @@ -212,11 +207,15 @@ export async function postHandleMessage(message: Message) { export async function sendMessage(opts: MessageOptions) { const message = await handleMessage({ ...opts, timestamp: new Date() }); - if((await PluginEventHandler.preMessageEvent({ - message - } as PreMessageEventArgs)).filter(x=>x.cancel).length > 0) return; + if ( + ( + await PluginEventHandler.preMessageEvent({ + message + } as PreMessageEventArgs) + ).filter((x) => x.cancel).length > 0 + ) + return; - //TODO: check this, removed toJSON call await Promise.all([ Message.insert(message), emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message } as MessageCreateEvent) diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts
index 4d60eb91..624c868a 100644 --- a/src/api/util/handlers/Voice.ts +++ b/src/api/util/handlers/Voice.ts
@@ -1,5 +1,5 @@ import { Config } from "@fosscord/util"; -import { distanceBetweenLocations, IPAnalysis } from "../utility/ipAddress"; +import { distanceBetweenLocations, IPAnalysis } from "../../../util/util/ipAddress"; export async function getVoiceRegions(ipAddress: string, vip: boolean) { const regions = Config.get().regions; @@ -12,7 +12,7 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) { let min = Number.POSITIVE_INFINITY; for (let ar of availableRegions) { - //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call + //TODO: the endpoint location should be saved in the database if not already present to prevent IPAnalysis call const dist = distanceBetweenLocations(clientIpAnalysis, ar.location || (await IPAnalysis(ar.endpoint))); if (dist < min) { diff --git a/src/api/util/index.ts b/src/api/util/index.ts
index f01c2f43..5180e17c 100644 --- a/src/api/util/index.ts +++ b/src/api/util/index.ts
@@ -1,12 +1,8 @@ +export * from "../../util/util/Base64"; +export * from "../../util/util/ipAddress"; export * from "./entities/AssetCacheItem"; export * from "./handlers/Message"; export * from "./handlers/route"; export * from "./handlers/Voice"; -export * from "./utility/Base64"; -export * from "./utility/captcha"; -export * from "./utility/ipAddress"; -export * from "./utility/passwordStrength"; -export * from "./utility/RandomInviteID"; -export * from "./utility/String"; export * from "./utility/captcha"; export * from "./TestClientPatcher"; \ No newline at end of file diff --git a/src/api/util/utility/Base64.ts b/src/api/util/utility/Base64.ts deleted file mode 100644
index 46cff77a..00000000 --- a/src/api/util/utility/Base64.ts +++ /dev/null
@@ -1,47 +0,0 @@ -const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+"; - -// binary to string lookup table -const b2s = alphabet.split(""); - -// string to binary lookup table -// 123 == 'z'.charCodeAt(0) + 1 -const s2b = new Array(123); -for (let i = 0; i < alphabet.length; i++) { - s2b[alphabet.charCodeAt(i)] = i; -} - -// number to base64 -export const ntob = (n: number): string => { - if (n < 0) return `-${ntob(-n)}`; - - let lo = n >>> 0; - let hi = (n / 4294967296) >>> 0; - - let right = ""; - while (hi > 0) { - right = b2s[0x3f & lo] + right; - lo >>>= 6; - lo |= (0x3f & hi) << 26; - hi >>>= 6; - } - - let left = ""; - do { - left = b2s[0x3f & lo] + left; - lo >>>= 6; - } while (lo > 0); - - return left + right; -}; - -// base64 to number -export const bton = (base64: string) => { - let number = 0; - const sign = base64.charAt(0) === "-" ? 1 : 0; - - for (let i = sign; i < base64.length; i++) { - number = number * 64 + s2b[base64.charCodeAt(i)]; - } - - return sign ? -number : number; -}; diff --git a/src/api/util/utility/RandomInviteID.ts b/src/api/util/utility/RandomInviteID.ts deleted file mode 100644
index feebfd3d..00000000 --- a/src/api/util/utility/RandomInviteID.ts +++ /dev/null
@@ -1,31 +0,0 @@ -import { Snowflake } from "@fosscord/util"; - -export function random(length = 6) { - // Declare all characters - let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - // Pick characers randomly - let str = ""; - for (let i = 0; i < length; i++) { - str += chars.charAt(Math.floor(Math.random() * chars.length)); - } - - return str; -} - -export function snowflakeBasedInvite() { - // Declare all characters - let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let base = BigInt(chars.length); - let snowflake = Snowflake.generateWorkerProcess(); - - // snowflakes hold ~10.75 characters worth of entropy; - // safe to generate a 8-char invite out of them - let str = ""; - for (let i = 0; i < 10; i++) { - str.concat(chars.charAt(Number(snowflake % base))); - snowflake = snowflake / base; - } - - return str.substr(3, 8).split("").reverse().join(""); -} diff --git a/src/api/util/utility/String.ts b/src/api/util/utility/String.ts deleted file mode 100644
index a2e491e4..00000000 --- a/src/api/util/utility/String.ts +++ /dev/null
@@ -1,18 +0,0 @@ -import { FieldErrors } from "@fosscord/util"; -import { Request } from "express"; -import { ntob } from "./Base64"; - -export function checkLength(str: string, min: number, max: number, key: string, req: Request) { - if (str.length < min || str.length > max) { - throw FieldErrors({ - [key]: { - code: "BASE_TYPE_BAD_LENGTH", - message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { length: `${min} - ${max}` }) - } - }); - } -} - -export function generateCode() { - return ntob(Date.now() + Math.randomIntBetween(0, 10000)); -} diff --git a/src/api/util/utility/ipAddress.ts b/src/api/util/utility/ipAddress.ts deleted file mode 100644
index c96feb9e..00000000 --- a/src/api/util/utility/ipAddress.ts +++ /dev/null
@@ -1,99 +0,0 @@ -import { Config } from "@fosscord/util"; -import { Request } from "express"; -// use ipdata package instead of simple fetch because of integrated caching -import fetch from "node-fetch"; - -const exampleData = { - ip: "", - is_eu: true, - city: "", - region: "", - region_code: "", - country_name: "", - country_code: "", - continent_name: "", - continent_code: "", - latitude: 0, - longitude: 0, - postal: "", - calling_code: "", - flag: "", - emoji_flag: "", - emoji_unicode: "", - asn: { - asn: "", - name: "", - domain: "", - route: "", - type: "isp" - }, - languages: [ - { - name: "", - native: "" - } - ], - currency: { - name: "", - code: "", - symbol: "", - native: "", - plural: "" - }, - time_zone: { - name: "", - abbr: "", - offset: "", - is_dst: true, - current_time: "" - }, - threat: { - is_tor: false, - is_proxy: false, - is_anonymous: false, - is_known_attacker: false, - is_known_abuser: false, - is_threat: false, - is_bogon: false - }, - count: 0, - status: 200 -}; - -//TODO add function that support both ip and domain names -export async function IPAnalysis(ip: string): Promise<typeof exampleData> { - const { ipdataApiKey } = Config.get().security; - if (!ipdataApiKey) return { ...exampleData, ip }; - - return (await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`)).json() as any; -} - -export function isProxy(data: typeof exampleData) { - if (!data || !data.asn || !data.threat) return false; - if (data.asn.type !== "isp") return true; - if (Object.values(data.threat).some((x) => x)) return true; - - return false; -} - -export function getIpAdress(req: Request): string { - // @ts-ignore - return ( - req.headers[Config.get().security.forwadedFor as string] || - req.headers[Config.get().security.forwadedFor?.toLowerCase() as string] || - req.socket.remoteAddress - ); -} - -export function distanceBetweenLocations(loc1: any, loc2: any): number { - return distanceBetweenCoords(loc1.latitude, loc1.longitude, loc2.latitude, loc2.longitude); -} - -//Haversine function -function distanceBetweenCoords(lat1: number, lon1: number, lat2: number, lon2: number) { - const p = 0.017453292519943295; // Math.PI / 180 - const c = Math.cos; - const a = 0.5 - c((lat2 - lat1) * p) / 2 + (c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p))) / 2; - - return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km -} diff --git a/src/api/util/utility/passwordStrength.ts b/src/api/util/utility/passwordStrength.ts deleted file mode 100644
index ff83d3df..00000000 --- a/src/api/util/utility/passwordStrength.ts +++ /dev/null
@@ -1,59 +0,0 @@ -import { Config } from "@fosscord/util"; - -const reNUMBER = /[0-9]/g; -const reUPPERCASELETTER = /[A-Z]/g; -const reSYMBOLS = /[A-Z,a-z,0-9]/g; - -const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored in db -/* - * https://en.wikipedia.org/wiki/Password_policy - * password must meet following criteria, to be perfect: - * - min <n> chars - * - min <n> numbers - * - min <n> symbols - * - min <n> uppercase chars - * - shannon entropy folded into [0, 1) interval - * - * Returns: 0 > pw > 1 - */ -export function checkPassword(password: string): number { - const { minLength, minNumbers, minUpperCase, minSymbols } = Config.get().register.password; - let strength = 0; - - // checks for total password len - if (password.length >= minLength - 1) { - strength += 0.05; - } - - // checks for amount of Numbers - if (password.count(reNUMBER) >= minNumbers - 1) { - strength += 0.05; - } - - // checks for amount of Uppercase Letters - if (password.count(reUPPERCASELETTER) >= minUpperCase - 1) { - strength += 0.05; - } - - // checks for amount of symbols - if (password.replace(reSYMBOLS, "").length >= minSymbols - 1) { - strength += 0.05; - } - - // checks if password only consists of numbers or only consists of chars - if (password.length == password.count(reNUMBER) || password.length === password.count(reUPPERCASELETTER)) { - strength = 0; - } - - let entropyMap: { [key: string]: number } = {}; - for (let i = 0; i < password.length; i++) { - if (entropyMap[password[i]]) entropyMap[password[i]]++; - else entropyMap[password[i]] = 1; - } - - let entropies = Object.values(entropyMap); - - entropies.map((x) => x / entropyMap.length); - strength += entropies.reduceRight((a: number, x: number) => a - x * Math.log2(x)) / Math.log2(password.length); - return strength; -}