diff --git a/src/Server.ts b/src/Server.ts
index b561f94e..fa4111db 100644
--- a/src/Server.ts
+++ b/src/Server.ts
@@ -1,5 +1,6 @@
import "missing-native-js-functions";
import fs from "fs/promises";
+import { Connection } from "mongoose";
import { Server, ServerOptions } from "lambert-server";
import { Authentication, GlobalRateLimit } from "./middlewares/";
import Config from "./util/Config";
@@ -29,8 +30,20 @@ export class DiscordServer extends Server {
super({ ...opts, errorHandler: false, jsonBody: false });
}
+ async setupSchema() {
+ await db.collection("users").createIndex({ id: 1 }, { unique: true });
+ await db.collection("messages").createIndex({ id: 1 }, { unique: true });
+ await db.collection("channels").createIndex({ id: 1 }, { unique: true });
+ await db.collection("guilds").createIndex({ id: 1 }, { unique: true });
+ await db.collection("members").createIndex({ id: 1 }, { unique: true });
+ await db.collection("roles").createIndex({ id: 1 }, { unique: true });
+ await db.collection("emojis").createIndex({ id: 1 }, { unique: true });
+ }
+
async start() {
- await db.init();
+ // @ts-ignore
+ await (db as Promise<Connection>);
+ await this.setupSchema();
console.log("[DB] connected");
await Promise.all([Config.init()]);
diff --git a/src/middlewares/GlobalRateLimit.ts b/src/middlewares/GlobalRateLimit.ts
index c729987a..33dc5e0f 100644
--- a/src/middlewares/GlobalRateLimit.ts
+++ b/src/middlewares/GlobalRateLimit.ts
@@ -6,6 +6,8 @@ import { db } from "fosscord-server-util";
// TODO: increment count on serverside
export async function GlobalRateLimit(req: Request, res: Response, next: NextFunction) {
+ return next();
+ // TODO: use new db mongoose models
if (!Config.get().limits.rate.ip.enabled) return next();
const ip = getIpAdress(req);
diff --git a/src/middlewares/RateLimit.ts b/src/middlewares/RateLimit.ts
index c42d773c..b015c7e0 100644
--- a/src/middlewares/RateLimit.ts
+++ b/src/middlewares/RateLimit.ts
@@ -5,6 +5,9 @@ import { getIpAdress } from "./GlobalRateLimit";
export function RateLimit({ count = 10, timespan = 1000 * 5, name = "/" }) {
return async (req: Request, res: Response, next: NextFunction) => {
+ return next();
+ // TODO: use new db mongoose models
+
let id = req.userid || getIpAdress(req);
const limit: { count: number; start: number } = (await db.data.ratelimit.routes[name][id].get()) || {
diff --git a/src/routes/api/v8/auth/login.ts b/src/routes/api/v8/auth/login.ts
index ac9775df..acdac1ce 100644
--- a/src/routes/api/v8/auth/login.ts
+++ b/src/routes/api/v8/auth/login.ts
@@ -2,7 +2,7 @@ import { Request, Response, Router } from "express";
import { check, FieldErrors, Length } from "../../../../util/instanceOf";
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
-import { db, User } from "fosscord-server-util";
+import { User, UserModel } from "fosscord-server-util";
import Config from "../../../../util/Config";
import { adjustEmail } from "./register";
@@ -23,10 +23,12 @@ router.post(
const { login, password } = req.body;
// * MongoDB Specific query for user with same email or phone number
- const userquery = { $or: [{ email: adjustEmail(login) }, { phone: login }] };
- const user: User = await db.data
- .users(userquery)
- .get({ hash: true, id: true, user_settings: { locale: true, theme: true } });
+ const user = await UserModel.findOne(
+ {
+ $or: [{ email: adjustEmail(login) }, { phone: login }],
+ },
+ `hash id user_settings.locale user_settings.theme`
+ ).exec();
if (!user) {
throw FieldErrors({
diff --git a/src/routes/api/v8/auth/register.ts b/src/routes/api/v8/auth/register.ts
index 1250b689..1205c462 100644
--- a/src/routes/api/v8/auth/register.ts
+++ b/src/routes/api/v8/auth/register.ts
@@ -1,6 +1,6 @@
import { Request, Response, Router } from "express";
import Config from "../../../../util/Config";
-import { db, trimSpecial, User, Snowflake } from "fosscord-server-util";
+import { trimSpecial, User, Snowflake, UserModel } from "fosscord-server-util";
import bcrypt from "bcrypt";
import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../../../util/instanceOf";
import "missing-native-js-functions";
@@ -80,7 +80,8 @@ router.post(
adjusted_email = adjustEmail(email);
// check if there is already an account with this email
- const exists = await db.data.users({ email: adjusted_email }).get();
+ const exists = await UserModel.findOne({ email: adjusted_email }).exec();
+
if (exists) {
throw FieldErrors({
email: {
@@ -116,7 +117,8 @@ router.post(
if (!register.allowMultipleAccounts) {
// TODO: check if fingerprint was eligible generated
- const exists = await db.data.users({ fingerprint }).get();
+ const exists = await UserModel.findOne({ fingerprints: fingerprint }).exec();
+
if (exists) {
throw FieldErrors({
email: {
@@ -150,7 +152,7 @@ router.post(
// TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the mongodb database?
for (let tries = 0; tries < 5; tries++) {
discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0");
- exists = await db.data.users({ discriminator, username: adjusted_username }).get({ id: true });
+ exists = await UserModel.findOne({ discriminator, username: adjusted_username }, "id").exec();
if (!exists) break;
}
@@ -164,6 +166,8 @@ router.post(
}
// constructing final user object
+ // TODO fix:
+ // @ts-ignore
const user: User = {
id: Snowflake.generate(),
created_at: Date.now(),
@@ -220,7 +224,7 @@ router.post(
};
// insert user into database
- await db.data.users.push(user);
+ await new UserModel(user).save({});
return res.json({ token: await generateToken(user.id) });
}
diff --git a/src/routes/api/v8/guilds/index.ts b/src/routes/api/v8/guilds/index.ts
index 2d7e081a..46372a68 100644
--- a/src/routes/api/v8/guilds/index.ts
+++ b/src/routes/api/v8/guilds/index.ts
@@ -1,19 +1,20 @@
import { Router, Request, Response } from "express";
-import { db, Guild, Snowflake } from "fosscord-server-util";
+import { GuildDeleteEvent, GuildModel, MemberModel, Snowflake } from "fosscord-server-util";
import { HTTPError } from "lambert-server";
import { check } from "./../../../../util/instanceOf";
-import { GuildCreateSchema, GuildGetSchema, GuildUpdateSchema } from "../../../../schema/Guild";
+import { GuildCreateSchema, GuildUpdateSchema } from "../../../../schema/Guild";
+import { emitEvent } from "../../../../util/Event";
const router: Router = Router();
router.get("/:id", async (req: Request, res: Response) => {
- const member = await db.data.guilds({ id: req.params.id }).members({ id: req.userid }).get({ id: true });
+ const guild = await GuildModel.findOne({ id: BigInt(req.params.id) }).exec();
+ if (!guild) throw new HTTPError("Guild doesn't exist");
- if (!member) {
- throw new HTTPError("you arent a member of the guild you are trying to access", 401);
- }
+ const member = await MemberModel.findOne({ guild_id: req.params.id, id: req.userid }, "id").exec();
+
+ if (!member) throw new HTTPError("you arent a member of the guild you are trying to access", 401);
- const guild = await db.data.guilds({ id: req.params.id }).get(GuildGetSchema);
return res.json(guild);
});
@@ -21,7 +22,7 @@ router.patch("/:id", check(GuildUpdateSchema), async (req: Request, res: Respons
// TODO: check permission of member
const body = req.body as GuildUpdateSchema;
- const guild = await db.data.guilds({ id: req.params.id }).get({ id: true });
+ const guild = await GuildModel.findOne({ id: BigInt(req.params.id) }).exec();
if (!guild) throw new HTTPError("This guild doesnt exist", 404);
throw "not finished";
@@ -30,70 +31,40 @@ router.patch("/:id", check(GuildUpdateSchema), async (req: Request, res: Respons
// // TODO: finish POST route
router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) => {
const body = req.body as GuildCreateSchema;
+ // TODO: check if user is in more than 100 (config max guilds)
const guildID = Snowflake.generate();
- const guild: Guild = {
- // name: undefined,
- // owner: undefined,
- ...body, // ! contains name & icon values
+ const guild = {
+ name: body.name,
+ region: body.region || "en-US",
owner_id: req.userid,
+ icon: undefined,
afk_channel_id: undefined,
afk_timeout: 300,
application_id: undefined,
banner: undefined,
- channels: [],
default_message_notifications: undefined,
description: undefined,
splash: undefined,
discovery_splash: undefined,
- emojis: [],
explicit_content_filter: undefined,
features: [],
- // icon: undefined,
id: guildID,
- // joined_at: undefined,
large: undefined,
max_members: 250000,
- max_presences: undefined,
+ max_presences: 250000,
max_video_channel_users: 25,
- member_count: 0,
presence_count: 0,
- members: [
- {
- id: req.userid,
- roles: [], // @everyone role is not explicitly set, the client and server automatically assumes it
- joined_at: Date.now(),
- nick: undefined,
- premium_since: undefined,
- deaf: false,
- mute: false,
- pending: false,
- permissions: 8n, // value will be computed if a role is changed
- },
- ],
+ member_count: 0,
mfa_level: 0,
preferred_locale: "en-US",
premium_subscription_count: 0,
premium_tier: 0,
- presences: [],
public_updates_channel_id: undefined,
- region: undefined,
- roles: [
- {
- color: 0,
- hoist: false,
- name: "@everyone",
- permissions: 0n,
- id: guildID,
- managed: true, // ? discord set this to true,
- mentionable: false,
- position: 0,
- },
- ],
rules_channel_id: undefined,
system_channel_flags: undefined,
system_channel_id: undefined,
- unavailable: undefined,
+ unavailable: false,
vanity_url_code: undefined,
verification_level: undefined,
voice_states: [],
@@ -103,7 +74,9 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) =
};
try {
- await db.data.guilds.push(guild);
+ await new GuildModel(guild).save();
+ // TODO: insert default everyone role
+ // TODO: automatically add user to guild
} catch (error) {
throw new HTTPError("Couldnt create Guild", 500);
}
@@ -111,16 +84,29 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) =
});
router.delete("/:id", async (req: Request, res: Response) => {
- const { id: guildID } = req.params;
-
- const guild = await db.data.guilds({ id: guildID }).get({ owner_id: true });
+ try {
+ var guildID = BigInt(req.params.id);
+ } catch (error) {
+ throw new HTTPError("Invalid id format", 400);
+ }
+ const guild = await GuildModel.findOne({ id: BigInt(req.params.id) }, "owner_id").exec();
if (!guild) throw new HTTPError("This guild doesnt exist", 404);
if (guild.owner_id !== req.userid) throw new HTTPError("You arent the owner of this guild", 401);
- await db.data.guilds({ id: guildID }).delete();
+ await emitEvent({
+ event: "GUILD_DELETE",
+ data: {
+ id: guildID,
+ },
+ guild_id: guildID,
+ } as GuildDeleteEvent);
+
+ await GuildModel.deleteOne({ id: guildID }).exec();
return res.status(204);
});
export default router;
+
+export async function addMember(guild: bigint, user: bigint) {}
diff --git a/src/test/mongo_test.ts b/src/test/mongo_test.ts
index b2cc2bce..5c973429 100644
--- a/src/test/mongo_test.ts
+++ b/src/test/mongo_test.ts
@@ -1,20 +1,28 @@
-import mongoose from "mongoose";
-import { Long } from "mongodb";
-import { Snowflake } from "fosscord-server-util";
+import mongoose, { Schema, Types } from "mongoose";
+import { Long as MongoTypeLong } from "mongodb";
+require("mongoose-long")(mongoose);
+
+const partSchema = new Schema({
+ long: {
+ type: mongoose.Types.Long,
+ },
+});
+
+const Part = mongoose.model("Part", partSchema, "test");
async function main() {
- const conn = await mongoose.createConnection(
- "mongodb://localhost:27017/lambert?readPreference=secondaryPreferred",
- {
- useNewUrlParser: true,
- useUnifiedTopology: false,
- }
- );
+ const conn = await mongoose.connect("mongodb://localhost:27017/lambert?readPreference=secondaryPreferred", {
+ useNewUrlParser: true,
+ useUnifiedTopology: false,
+ });
console.log("connected");
- const result = await conn.collection("users").insertOne({ test: Long.fromString(Snowflake.generate().toString()) });
- // .project(undefined)
- console.log(result);
+ const part = new Part({ long: 390810485244821505n });
+
+ // await part.save();
+ console.log("saved");
+ const test = await Part.find({});
+ console.log(test);
}
main();
diff --git a/src/util/Event.ts b/src/util/Event.ts
index 53c08e2b..c75c909f 100644
--- a/src/util/Event.ts
+++ b/src/util/Event.ts
@@ -1,26 +1,10 @@
-import { db } from "fosscord-server-util";
+import { Event, EventModel } from "fosscord-server-util";
-export async function emitEvent({
- guild,
- user,
- channel,
- event,
- data,
-}: {
- guild?: bigint;
- channel?: bigint;
- user?: bigint;
- event: string;
- data: any;
-}) {
+export async function emitEvent(payload: Omit<Event, "created_at">) {
const emitEvent = {
created_at: Math.floor(Date.now() / 1000), // in seconds
- guild_id: guild,
- user_id: user,
- channel_id: channel,
- data,
- event,
+ ...payload,
};
- return await db.data.events.push(emitEvent);
+ return await new EventModel(emitEvent).save();
}
|