update user modify for unique usernames

This commit is contained in:
Puyodead1
2023-06-14 11:37:17 -04:00
committed by Rory&
parent 9a415989b1
commit 08fcec36ba
6 changed files with 80 additions and 31 deletions

View File

@@ -13,7 +13,11 @@
"BASE_TYPE_CONSTANT": "This field must be {{value}}",
"EMAIL_TYPE_INVALID_EMAIL": "Not a well-formed email address",
"DATE_TYPE_PARSE": "Could not parse {{date}}. Should be ISO8601",
"BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length"
"BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length",
"PASSWORD_DOES_NOT_MATCH": "Password does not match.",
"DISCRIMINATOR_UPDATE_BLOCKED": "This discriminator cannot be updated",
"USERNAME_ALREADY_TAKEN": "Username is unavailable. Try adding numbers, letters, underscores _ , or periods.",
"INVALID_DISCRIMINATOR": "This discriminator is already in use."
},
"body": {
"INVALID_BODY": "Invalid Body",

View File

@@ -61,6 +61,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 },
@@ -120,9 +122,53 @@ router.patch(
newToken = (await generateToken(user.id)) as string;
}
// TODO: uniqueUsernames: disallow if uniqueUsernames is enabled
if (body.username) {
const check_username = body?.username?.replace(/\s/g, "").trim();
// 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({
username: {
@@ -132,8 +178,7 @@ router.patch(
});
}
const { maxUsername } = Config.get().limits.user;
if (check_username.length > maxUsername || check_username.length < 2) {
if (check_username.length > maxUsername) {
throw FieldErrors({
username: {
code: "BASE_TYPE_BAD_LENGTH",
@@ -152,8 +197,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: {
@@ -165,7 +220,7 @@ router.patch(
throw FieldErrors({
discriminator: {
code: "INVALID_DISCRIMINATOR",
message: "This discriminator is already in use.",
message: req.t("common.field.INVALID_DISCRIMINATOR"),
},
});
}

View File

@@ -18,35 +18,25 @@
export interface UserModifySchema {
/**
* @minLength 2
* @minLength 1
* @maxLength 100
*/
username?: string;
avatar?: string | null;
/**
* @maxLength 1024
*/
bio?: string;
accent_color?: number;
banner?: string | null;
/**
* @minLength 1
* @maxLength 72
*/
password?: string;
/**
* @minLength 1
* @maxLength 72
*/
new_password?: string;
/**
* @minLength 6
* @maxLength 6
*/
code?: string;
/**
* @TJS-format email
*/
email?: string;
/**
* @minLength 4
* @maxLength 4
*/
discriminator?: string;
global_name?: string;
}

View File

@@ -19,4 +19,4 @@
export class UserConfiguration {
blockedContains: string[] = ["discord", "clyde", "spacebar", "steam", "community", "support", "ticket"];
blockedEquals: string[] = ["everyone", "here"];
}
}

View File

@@ -18,6 +18,7 @@
export class UserLimits {
maxGuilds: number = 1048576;
minUsername: number = 2;
maxUsername: number = 32;
maxFriends: number = 5000;
maxBio: number = 190;

View File

@@ -32,7 +32,6 @@ import { ChannelType, PrivateUserProjection, PublicUser, PublicUserProjection, U
export enum PublicUserEnum {
username,
global_name,
legacy_username,
discriminator,
id,
public_flags,
@@ -195,7 +194,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) || !(typeof discrim == "number") || !Number.isInteger(discrim) || discrim <= 0 || discrim >= 10000)
throw FieldErrors({
@@ -273,9 +272,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}`;
}
@@ -325,7 +323,7 @@ export class User extends BaseClass {
});
const user = User.create({
username: username,
username: uniqueUsernames ? username.toLowerCase() : username,
discriminator,
id: id || Snowflake.generate(),
email: email,
@@ -334,8 +332,9 @@ export class User extends BaseClass {
valid_tokens_since: new Date(),
},
settings: settings,
premium_since: Config.get().defaults.user.premium ? new Date() : undefined,
premium_since: Config.get().defaults.user.premium
? new Date()
: undefined,
rights: Config.get().register.defaultRights,
premium: Config.get().defaults.user.premium ?? false,
premium_type: Config.get().defaults.user.premiumType ?? 0,