diff --git a/Guestlist/InputRules.cs b/Guestlist/InputRules.cs new file mode 100644 index 0000000..7f98b1a --- /dev/null +++ b/Guestlist/InputRules.cs @@ -0,0 +1,114 @@ +using System.Text.RegularExpressions; + +namespace Guestlist; + +public static partial class InputRules +{ + public const int UsernameMaxLength = 40; + public const int DisplayNameMaxLength = 80; + public const int PasswordMinLength = 8; + public const int PasswordMaxLength = 200; + public const int GuestNameMaxLength = 120; + public const int GuestNotesMaxLength = 500; + public const int AccessCodeMinLength = 6; + public const int AccessCodeMaxLength = 120; + + public static string NormalizeUsername(string username) + { + var normalizedUsername = username.Trim().ToLowerInvariant(); + + if (string.IsNullOrWhiteSpace(normalizedUsername)) + { + throw new InvalidOperationException("Provide a username."); + } + + if (normalizedUsername.Length > UsernameMaxLength) + { + throw new InvalidOperationException($"Username must be {UsernameMaxLength} characters or less."); + } + + if (!UsernameRegex().IsMatch(normalizedUsername)) + { + throw new InvalidOperationException("Username may only contain letters, numbers, dots, dashes and underscores."); + } + + return normalizedUsername; + } + + public static string CleanRequiredText(string value, string fieldName, int maxLength) + { + var cleanedValue = value.Trim(); + + if (string.IsNullOrWhiteSpace(cleanedValue)) + { + throw new InvalidOperationException($"Provide {fieldName}."); + } + + if (cleanedValue.Length > maxLength) + { + throw new InvalidOperationException($"{fieldName} must be {maxLength} characters or less."); + } + + return cleanedValue; + } + + public static string? CleanOptionalText(string? value, string fieldName, int maxLength) + { + if (string.IsNullOrWhiteSpace(value)) + { + return null; + } + + var cleanedValue = value.Trim(); + + if (cleanedValue.Length > maxLength) + { + throw new InvalidOperationException($"{fieldName} must be {maxLength} characters or less."); + } + + return cleanedValue; + } + + public static void ValidatePassword(string password) + { + if (string.IsNullOrWhiteSpace(password)) + { + throw new InvalidOperationException("Provide a password."); + } + + if (password.Length < PasswordMinLength) + { + throw new InvalidOperationException($"Password must be at least {PasswordMinLength} characters long."); + } + + if (password.Length > PasswordMaxLength) + { + throw new InvalidOperationException($"Password must be {PasswordMaxLength} characters or less."); + } + } + + public static string CleanAccessCode(string code) + { + var cleanedCode = code.Trim(); + + if (string.IsNullOrWhiteSpace(cleanedCode)) + { + throw new InvalidOperationException("Provide a guest access code."); + } + + if (cleanedCode.Length < AccessCodeMinLength) + { + throw new InvalidOperationException($"Guest access code must be at least {AccessCodeMinLength} characters long."); + } + + if (cleanedCode.Length > AccessCodeMaxLength) + { + throw new InvalidOperationException($"Guest access code must be {AccessCodeMaxLength} characters or less."); + } + + return cleanedCode; + } + + [GeneratedRegex("^[a-z0-9._-]+$")] + private static partial Regex UsernameRegex(); +}