diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 88ef30be4..6b1196054 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,8 @@ * New: Support for unicode characters in type names. This simplifies using an [ubiquitous language](http://www.jamesshore.com/Agile-Book/ubiquitous_language.html) in non-english domains +* Fixed: Include hyphen in prefix validation for identity values. This fixes a bug + where invalid identities could be created (e.g. `ThingyId.With("thingyINVALID-a41e...")`) ### New in 0.51.3155 (released 2017-10-25) diff --git a/Source/EventFlow.Tests/UnitTests/Core/IdentityTests.cs b/Source/EventFlow.Tests/UnitTests/Core/IdentityTests.cs index 1127a29b7..014aae993 100644 --- a/Source/EventFlow.Tests/UnitTests/Core/IdentityTests.cs +++ b/Source/EventFlow.Tests/UnitTests/Core/IdentityTests.cs @@ -118,6 +118,7 @@ public void NewDeterministic_IsValid() } [TestCase("da7ab6b1-c513-581f-a1a0-7cdf17109deb")] + [TestCase("thingyid-da7ab6b1-c513-581f-a1a0-7cdf17109deb")] [TestCase("thingy-769077C6-F84D-46E3-AD2E-828A576AAAF3")] [TestCase("thingy-pppppppp-pppp-pppp-pppp-pppppppppppp")] [TestCase("funny-da7ab6b1-c513-581f-a1a0-7cdf17109deb")] diff --git a/Source/EventFlow/Core/Identity.cs b/Source/EventFlow/Core/Identity.cs index 70ad7aa22..eb5a28b0c 100644 --- a/Source/EventFlow/Core/Identity.cs +++ b/Source/EventFlow/Core/Identity.cs @@ -35,16 +35,16 @@ public abstract class Identity : SingleValueObject, IIdentity where T : Identity { // ReSharper disable StaticMemberInGenericType - private static readonly string Name; + private static readonly string NameWithDash; private static readonly Regex ValueValidation; // ReSharper enable StaticMemberInGenericType static Identity() { var nameReplace = new Regex("Id$"); - Name = nameReplace.Replace(typeof(T).Name, string.Empty).ToLowerInvariant(); + NameWithDash = nameReplace.Replace(typeof(T).Name, string.Empty).ToLowerInvariant() + "-"; ValueValidation = new Regex( - @"^[\p{Ll}\p{Lm}\p{Lo}\p{Nd}]+\-(?[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})$", + @"^[^\-]+\-(?[a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})$", RegexOptions.Compiled); } @@ -86,7 +86,7 @@ public static T With(string value) public static T With(Guid guid) { - var value = $"{Name}-{guid:D}"; + var value = $"{NameWithDash}{guid:D}"; return With(value); } @@ -105,8 +105,8 @@ public static IEnumerable Validate(string value) if (!string.Equals(value.Trim(), value, StringComparison.OrdinalIgnoreCase)) yield return $"Identity '{value}' of type '{typeof(T).PrettyPrint()}' contains leading and/or traling spaces"; - if (!value.StartsWith(Name)) - yield return $"Identity '{value}' of type '{typeof(T).PrettyPrint()}' does not start with '{Name}'"; + if (!value.StartsWith(NameWithDash)) + yield return $"Identity '{value}' of type '{typeof(T).PrettyPrint()}' does not start with '{NameWithDash}'"; if (!ValueValidation.IsMatch(value)) yield return $"Identity '{value}' of type '{typeof(T).PrettyPrint()}' does not follow the syntax '[NAME]-[GUID]' in lower case"; }