105 lines
3.5 KiB
C#
105 lines
3.5 KiB
C#
using GameList.Contracts;
|
|
|
|
namespace GameList.Endpoints;
|
|
|
|
internal static class AuthValidator
|
|
{
|
|
public const int MaxUsernameLength = 24;
|
|
public const int MaxDisplayNameLength = 16;
|
|
public const int MaxAdminKeyLength = 128;
|
|
public const int MinPasswordLength = 8;
|
|
public const int MaxPasswordLength = 128;
|
|
|
|
public static bool TryValidateRegistration(RegisterRequest request, out ValidatedRegistration validated, out string error)
|
|
{
|
|
var username = (request.Username).Trim();
|
|
if (string.IsNullOrWhiteSpace(username) || username.Length > MaxUsernameLength)
|
|
{
|
|
validated = default;
|
|
error = $"Username is required and must be <= {MaxUsernameLength} characters.";
|
|
return false;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(request.Password))
|
|
{
|
|
validated = default;
|
|
error = "Password is required.";
|
|
return false;
|
|
}
|
|
|
|
var password = request.Password.Trim();
|
|
if (password.Length < MinPasswordLength || password.Length > MaxPasswordLength)
|
|
{
|
|
validated = default;
|
|
error = $"Password must be between {MinPasswordLength} and {MaxPasswordLength} characters.";
|
|
return false;
|
|
}
|
|
|
|
var hasUpper = password.Any(char.IsUpper);
|
|
var hasLower = password.Any(char.IsLower);
|
|
var hasDigit = password.Any(char.IsDigit);
|
|
var hasSymbol = password.Any(ch => !char.IsLetterOrDigit(ch));
|
|
if (!hasUpper || !hasLower || !hasDigit || !hasSymbol)
|
|
{
|
|
validated = default;
|
|
error = "Password must include uppercase, lowercase, number, and symbol.";
|
|
return false;
|
|
}
|
|
|
|
if ((request.DisplayName ?? string.Empty).Trim().Length > MaxDisplayNameLength)
|
|
{
|
|
validated = default;
|
|
error = $"Display name must be <= {MaxDisplayNameLength} characters.";
|
|
return false;
|
|
}
|
|
|
|
var displayName = EndpointHelpers.TrimTo(request.DisplayName, MaxDisplayNameLength);
|
|
if (string.IsNullOrWhiteSpace(displayName))
|
|
{
|
|
validated = default;
|
|
error = "Display name is required.";
|
|
return false;
|
|
}
|
|
|
|
var adminKey = EndpointHelpers.TrimTo(request.AdminKey, MaxAdminKeyLength);
|
|
validated = new ValidatedRegistration(username, username.ToLowerInvariant(), displayName, adminKey);
|
|
error = string.Empty;
|
|
return true;
|
|
}
|
|
|
|
public static bool TryValidateLogin(LoginRequest request, out string username, out string normalizedUsername, out string error)
|
|
{
|
|
username = (request.Username).Trim();
|
|
normalizedUsername = string.Empty;
|
|
|
|
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(request.Password))
|
|
{
|
|
error = "Username and password are required.";
|
|
return false;
|
|
}
|
|
|
|
if (username.Length > MaxUsernameLength)
|
|
{
|
|
error = $"Username must be <= {MaxUsernameLength} characters.";
|
|
return false;
|
|
}
|
|
|
|
if (request.Password.Length > MaxPasswordLength)
|
|
{
|
|
error = $"Password must be <= {MaxPasswordLength} characters.";
|
|
return false;
|
|
}
|
|
|
|
normalizedUsername = username.ToLowerInvariant();
|
|
error = string.Empty;
|
|
return true;
|
|
}
|
|
|
|
public readonly record struct ValidatedRegistration(
|
|
string Username,
|
|
string NormalizedUsername,
|
|
string DisplayName,
|
|
string? AdminKey
|
|
);
|
|
}
|