chore: add csharpier to husky, format backend with csharpier
This commit is contained in:
parent
5fab66444f
commit
7f971e8549
73 changed files with 2098 additions and 1048 deletions
|
@ -7,12 +7,28 @@ public static class AuthUtils
|
|||
{
|
||||
public const string ClientCredentials = "client_credentials";
|
||||
public const string AuthorizationCode = "authorization_code";
|
||||
private static readonly string[] ForbiddenSchemes = ["javascript", "file", "data", "mailto", "tel"];
|
||||
private static readonly string[] ForbiddenSchemes =
|
||||
[
|
||||
"javascript",
|
||||
"file",
|
||||
"data",
|
||||
"mailto",
|
||||
"tel",
|
||||
];
|
||||
|
||||
public static readonly string[] UserScopes =
|
||||
["user.read_hidden", "user.read_privileged", "user.update"];
|
||||
[
|
||||
"user.read_hidden",
|
||||
"user.read_privileged",
|
||||
"user.update",
|
||||
];
|
||||
|
||||
public static readonly string[] MemberScopes = ["member.read", "member.update", "member.create"];
|
||||
public static readonly string[] MemberScopes =
|
||||
[
|
||||
"member.read",
|
||||
"member.update",
|
||||
"member.create",
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// All scopes endpoints can be secured by. This does *not* include the catch-all token scopes.
|
||||
|
@ -27,10 +43,13 @@ public static class AuthUtils
|
|||
|
||||
public static string[] ExpandScopes(this string[] scopes)
|
||||
{
|
||||
if (scopes.Contains("*")) return ["*", ..Scopes];
|
||||
if (scopes.Contains("*"))
|
||||
return ["*", .. Scopes];
|
||||
List<string> expandedScopes = ["identify"];
|
||||
if (scopes.Contains("user")) expandedScopes.AddRange(UserScopes);
|
||||
if (scopes.Contains("member")) expandedScopes.AddRange(MemberScopes);
|
||||
if (scopes.Contains("user"))
|
||||
expandedScopes.AddRange(UserScopes);
|
||||
if (scopes.Contains("member"))
|
||||
expandedScopes.AddRange(MemberScopes);
|
||||
|
||||
return expandedScopes.ToArray();
|
||||
}
|
||||
|
@ -41,8 +60,10 @@ public static class AuthUtils
|
|||
private static string[] ExpandAppScopes(this string[] scopes)
|
||||
{
|
||||
var expandedScopes = scopes.ExpandScopes().ToList();
|
||||
if (scopes.Contains("user")) expandedScopes.Add("user");
|
||||
if (scopes.Contains("member")) expandedScopes.Add("member");
|
||||
if (scopes.Contains("user"))
|
||||
expandedScopes.Add("user");
|
||||
if (scopes.Contains("member"))
|
||||
expandedScopes.Add("member");
|
||||
return expandedScopes.ToArray();
|
||||
}
|
||||
|
||||
|
@ -84,7 +105,8 @@ public static class AuthUtils
|
|||
{
|
||||
rawToken = [];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input)) return false;
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return false;
|
||||
if (input.StartsWith("bearer ", StringComparison.InvariantCultureIgnoreCase))
|
||||
input = input["bearer ".Length..];
|
||||
|
||||
|
@ -95,4 +117,4 @@ public static class AuthUtils
|
|||
Convert.ToBase64String(RandomNumberGenerator.GetBytes(bytes)).Trim('=');
|
||||
|
||||
public const int MaxAuthMethodsPerType = 3; // Maximum of 3 Discord accounts, 3 emails, etc
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,4 +6,4 @@ public static class Limits
|
|||
public const int FieldNameLimit = 100;
|
||||
public const int FieldEntryTextLimit = 100;
|
||||
public const int FieldEntriesLimit = 100;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ namespace Foxnouns.Backend.Utils;
|
|||
public abstract class PatchRequest
|
||||
{
|
||||
private readonly HashSet<string> _properties = [];
|
||||
|
||||
public bool HasProperty(string propertyName) => _properties.Contains(propertyName);
|
||||
|
||||
public void SetHasProperty(string propertyName) => _properties.Add(propertyName);
|
||||
}
|
||||
|
||||
|
@ -23,16 +25,20 @@ public abstract class PatchRequest
|
|||
/// </summary>
|
||||
public class PatchRequestContractResolver : DefaultContractResolver
|
||||
{
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
|
||||
protected override JsonProperty CreateProperty(
|
||||
MemberInfo member,
|
||||
MemberSerialization memberSerialization
|
||||
)
|
||||
{
|
||||
var prop = base.CreateProperty(member, memberSerialization);
|
||||
|
||||
prop.SetIsSpecified += (o, _) =>
|
||||
{
|
||||
if (o is not PatchRequest patchRequest) return;
|
||||
if (o is not PatchRequest patchRequest)
|
||||
return;
|
||||
patchRequest.SetHasProperty(prop.UnderlyingName!);
|
||||
};
|
||||
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@ namespace Foxnouns.Backend.Utils;
|
|||
/// A custom StringEnumConverter that converts enum members to SCREAMING_SNAKE_CASE, rather than CamelCase as is the default.
|
||||
/// Newtonsoft.Json doesn't provide a screaming snake case naming strategy, so we just wrap the normal snake case one and convert it to uppercase.
|
||||
/// </summary>
|
||||
public class ScreamingSnakeCaseEnumConverter() : StringEnumConverter(new ScreamingSnakeCaseNamingStrategy(), false)
|
||||
public class ScreamingSnakeCaseEnumConverter()
|
||||
: StringEnumConverter(new ScreamingSnakeCaseNamingStrategy(), false)
|
||||
{
|
||||
private class ScreamingSnakeCaseNamingStrategy : SnakeCaseNamingStrategy
|
||||
{
|
||||
protected override string ResolvePropertyName(string name) =>
|
||||
base.ResolvePropertyName(name).ToUpper(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public static partial class ValidationUtils
|
|||
"pronouns",
|
||||
"settings",
|
||||
"pronouns.cc",
|
||||
"pronounscc"
|
||||
"pronounscc",
|
||||
];
|
||||
|
||||
private static readonly string[] InvalidMemberNames =
|
||||
|
@ -30,7 +30,7 @@ public static partial class ValidationUtils
|
|||
".",
|
||||
"..",
|
||||
// the user edit page lives at `/@{username}/edit`, so a member named "edit" would be inaccessible
|
||||
"edit"
|
||||
"edit",
|
||||
];
|
||||
|
||||
public static ValidationError? ValidateUsername(string username)
|
||||
|
@ -42,10 +42,15 @@ public static partial class ValidationUtils
|
|||
> 40 => ValidationError.LengthError("Username is too long", 2, 40, username.Length),
|
||||
_ => ValidationError.GenericValidationError(
|
||||
"Username is invalid, can only contain alphanumeric characters, dashes, underscores, and periods",
|
||||
username)
|
||||
username
|
||||
),
|
||||
};
|
||||
|
||||
if (InvalidUsernames.Any(u => string.Equals(u, username, StringComparison.InvariantCultureIgnoreCase)))
|
||||
if (
|
||||
InvalidUsernames.Any(u =>
|
||||
string.Equals(u, username, StringComparison.InvariantCultureIgnoreCase)
|
||||
)
|
||||
)
|
||||
return ValidationError.GenericValidationError("Username is not allowed", username);
|
||||
return null;
|
||||
}
|
||||
|
@ -58,13 +63,18 @@ public static partial class ValidationUtils
|
|||
< 1 => ValidationError.LengthError("Name is too short", 1, 100, memberName.Length),
|
||||
> 100 => ValidationError.LengthError("Name is too long", 1, 100, memberName.Length),
|
||||
_ => ValidationError.GenericValidationError(
|
||||
"Member name cannot contain any of the following: " +
|
||||
" @, ?, !, #, /, \\, [, ], \", ', $, %, &, (, ), {, }, +, <, =, >, ^, |, ~, `, , " +
|
||||
"and cannot be one or two periods",
|
||||
memberName)
|
||||
"Member name cannot contain any of the following: "
|
||||
+ " @, ?, !, #, /, \\, [, ], \", ', $, %, &, (, ), {, }, +, <, =, >, ^, |, ~, `, , "
|
||||
+ "and cannot be one or two periods",
|
||||
memberName
|
||||
),
|
||||
};
|
||||
|
||||
if (InvalidMemberNames.Any(u => string.Equals(u, memberName, StringComparison.InvariantCultureIgnoreCase)))
|
||||
if (
|
||||
InvalidMemberNames.Any(u =>
|
||||
string.Equals(u, memberName, StringComparison.InvariantCultureIgnoreCase)
|
||||
)
|
||||
)
|
||||
return ValidationError.GenericValidationError("Name is not allowed", memberName);
|
||||
return null;
|
||||
}
|
||||
|
@ -72,12 +82,14 @@ public static partial class ValidationUtils
|
|||
public static void Validate(IEnumerable<(string, ValidationError?)> errors)
|
||||
{
|
||||
errors = errors.Where(e => e.Item2 != null).ToList();
|
||||
if (!errors.Any()) return;
|
||||
if (!errors.Any())
|
||||
return;
|
||||
|
||||
var errorDict = new Dictionary<string, IEnumerable<ValidationError>>();
|
||||
foreach (var error in errors)
|
||||
{
|
||||
if (errorDict.TryGetValue(error.Item1, out var value)) errorDict[error.Item1] = value.Append(error.Item2!);
|
||||
if (errorDict.TryGetValue(error.Item1, out var value))
|
||||
errorDict[error.Item1] = value.Append(error.Item2!);
|
||||
errorDict.Add(error.Item1, [error.Item2!]);
|
||||
}
|
||||
|
||||
|
@ -88,9 +100,19 @@ public static partial class ValidationUtils
|
|||
{
|
||||
return displayName?.Length switch
|
||||
{
|
||||
0 => ValidationError.LengthError("Display name is too short", 1, 100, displayName.Length),
|
||||
> 100 => ValidationError.LengthError("Display name is too long", 1, 100, displayName.Length),
|
||||
_ => null
|
||||
0 => ValidationError.LengthError(
|
||||
"Display name is too short",
|
||||
1,
|
||||
100,
|
||||
displayName.Length
|
||||
),
|
||||
> 100 => ValidationError.LengthError(
|
||||
"Display name is too long",
|
||||
1,
|
||||
100,
|
||||
displayName.Length
|
||||
),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -99,9 +121,13 @@ public static partial class ValidationUtils
|
|||
|
||||
public static IEnumerable<(string, ValidationError?)> ValidateLinks(string[]? links)
|
||||
{
|
||||
if (links == null) return [];
|
||||
if (links == null)
|
||||
return [];
|
||||
if (links.Length > MaxLinks)
|
||||
return [("links", ValidationError.LengthError("Too many links", 0, MaxLinks, links.Length))];
|
||||
return
|
||||
[
|
||||
("links", ValidationError.LengthError("Too many links", 0, MaxLinks, links.Length)),
|
||||
];
|
||||
|
||||
var errors = new List<(string, ValidationError?)>();
|
||||
foreach (var (link, idx) in links.Select((l, i) => (l, i)))
|
||||
|
@ -109,12 +135,25 @@ public static partial class ValidationUtils
|
|||
switch (link.Length)
|
||||
{
|
||||
case 0:
|
||||
errors.Add(($"links.{idx}",
|
||||
ValidationError.LengthError("Link cannot be empty", 1, 256, 0)));
|
||||
errors.Add(
|
||||
(
|
||||
$"links.{idx}",
|
||||
ValidationError.LengthError("Link cannot be empty", 1, 256, 0)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case > MaxLinkLength:
|
||||
errors.Add(($"links.{idx}",
|
||||
ValidationError.LengthError("Link is too long", 1, MaxLinkLength, link.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"links.{idx}",
|
||||
ValidationError.LengthError(
|
||||
"Link is too long",
|
||||
1,
|
||||
MaxLinkLength,
|
||||
link.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -129,8 +168,13 @@ public static partial class ValidationUtils
|
|||
return bio?.Length switch
|
||||
{
|
||||
0 => ValidationError.LengthError("Bio is too short", 1, MaxBioLength, bio.Length),
|
||||
> MaxBioLength => ValidationError.LengthError("Bio is too long", 1, MaxBioLength, bio.Length),
|
||||
_ => null
|
||||
> MaxBioLength => ValidationError.LengthError(
|
||||
"Bio is too long",
|
||||
1,
|
||||
MaxBioLength,
|
||||
bio.Length
|
||||
),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -140,121 +184,222 @@ public static partial class ValidationUtils
|
|||
{
|
||||
0 => ValidationError.GenericValidationError("Avatar cannot be empty", null),
|
||||
> 1_500_000 => ValidationError.GenericValidationError("Avatar is too large", null),
|
||||
_ => null
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static readonly string[] DefaultStatusOptions =
|
||||
[
|
||||
"favourite",
|
||||
"okay",
|
||||
"jokingly",
|
||||
"friends_only",
|
||||
"avoid"
|
||||
"avoid",
|
||||
];
|
||||
|
||||
public static IEnumerable<(string, ValidationError?)> ValidateFields(List<Field>? fields,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences)
|
||||
public static IEnumerable<(string, ValidationError?)> ValidateFields(
|
||||
List<Field>? fields,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
)
|
||||
{
|
||||
if (fields == null) return [];
|
||||
if (fields == null)
|
||||
return [];
|
||||
|
||||
var errors = new List<(string, ValidationError?)>();
|
||||
if (fields.Count > 25)
|
||||
errors.Add(("fields", ValidationError.LengthError("Too many fields", 0, Limits.FieldLimit, fields.Count)));
|
||||
errors.Add(
|
||||
(
|
||||
"fields",
|
||||
ValidationError.LengthError(
|
||||
"Too many fields",
|
||||
0,
|
||||
Limits.FieldLimit,
|
||||
fields.Count
|
||||
)
|
||||
)
|
||||
);
|
||||
// No overwhelming this function, thank you
|
||||
if (fields.Count > 100) return errors;
|
||||
if (fields.Count > 100)
|
||||
return errors;
|
||||
|
||||
foreach (var (field, index) in fields.Select((field, index) => (field, index)))
|
||||
{
|
||||
switch (field.Name.Length)
|
||||
{
|
||||
case > Limits.FieldNameLimit:
|
||||
errors.Add(($"fields.{index}.name",
|
||||
ValidationError.LengthError("Field name is too long", 1, Limits.FieldNameLimit,
|
||||
field.Name.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"fields.{index}.name",
|
||||
ValidationError.LengthError(
|
||||
"Field name is too long",
|
||||
1,
|
||||
Limits.FieldNameLimit,
|
||||
field.Name.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case < 1:
|
||||
errors.Add(($"fields.{index}.name",
|
||||
ValidationError.LengthError("Field name is too short", 1, Limits.FieldNameLimit,
|
||||
field.Name.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"fields.{index}.name",
|
||||
ValidationError.LengthError(
|
||||
"Field name is too short",
|
||||
1,
|
||||
Limits.FieldNameLimit,
|
||||
field.Name.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
errors = errors.Concat(ValidateFieldEntries(field.Entries, customPreferences, $"fields.{index}.entries"))
|
||||
errors = errors
|
||||
.Concat(
|
||||
ValidateFieldEntries(
|
||||
field.Entries,
|
||||
customPreferences,
|
||||
$"fields.{index}.entries"
|
||||
)
|
||||
)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static IEnumerable<(string, ValidationError?)> ValidateFieldEntries(FieldEntry[]? entries,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences, string errorPrefix = "fields")
|
||||
public static IEnumerable<(string, ValidationError?)> ValidateFieldEntries(
|
||||
FieldEntry[]? entries,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences,
|
||||
string errorPrefix = "fields"
|
||||
)
|
||||
{
|
||||
if (entries == null || entries.Length == 0) return [];
|
||||
if (entries == null || entries.Length == 0)
|
||||
return [];
|
||||
var errors = new List<(string, ValidationError?)>();
|
||||
|
||||
if (entries.Length > Limits.FieldEntriesLimit)
|
||||
errors.Add((errorPrefix,
|
||||
ValidationError.LengthError("Field has too many entries", 0, Limits.FieldEntriesLimit,
|
||||
entries.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
errorPrefix,
|
||||
ValidationError.LengthError(
|
||||
"Field has too many entries",
|
||||
0,
|
||||
Limits.FieldEntriesLimit,
|
||||
entries.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Same as above, no overwhelming this function with a ridiculous amount of entries
|
||||
if (entries.Length > Limits.FieldEntriesLimit + 50) return errors;
|
||||
if (entries.Length > Limits.FieldEntriesLimit + 50)
|
||||
return errors;
|
||||
|
||||
foreach (var (entry, entryIdx) in entries.Select((entry, entryIdx) => (entry, entryIdx)))
|
||||
{
|
||||
switch (entry.Value.Length)
|
||||
{
|
||||
case > Limits.FieldEntryTextLimit:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Field value is too long", 1, Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Field value is too long",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case < 1:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Field value is too short", 1, Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Field value is too short",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
var customPreferenceIds = customPreferences?.Keys.Select(id => id.ToString()) ?? [];
|
||||
|
||||
if (!DefaultStatusOptions.Contains(entry.Status) && !customPreferenceIds.Contains(entry.Status))
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.status",
|
||||
ValidationError.GenericValidationError("Invalid status", entry.Status)));
|
||||
if (
|
||||
!DefaultStatusOptions.Contains(entry.Status)
|
||||
&& !customPreferenceIds.Contains(entry.Status)
|
||||
)
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.status",
|
||||
ValidationError.GenericValidationError("Invalid status", entry.Status)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
public static IEnumerable<(string, ValidationError?)> ValidatePronouns(Pronoun[]? entries,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences, string errorPrefix = "pronouns")
|
||||
public static IEnumerable<(string, ValidationError?)> ValidatePronouns(
|
||||
Pronoun[]? entries,
|
||||
IReadOnlyDictionary<Snowflake, User.CustomPreference> customPreferences,
|
||||
string errorPrefix = "pronouns"
|
||||
)
|
||||
{
|
||||
if (entries == null || entries.Length == 0) return [];
|
||||
if (entries == null || entries.Length == 0)
|
||||
return [];
|
||||
var errors = new List<(string, ValidationError?)>();
|
||||
|
||||
if (entries.Length > Limits.FieldEntriesLimit)
|
||||
errors.Add((errorPrefix,
|
||||
ValidationError.LengthError("Too many pronouns", 0, Limits.FieldEntriesLimit,
|
||||
entries.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
errorPrefix,
|
||||
ValidationError.LengthError(
|
||||
"Too many pronouns",
|
||||
0,
|
||||
Limits.FieldEntriesLimit,
|
||||
entries.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Same as above, no overwhelming this function with a ridiculous amount of entries
|
||||
if (entries.Length > Limits.FieldEntriesLimit + 50) return errors;
|
||||
if (entries.Length > Limits.FieldEntriesLimit + 50)
|
||||
return errors;
|
||||
|
||||
foreach (var (entry, entryIdx) in entries.Select((entry, entryIdx) => (entry, entryIdx)))
|
||||
{
|
||||
switch (entry.Value.Length)
|
||||
{
|
||||
case > Limits.FieldEntryTextLimit:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Pronoun value is too long", 1, Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Pronoun value is too long",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case < 1:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Pronoun value is too short", 1, Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Pronoun value is too short",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -263,25 +408,46 @@ public static partial class ValidationUtils
|
|||
switch (entry.DisplayText.Length)
|
||||
{
|
||||
case > Limits.FieldEntryTextLimit:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Pronoun display text is too long", 1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Pronoun display text is too long",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case < 1:
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError("Pronoun display text is too short", 1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length)));
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.value",
|
||||
ValidationError.LengthError(
|
||||
"Pronoun display text is too short",
|
||||
1,
|
||||
Limits.FieldEntryTextLimit,
|
||||
entry.Value.Length
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var customPreferenceIds = customPreferences?.Keys.Select(id => id.ToString()) ?? [];
|
||||
|
||||
if (!DefaultStatusOptions.Contains(entry.Status) && !customPreferenceIds.Contains(entry.Status))
|
||||
errors.Add(($"{errorPrefix}.{entryIdx}.status",
|
||||
ValidationError.GenericValidationError("Invalid status", entry.Status)));
|
||||
if (
|
||||
!DefaultStatusOptions.Contains(entry.Status)
|
||||
&& !customPreferenceIds.Contains(entry.Status)
|
||||
)
|
||||
errors.Add(
|
||||
(
|
||||
$"{errorPrefix}.{entryIdx}.status",
|
||||
ValidationError.GenericValidationError("Invalid status", entry.Status)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
@ -290,6 +456,10 @@ public static partial class ValidationUtils
|
|||
[GeneratedRegex(@"^[a-zA-Z_0-9\-\.]{2,40}$", RegexOptions.IgnoreCase, "en-NL")]
|
||||
private static partial Regex UsernameRegex();
|
||||
|
||||
[GeneratedRegex("""^[^@'$%&()+<=>^|~`,*!#/\\\[\]""\{\}\?]{1,100}$""", RegexOptions.IgnoreCase, "en-NL")]
|
||||
[GeneratedRegex(
|
||||
"""^[^@'$%&()+<=>^|~`,*!#/\\\[\]""\{\}\?]{1,100}$""",
|
||||
RegexOptions.IgnoreCase,
|
||||
"en-NL"
|
||||
)]
|
||||
private static partial Regex MemberRegex();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue