diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index de1cbd3d..33fc6062 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -50,9 +50,18 @@ router.post(
}),
async (req: Request, res: Response) => {
const body = req.body as RegisterSchema;
- const { register, security, limits } = Config.get();
+ const { register, security, limits, general } = Config.get();
const ip = getIpAdress(req);
+ if (!general.uniqueUsernames && body.unique_username_registration) {
+ throw FieldErrors({
+ unique_username_registration: {
+ code: "UNIQUE_USERNAMES_DISABLED",
+ message: req.t("auth:register.UNIQUE_USERNAMES_DISABLED"),
+ },
+ });
+ }
+
// Reg tokens
// They're a one time use token that bypasses registration limits ( rates, disabled reg, etc )
let regTokenUsed = false;
diff --git a/src/api/routes/unique-username/username-attempt-unauthed.ts b/src/api/routes/unique-username/username-attempt-unauthed.ts
new file mode 100644
index 00000000..a1f63a69
--- /dev/null
+++ b/src/api/routes/unique-username/username-attempt-unauthed.ts
@@ -0,0 +1,33 @@
+import { route } from "@spacebar/api";
+import { Config, User, UsernameAttemptUnauthedSchema } from "@spacebar/util";
+import { Request, Response, Router } from "express";
+import { HTTPError } from "lambert-server";
+const router = Router();
+
+router.post(
+ "/",
+ route({
+ requestBody: "UsernameAttemptUnauthedSchema",
+ responses: {
+ 200: { body: "UsernameAttemptResponse" },
+ 400: { body: "APIErrorResponse" },
+ },
+ description: "Check if a username is available",
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as UsernameAttemptUnauthedSchema;
+ const { uniqueUsernames } = Config.get().general;
+ if (!uniqueUsernames) {
+ throw new HTTPError(
+ "Unique Usernames feature is not enabled on this instance.",
+ 400,
+ );
+ }
+
+ res.json({
+ taken: !User.isUsernameAvailable(body.username),
+ });
+ },
+);
+
+export default router;
diff --git a/src/api/routes/unique-username/username-suggestions-unauthed.ts b/src/api/routes/unique-username/username-suggestions-unauthed.ts
new file mode 100644
index 00000000..9b112b55
--- /dev/null
+++ b/src/api/routes/unique-username/username-suggestions-unauthed.ts
@@ -0,0 +1,37 @@
+import { route } from "@spacebar/api";
+import { Request, Response, Router } from "express";
+import { HTTPError } from "lambert-server";
+import { Config } from "../../../util";
+const router = Router();
+
+router.get(
+ "/",
+ route({
+ query: {
+ global_name: {
+ type: "string",
+ required: false,
+ },
+ },
+ responses: {
+ 400: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const globalName = req.query.globalName as string | undefined;
+ const { uniqueUsernames } = Config.get().general;
+ if (!uniqueUsernames) {
+ throw new HTTPError(
+ "Unique Usernames feature is not enabled on this instance.",
+ 400,
+ );
+ }
+
+ // return a random suggestion
+ if (!globalName) return res.json({ username: "" });
+ // return a suggestion based on the globalName
+ return res.json({ username: globalName });
+ },
+);
+
+export default router;
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index f4578126..55d2ce12 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -172,10 +172,7 @@ router.patch(
}
// check if username is already taken (pomelo only)
- const userCount = await User.count({
- where: { username: body.username },
- });
- if (userCount > 0) {
+ if (!User.isUsernameAvailable(body.username))
throw FieldErrors({
username: {
code: "USERNAME_ALREADY_TAKEN",
@@ -184,7 +181,6 @@ router.patch(
),
},
});
- }
}
// handle username changes (old username system)
|