diff --git a/AMWD.Common/AMWD.Common.csproj b/AMWD.Common/AMWD.Common.csproj index 8e20452..66140a5 100644 --- a/AMWD.Common/AMWD.Common.csproj +++ b/AMWD.Common/AMWD.Common.csproj @@ -37,6 +37,7 @@ + diff --git a/AMWD.Common/Extensions/IPAddressExtensions.cs b/AMWD.Common/Extensions/IPAddressExtensions.cs new file mode 100644 index 0000000..5a42153 --- /dev/null +++ b/AMWD.Common/Extensions/IPAddressExtensions.cs @@ -0,0 +1,46 @@ +namespace System.Net +{ + /// + /// Provides extension methods for es. + /// + public static class IPAddressExtensions + { + /// + /// Increments the by one and returns a new instance. + /// + /// The to increment. + public static IPAddress Increment(this IPAddress address) + { + byte[] bytes = address.GetAddressBytes(); + int bytePos = bytes.Length - 1; + + while (bytes[bytePos] == byte.MaxValue) + { + bytes[bytePos] = 0; + bytePos--; + } + bytes[bytePos]++; + + return new IPAddress(bytes); + } + + /// + /// Decrements the by one and returns a new instance. + /// + /// The to decrement. + public static IPAddress Decrement(this IPAddress address) + { + byte[] bytes = address.GetAddressBytes(); + int bytePos = bytes.Length - 1; + + while (bytes[bytePos] == 0) + { + bytes[bytePos] = byte.MaxValue; + bytePos--; + } + bytes[bytePos]--; + + return new IPAddress(bytes); + } + } +} diff --git a/AMWD.Common/Utilities/NetworkHelper.cs b/AMWD.Common/Utilities/NetworkHelper.cs index b52f1d7..33dcd99 100644 --- a/AMWD.Common/Utilities/NetworkHelper.cs +++ b/AMWD.Common/Utilities/NetworkHelper.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; +using Microsoft.AspNetCore.HttpOverrides; namespace AMWD.Common.Utilities { @@ -77,6 +78,66 @@ namespace AMWD.Common.Utilities } } + /// + /// Parses a CIDR network definition. + /// + /// The network in CIDR. + /// The or null. + public static IPNetwork ParseNetwork(string network) + { + TryParseNetwork(network, out var ipNetwork); + return ipNetwork; + } + + /// + /// Tries to parse a CIDR network definition. + /// + /// The network in CIDR. + /// The parsed . + /// true on success, otherwise false. + public static bool TryParseNetwork(string network, out IPNetwork ipNetwork) + { + try + { + string[] parts = network.Split('/'); + if (parts.Length != 2) + throw new ArgumentException($"Invalid network type"); + + var prefix = IPAddress.Parse(parts.First()); + int prefixLength = int.Parse(parts.Last()); + + ipNetwork = new IPNetwork(prefix, prefixLength); + return true; + } + catch + { + ipNetwork = null; + return false; + } + } + + /// + /// Uses the and expands the whole subnet. + /// + /// + /// The network identifier and the broadcast address are included in the response list. + /// + /// The to expand. + /// A list with all valid es. + public static List ExpandNetwork(this IPNetwork network) + { + var list = new List(); + + var ipAddress = network.Prefix; + while (network.Contains(ipAddress)) + { + list.Add(ipAddress); + ipAddress = ipAddress.Increment(); + } + + return list; + } + private static IPAddress ResolveIpAddress(string address, AddressFamily addressFamily) { if (IPAddress.TryParse(address, out var ipAddress)) diff --git a/CHANGELOG.md b/CHANGELOG.md index addca60..bb9610a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,42 +6,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://git.am-wd.de/AM.WD/common/compare/v1.6.1...master) - 0000-00-00 ### Added -- UnitTests for `AspNetCore` as far as testable without massive work. +- UnitTests for `AspNetCore` as far as testable without massive work +- `IPAddress.Increment` and `IPAddress.Decrement` extensions +- `NetworkHelper.ParseNetwork` and `NetworkHelper.TryParseNetwork` to parse a CIDR (e.g. 192.168.178.0/24) network +- `IPNetwork.ExpandNetwork` to create a list with all contained `IPAddress`es ### Changed -- `BasicAuthenticationAttribute` now respects the `IBasicAuthenticationValidator.Realm` when the own `Realm` property is not set. +- `BasicAuthenticationAttribute` now respects the `IBasicAuthenticationValidator.Realm` when the own `Realm` property is not set - CI scripts +- Updated all package references to latest builds (as on 2022-07-23) ### Removed -- `IBasicAuthenticationValidator.Realm` is now a read-only property (removed public set). +- `IBasicAuthenticationValidator.Realm` is now a read-only property (removed public set) ## [v1.6.1](https://git.am-wd.de/AM.WD/common/compare/v1.6.0...v1.6.1) - 2022-06-23 ### Added -- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated. +- `BasicAuthenticationAttribute` sets the `HttpContext.User` property when successfully validated ### Changed -- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter`. +- Moved `BasicAuthenticationAttribute` from `ActionFilter` to `IAsyncAuthorizationFilter` ### Fixed -- `TimeSpan.ToShortString()` is now capable of negative values. +- `TimeSpan.ToShortString()` is now capable of negative values ## [v1.6.0](https://git.am-wd.de/AM.WD/common/compare/v1.5.3...v1.6.0) - 2022-06-22 ### Changed -- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace. +- All attributes now reside in `Microsoft.AspNetCore.Mvc.Filters` namespace ### Fixed -- Fixed `BasicAuthenticationAttribute`. +- Fixed `BasicAuthenticationAttribute` ## [v1.5.3](https://git.am-wd.de/AM.WD/common/compare/v1.5.2...v1.5.3) - 2022-06-22 ### Changed -- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes`. +- `BasicAuthenticationAttribute` is now in namespace `AMWD.Common.AspNetCore.Attributes` ### Fixed -- Fixed problem with `ForbidResult` without having an authentication schema defined. - Now only HTTP Status 403 (Forbid) is returned. +- Fixed problem with `ForbidResult` without having an authentication schema defined + Now only HTTP Status 403 (Forbid) is returned ## [v1.5.2](https://git.am-wd.de/AM.WD/common/compare/v1.5.1...v1.5.2) - 2022-06-20 @@ -51,15 +55,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v1.5.1](https://git.am-wd.de/AM.WD/common/compare/v1.5.0...v1.5.1) - 2022-06-20 ### Changed -- Changed from `Assembly.GetExecutingAssmebly().Location` to `AppContext.BaseDirectory` due to single-file applications. +- Changed from `Assembly.GetExecutingAssmebly().Location` to `AppContext.BaseDirectory` due to single-file applications ## [v1.5.0](https://git.am-wd.de/AM.WD/common/compare/v1.4.3...v1.5.0) - 2022-06-15 ### Added - `TcpClientMoq` to test communication via a `TcpClient` - EntityFramework Core Converters for new `DateOnly` and `TimeOnly` datatypes when using SQL Server on .NET 6.0 (Bug on Microsoft's EntityFramework) -- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote. -- `IPWhitelistAttribute` and `IPBlacklistAttribute` to allow/restrict access on specific controllers/actions. +- `HttpContext.IsLocalRequest()` to determine whether the request was from local or remote +- `IPWhitelistAttribute` and `IPBlacklistAttribute` to allow/restrict access on specific controllers/actions ## [v1.4.3](https://git.am-wd.de/AM.WD/common/compare/v1.4.2...v1.4.3) - 2022-05-12 @@ -69,16 +73,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v1.4.2](https://git.am-wd.de/AM.WD/common/compare/v1.4.1...v1.4.2) - 2022-05-06 ### Added -- New extension for `StringBuilder` `AppendLine(value: string, newLine: string)` to add a line with a explicit defined new line character. +- New extension for `StringBuilder` `AppendLine(value: string, newLine: string)` to add a line with a explicit defined new line character ## [v1.4.1](https://git.am-wd.de/AM.WD/common/compare/v1.4.0...v1.4.1) - 2022-03-23 ### Added - `IntegrityHashTagHelper` can be used with `asp-integrity="true|false"` and `asp-integrity-strength="256|384|512"` -- `WaitAvailableAsync` can be used to wait for a database connection to be available. +- `WaitAvailableAsync` can be used to wait for a database connection to be available ### Changed -- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally. +- `ApplyMigrationsAsync` uses `WaitAvailableAsync` internally ### Fixed - `InMemory` database provider does not fail on "migration" (none possible) diff --git a/UnitTests/Common/Extensions/IPAddressExtensionsTests.cs b/UnitTests/Common/Extensions/IPAddressExtensionsTests.cs new file mode 100644 index 0000000..942b18b --- /dev/null +++ b/UnitTests/Common/Extensions/IPAddressExtensionsTests.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace UnitTests.Common.Extensions +{ + [TestClass] + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] + public class IPAddressExtensionsTests + { + [TestMethod] + public void ShouldIncrementLastByte() + { + // arrange + var ipAddress = IPAddress.Parse("192.168.178.22"); + + // act + var incremented = ipAddress.Increment(); + + // assert + Assert.AreEqual("192.168.178.23", incremented.ToString()); + } + + [TestMethod] + public void ShouldIncrementAllBytes() + { + // arrange + var ipAddress = IPAddress.Parse("192.255.255.255"); + + // act + var incremented = ipAddress.Increment(); + + // assert + Assert.AreEqual("193.0.0.0", incremented.ToString()); + } + + [TestMethod] + public void ShouldDecrementLastByte() + { + // arrange + var ipAddress = IPAddress.Parse("192.168.178.22"); + + // act + var decremented = ipAddress.Decrement(); + + // assert + Assert.AreEqual("192.168.178.21", decremented.ToString()); + } + + [TestMethod] + public void ShouldDecrementAllBytes() + { + // arrange + var ipAddress = IPAddress.Parse("192.0.0.0"); + + // act + var decremented = ipAddress.Decrement(); + + // assert + Assert.AreEqual("191.255.255.255", decremented.ToString()); + } + } +}