diff --git a/Core/Utils/HashUtil.cs b/Core/Utils/HashUtil.cs
index 23de8a29..993d228c 100644
--- a/Core/Utils/HashUtil.cs
+++ b/Core/Utils/HashUtil.cs
@@ -9,14 +9,40 @@ namespace Core.Utils;
public class HashUtil
{
private readonly Regex MongoIdRegex = new Regex("^[a-fA-F0-9]{24}$");
+
+ private readonly RandomUtil _randomUtil;
+
+ public HashUtil(RandomUtil randomUtil)
+ {
+ _randomUtil = randomUtil;
+ }
///
- /// Create a 24 character id using the sha256 algorithm + current timestamp
+ /// Create a 24 character MongoId
///
- /// 24 character hash
+ /// 24 character objectId
public string Generate()
{
- throw new NotImplementedException();
+ var objectId = new byte[12];
+
+ // Time stamp (4 bytes)
+ var timestamp = BitConverter.GetBytes((int)DateTimeOffset.UtcNow.ToUnixTimeSeconds());
+ // Convert to big-endian
+ Array.Reverse(timestamp);
+ Array.Copy(timestamp, 0, objectId, 0, 4);
+
+ // Random value (5 bytes)
+ var randomValue = new byte[5];
+ _randomUtil.Random.NextBytes(randomValue);
+ Array.Copy(randomValue, 0, objectId, 4, 5);
+
+ // Incrementing counter (3 bytes)
+ // 24-bit counter
+ var counter = BitConverter.GetBytes(_randomUtil.GetInt(0, 16777215));
+ Array.Reverse(counter);
+ Array.Copy(counter, 0, objectId, 9, 3);
+
+ return Convert.ToHexStringLower(objectId);
}
///
diff --git a/Core/Utils/RandomUtil.cs b/Core/Utils/RandomUtil.cs
index 5da25cd3..7e5993d8 100644
--- a/Core/Utils/RandomUtil.cs
+++ b/Core/Utils/RandomUtil.cs
@@ -7,7 +7,7 @@ namespace Core.Utils;
[Injectable(InjectionType.Singleton)]
public class RandomUtil
{
- private readonly Random _random = new();
+ public readonly Random Random = new();
///
/// The IEEE-754 standard for double-precision floating-point numbers limits the number of digits (including both
@@ -30,7 +30,7 @@ public class RandomUtil
}
// maxVal is exclusive of the passed value, so add 1
- return max > min ? _random.Next(min, max + 1) : min;
+ return max > min ? Random.Next(min, max + 1) : min;
}
///
@@ -41,7 +41,7 @@ public class RandomUtil
/// A random integer between 1 and max - 1, or 1 if max is less than or equal to 1.
public int GetIntEx(int max)
{
- return max > 2 ? _random.Next(1, max - 1) : 1;
+ return max > 2 ? Random.Next(1, max - 1) : 1;
}
///
@@ -214,13 +214,13 @@ public class RandomUtil
// Return a random integer from 0 to low if high is not provided
if (high is null)
{
- return _random.Next(0, low);
+ return Random.Next(0, low);
}
// Return low directly when low and high are equal
return low == high
? low
- : _random.Next(low, (int)high);
+ : Random.Next(low, (int)high);
}
///
diff --git a/UnitTests/Tests/Utils/HashUtilTests.cs b/UnitTests/Tests/Utils/HashUtilTests.cs
index c9a06405..d6f91006 100644
--- a/UnitTests/Tests/Utils/HashUtilTests.cs
+++ b/UnitTests/Tests/Utils/HashUtilTests.cs
@@ -5,7 +5,26 @@ namespace UnitTests.Tests.Utils;
[TestClass]
public class HashUtilTests
{
- private readonly HashUtil _hashUtil = new();
+ private readonly HashUtil _hashUtil = new(new RandomUtil());
+
+ [TestMethod]
+ public void GenerateTest()
+ {
+ // Generate 100 MongoId's
+ for (var i = 0; i < 100; i++)
+ {
+ // Invalid mongoId character
+ var result = _hashUtil.Generate();
+
+ // Invalid mongoId length
+ var test = _hashUtil.IsValidMongoId(result);
+
+ Assert.AreEqual(
+ true,
+ test,
+ $"IsValidMongoId() `{result}` is not a valid MongoId.");
+ }
+ }
[TestMethod]
public void IsValidMongoIdTest()