diff --git a/api/assets/schemas.json b/api/assets/schemas.json
index bfe6092b..da193b28 100644
--- a/api/assets/schemas.json
+++ b/api/assets/schemas.json
@@ -38,7 +38,6 @@
"additionalProperties": false,
"required": [
"consent",
- "password",
"username"
],
"$schema": "http://json-schema.org/draft-07/schema#"
diff --git a/api/client_test/index.html b/api/client_test/index.html
index ac66df06..ebe92e4c 100644
--- a/api/client_test/index.html
+++ b/api/client_test/index.html
@@ -19,7 +19,7 @@
ASSET_ENDPOINT: "",
MEDIA_PROXY_ENDPOINT: "https://media.discordapp.net",
WIDGET_ENDPOINT: `//${location.host}/widget`,
- INVITE_HOST: `${location.hostname}`,
+ INVITE_HOST: `${location.host}/invite`,
GUILD_TEMPLATE_HOST: "discord.new",
GIFT_CODE_HOST: "discord.gift",
RELEASE_CHANNEL: "stable",
@@ -45,9 +45,9 @@
`{"trace":false,"canary":false,"logGatewayEvents":true,"logOverlayEvents":true,"logAnalyticsEvents":true,"sourceMapsEnabled":false,"axeEnabled":false}`
);
</script>
- <script src="/assets/1dfc47a02b92fa11de87.js"></script>
- <script src="/assets/60611ef20efa1f11238a.js"></script>
- <script src="/assets/b83bc9f9c08cf5073adf.js"></script>
- <script src="/assets/e92920082b09191a5bb0.js"></script>
+ <script src="/assets/479a2f1e7d625dc134b9.js"></script>
+ <script src="/assets/a15fd133a1d2d77a2424.js"></script>
+ <script src="/assets/97e6fa22aa08ee4daa5e.js"></script>
+ <script src="/assets/9b2b7f0632acd0c5e781.js"></script>
</body>
</html>
diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts
index c0b0e18a..4d3f2860 100644
--- a/api/src/routes/auth/register.ts
+++ b/api/src/routes/auth/register.ts
@@ -1,5 +1,5 @@
import { Request, Response, Router } from "express";
-import { trimSpecial, User, Snowflake, Config, defaultSettings } from "@fosscord/util";
+import { trimSpecial, User, Snowflake, Config, defaultSettings, Member, Invite } from "@fosscord/util";
import bcrypt from "bcrypt";
import { EMAIL_REGEX, FieldErrors, route } from "@fosscord/api";
import "missing-native-js-functions";
@@ -19,7 +19,7 @@ export interface RegisterSchema {
* @minLength 1
* @maxLength 72
*/
- password: string; // TODO: use password strength of config
+ password?: string;
consent: boolean;
/**
* @TJS-format email
@@ -60,7 +60,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
}
console.log("register", req.body.email, req.body.username, ip);
- // TODO: automatically join invite
// TODO: gift_code_sku_id?
// TODO: check password strength
@@ -87,13 +86,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
});
}
- // require invite to register -> e.g. for organizations to send invites to their employees
- if (register.requireInvite && !invite) {
- throw FieldErrors({
- email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") }
- });
- }
-
if (email) {
// replace all dots and chars after +, if its a gmail.com email
if (!email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } });
@@ -109,13 +101,13 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
}
});
}
- } else if (register.email.necessary) {
+ } else if (register.email.required) {
throw FieldErrors({
email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }
});
}
- if (register.dateOfBirth.necessary && !date_of_birth) {
+ if (register.dateOfBirth.required && !date_of_birth) {
throw FieldErrors({
date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }
});
@@ -162,8 +154,14 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
// TODO: check captcha
}
- // the salt is saved in the password refer to bcrypt docs
- password = await bcrypt.hash(password, 12);
+ if (password) {
+ // the salt is saved in the password refer to bcrypt docs
+ password = await bcrypt.hash(password, 12);
+ } else if (register.password.required) {
+ throw FieldErrors({
+ password: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") }
+ });
+ }
let exists;
// randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists
@@ -217,6 +215,16 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re
fingerprints: []
}).save();
+ if (invite) {
+ // await to fail if the invite doesn't exist (necessary for requireInvite to work properly) (username only signups are possible)
+ await Invite.joinGuild(user.id, invite);
+ } else if (register.requireInvite) {
+ // require invite to register -> e.g. for organizations to send invites to their employees
+ throw FieldErrors({
+ email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") }
+ });
+ }
+
return res.json({ token: await generateToken(user.id) });
});
diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts
index 1063b151..61c851e8 100644
--- a/api/src/routes/channels/#channel_id/index.ts
+++ b/api/src/routes/channels/#channel_id/index.ts
@@ -38,7 +38,6 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
} else if (channel.type === ChannelType.GROUP_DM) {
await Channel.removeRecipientFromChannel(channel, req.user_id);
} else {
- //TODO messages in this channel should be deleted before deleting the channel
await Promise.all([
Channel.delete({ id: channel_id }),
emitEvent({ event: "CHANNEL_DELETE", data: channel, channel_id } as ChannelDeleteEvent)
diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts
index ae8a5944..0fcf7c86 100644
--- a/api/src/routes/invites/index.ts
+++ b/api/src/routes/invites/index.ts
@@ -15,14 +15,9 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
router.post("/:code", route({}), async (req: Request, res: Response) => {
const { code } = req.params;
+ const invite = await Invite.joinGuild(req.user_id, code);
- const invite = await Invite.findOneOrFail({ code });
- if (invite.uses++ >= invite.max_uses) await Invite.delete({ code });
- else await invite.save();
-
- await Member.addToGuild(req.user_id, invite.guild_id);
-
- res.status(200).send(invite);
+ res.json(invite);
});
// * cant use permission of route() function because path doesn't have guild_id/channel_id
diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts
index 1d72f11a..6ad873a6 100644
--- a/api/src/routes/users/@me/relationships.ts
+++ b/api/src/routes/users/@me/relationships.ts
@@ -59,7 +59,7 @@ router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request,
relations: ["relationships", "relationships.to"],
select: userProjection,
where: {
- discriminator: String(req.body.discriminator,).padStart(4, '0'), //Discord send the discriminator as integer, we need to add leading zeroes
+ discriminator: String(req.body.discriminator).padStart(4, '0'), //Discord send the discriminator as integer, we need to add leading zeroes
username: req.body.username
}
}),
diff --git a/api/src/util/route.ts b/api/src/util/route.ts
index 678ca64c..b7e6296b 100644
--- a/api/src/util/route.ts
+++ b/api/src/util/route.ts
@@ -14,6 +14,7 @@ export const ajv = new Ajv({
parseDate: true,
allowDate: true,
schemas,
+ coerceTypes: true,
messages: true,
strict: true,
strictRequired: true
|