Files
Core_Be/Helpers/SandboxTokenHelper.cs
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

51 lines
1.9 KiB
C#

using System.Security.Cryptography;
using System.Text;
namespace Fitness_core_BE.Helpers
{
// Short, shareable /sandbox/{token} code — replaces the old raw Guid. Made of a
// time-derived prefix (minutes since a fixed epoch, base62) so codes drift forward
// over time, plus a random suffix for uniqueness among requests created in the same
// minute. Not a security boundary: the sandbox is a temporary trial state, not a
// login credential.
public static class SandboxTokenHelper
{
private const string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private const int TimePartLength = 5;
private const int RandomPartLength = 5;
private static readonly DateTime Epoch = new(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static string Generate(DateTime createdAtUtc)
{
long minutesSinceEpoch = Math.Max(0, (long)(createdAtUtc - Epoch).TotalMinutes);
string timePart = ToBaseAlphabet(minutesSinceEpoch).PadLeft(TimePartLength, '0');
if (timePart.Length > TimePartLength)
timePart = timePart[^TimePartLength..];
return timePart + RandomSuffix(RandomPartLength);
}
private static string RandomSuffix(int length)
{
var bytes = new byte[length];
RandomNumberGenerator.Fill(bytes);
var sb = new StringBuilder(length);
foreach (var b in bytes)
sb.Append(Alphabet[b % Alphabet.Length]);
return sb.ToString();
}
private static string ToBaseAlphabet(long value)
{
if (value <= 0) return "0";
var sb = new StringBuilder();
while (value > 0)
{
sb.Insert(0, Alphabet[(int)(value % Alphabet.Length)]);
value /= Alphabet.Length;
}
return sb.ToString();
}
}
}