diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index fc44e17e..f4578126 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -70,6 +70,8 @@ router.patch(
}),
async (req: Request, res: Response) => {
const body = req.body as UserModifySchema;
+ const { uniqueUsernames } = Config.get().general;
+ const { minUsername, maxUsername } = Config.get().limits.user;
const user = await User.findOneOrFail({
where: { id: req.user_id },
@@ -140,8 +142,52 @@ router.patch(
newToken = (await generateToken(user.id)) as string;
}
- // TODO: uniqueUsernames: disallow if uniqueUsernames is enabled
if (body.username) {
+ // password is required to update username
+ if (!body.password)
+ throw FieldErrors({
+ password: {
+ message: req.t("common:field.PASSWORD_DOES_NOT_MATCH"),
+ code: "PASSWORD_DOES_NOT_MATCH",
+ },
+ });
+
+ // handle username changes (pomelo)
+ if (uniqueUsernames) {
+ body.username = body.username.toLowerCase();
+ // validate username length
+ if (
+ body.username.length < minUsername ||
+ body.username.length > maxUsername
+ ) {
+ throw FieldErrors({
+ username: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: req.t(
+ "common:field.BASE_TYPE_BAD_LENGTH",
+ { length: `${minUsername} and ${maxUsername}` },
+ ),
+ },
+ });
+ }
+
+ // check if username is already taken (pomelo only)
+ const userCount = await User.count({
+ where: { username: body.username },
+ });
+ if (userCount > 0) {
+ throw FieldErrors({
+ username: {
+ code: "USERNAME_ALREADY_TAKEN",
+ message: req.t(
+ "common:field.USERNAME_ALREADY_TAKEN",
+ ),
+ },
+ });
+ }
+ }
+
+ // handle username changes (old username system)
const check_username = body?.username?.replace(/\s/g, "");
if (!check_username) {
throw FieldErrors({
@@ -152,7 +198,6 @@ router.patch(
});
}
- const { maxUsername } = Config.get().limits.user;
if (check_username.length > maxUsername) {
throw FieldErrors({
username: {
@@ -163,8 +208,18 @@ router.patch(
}
}
- // TODO: uniqueUsernames: disallow if uniqueUsernames is enabled
if (body.discriminator) {
+ if (uniqueUsernames) {
+ throw FieldErrors({
+ username: {
+ code: "DISCRIMINATOR_UPDATE_BLOCKED",
+ message: req.t(
+ "common:field.DISCRIMINATOR_UPDATE_BLOCKED",
+ ),
+ },
+ });
+ }
+
if (
await User.findOne({
where: {
@@ -176,7 +231,7 @@ router.patch(
throw FieldErrors({
discriminator: {
code: "INVALID_DISCRIMINATOR",
- message: "This discriminator is already in use.",
+ message: req.t("common.field.INVALID_DISCRIMINATOR"),
},
});
}
diff --git a/src/util/config/types/subconfigurations/limits/UserLimits.ts b/src/util/config/types/subconfigurations/limits/UserLimits.ts
index 8f9b1a97..77092344 100644
--- a/src/util/config/types/subconfigurations/limits/UserLimits.ts
+++ b/src/util/config/types/subconfigurations/limits/UserLimits.ts
@@ -18,6 +18,7 @@
export class UserLimits {
maxGuilds: number = 1048576;
+ minUsername: number = 2;
maxUsername: number = 32;
maxFriends: number = 5000;
}
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index acd2ea74..d1fbb5c2 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -38,7 +38,6 @@ import { UserSettings } from "./UserSettings";
export enum PublicUserEnum {
username,
global_name,
- legacy_username,
discriminator,
id,
public_flags,
@@ -241,7 +240,7 @@ export class User extends BaseClass {
// TODO: I don't like this method?
validate() {
- if (this.discriminator) {
+ if (this.discriminator && this.discriminator !== "0") {
const discrim = Number(this.discriminator);
if (
isNaN(discrim) ||
@@ -334,9 +333,8 @@ export class User extends BaseClass {
public get tag(): string {
const { uniqueUsernames } = Config.get().general;
- // if uniqueUsernames is enabled, global_name should be set
return uniqueUsernames
- ? (this.global_name as string)
+ ? this.username
: `${this.username}#${this.discriminator}`;
}
@@ -387,7 +385,7 @@ export class User extends BaseClass {
});
const user = User.create({
- username: username,
+ username: uniqueUsernames ? username.toLowerCase() : username,
discriminator,
id: id || Snowflake.generate(),
email: email,
@@ -397,7 +395,6 @@ export class User extends BaseClass {
},
extended_settings: "{}",
settings: settings,
-
premium_since: Config.get().defaults.user.premium
? new Date()
: undefined,
diff --git a/src/util/schemas/UserModifySchema.ts b/src/util/schemas/UserModifySchema.ts
index e155b9af..72d15dcb 100644
--- a/src/util/schemas/UserModifySchema.ts
+++ b/src/util/schemas/UserModifySchema.ts
@@ -38,4 +38,5 @@ export interface UserModifySchema {
* @maxLength 4
*/
discriminator?: string;
+ global_name?: string;
}
|