diff --git a/api/src/middlewares/ErrorHandler.ts b/api/src/middlewares/ErrorHandler.ts
index d080e498..8e2cd923 100644
--- a/api/src/middlewares/ErrorHandler.ts
+++ b/api/src/middlewares/ErrorHandler.ts
@@ -2,6 +2,7 @@ import { NextFunction, Request, Response } from "express";
import { HTTPError } from "lambert-server";
import { FieldError } from "../util/instanceOf";
+// TODO: update with new body/typorm validation
export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) {
if (!error) next();
diff --git a/api/src/routes/auth/login.ts b/api/src/routes/auth/login.ts
index 579a097e..c0acad4e 100644
--- a/api/src/routes/auth/login.ts
+++ b/api/src/routes/auth/login.ts
@@ -21,9 +21,6 @@ router.post(
async (req: Request, res: Response) => {
const { login, password, captcha_key, undelete } = req.body;
const email = adjustEmail(login);
- const query: any[] = [{ phone: login }];
- if (email) query.push({ email });
-
console.log(req.body, email);
const config = Config.get();
@@ -41,11 +38,10 @@ router.post(
// TODO: check captcha
}
- const user = await User.findOneOrFail(
- { $or: query },
- { "data.hash": true, id: true, disabled: true, deleted: true, "settings.locale": true, "settings.theme": true }
- ).catch((e) => {
- console.log(e, query);
+ const user = await User.findOneOrFail({
+ where: [{ phone: login }, { email: login }],
+ select: ["data", "id", "disabled", "deleted", "settings"]
+ }).catch((e) => {
throw FieldErrors({ login: { message: req.t("auth:login.INVALID_LOGIN"), code: "INVALID_LOGIN" } });
});
diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts
index 1405e219..62b039d5 100644
--- a/api/src/routes/auth/register.ts
+++ b/api/src/routes/auth/register.ts
@@ -1,12 +1,12 @@
import { Request, Response, Router } from "express";
-import { trimSpecial, User, Snowflake, User, Config } from "@fosscord/util";
+import { trimSpecial, User, Snowflake, Config } from "@fosscord/util";
import bcrypt from "bcrypt";
import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../util/instanceOf";
import "missing-native-js-functions";
import { generateToken } from "./login";
import { getIpAdress, IPAnalysis, isProxy } from "../../util/ipAddress";
import { HTTPError } from "lambert-server";
-import RateLimit from "../../middlewares/RateLimit";
+import { In } from "typeorm";
const router: Router = Router();
@@ -55,13 +55,13 @@ router.post(
// TODO: check password strength
// adjusted_email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick
- let adjusted_email: string | null = adjustEmail(email);
+ let adjusted_email = adjustEmail(email);
// adjusted_password will be the hash of the password
- let adjusted_password: string = "";
+ let adjusted_password = "";
// trim special uf8 control characters -> Backspace, Newline, ...
- let adjusted_username: string = trimSpecial(username);
+ let adjusted_username = trimSpecial(username);
// discriminator will be randomly generated
let discriminator = "";
@@ -129,7 +129,7 @@ router.post(
if (!register.allowMultipleAccounts) {
// TODO: check if fingerprint was eligible generated
- const exists = await User.findOneOrFail({ fingerprints: fingerprint }).catch((e) => {});
+ const exists = await User.findOne({ where: { fingerprints: In(fingerprint) } });
if (exists) {
throw FieldErrors({
@@ -164,12 +164,8 @@ 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");
- try {
- exists = await User.findOneOrFail({ discriminator, username: adjusted_username }, "id");
- } catch (error) {
- // doesn't exist -> break
- break;
- }
+ exists = await User.findOne({ where: { discriminator, username: adjusted_username }, select: ["id"] });
+ if (!exists) break;
}
if (exists) {
@@ -185,35 +181,26 @@ router.post(
// appearently discord doesn't save the date of birth and just calculate if nsfw is allowed
// if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false
- const user: User = {
+ const user = await new User({
id: Snowflake.generate(),
created_at: new Date(),
username: adjusted_username,
discriminator,
- avatar: null,
- accent_color: null,
- banner: null,
+ avatar: undefined,
+ accent_color: undefined,
+ banner: undefined,
bot: false,
system: false,
desktop: false,
mobile: false,
premium: true,
premium_type: 2,
- phone: null,
+ phone: undefined,
bio: "",
mfa_enabled: false,
verified: false,
disabled: false,
deleted: false,
- presence: {
- activities: [],
- client_status: {
- desktop: undefined,
- mobile: undefined,
- web: undefined
- },
- status: "offline"
- },
email: adjusted_email,
nsfw_allowed: true, // TODO: depending on age
public_flags: 0n,
@@ -221,10 +208,7 @@ router.post(
guilds: [],
data: {
hash: adjusted_password,
- valid_tokens_since: new Date(),
- relationships: [],
- connected_accounts: [],
- fingerprints: []
+ valid_tokens_since: new Date()
},
settings: {
afk_timeout: 300,
@@ -234,10 +218,10 @@ router.post(
contact_sync_enabled: false,
convert_emoticons: false,
custom_status: {
- emoji_id: null,
- emoji_name: null,
- expires_at: null,
- text: null
+ emoji_id: undefined,
+ emoji_name: undefined,
+ expires_at: undefined,
+ text: undefined
},
default_guilds_restricted: false,
detect_platform_accounts: true,
@@ -265,16 +249,13 @@ router.post(
timezone_offset: 0
// timezone_offset: // TODO: timezone from request
}
- };
-
- // insert user into database
- await new User(user).save();
+ }).save();
return res.json({ token: await generateToken(user.id) });
}
);
-export function adjustEmail(email: string): string | null {
+export function adjustEmail(email: string): string | undefined {
// body parser already checked if it is a valid email
const parts = <RegExpMatchArray>email.match(EMAIL_REGEX);
// @ts-ignore
diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/api/src/routes/guilds/#guild_id/channels.ts
index b53c9a5a..7b0e94b6 100644
--- a/api/src/routes/guilds/#guild_id/channels.ts
+++ b/api/src/routes/guilds/#guild_id/channels.ts
@@ -1,5 +1,5 @@
import { Router, Response, Request } from "express";
-import { Channel, toObject, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
+import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { ChannelModifySchema } from "../../../schema/Channel";
@@ -48,15 +48,19 @@ router.patch(
if (x.parent_id) {
opts.parent_id = x.parent_id;
- const parent_channel = await Channel.findOneOrFail({ id: x.parent_id, guild_id }, { permission_overwrites: true });
+ const parent_channel = await Channel.findOneOrFail({
+ where: { id: x.parent_id, guild_id },
+ select: ["permission_overwrites"]
+ });
if (x.lock_permissions) {
opts.permission_overwrites = parent_channel.permission_overwrites;
}
}
- const channel = await Channel.findOneOrFailAndUpdate({ id: x.id, guild_id }, opts, { new: true });
+ await Channel.update({ guild_id, id: x.id }, opts);
+ const channel = await Channel.findOneOrFail({ guild_id, id: x.id });
- await emitEvent({ event: "CHANNEL_UPDATE", data: channel), channel_id: x.id, guild_id } as ChannelUpdateEvent;
+ await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: x.id, guild_id } as ChannelUpdateEvent);
})
]);
diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/api/src/routes/guilds/#guild_id/templates.ts
index 13917dbd..e1d2f5fd 100644
--- a/api/src/routes/guilds/#guild_id/templates.ts
+++ b/api/src/routes/guilds/#guild_id/templates.ts
@@ -1,5 +1,5 @@
import { Request, Response, Router } from "express";
-import { TemplateModel, Guild, getPermission, toObject, User, Snowflake } from "@fosscord/util";
+import { Guild, getPermission, Template } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { TemplateCreateSchema, TemplateModifySchema } from "../../../schema/Template";
import { check } from "../../../util/instanceOf";
@@ -7,22 +7,22 @@ import { generateCode } from "../../../util/String";
const router: Router = Router();
-const TemplateGuildProjection = {
- name: true,
- description: true,
- region: true,
- verification_level: true,
- default_message_notifications: true,
- explicit_content_filter: true,
- preferred_locale: true,
- afk_timeout: true,
- roles: true,
- channels: true,
- afk_channel_id: true,
- system_channel_id: true,
- system_channel_flags: true,
- icon_hash: true
-};
+const TemplateGuildProjection: (keyof Guild)[] = [
+ "name",
+ "description",
+ "region",
+ "verification_level",
+ "default_message_notifications",
+ "explicit_content_filter",
+ "preferred_locale",
+ "afk_timeout",
+ "roles",
+ "channels",
+ "afk_channel_id",
+ "system_channel_id",
+ "system_channel_flags",
+ "icon"
+];
router.get("/", async (req: Request, res: Response) => {
const { guild_id } = req.params;
@@ -34,14 +34,14 @@ router.get("/", async (req: Request, res: Response) => {
router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response) => {
const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id }, TemplateGuildProjection);
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection });
const perms = await getPermission(req.user_id, guild_id);
perms.hasThrow("MANAGE_GUILD");
const exists = await Template.findOneOrFail({ id: guild_id }).catch((e) => {});
if (exists) throw new HTTPError("Template already exists", 400);
- const template = await new TemplateModel({
+ const template = await new Template({
...req.body,
code: generateCode(),
creator_id: req.user_id,
@@ -51,7 +51,7 @@ router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response
serialized_source_guild: guild
}).save();
- res.json(template)).send(;
+ res.json(template);
});
router.delete("/:code", async (req: Request, res: Response) => {
@@ -61,37 +61,39 @@ router.delete("/:code", async (req: Request, res: Response) => {
const perms = await getPermission(req.user_id, guild_id);
perms.hasThrow("MANAGE_GUILD");
- const template = await Template.findOneOrFailAndDelete({
+ const template = await Template.delete({
code
});
- res.send(template);
+ res.json(template);
});
router.put("/:code", async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const { code } = req.params;
+ // synchronizes the template
+ const { code, guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ id: guild_id }, TemplateGuildProjection);
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection });
const perms = await getPermission(req.user_id, guild_id);
perms.hasThrow("MANAGE_GUILD");
- const template = await Template.findOneOrFailAndUpdate({ code }, { serialized_source_guild: guild }, { new: true });
+ const template = await new Template({ code, serialized_source_guild: guild }).save();
- res.json(template)).send(;
+ res.json(template);
});
router.patch("/:code", check(TemplateModifySchema), async (req: Request, res: Response) => {
+ // updates the template description
const { guild_id } = req.params;
const { code } = req.params;
+ const { name, description } = req.body;
const perms = await getPermission(req.user_id, guild_id);
perms.hasThrow("MANAGE_GUILD");
- const template = await Template.findOneOrFailAndUpdate({ code }, { name: req.body.name, description: req.body.description }, { new: true });
+ const template = await new Template({ code, name: name, description: description }).save();
- res.json(template)).send(;
+ res.json(template);
});
export default router;
diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts
index ad8b676b..b8c1012d 100644
--- a/api/src/routes/guilds/templates/index.ts
+++ b/api/src/routes/guilds/templates/index.ts
@@ -1,9 +1,8 @@
import { Request, Response, Router } from "express";
const router: Router = Router();
-import { TemplateModel, Guild, toObject, User, Role, Snowflake, Guild, Config } from "@fosscord/util";
+import { Template, Guild, Role, Snowflake, Config, User } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { GuildTemplateCreateSchema } from "../../../schema/Guild";
-import { getPublicUser } from "../../../util/User";
import { check } from "../../../util/instanceOf";
import { addMember } from "../../../util/Member";
@@ -12,7 +11,7 @@ router.get("/:code", async (req: Request, res: Response) => {
const template = await Template.findOneOrFail({ code: code });
- res.json(template)).send(;
+ res.json(template);
});
router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res: Response) => {
@@ -20,7 +19,7 @@ router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res
const body = req.body as GuildTemplateCreateSchema;
const { maxGuilds } = Config.get().limits.user;
- const user = await getPublicUser(req.user_id, { guilds: true });
+ const user = await User.getPublicUser(req.user_id, { guilds: true });
if (user.guilds.length >= maxGuilds) {
throw new HTTPError(`Maximum number of guilds reached ${maxGuilds}`, 403);
diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts
index e871af86..a488c44b 100644
--- a/api/src/routes/invites/index.ts
+++ b/api/src/routes/invites/index.ts
@@ -1,5 +1,5 @@
import { Router, Request, Response } from "express";
-import { getPermission, Guild, InviteModel, toObject } from "@fosscord/util";
+import { getPermission, Guild, Invite } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { addMember } from "../../util/Member";
const router: Router = Router();
@@ -40,7 +40,7 @@ router.delete("/:code", async (req: Request, res: Response) => {
await Guild.update({ vanity_url_code: code }, { $unset: { vanity_url_code: 1 } }).catch((e) => {});
- res.status(200).send({ invite: invite) };
+ res.json({ invite: invite });
});
export default router;
diff --git a/api/src/routes/users/#id/profile.ts b/api/src/routes/users/#id/profile.ts
index 46c96698..9b2e2d5e 100644
--- a/api/src/routes/users/#id/profile.ts
+++ b/api/src/routes/users/#id/profile.ts
@@ -7,7 +7,7 @@ router.get("/", async (req: Request, res: Response) => {
const user = await getPublicUser(req.params.id, { data: true });
res.json({
- connected_accounts: user.data.connected_accounts,
+ connected_accounts: user.connected_accounts,
premium_guild_since: null, // TODO
premium_since: null, // TODO
user: {
diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts
index 9b8d6199..8c7469ed 100644
--- a/api/src/routes/users/@me/relationships.ts
+++ b/api/src/routes/users/@me/relationships.ts
@@ -15,14 +15,14 @@ import { check, Length } from "../../../util/instanceOf";
const router = Router();
-const userProjection = { "user_data.relationships": true, ...PublicUserProjection };
+const userProjection = { "data.relationships": true, ...PublicUserProjection };
router.get("/", async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({ id: req.user_id }, { user_data: { relationships: true } }).populate({
- path: "user_data.relationships.id",
+ const user = await User.findOneOrFail({ id: req.user_id }, { data: { relationships: true } }).populate({
+ path: "data.relationships.id",
model: User
});
- return res.json(user.user_data.relationships);
+ return res.json(user.data.relationships);
});
async function addRelationship(req: Request, res: Response, friend: UserDocument, type: RelationshipType) {
@@ -30,8 +30,8 @@ async function addRelationship(req: Request, res: Response, friend: UserDocument
if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
const user = await User.findOneOrFail({ id: req.user_id }, userProjection);
- const newUserRelationships = [...user.user_data.relationships];
- const newFriendRelationships = [...friend.user_data.relationships];
+ const newUserRelationships = [...user.data.relationships];
+ const newFriendRelationships = [...friend.data.relationships];
var relationship = newUserRelationships.find((x) => x.id === id);
const friendRequest = newFriendRelationships.find((x) => x.id === req.user_id);
@@ -48,7 +48,7 @@ async function addRelationship(req: Request, res: Response, friend: UserDocument
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
newFriendRelationships.remove(friendRequest);
await Promise.all([
- User.update({ id: friend.id }, { "user_data.relationships": newFriendRelationships }),
+ User.update({ id: friend.id }, { "data.relationships": newFriendRelationships }),
emitEvent({
event: "RELATIONSHIP_REMOVE",
data: friendRequest,
@@ -58,12 +58,12 @@ async function addRelationship(req: Request, res: Response, friend: UserDocument
}
await Promise.all([
- User.update({ id: req.user_id }, { "user_data.relationships": newUserRelationships }),
+ User.update({ id: req.user_id }, { "data.relationships": newUserRelationships }),
emitEvent({
event: "RELATIONSHIP_ADD",
data: {
...relationship,
- user: { ...friend, user_data: undefined }
+ user: { ...friend, data: undefined }
},
user_id: req.user_id
} as RelationshipAddEvent)
@@ -91,13 +91,13 @@ async function addRelationship(req: Request, res: Response, friend: UserDocument
} else newUserRelationships.push(outgoing_relationship);
await Promise.all([
- User.update({ id: req.user_id }, { "user_data.relationships": newUserRelationships }),
- User.update({ id: friend.id }, { "user_data.relationships": newFriendRelationships }),
+ User.update({ id: req.user_id }, { "data.relationships": newUserRelationships }),
+ User.update({ id: friend.id }, { "data.relationships": newFriendRelationships }),
emitEvent({
event: "RELATIONSHIP_ADD",
data: {
...outgoing_relationship,
- user: { ...friend, user_data: undefined }
+ user: { ...friend, data: undefined }
},
user_id: req.user_id
} as RelationshipAddEvent),
@@ -106,7 +106,7 @@ async function addRelationship(req: Request, res: Response, friend: UserDocument
data: {
...incoming_relationship,
should_notify: true,
- user: { ...user, user_data: undefined }
+ user: { ...user, data: undefined }
},
user_id: id
} as RelationshipAddEvent)
@@ -138,11 +138,11 @@ router.delete("/:id", async (req: Request, res: Response) => {
const friend = await User.findOneOrFail({ id }, userProjection);
if (!friend) throw new HTTPError("User not found", 404);
- const relationship = user.user_data.relationships.find((x) => x.id === id);
- const friendRequest = friend.user_data.relationships.find((x) => x.id === req.user_id);
+ const relationship = user.data.relationships.find((x) => x.id === id);
+ const friendRequest = friend.data.relationships.find((x) => x.id === req.user_id);
if (relationship?.type === RelationshipType.blocked) {
// unblock user
- user.user_data.relationships.remove(relationship);
+ user.data.relationships.remove(relationship);
await Promise.all([
user.save(),
@@ -153,8 +153,8 @@ router.delete("/:id", async (req: Request, res: Response) => {
if (!relationship || !friendRequest) throw new HTTPError("You are not friends with the user", 404);
if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
- user.user_data.relationships.remove(relationship);
- friend.user_data.relationships.remove(friendRequest);
+ user.data.relationships.remove(relationship);
+ friend.data.relationships.remove(friendRequest);
await Promise.all([
user.save(),
diff --git a/api/src/util/Channel.ts b/api/src/util/Channel.ts
index a618d2df..f518aefd 100644
--- a/api/src/util/Channel.ts
+++ b/api/src/util/Channel.ts
@@ -57,7 +57,7 @@ export async function createChannel(
recipient_ids: null
}).save();
- await emitEvent({ event: "CHANNEL_CREATE", data: channel), guild_id: channel.guild_id } as ChannelCreateEvent;
+ await emitEvent({ event: "CHANNEL_CREATE", data: channel, guild_id: channel.guild_id } as ChannelCreateEvent);
return channel;
}
diff --git a/api/src/util/User.ts b/api/src/util/User.ts
deleted file mode 100644
index 4d9065c4..00000000
--- a/api/src/util/User.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { toObject, User, PublicUserProjection } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
-
-export { PublicUserProjection };
-
-export async function getPublicUser(user_id: string, additional_fields?: any) {
- const user = await User.findOneOrFail(
- { id: user_id },
- {
- ...PublicUserProjection,
- ...additional_fields
- }
- );
- if (!user) throw new HTTPError("User not found", 404);
- return user;
-}
|