ThrowIfInvalid.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System.ComponentModel.DataAnnotations;
  2. using RackPeek.Domain.Resources.SubResources;
  3. using RackPeek.Domain.Resources.SystemResources;
  4. namespace RackPeek.Domain.Helpers;
  5. public static class ThrowIfInvalid {
  6. public const int MaxResourceNameLength = 50;
  7. public const int MaxLabelValueLength = 200;
  8. public static void ResourceName(string name) {
  9. if (string.IsNullOrWhiteSpace(name)) throw new ValidationException("Name is required.");
  10. if (name.Length > MaxResourceNameLength) throw new ValidationException("Name is too long.");
  11. }
  12. public static void LabelKey(string key) {
  13. if (string.IsNullOrWhiteSpace(key)) throw new ValidationException("Label key is required.");
  14. if (key.Length > 50) throw new ValidationException("Label key is too long.");
  15. }
  16. public static void LabelValue(string value) {
  17. if (string.IsNullOrWhiteSpace(value)) throw new ValidationException("Label value is required.");
  18. if (value.Length > MaxLabelValueLength) throw new ValidationException("Label value is too long.");
  19. }
  20. public static void AccessPointModelName(string name) {
  21. if (string.IsNullOrWhiteSpace(name))
  22. throw new ValidationException("Model name is required.");
  23. if (name.Length > 50)
  24. throw new ValidationException("Model name is too long.");
  25. }
  26. public static void RamGb(double? value) {
  27. if (value is null) throw new ValidationException("RAM value must be specified.");
  28. if (value < 0) throw new ValidationException("RAM value must be a non negative number of gigabytes.");
  29. }
  30. public static void SystemType(string systemType) {
  31. if (string.IsNullOrWhiteSpace(systemType)) throw new ValidationException("System type is required.");
  32. var normalized = systemType.Trim().ToLowerInvariant();
  33. if (SystemResource.ValidSystemTypes.Contains(normalized)) return;
  34. var suggestions = GetSystemTypeSuggestions(normalized).ToList();
  35. var message = suggestions.Any()
  36. ? $"System type '{systemType}' is not valid. Did you mean: {string.Join(", ", suggestions)}?"
  37. : $"System type '{systemType}' is not valid. Valid System types include hypervisor, baremetal vm, container, cluster, other etc";
  38. throw new ValidationException(message);
  39. }
  40. private static IEnumerable<string> GetSystemTypeSuggestions(string input) {
  41. return SystemResource.ValidSystemTypes.Select(type => new { Type = type, Score = SimilarityScore(input, type) })
  42. .Where(x => x.Score >= 0.5)
  43. .OrderByDescending(x => x.Score)
  44. .Take(3)
  45. .Select(x => x.Type);
  46. }
  47. #region Nics
  48. public static void NicType(string nicType) {
  49. if (string.IsNullOrWhiteSpace(nicType)) throw new ValidationException("NIC type is required.");
  50. var normalized = nicType.Trim().ToLowerInvariant();
  51. if (Nic.ValidNicTypes.Contains(normalized)) return;
  52. var suggestions = GetNicTypeSuggestions(normalized).ToList();
  53. var message = suggestions.Any()
  54. ? $"NIC type '{nicType}' is not valid. Did you mean: {string.Join(", ", suggestions)}?"
  55. : $"NIC type '{nicType}' is not valid. Valid NIC types include rj45, sfp, sfp+, qsfp+ etc";
  56. throw new ValidationException(message);
  57. }
  58. private static IEnumerable<string> GetNicTypeSuggestions(string input) {
  59. return Nic.ValidNicTypes.Select(type => new { Type = type, Score = SimilarityScore(input, type) })
  60. .Where(x => x.Score >= 0.5)
  61. .OrderByDescending(x => x.Score)
  62. .Take(3)
  63. .Select(x => x.Type);
  64. }
  65. private static double SimilarityScore(string a, string b) {
  66. if (a == b) return 1.0;
  67. if (b.StartsWith(a) || a.StartsWith(b)) return 0.9;
  68. var commonChars = a.Intersect(b).Count();
  69. return (double)commonChars / Math.Max(a.Length, b.Length);
  70. }
  71. public static void NicSpeed(double speed) {
  72. if (speed < 0) throw new ValidationException("NIC speed must be a non negative number of gigabits per second.");
  73. }
  74. public static void NetworkSpeed(double speed) {
  75. if (speed < 0)
  76. throw new ValidationException(
  77. "Network speed must be a non negative number of gigabits per second.");
  78. }
  79. public static void NicPorts(int ports) {
  80. if (ports < 0) throw new ValidationException("NIC port count must be a non negative integer.");
  81. }
  82. #endregion
  83. #region Drives
  84. public static void DriveType(string driveType) {
  85. if (string.IsNullOrWhiteSpace(driveType)) throw new ValidationException("Drive type is required.");
  86. var normalized = driveType.Trim().ToLowerInvariant();
  87. if (Drive.ValidDriveTypes.Contains(normalized)) return;
  88. var suggestions = GetDriveTypeSuggestions(normalized).ToList();
  89. var message = suggestions.Any()
  90. ? $"Drive type '{driveType}' is not valid. Did you mean: {string.Join(", ", suggestions)}?"
  91. : $"Drive type '{driveType}' is not valid. Valid Drive types include nvme, ssd, hdd, sata, sas etc.";
  92. throw new ValidationException(message);
  93. }
  94. private static IEnumerable<string> GetDriveTypeSuggestions(string input) {
  95. return Drive.ValidDriveTypes.Select(type => new { Type = type, Score = SimilarityScore(input, type) })
  96. .Where(x => x.Score >= 0.5)
  97. .OrderByDescending(x => x.Score)
  98. .Take(3)
  99. .Select(x => x.Type);
  100. }
  101. public static void DriveSize(int size) {
  102. if (size < 0) throw new ValidationException("Drive size value must be a non negative number of gigabytes.");
  103. }
  104. #endregion
  105. }