summary refs log tree commit diff
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/assets/schemas.json1
-rw-r--r--api/client_test/index.html2
-rw-r--r--api/src/middlewares/TestClient.ts2
-rw-r--r--api/src/routes/auth/register.ts36
-rw-r--r--api/src/routes/invites/index.ts9
5 files changed, 27 insertions, 23 deletions
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 9a0aeae1..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",
diff --git a/api/src/middlewares/TestClient.ts b/api/src/middlewares/TestClient.ts
index 73e7b9c2..79f8f442 100644
--- a/api/src/middlewares/TestClient.ts
+++ b/api/src/middlewares/TestClient.ts
@@ -67,6 +67,8 @@ export default function TestClient(app: Application) {
 		res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
 		res.set("content-type", "text/html");
 
+		if (req.url.startsWith("/invite")) return res.send(html.replace("9b2b7f0632acd0c5e781", "9f24f709a3de09b67c49"));
+
 		res.send(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/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