aboutsummaryrefslogtreecommitdiffstats
path: root/src/IOL.Helpers
diff options
context:
space:
mode:
authorivarlovlie <git@ivarlovlie.no>2021-11-20 21:31:30 +0100
committerivarlovlie <git@ivarlovlie.no>2021-11-20 21:31:30 +0100
commit7ff7f3902e5bdcc33bfc07fa6ad71a5798d7f8d6 (patch)
tree6e7eaaed636558c4feb88f2bb18bbb7d4c0c87be /src/IOL.Helpers
parent4e41b1f31a7309b299398fd9dd53d499204fa6cf (diff)
downloaddotnet-helpers-7ff7f3902e5bdcc33bfc07fa6ad71a5798d7f8d6.tar.xz
dotnet-helpers-7ff7f3902e5bdcc33bfc07fa6ad71a5798d7f8d6.zip
Change to file-scoped namespaces.
Add ConditionalWhere to QueryableHelpers.cs
Diffstat (limited to 'src/IOL.Helpers')
-rw-r--r--src/IOL.Helpers/CryptographyHelpers.cs263
-rw-r--r--src/IOL.Helpers/DateTimeHelpers.cs37
-rw-r--r--src/IOL.Helpers/DoubleHelpers.cs13
-rw-r--r--src/IOL.Helpers/EnumHelpers.cs13
-rw-r--r--src/IOL.Helpers/HttpRequestHelpers.cs37
-rw-r--r--src/IOL.Helpers/InMemoryZipArchive.cs37
-rw-r--r--src/IOL.Helpers/PasswordHelpers.cs107
-rw-r--r--src/IOL.Helpers/QueryableHelpers.cs24
-rw-r--r--src/IOL.Helpers/RandomStringGenerator.cs19
-rw-r--r--src/IOL.Helpers/SlugGenerator.cs151
-rw-r--r--src/IOL.Helpers/StringHelpers.cs123
-rw-r--r--src/IOL.Helpers/Validators.cs21
12 files changed, 429 insertions, 416 deletions
diff --git a/src/IOL.Helpers/CryptographyHelpers.cs b/src/IOL.Helpers/CryptographyHelpers.cs
index 6ea18b6..4821613 100644
--- a/src/IOL.Helpers/CryptographyHelpers.cs
+++ b/src/IOL.Helpers/CryptographyHelpers.cs
@@ -3,171 +3,170 @@ using System.Linq;
using System.Security.Cryptography;
using System.Text;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class CryptographyHelpers
{
- public static class CryptographyHelpers
- {
- // https://github.com/DuendeSoftware/IdentityServer/blob/main/src/IdentityServer/Extensions/HashExtensions.cs
+ // https://github.com/DuendeSoftware/IdentityServer/blob/main/src/IdentityServer/Extensions/HashExtensions.cs
- private const int AES_BLOCK_BYTE_SIZE = 128 / 8;
- private static readonly RandomNumberGenerator _random = RandomNumberGenerator.Create();
+ private const int AES_BLOCK_BYTE_SIZE = 128 / 8;
+ private static readonly RandomNumberGenerator _random = RandomNumberGenerator.Create();
- /// <summary>
- /// Creates a MD5 hash of the specified input.
- /// </summary>
- /// <returns>A hash</returns>
- public static string Md5(this string input, string salt = default) {
- if (input.IsNullOrWhiteSpace()) return string.Empty;
+ /// <summary>
+ /// Creates a MD5 hash of the specified input.
+ /// </summary>
+ /// <returns>A hash</returns>
+ public static string Md5(this string input, string salt = default) {
+ if (input.IsNullOrWhiteSpace()) return string.Empty;
- var hmacMd5 = salt.HasValue() ? new HMACMD5(Encoding.UTF8.GetBytes(salt ?? "")) : new HMACMD5();
- var saltedHash = hmacMd5.ComputeHash(Encoding.UTF8.GetBytes(input));
- return Convert.ToBase64String(saltedHash);
- }
+ var hmacMd5 = salt.HasValue() ? new HMACMD5(Encoding.UTF8.GetBytes(salt ?? "")) : new HMACMD5();
+ var saltedHash = hmacMd5.ComputeHash(Encoding.UTF8.GetBytes(input));
+ return Convert.ToBase64String(saltedHash);
+ }
- /// <summary>
- /// Method to perform a very simple (and classical) encryption for a string. This is NOT at
- /// all secure, it is only intended to make the string value non-obvious at a first glance.
- ///
- /// The shiftOrUnshift argument is an arbitrary "key value", and must be a non-zero integer
- /// between -65535 and 65535 (inclusive). To decrypt the encrypted string you use the negative
- /// value. For example, if you encrypt with -42, then you decrypt with +42, or vice-versa.
- ///
- /// This is inspired by, and largely based on, this:
- /// https://stackoverflow.com/a/13026595/253938
- /// </summary>
- /// <param name="inputString">string to be encrypted or decrypted, must not be null</param>
- /// <param name="shiftOrUnshift">see above</param>
- /// <returns>encrypted or decrypted string</returns>
- public static string CaesarCipher(string inputString, int shiftOrUnshift) {
- const int C64_K = ushort.MaxValue + 1;
- if (inputString == null) throw new ArgumentException("Must not be null.", nameof(inputString));
- switch (shiftOrUnshift) {
- case 0: throw new ArgumentException("Must not be zero.", nameof(shiftOrUnshift));
- case <= -C64_K:
- case >= C64_K: throw new ArgumentException("Out of range.", nameof(shiftOrUnshift));
- }
+ /// <summary>
+ /// Method to perform a very simple (and classical) encryption for a string. This is NOT at
+ /// all secure, it is only intended to make the string value non-obvious at a first glance.
+ ///
+ /// The shiftOrUnshift argument is an arbitrary "key value", and must be a non-zero integer
+ /// between -65535 and 65535 (inclusive). To decrypt the encrypted string you use the negative
+ /// value. For example, if you encrypt with -42, then you decrypt with +42, or vice-versa.
+ ///
+ /// This is inspired by, and largely based on, this:
+ /// https://stackoverflow.com/a/13026595/253938
+ /// </summary>
+ /// <param name="inputString">string to be encrypted or decrypted, must not be null</param>
+ /// <param name="shiftOrUnshift">see above</param>
+ /// <returns>encrypted or decrypted string</returns>
+ public static string CaesarCipher(string inputString, int shiftOrUnshift) {
+ const int C64_K = ushort.MaxValue + 1;
+ if (inputString == null) throw new ArgumentException("Must not be null.", nameof(inputString));
+ switch (shiftOrUnshift) {
+ case 0: throw new ArgumentException("Must not be zero.", nameof(shiftOrUnshift));
+ case <= -C64_K:
+ case >= C64_K: throw new ArgumentException("Out of range.", nameof(shiftOrUnshift));
+ }
- // Perform the Caesar cipher shifting, using modulo operator to provide wrap-around
- var charArray = new char[inputString.Length];
- for (var i = 0; i < inputString.Length; i++) {
- charArray[i] =
+ // Perform the Caesar cipher shifting, using modulo operator to provide wrap-around
+ var charArray = new char[inputString.Length];
+ for (var i = 0; i < inputString.Length; i++) {
+ charArray[i] =
Convert.ToChar((Convert.ToInt32(inputString[i]) + shiftOrUnshift + C64_K) % C64_K);
- }
-
- return new string(charArray);
}
- //https://tomrucki.com/posts/aes-encryption-in-csharp/
- public static string EncryptWithAes(this string toEncrypt, string password) {
- var key = GetKey(password);
+ return new string(charArray);
+ }
+
+ //https://tomrucki.com/posts/aes-encryption-in-csharp/
+ public static string EncryptWithAes(this string toEncrypt, string password) {
+ var key = GetKey(password);
- using var aes = CreateAes();
- var iv = GenerateRandomBytes(AES_BLOCK_BYTE_SIZE);
- var plainText = Encoding.UTF8.GetBytes(toEncrypt);
+ using var aes = CreateAes();
+ var iv = GenerateRandomBytes(AES_BLOCK_BYTE_SIZE);
+ var plainText = Encoding.UTF8.GetBytes(toEncrypt);
- using var encryptor = aes.CreateEncryptor(key, iv);
- var cipherText = encryptor
+ using var encryptor = aes.CreateEncryptor(key, iv);
+ var cipherText = encryptor
.TransformFinalBlock(plainText, 0, plainText.Length);
- var result = new byte[iv.Length + cipherText.Length];
- iv.CopyTo(result, 0);
- cipherText.CopyTo(result, iv.Length);
+ var result = new byte[iv.Length + cipherText.Length];
+ iv.CopyTo(result, 0);
+ cipherText.CopyTo(result, iv.Length);
- return Convert.ToBase64String(result);
- }
+ return Convert.ToBase64String(result);
+ }
- private static Aes CreateAes() {
- var aes = Aes.Create();
- aes.Mode = CipherMode.CBC;
- aes.Padding = PaddingMode.PKCS7;
- return aes;
- }
+ private static Aes CreateAes() {
+ var aes = Aes.Create();
+ aes.Mode = CipherMode.CBC;
+ aes.Padding = PaddingMode.PKCS7;
+ return aes;
+ }
- public static string DecryptWithAes(this string input, string password) {
- var key = GetKey(password);
- var encryptedData = Convert.FromBase64String(input);
+ public static string DecryptWithAes(this string input, string password) {
+ var key = GetKey(password);
+ var encryptedData = Convert.FromBase64String(input);
- using var aes = CreateAes();
- var iv = encryptedData.Take(AES_BLOCK_BYTE_SIZE).ToArray();
- var cipherText = encryptedData.Skip(AES_BLOCK_BYTE_SIZE).ToArray();
+ using var aes = CreateAes();
+ var iv = encryptedData.Take(AES_BLOCK_BYTE_SIZE).ToArray();
+ var cipherText = encryptedData.Skip(AES_BLOCK_BYTE_SIZE).ToArray();
- using var decryptor = aes.CreateDecryptor(key, iv);
- var decryptedBytes = decryptor
+ using var decryptor = aes.CreateDecryptor(key, iv);
+ var decryptedBytes = decryptor
.TransformFinalBlock(cipherText, 0, cipherText.Length);
- return Encoding.UTF8.GetString(decryptedBytes);
- }
-
- private static byte[] GetKey(string password) {
- var keyBytes = Encoding.UTF8.GetBytes(password);
- using var md5 = MD5.Create();
- return md5.ComputeHash(keyBytes);
- }
+ return Encoding.UTF8.GetString(decryptedBytes);
+ }
- private static byte[] GenerateRandomBytes(int numberOfBytes) {
- var randomBytes = new byte[numberOfBytes];
- _random.GetBytes(randomBytes);
- return randomBytes;
- }
+ private static byte[] GetKey(string password) {
+ var keyBytes = Encoding.UTF8.GetBytes(password);
+ using var md5 = MD5.Create();
+ return md5.ComputeHash(keyBytes);
+ }
+ private static byte[] GenerateRandomBytes(int numberOfBytes) {
+ var randomBytes = new byte[numberOfBytes];
+ _random.GetBytes(randomBytes);
+ return randomBytes;
+ }
- /// <summary>
- /// Creates a SHA256 hash of the specified input.
- /// </summary>
- /// <param name="input">The input.</param>
- /// <returns>A hash</returns>
- public static string Sha256(this string input) {
- if (input.IsNullOrWhiteSpace()) return string.Empty;
- using var sha = SHA256.Create();
- var bytes = Encoding.UTF8.GetBytes(input);
- var hash = sha.ComputeHash(bytes);
+ /// <summary>
+ /// Creates a SHA256 hash of the specified input.
+ /// </summary>
+ /// <param name="input">The input.</param>
+ /// <returns>A hash</returns>
+ public static string Sha256(this string input) {
+ if (input.IsNullOrWhiteSpace()) return string.Empty;
- return Convert.ToBase64String(hash);
- }
+ using var sha = SHA256.Create();
+ var bytes = Encoding.UTF8.GetBytes(input);
+ var hash = sha.ComputeHash(bytes);
- /// <summary>
- /// Creates a SHA256 hash of the specified input.
- /// </summary>
- /// <param name="input">The input.</param>
- /// <returns>A hash.</returns>
- public static byte[] Sha256(this byte[] input) {
- if (input == null) {
- return null;
- }
+ return Convert.ToBase64String(hash);
+ }
- using var sha = SHA256.Create();
- return sha.ComputeHash(input);
+ /// <summary>
+ /// Creates a SHA256 hash of the specified input.
+ /// </summary>
+ /// <param name="input">The input.</param>
+ /// <returns>A hash.</returns>
+ public static byte[] Sha256(this byte[] input) {
+ if (input == null) {
+ return null;
}
- /// <summary>
- /// Creates a SHA512 hash of the specified input.
- /// </summary>
- /// <param name="input">The input.</param>
- /// <returns>A hash</returns>
- public static string Sha512(this string input) {
- if (input.IsNullOrWhiteSpace()) return string.Empty;
+ using var sha = SHA256.Create();
+ return sha.ComputeHash(input);
+ }
- using var sha = SHA512.Create();
- var bytes = Encoding.UTF8.GetBytes(input);
- var hash = sha.ComputeHash(bytes);
+ /// <summary>
+ /// Creates a SHA512 hash of the specified input.
+ /// </summary>
+ /// <param name="input">The input.</param>
+ /// <returns>A hash</returns>
+ public static string Sha512(this string input) {
+ if (input.IsNullOrWhiteSpace()) return string.Empty;
- return Convert.ToBase64String(hash);
- }
+ using var sha = SHA512.Create();
+ var bytes = Encoding.UTF8.GetBytes(input);
+ var hash = sha.ComputeHash(bytes);
+ return Convert.ToBase64String(hash);
+ }
- /// <summary>
- /// Creates a SHA256 hash of the specified input.
- /// </summary>
- /// <param name="input">The input.</param>
- /// <returns>A hash.</returns>
- public static byte[] Sha512(this byte[] input) {
- if (input == null) {
- return null;
- }
- using var sha = SHA512.Create();
- return sha.ComputeHash(input);
+ /// <summary>
+ /// Creates a SHA256 hash of the specified input.
+ /// </summary>
+ /// <param name="input">The input.</param>
+ /// <returns>A hash.</returns>
+ public static byte[] Sha512(this byte[] input) {
+ if (input == null) {
+ return null;
}
+
+ using var sha = SHA512.Create();
+ return sha.ComputeHash(input);
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/DateTimeHelpers.cs b/src/IOL.Helpers/DateTimeHelpers.cs
index 98b3ee9..16ece6b 100644
--- a/src/IOL.Helpers/DateTimeHelpers.cs
+++ b/src/IOL.Helpers/DateTimeHelpers.cs
@@ -1,27 +1,26 @@
using System;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class DateTimeHelpers
{
- public static class DateTimeHelpers
- {
- public static DateTime ToTimeZoneId(this DateTime value, string timeZoneId) {
- try {
- var cstZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
- return TimeZoneInfo.ConvertTimeFromUtc(value, cstZone);
- } catch (TimeZoneNotFoundException) {
- Console.WriteLine("The registry does not define the " + timeZoneId + " zone.");
- return default;
- } catch (InvalidTimeZoneException) {
- Console.WriteLine("Registry data on the " + timeZoneId + " zone has been corrupted.");
- return default;
- }
+ public static DateTime ToTimeZoneId(this DateTime value, string timeZoneId) {
+ try {
+ var cstZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
+ return TimeZoneInfo.ConvertTimeFromUtc(value, cstZone);
+ } catch (TimeZoneNotFoundException) {
+ Console.WriteLine("The registry does not define the " + timeZoneId + " zone.");
+ return default;
+ } catch (InvalidTimeZoneException) {
+ Console.WriteLine("Registry data on the " + timeZoneId + " zone has been corrupted.");
+ return default;
}
+ }
- public static DateTime ToOsloTimeZone(this DateTime value) => ToTimeZoneId(value, "Europe/Oslo");
+ public static DateTime ToOsloTimeZone(this DateTime value) => ToTimeZoneId(value, "Europe/Oslo");
- public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek) {
- var diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
- return dt.AddDays(-1 * diff).Date;
- }
+ public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek) {
+ var diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
+ return dt.AddDays(-1 * diff).Date;
}
}
diff --git a/src/IOL.Helpers/DoubleHelpers.cs b/src/IOL.Helpers/DoubleHelpers.cs
index 91d88ee..44f01d5 100644
--- a/src/IOL.Helpers/DoubleHelpers.cs
+++ b/src/IOL.Helpers/DoubleHelpers.cs
@@ -1,11 +1,10 @@
using System;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class DoubleHelpers
{
- public static class DoubleHelpers
- {
- public static string ToStringWithFixedDecimalPoints(this double value) {
- return $"{Math.Truncate(value * 10) / 10:0.0}";
- }
+ public static string ToStringWithFixedDecimalPoints(this double value) {
+ return $"{Math.Truncate(value * 10) / 10:0.0}";
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/EnumHelpers.cs b/src/IOL.Helpers/EnumHelpers.cs
index b63e045..5434992 100644
--- a/src/IOL.Helpers/EnumHelpers.cs
+++ b/src/IOL.Helpers/EnumHelpers.cs
@@ -2,12 +2,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class EnumHelpers
{
- public static class EnumHelpers
- {
- public static IEnumerable<T> GetValues<T>() {
- return Enum.GetValues(typeof(T)).Cast<T>();
- }
+ public static IEnumerable<T> GetValues<T>() {
+ return Enum.GetValues(typeof(T)).Cast<T>();
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/HttpRequestHelpers.cs b/src/IOL.Helpers/HttpRequestHelpers.cs
index 60dbd90..59332f4 100644
--- a/src/IOL.Helpers/HttpRequestHelpers.cs
+++ b/src/IOL.Helpers/HttpRequestHelpers.cs
@@ -1,25 +1,24 @@
using Microsoft.AspNetCore.Http;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class HttpRequestHelpers
{
- public static class HttpRequestHelpers
- {
- /// <summary>
- /// Get's the scheme and host (scheme://host) value of the current HttpRequest
- /// </summary>
- /// <param name="request">HttpRequest to retrieve value from</param>
- /// <param name="ignoreForwared">Ignore header values like X-Forwarded-Host|Proto</param>
- /// <returns></returns>
- public static string GetRequestHost(this HttpRequest request, bool ignoreForwared = false) {
- if (!ignoreForwared) {
- var forwardedHostHeader = request.Headers["X-Forwarded-Host"].ToString();
- var forwardedProtoHeader = request.Headers["X-Forwarded-Proto"].ToString();
- if (forwardedHostHeader.HasValue()) {
- return (forwardedProtoHeader ?? "https") + "://" + forwardedHostHeader;
- }
+ /// <summary>
+ /// Get's the scheme and host (scheme://host) value of the current HttpRequest
+ /// </summary>
+ /// <param name="request">HttpRequest to retrieve value from</param>
+ /// <param name="ignoreForwared">Ignore header values like X-Forwarded-Host|Proto</param>
+ /// <returns></returns>
+ public static string GetRequestHost(this HttpRequest request, bool ignoreForwared = false) {
+ if (!ignoreForwared) {
+ var forwardedHostHeader = request.Headers["X-Forwarded-Host"].ToString();
+ var forwardedProtoHeader = request.Headers["X-Forwarded-Proto"].ToString();
+ if (forwardedHostHeader.HasValue()) {
+ return (forwardedProtoHeader ?? "https") + "://" + forwardedHostHeader;
}
-
- return request.Scheme + "://" + request.Host;
}
+
+ return request.Scheme + "://" + request.Host;
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/InMemoryZipArchive.cs b/src/IOL.Helpers/InMemoryZipArchive.cs
index 8d3fc94..efb4f79 100644
--- a/src/IOL.Helpers/InMemoryZipArchive.cs
+++ b/src/IOL.Helpers/InMemoryZipArchive.cs
@@ -3,28 +3,27 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class InMemoryZipArchive
{
- public static class InMemoryZipArchive
- {
- public static byte[] Create(IEnumerable<InMemoryFile> files, string unixPermissionString = "664") {
- using var archiveStream = new MemoryStream();
- using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true)) {
- foreach (var file in files) {
- var zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
- zipArchiveEntry.ExternalAttributes |= Convert.ToInt32(unixPermissionString, 8) << 16;
- using var zipStream = zipArchiveEntry.Open();
- zipStream.Write(file.Content, 0, file.Content.Length);
- }
+ public static byte[] Create(IEnumerable<InMemoryFile> files, string unixPermissionString = "664") {
+ using var archiveStream = new MemoryStream();
+ using (var archive = new ZipArchive(archiveStream, ZipArchiveMode.Create, true)) {
+ foreach (var file in files) {
+ var zipArchiveEntry = archive.CreateEntry(file.FileName, CompressionLevel.Fastest);
+ zipArchiveEntry.ExternalAttributes |= Convert.ToInt32(unixPermissionString, 8) << 16;
+ using var zipStream = zipArchiveEntry.Open();
+ zipStream.Write(file.Content, 0, file.Content.Length);
}
-
- return archiveStream.ToArray();
}
- public class InMemoryFile
- {
- public string FileName { get; set; }
- public byte[] Content { get; set; }
- }
+ return archiveStream.ToArray();
+ }
+
+ public class InMemoryFile
+ {
+ public string FileName { get; set; }
+ public byte[] Content { get; set; }
}
}
diff --git a/src/IOL.Helpers/PasswordHelpers.cs b/src/IOL.Helpers/PasswordHelpers.cs
index 5b85219..ebebeb9 100644
--- a/src/IOL.Helpers/PasswordHelpers.cs
+++ b/src/IOL.Helpers/PasswordHelpers.cs
@@ -3,68 +3,67 @@ using System.Collections.Generic;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class PasswordHelper
{
- public static class PasswordHelper
- {
- private const int ITERATION_COUNT = 10000;
- private const int SALT_SIZE = 128 / 8;
- private const KeyDerivationPrf PRF = KeyDerivationPrf.HMACSHA256;
+ private const int ITERATION_COUNT = 10000;
+ private const int SALT_SIZE = 128 / 8;
+ private const KeyDerivationPrf PRF = KeyDerivationPrf.HMACSHA256;
- public static string HashPassword(string value) {
- using var rng = RandomNumberGenerator.Create();
- var salt = new byte[SALT_SIZE];
- rng.GetBytes(salt);
- var subkey = KeyDerivation.Pbkdf2(value, salt, PRF, ITERATION_COUNT, 256 / 8);
- var outputBytes = new byte[13 + salt.Length + subkey.Length];
- WriteNetworkByteOrder(outputBytes, 1, (uint) PRF);
- WriteNetworkByteOrder(outputBytes, 5, (uint) ITERATION_COUNT);
- WriteNetworkByteOrder(outputBytes, 9, (uint) SALT_SIZE);
- Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
- Buffer.BlockCopy(subkey, 0, outputBytes, 13 + SALT_SIZE, subkey.Length);
- return Convert.ToBase64String(outputBytes);
- }
+ public static string HashPassword(string value) {
+ using var rng = RandomNumberGenerator.Create();
+ var salt = new byte[SALT_SIZE];
+ rng.GetBytes(salt);
+ var subkey = KeyDerivation.Pbkdf2(value, salt, PRF, ITERATION_COUNT, 256 / 8);
+ var outputBytes = new byte[13 + salt.Length + subkey.Length];
+ WriteNetworkByteOrder(outputBytes, 1, (uint)PRF);
+ WriteNetworkByteOrder(outputBytes, 5, ITERATION_COUNT);
+ WriteNetworkByteOrder(outputBytes, 9, SALT_SIZE);
+ Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
+ Buffer.BlockCopy(subkey, 0, outputBytes, 13 + SALT_SIZE, subkey.Length);
+ return Convert.ToBase64String(outputBytes);
+ }
- public static bool Verify(string password, string hashedPassword) {
- var decodedHashedPassword = Convert.FromBase64String(hashedPassword);
- if (decodedHashedPassword.Length == 0) return false;
- try {
- // Read header information
- var networkByteOrder = (KeyDerivationPrf) ReadNetworkByteOrder(decodedHashedPassword, 1);
- var saltLength = (int) ReadNetworkByteOrder(decodedHashedPassword, 9);
+ public static bool Verify(string password, string hashedPassword) {
+ var decodedHashedPassword = Convert.FromBase64String(hashedPassword);
+ if (decodedHashedPassword.Length == 0) return false;
+ try {
+ // Read header information
+ var networkByteOrder = (KeyDerivationPrf)ReadNetworkByteOrder(decodedHashedPassword, 1);
+ var saltLength = (int)ReadNetworkByteOrder(decodedHashedPassword, 9);
- // Read the salt: must be >= 128 bits
- if (saltLength < SALT_SIZE) return false;
- var salt = new byte[saltLength];
- Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);
+ // Read the salt: must be >= 128 bits
+ if (saltLength < SALT_SIZE) return false;
+ var salt = new byte[saltLength];
+ Buffer.BlockCopy(decodedHashedPassword, 13, salt, 0, salt.Length);
- // Read the subkey (the rest of the payload): must be >= 128 bits
- var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
- if (subkeyLength < SALT_SIZE) return false;
- var expectedSubkey = new byte[subkeyLength];
- Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
+ // Read the subkey (the rest of the payload): must be >= 128 bits
+ var subkeyLength = decodedHashedPassword.Length - 13 - salt.Length;
+ if (subkeyLength < SALT_SIZE) return false;
+ var expectedSubkey = new byte[subkeyLength];
+ Buffer.BlockCopy(decodedHashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
- // Hash the incoming password and verify it
- var actualSubkey =
+ // Hash the incoming password and verify it
+ var actualSubkey =
KeyDerivation.Pbkdf2(password, salt, networkByteOrder, ITERATION_COUNT, subkeyLength);
- return CryptographicOperations.FixedTimeEquals(actualSubkey, expectedSubkey);
- } catch {
- return false;
- }
+ return CryptographicOperations.FixedTimeEquals(actualSubkey, expectedSubkey);
+ } catch {
+ return false;
}
+ }
- private static uint ReadNetworkByteOrder(IReadOnlyList<byte> buffer, int offset) {
- return ((uint) buffer[offset + 0] << 24)
- | ((uint) buffer[offset + 1] << 16)
- | ((uint) buffer[offset + 2] << 8)
- | buffer[offset + 3];
- }
+ private static uint ReadNetworkByteOrder(IReadOnlyList<byte> buffer, int offset) {
+ return ((uint)buffer[offset + 0] << 24)
+ | ((uint)buffer[offset + 1] << 16)
+ | ((uint)buffer[offset + 2] << 8)
+ | buffer[offset + 3];
+ }
- private static void WriteNetworkByteOrder(IList<byte> buffer, int offset, uint value) {
- buffer[offset + 0] = (byte) (value >> 24);
- buffer[offset + 1] = (byte) (value >> 16);
- buffer[offset + 2] = (byte) (value >> 8);
- buffer[offset + 3] = (byte) (value >> 0);
- }
+ private static void WriteNetworkByteOrder(IList<byte> buffer, int offset, uint value) {
+ buffer[offset + 0] = (byte)(value >> 24);
+ buffer[offset + 1] = (byte)(value >> 16);
+ buffer[offset + 2] = (byte)(value >> 8);
+ buffer[offset + 3] = (byte)(value >> 0);
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/QueryableHelpers.cs b/src/IOL.Helpers/QueryableHelpers.cs
new file mode 100644
index 0000000..00f422b
--- /dev/null
+++ b/src/IOL.Helpers/QueryableHelpers.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace IOL.Helpers;
+
+public static class QueryableHelpers
+{
+ public static IQueryable<T> ConditionalWhere<T>(
+ this IQueryable<T> source,
+ Func<bool> condition,
+ Expression<Func<T, bool>> predicate
+ ) {
+ return condition() ? source.Where(predicate) : source;
+ }
+
+ public static IQueryable<T> ConditionalWhere<T>(
+ this IQueryable<T> source,
+ bool condition,
+ Expression<Func<T, bool>> predicate
+ ) {
+ return condition ? source.Where(predicate) : source;
+ }
+}
diff --git a/src/IOL.Helpers/RandomStringGenerator.cs b/src/IOL.Helpers/RandomStringGenerator.cs
index 0d691db..2f39d67 100644
--- a/src/IOL.Helpers/RandomStringGenerator.cs
+++ b/src/IOL.Helpers/RandomStringGenerator.cs
@@ -1,18 +1,17 @@
using System;
using System.Linq;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class RandomString
{
- public static class RandomString
- {
- private static readonly Random _random = new Random();
+ private static readonly Random _random = new();
- public static string Generate(int length, bool numeric = false) {
- var chars = numeric switch {
+ public static string Generate(int length, bool numeric = false) {
+ var chars = numeric switch {
false => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
true => "0123456789"
- };
- return new string(Enumerable.Repeat(chars, length).Select(s => s[_random.Next(s.Length)]).ToArray());
- }
+ };
+ return new string(Enumerable.Repeat(chars, length).Select(s => s[_random.Next(s.Length)]).ToArray());
}
-} \ No newline at end of file
+}
diff --git a/src/IOL.Helpers/SlugGenerator.cs b/src/IOL.Helpers/SlugGenerator.cs
index 3f53dd6..6e669c0 100644
--- a/src/IOL.Helpers/SlugGenerator.cs
+++ b/src/IOL.Helpers/SlugGenerator.cs
@@ -1,98 +1,98 @@
using System.Text;
-namespace IOL.Helpers
-{
- public static class Slug
- {
- public static string Generate(bool toLower, params string[] values) {
- return Create(string.Join("-", values), toLower);
- }
+namespace IOL.Helpers;
- /// <summary>
- /// Creates a slug.
- /// References:
- /// http://www.unicode.org/reports/tr15/tr15-34.html
- /// https://meta.stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696
- /// https://stackoverflow.com/questions/25259/how-do-you-include-a-webpage-title-as-part-of-a-webpage-url/25486#25486
- /// https://stackoverflow.com/questions/3769457/how-can-i-remove-accents-on-a-string
- /// </summary>
- /// <param name="value"></param>
- /// <param name="toLower"></param>
- /// <returns>Slugified string</returns>
- public static string Create(string value, bool toLower) {
- if (string.IsNullOrWhiteSpace(value))
- return value;
+public static class Slug
+{
+ public static string Generate(bool toLower, params string[] values) {
+ return Create(string.Join("-", values), toLower);
+ }
- var normalised = value.Normalize(NormalizationForm.FormKD);
+ /// <summary>
+ /// Creates a slug.
+ /// References:
+ /// http://www.unicode.org/reports/tr15/tr15-34.html
+ /// https://meta.stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696
+ /// https://stackoverflow.com/questions/25259/how-do-you-include-a-webpage-title-as-part-of-a-webpage-url/25486#25486
+ /// https://stackoverflow.com/questions/3769457/how-can-i-remove-accents-on-a-string
+ /// </summary>
+ /// <param name="value"></param>
+ /// <param name="toLower"></param>
+ /// <returns>Slugified string</returns>
+ public static string Create(string value, bool toLower) {
+ if (string.IsNullOrWhiteSpace(value))
+ return value;
- const int MAXLEN = 80;
- var len = normalised.Length;
- var prevDash = false;
- var sb = new StringBuilder(len);
+ var normalised = value.Normalize(NormalizationForm.FormKD);
- for (var i = 0; i < len; i++) {
- var c = normalised[i];
- switch (c) {
- case >= 'a' and <= 'z':
- case >= '0' and <= '9': {
- if (prevDash) {
- sb.Append('-');
- prevDash = false;
- }
+ const int MAXLEN = 80;
+ var len = normalised.Length;
+ var prevDash = false;
+ var sb = new StringBuilder(len);
- sb.Append(c);
- break;
+ for (var i = 0; i < len; i++) {
+ var c = normalised[i];
+ switch (c) {
+ case >= 'a' and <= 'z':
+ case >= '0' and <= '9': {
+ if (prevDash) {
+ sb.Append('-');
+ prevDash = false;
}
- case >= 'A' and <= 'Z': {
- if (prevDash) {
- sb.Append('-');
- prevDash = false;
- }
- // Tricky way to convert to lowercase
- if (toLower)
- sb.Append((char) (c | 32));
- else
- sb.Append(c);
- break;
+ sb.Append(c);
+ break;
+ }
+ case >= 'A' and <= 'Z': {
+ if (prevDash) {
+ sb.Append('-');
+ prevDash = false;
}
- case ' ':
- case ',':
- case '.':
- case '/':
- case '\\':
- case '-':
- case '_':
- case '=': {
- if (!prevDash && sb.Length > 0) {
- prevDash = true;
- }
- break;
+ // Tricky way to convert to lowercase
+ if (toLower)
+ sb.Append((char)(c | 32));
+ else
+ sb.Append(c);
+ break;
+ }
+ case ' ':
+ case ',':
+ case '.':
+ case '/':
+ case '\\':
+ case '-':
+ case '_':
+ case '=': {
+ if (!prevDash && sb.Length > 0) {
+ prevDash = true;
}
- default: {
- var swap = ConvertEdgeCases(c, toLower);
- if (swap != null) {
- if (prevDash) {
- sb.Append('-');
- prevDash = false;
- }
- sb.Append(swap);
+ break;
+ }
+ default: {
+ var swap = ConvertEdgeCases(c, toLower);
+ if (swap != null) {
+ if (prevDash) {
+ sb.Append('-');
+ prevDash = false;
}
- break;
+ sb.Append(swap);
}
- }
- if (sb.Length == MAXLEN)
break;
+ }
}
- return sb.ToString();
+ if (sb.Length == MAXLEN)
+ break;
}
- private static string ConvertEdgeCases(char c, bool toLower) => c switch {
+ return sb.ToString();
+ }
+
+ private static string ConvertEdgeCases(char c, bool toLower) => c switch {
'ı' => "i",
'ł' => "l",
'Ł' => toLower ? "l" : "L",
@@ -103,6 +103,5 @@ namespace IOL.Helpers
'æ' => "ae",
'Þ' => "th",
_ => null
- };
- }
-} \ No newline at end of file
+ };
+}
diff --git a/src/IOL.Helpers/StringHelpers.cs b/src/IOL.Helpers/StringHelpers.cs
index 6589df6..783d238 100644
--- a/src/IOL.Helpers/StringHelpers.cs
+++ b/src/IOL.Helpers/StringHelpers.cs
@@ -5,84 +5,83 @@ using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Configuration;
-namespace IOL.Helpers
-{
- public static class StringHelpers
- {
- public static bool IsNullOrWhiteSpace(this string value) {
- return string.IsNullOrWhiteSpace(value);
- }
+namespace IOL.Helpers;
- public static string Slugified(this string input) {
- return Slug.Generate(true, input);
- }
+public static class StringHelpers
+{
+ public static bool IsNullOrWhiteSpace(this string value) {
+ return string.IsNullOrWhiteSpace(value);
+ }
- public static bool HasValue(this string value) {
- return !value.IsNullOrWhiteSpace();
- }
+ public static string Slugified(this string input) {
+ return Slug.Generate(true, input);
+ }
- public static string UnicornFormat(this string input, IDictionary<string, string> values) {
- if (string.IsNullOrWhiteSpace(input)) return default;
- return values.Count == 0 ? default : values.Aggregate(input, (current, value1) => current.Replace("{" + value1.Key + "}", value1.Value));
- }
+ public static bool HasValue(this string value) {
+ return !value.IsNullOrWhiteSpace();
+ }
+ public static string UnicornFormat(this string input, IDictionary<string, string> values) {
+ if (string.IsNullOrWhiteSpace(input)) return default;
+ return values.Count == 0 ? default : values.Aggregate(input, (current, value1) => current.Replace("{" + value1.Key + "}", value1.Value));
+ }
- public static string UnicornFormatWithEnvironment(this string input, IConfiguration configuration) {
- if (string.IsNullOrWhiteSpace(input)) return default;
- var matchList = Regex.Matches(input, "{[a-z|_]*}", RegexOptions.IgnoreCase);
- foreach (var key in matchList.Select(match => match.Value)) {
- var value = configuration.GetValue<string>(key.Substring(1, key.Length - 2));
- if (string.IsNullOrWhiteSpace(value)) continue;
- input = input.Replace(key, value);
- }
- return input;
+ public static string UnicornFormatWithEnvironment(this string input, IConfiguration configuration) {
+ if (string.IsNullOrWhiteSpace(input)) return default;
+ var matchList = Regex.Matches(input, "{[a-z|_]*}", RegexOptions.IgnoreCase);
+ foreach (var key in matchList.Select(match => match.Value)) {
+ var value = configuration.GetValue<string>(key.Substring(1, key.Length - 2));
+ if (string.IsNullOrWhiteSpace(value)) continue;
+ input = input.Replace(key, value);
}
- public static Guid ToGuid(this string value) {
- return !Guid.TryParse(value, out var res) ? default : res;
- }
+ return input;
+ }
- public static string Base64Encode(this string text) {
- return Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
- }
+ public static Guid ToGuid(this string value) {
+ return !Guid.TryParse(value, out var res) ? default : res;
+ }
- public static string ExtractFileName(this string value) {
- if (value.IsNullOrWhiteSpace()) return default;
- var lastIndex = value.LastIndexOf('.');
- return lastIndex <= 0 ? default : value[..lastIndex];
- }
+ public static string Base64Encode(this string text) {
+ return Convert.ToBase64String(Encoding.UTF8.GetBytes(text));
+ }
- public static string ExtractExtension(this string value) {
- if (value.IsNullOrWhiteSpace()) return default;
- var lastIndex = value.LastIndexOf('.');
- return lastIndex <= 0 ? default : value.Substring(lastIndex);
- }
+ public static string ExtractFileName(this string value) {
+ if (value.IsNullOrWhiteSpace()) return default;
+ var lastIndex = value.LastIndexOf('.');
+ return lastIndex <= 0 ? default : value[..lastIndex];
+ }
- public static string Capitalize(this string input) {
- return input.IsNullOrWhiteSpace()
- ? input
- : Regex.Replace(input, @"\b(\w)", m => m.Value.ToUpper(), RegexOptions.None);
- }
+ public static string ExtractExtension(this string value) {
+ if (value.IsNullOrWhiteSpace()) return default;
+ var lastIndex = value.LastIndexOf('.');
+ return lastIndex <= 0 ? default : value.Substring(lastIndex);
+ }
+ public static string Capitalize(this string input) {
+ return input.IsNullOrWhiteSpace()
+ ? input
+ : Regex.Replace(input, @"\b(\w)", m => m.Value.ToUpper(), RegexOptions.None);
+ }
- /// <summary>
- /// Check if the given MIME is a JSON MIME.
- /// </summary>
- /// <param name="mime">MIME</param>
- /// <returns>Returns true if MIME type is json.</returns>
- public static bool IsJsonMime(this string mime) {
- var jsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$");
- return mime != null && (jsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json"));
- }
- public static string Obfuscate(this string value) {
- var last4Chars = "****";
- if (value.HasValue() && value.Length > 4) {
- last4Chars = value.Substring(value.Length - 4);
- }
+ /// <summary>
+ /// Check if the given MIME is a JSON MIME.
+ /// </summary>
+ /// <param name="mime">MIME</param>
+ /// <returns>Returns true if MIME type is json.</returns>
+ public static bool IsJsonMime(this string mime) {
+ var jsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$");
+ return mime != null && (jsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json"));
+ }
- return "****" + last4Chars;
+ public static string Obfuscate(this string value) {
+ var last4Chars = "****";
+ if (value.HasValue() && value.Length > 4) {
+ last4Chars = value.Substring(value.Length - 4);
}
+
+ return "****" + last4Chars;
}
}
diff --git a/src/IOL.Helpers/Validators.cs b/src/IOL.Helpers/Validators.cs
index d60afcf..a6937d6 100644
--- a/src/IOL.Helpers/Validators.cs
+++ b/src/IOL.Helpers/Validators.cs
@@ -1,18 +1,17 @@
using System.Net.Mail;
using System.Text.RegularExpressions;
-namespace IOL.Helpers
+namespace IOL.Helpers;
+
+public static class Validators
{
- public static class Validators
- {
- private static readonly Regex _norwegianPhoneNumber = new(@"^(0047|\+47|47)?[2-9]\d{7}$");
+ private static readonly Regex _norwegianPhoneNumber = new(@"^(0047|\+47|47)?[2-9]\d{7}$");
- public static bool IsValidEmailAddress(this string value) {
- return MailAddress.TryCreate(value, out _);
- }
+ public static bool IsValidEmailAddress(this string value) {
+ return MailAddress.TryCreate(value, out _);
+ }
- public static bool IsValidNorwegianPhoneNumber(this string value) {
- return _norwegianPhoneNumber.IsMatch(value);
- }
+ public static bool IsValidNorwegianPhoneNumber(this string value) {
+ return _norwegianPhoneNumber.IsMatch(value);
}
-} \ No newline at end of file
+}