2022-06-30 01:46:41 +02:00
|
|
|
|
using System.Globalization;
|
2017-08-11 23:06:31 +02:00
|
|
|
|
using System.Reflection;
|
2017-06-29 21:55:39 +02:00
|
|
|
|
using System.Security.Cryptography;
|
2017-01-13 00:35:26 +01:00
|
|
|
|
using System.Security.Cryptography.X509Certificates;
|
2017-06-29 21:55:39 +02:00
|
|
|
|
using System.Text;
|
2021-01-12 17:02:39 +01:00
|
|
|
|
using System.Text.Json;
|
2017-01-13 00:35:26 +01:00
|
|
|
|
using System.Text.RegularExpressions;
|
2018-03-22 18:18:18 +01:00
|
|
|
|
using System.Web;
|
2021-12-22 19:47:35 +01:00
|
|
|
|
using Azure;
|
|
|
|
|
using Azure.Storage.Blobs;
|
|
|
|
|
using Azure.Storage.Blobs.Models;
|
2018-12-20 04:27:45 +01:00
|
|
|
|
using Azure.Storage.Queues.Models;
|
2023-10-26 19:38:29 +02:00
|
|
|
|
using Bit.Core.AdminConsole.Context;
|
|
|
|
|
using Bit.Core.AdminConsole.Enums.Provider;
|
2023-04-14 19:25:56 +02:00
|
|
|
|
using Bit.Core.Auth.Enums;
|
2021-02-04 19:54:21 +01:00
|
|
|
|
using Bit.Core.Context;
|
2022-01-11 10:40:51 +01:00
|
|
|
|
using Bit.Core.Entities;
|
2019-07-11 02:05:07 +02:00
|
|
|
|
using Bit.Core.Enums;
|
2023-01-13 15:02:53 +01:00
|
|
|
|
using Bit.Core.Identity;
|
2020-11-10 21:15:29 +01:00
|
|
|
|
using Bit.Core.Settings;
|
|
|
|
|
using IdentityModel;
|
2021-06-30 09:35:26 +02:00
|
|
|
|
using Microsoft.AspNetCore.DataProtection;
|
2021-08-31 05:49:11 +02:00
|
|
|
|
using MimeKit;
|
2016-05-21 23:16:22 +02:00
|
|
|
|
|
|
|
|
|
namespace Bit.Core.Utilities;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2016-05-21 23:16:22 +02:00
|
|
|
|
public static class CoreHelpers
|
|
|
|
|
{
|
|
|
|
|
private static readonly long _baseDateTicks = new DateTime(1900, 1, 1).Ticks;
|
2017-07-14 15:05:15 +02:00
|
|
|
|
private static readonly DateTime _epoc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
2017-12-15 21:23:57 +01:00
|
|
|
|
private static readonly DateTime _max = new DateTime(9999, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
2017-07-28 06:17:31 +02:00
|
|
|
|
private static readonly Random _random = new Random();
|
2023-08-29 15:25:47 +02:00
|
|
|
|
private static readonly string RealConnectingIp = "X-Connecting-IP";
|
2024-02-06 19:30:37 +01:00
|
|
|
|
private static readonly Regex _whiteSpaceRegex = new Regex(@"\s+");
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2016-05-21 23:16:22 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Generate sequential Guid for Sql Server.
|
|
|
|
|
/// ref: https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Id/GuidCombGenerator.cs
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>A comb Guid.</returns>
|
|
|
|
|
public static Guid GenerateComb()
|
2022-05-10 23:12:09 +02:00
|
|
|
|
=> GenerateComb(Guid.NewGuid(), DateTime.UtcNow);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2022-05-10 23:12:09 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Implementation of <see cref="GenerateComb()" /> with input parameters to remove randomness.
|
|
|
|
|
/// This should NOT be used outside of testing.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// You probably don't want to use this method and instead want to use <see cref="GenerateComb()" /> with no parameters
|
|
|
|
|
/// </remarks>
|
|
|
|
|
internal static Guid GenerateComb(Guid startingGuid, DateTime time)
|
|
|
|
|
{
|
|
|
|
|
var guidArray = startingGuid.ToByteArray();
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2023-08-30 08:23:45 +02:00
|
|
|
|
// Get the days and milliseconds which will be used to build the byte string
|
2022-05-10 23:12:09 +02:00
|
|
|
|
var days = new TimeSpan(time.Ticks - _baseDateTicks);
|
|
|
|
|
var msecs = time.TimeOfDay;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2023-08-30 08:23:45 +02:00
|
|
|
|
// Convert to a byte array
|
|
|
|
|
// Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
|
2016-05-21 23:16:22 +02:00
|
|
|
|
var daysArray = BitConverter.GetBytes(days.Days);
|
|
|
|
|
var msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2023-08-30 08:23:45 +02:00
|
|
|
|
// Reverse the bytes to match SQL Servers ordering
|
2016-05-21 23:16:22 +02:00
|
|
|
|
Array.Reverse(daysArray);
|
|
|
|
|
Array.Reverse(msecsArray);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2023-08-30 08:23:45 +02:00
|
|
|
|
// Copy the bytes into the guid
|
2016-05-21 23:16:22 +02:00
|
|
|
|
Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
|
|
|
|
|
Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2016-05-21 23:16:22 +02:00
|
|
|
|
return new Guid(guidArray);
|
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2017-08-11 23:06:31 +02:00
|
|
|
|
public static string CleanCertificateThumbprint(string thumbprint)
|
|
|
|
|
{
|
2017-01-13 00:35:26 +01:00
|
|
|
|
// Clean possible garbage characters from thumbprint copy/paste
|
|
|
|
|
// ref http://stackoverflow.com/questions/8448147/problems-with-x509store-certificates-find-findbythumbprint
|
|
|
|
|
return Regex.Replace(thumbprint, @"[^\da-fA-F]", string.Empty).ToUpper();
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2017-01-14 18:47:44 +01:00
|
|
|
|
|
2017-08-07 17:24:16 +02:00
|
|
|
|
public static X509Certificate2 GetCertificate(string thumbprint)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-07 17:24:16 +02:00
|
|
|
|
thumbprint = CleanCertificateThumbprint(thumbprint);
|
|
|
|
|
|
2021-12-22 19:47:35 +01:00
|
|
|
|
X509Certificate2 cert = null;
|
|
|
|
|
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
|
2017-01-13 00:35:26 +01:00
|
|
|
|
certStore.Open(OpenFlags.ReadOnly);
|
2021-12-22 19:47:35 +01:00
|
|
|
|
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
|
|
|
|
|
if (certCollection.Count > 0)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-08-11 23:06:31 +02:00
|
|
|
|
cert = certCollection[0];
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-13 00:35:26 +01:00
|
|
|
|
certStore.Close();
|
2017-08-07 17:24:16 +02:00
|
|
|
|
return cert;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 19:47:35 +01:00
|
|
|
|
public static X509Certificate2 GetCertificate(string file, string password)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 23:06:31 +02:00
|
|
|
|
return new X509Certificate2(file, password);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-13 21:35:50 +01:00
|
|
|
|
public async static Task<X509Certificate2> GetEmbeddedCertificateAsync(string file, string password)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 23:06:31 +02:00
|
|
|
|
var assembly = typeof(CoreHelpers).GetTypeInfo().Assembly;
|
2020-03-27 19:36:37 +01:00
|
|
|
|
using (var s = assembly.GetManifestResourceStream($"Bit.Core.{file}"))
|
|
|
|
|
using (var ms = new MemoryStream())
|
2017-08-11 23:06:31 +02:00
|
|
|
|
{
|
2020-01-13 21:35:50 +01:00
|
|
|
|
await s.CopyToAsync(ms);
|
2017-08-11 23:06:31 +02:00
|
|
|
|
return new X509Certificate2(ms.ToArray(), password);
|
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-08-11 23:06:31 +02:00
|
|
|
|
|
2021-10-05 18:12:05 +02:00
|
|
|
|
public static string GetEmbeddedResourceContentsAsync(string file)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-10-05 18:12:05 +02:00
|
|
|
|
var assembly = Assembly.GetCallingAssembly();
|
|
|
|
|
var resourceName = assembly.GetManifestResourceNames().Single(n => n.EndsWith(file));
|
|
|
|
|
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
|
|
|
|
using (var reader = new StreamReader(stream))
|
|
|
|
|
{
|
|
|
|
|
return reader.ReadToEnd();
|
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2021-10-05 18:12:05 +02:00
|
|
|
|
|
2021-12-22 19:47:35 +01:00
|
|
|
|
public async static Task<X509Certificate2> GetBlobCertificateAsync(string connectionString, string container, string file, string password)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
|
|
|
|
try
|
2019-07-11 02:05:07 +02:00
|
|
|
|
{
|
2021-12-22 19:47:35 +01:00
|
|
|
|
var blobServiceClient = new BlobServiceClient(connectionString);
|
|
|
|
|
var containerRef2 = blobServiceClient.GetBlobContainerClient(container);
|
|
|
|
|
var blobRef = containerRef2.GetBlobClient(file);
|
|
|
|
|
|
|
|
|
|
using var memStream = new MemoryStream();
|
|
|
|
|
await blobRef.DownloadToAsync(memStream).ConfigureAwait(false);
|
|
|
|
|
return new X509Certificate2(memStream.ToArray(), password);
|
2019-07-11 02:05:07 +02:00
|
|
|
|
}
|
2017-03-23 05:17:34 +01:00
|
|
|
|
catch (RequestFailedException ex)
|
|
|
|
|
when (ex.ErrorCode == BlobErrorCode.ContainerNotFound || ex.ErrorCode == BlobErrorCode.BlobNotFound)
|
2017-01-14 18:47:44 +01:00
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2017-03-23 05:17:34 +01:00
|
|
|
|
catch (Exception)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-08-12 04:55:25 +02:00
|
|
|
|
|
2017-03-23 05:17:34 +01:00
|
|
|
|
public static long ToEpocMilliseconds(DateTime date)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-01-14 18:47:44 +01:00
|
|
|
|
return (long)Math.Round((date - _epoc).TotalMilliseconds, 0);
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
public static DateTime FromEpocMilliseconds(long milliseconds)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
return _epoc.AddMilliseconds(milliseconds);
|
2017-06-22 23:03:35 +02:00
|
|
|
|
}
|
2022-08-29 20:53:16 +02:00
|
|
|
|
|
2017-03-23 05:17:34 +01:00
|
|
|
|
public static long ToEpocSeconds(DateTime date)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-01-14 18:47:44 +01:00
|
|
|
|
return (long)Math.Round((date - _epoc).TotalSeconds, 0);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 05:17:34 +01:00
|
|
|
|
public static DateTime FromEpocSeconds(long seconds)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-03-23 05:17:34 +01:00
|
|
|
|
return _epoc.AddSeconds(seconds);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
public static string U2fAppIdUrl(GlobalSettings globalSettings)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
return string.Concat(globalSettings.BaseServiceUri.Vault, "/app-id.json");
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
public static string RandomString(int length, bool alpha = true, bool upper = true, bool lower = true,
|
|
|
|
|
bool numeric = true, bool special = false)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
return RandomString(length, RandomStringCharacters(alpha, upper, lower, numeric, special));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
public static string RandomString(int length, string characters)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
return new string(Enumerable.Repeat(characters, length).Select(s => s[_random.Next(s.Length)]).ToArray());
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
public static string SecureRandomString(int length, bool alpha = true, bool upper = true, bool lower = true,
|
|
|
|
|
bool numeric = true, bool special = false)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
return SecureRandomString(length, RandomStringCharacters(alpha, upper, lower, numeric, special));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-06-29 21:55:39 +02:00
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
// ref https://stackoverflow.com/a/8996788/1090359 with modifications
|
|
|
|
|
public static string SecureRandomString(int length, string characters)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
if (length < 0)
|
2017-06-29 21:55:39 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(length), "length cannot be less than zero.");
|
|
|
|
|
}
|
2017-06-29 21:55:39 +02:00
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
if ((characters?.Length ?? 0) == 0)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(characters), "characters invalid.");
|
|
|
|
|
}
|
2017-06-29 21:55:39 +02:00
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
const int byteSize = 0x100;
|
|
|
|
|
if (byteSize < characters.Length)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException(
|
|
|
|
|
string.Format("{0} may contain no more than {1} characters.", nameof(characters), byteSize),
|
|
|
|
|
nameof(characters));
|
2017-06-29 21:55:39 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var outOfRangeStart = byteSize - (byteSize % characters.Length);
|
|
|
|
|
using (var rng = RandomNumberGenerator.Create())
|
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
var sb = new StringBuilder();
|
2017-06-29 21:55:39 +02:00
|
|
|
|
var buffer = new byte[128];
|
|
|
|
|
while (sb.Length < length)
|
2022-08-29 21:53:48 +02:00
|
|
|
|
{
|
2020-03-27 19:36:37 +01:00
|
|
|
|
rng.GetBytes(buffer);
|
|
|
|
|
for (var i = 0; i < buffer.Length && sb.Length < length; ++i)
|
2017-06-29 21:55:39 +02:00
|
|
|
|
{
|
|
|
|
|
// Divide the byte into charSet-sized groups. If the random value falls into the last group and the
|
2020-03-27 19:36:37 +01:00
|
|
|
|
// last group is too small to choose from the entire allowedCharSet, ignore the value in order to
|
|
|
|
|
// avoid biasing the result.
|
|
|
|
|
if (outOfRangeStart <= buffer[i])
|
2017-06-29 21:55:39 +02:00
|
|
|
|
{
|
|
|
|
|
continue;
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2022-08-29 20:53:16 +02:00
|
|
|
|
|
2018-12-20 04:27:45 +01:00
|
|
|
|
sb.Append(characters[buffer[i] % characters.Length]);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2018-12-20 04:27:45 +01:00
|
|
|
|
return sb.ToString();
|
2017-06-29 21:55:39 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-07-01 05:01:41 +02:00
|
|
|
|
|
2017-07-28 06:17:31 +02:00
|
|
|
|
private static string RandomStringCharacters(bool alpha, bool upper, bool lower, bool numeric, bool special)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2020-03-27 19:36:37 +01:00
|
|
|
|
var characters = string.Empty;
|
|
|
|
|
if (alpha)
|
2017-07-28 06:17:31 +02:00
|
|
|
|
{
|
2022-08-29 21:53:48 +02:00
|
|
|
|
if (upper)
|
2017-07-28 06:17:31 +02:00
|
|
|
|
{
|
|
|
|
|
characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (lower)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-07-28 06:17:31 +02:00
|
|
|
|
characters += "abcdefghijklmnopqrstuvwxyz";
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2022-08-29 21:53:48 +02:00
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (numeric)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-01 05:01:41 +02:00
|
|
|
|
characters += "0123456789";
|
2017-07-28 06:17:31 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-01 05:01:41 +02:00
|
|
|
|
if (special)
|
|
|
|
|
{
|
|
|
|
|
characters += "!@#$%^*&";
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-07-01 05:01:41 +02:00
|
|
|
|
|
|
|
|
|
return characters;
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2017-07-01 05:01:41 +02:00
|
|
|
|
|
|
|
|
|
// ref: https://stackoverflow.com/a/11124118/1090359
|
|
|
|
|
// Returns the human-readable file size for an arbitrary 64-bit file size .
|
|
|
|
|
// The format is "0.## XB", ex: "4.2 KB" or "1.43 GB"
|
|
|
|
|
public static string ReadableBytesSize(long size)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-01 05:01:41 +02:00
|
|
|
|
// Get absolute value
|
|
|
|
|
var absoluteSize = (size < 0 ? -size : size);
|
|
|
|
|
|
|
|
|
|
// Determine the suffix and readable value
|
|
|
|
|
string suffix;
|
|
|
|
|
double readable;
|
|
|
|
|
if (absoluteSize >= 0x40000000) // 1 Gigabyte
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-07-01 05:01:41 +02:00
|
|
|
|
suffix = "GB";
|
|
|
|
|
readable = (size >> 20);
|
2017-07-10 20:30:12 +02:00
|
|
|
|
}
|
2017-08-08 23:27:01 +02:00
|
|
|
|
else if (absoluteSize >= 0x100000) // 1 Megabyte
|
2019-03-12 04:31:45 +01:00
|
|
|
|
{
|
2017-07-01 05:01:41 +02:00
|
|
|
|
suffix = "MB";
|
2019-03-12 04:31:45 +01:00
|
|
|
|
readable = (size >> 10);
|
|
|
|
|
}
|
|
|
|
|
else if (absoluteSize >= 0x400) // 1 Kilobyte
|
|
|
|
|
{
|
2017-07-01 05:01:41 +02:00
|
|
|
|
suffix = "KB";
|
2019-03-12 04:31:45 +01:00
|
|
|
|
readable = size;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return size.ToString("0 Bytes"); // Byte
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-29 21:55:39 +02:00
|
|
|
|
// Divide by 1024 to get fractional value
|
2017-07-01 05:01:41 +02:00
|
|
|
|
readable = (readable / 1024);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2017-07-01 05:01:41 +02:00
|
|
|
|
// Return formatted number with suffix
|
|
|
|
|
return readable.ToString("0.## ") + suffix;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-12-08 02:35:34 +01:00
|
|
|
|
/// <summary>
|
2017-08-08 23:27:01 +02:00
|
|
|
|
/// Creates a clone of the given object through serializing to json and deserializing.
|
|
|
|
|
/// This method is subject to the limitations of System.Text.Json. For example, properties with
|
2018-08-16 00:43:26 +02:00
|
|
|
|
/// inaccessible setters will not be set.
|
2020-12-08 02:35:34 +01:00
|
|
|
|
/// </summary>
|
2017-07-10 20:30:12 +02:00
|
|
|
|
public static T CloneObject<T>(T obj)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
return JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(obj));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 04:31:45 +01:00
|
|
|
|
public static bool SettingHasValue(string setting)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
var normalizedSetting = setting?.ToLowerInvariant();
|
|
|
|
|
return !string.IsNullOrWhiteSpace(normalizedSetting) && !normalizedSetting.Equals("secret") &&
|
2018-08-16 00:43:26 +02:00
|
|
|
|
!normalizedSetting.Equals("replace");
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 04:31:45 +01:00
|
|
|
|
public static string Base64EncodeString(string input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
return Convert.ToBase64String(Encoding.UTF8.GetBytes(input));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 04:31:45 +01:00
|
|
|
|
public static string Base64DecodeString(string input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
return Encoding.UTF8.GetString(Convert.FromBase64String(input));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-12 04:31:45 +01:00
|
|
|
|
public static string Base64UrlEncodeString(string input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
return Base64UrlEncode(Encoding.UTF8.GetBytes(input));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-11 16:04:59 +02:00
|
|
|
|
public static string Base64UrlDecodeString(string input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
return Encoding.UTF8.GetString(Base64UrlDecode(input));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 13:59:16 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Encodes a Base64 URL formatted string.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">Byte data</param>
|
|
|
|
|
/// <returns>Base64 URL formatted string</returns>
|
2017-08-11 16:04:59 +02:00
|
|
|
|
public static string Base64UrlEncode(byte[] input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2024-01-10 13:59:16 +01:00
|
|
|
|
// Standard base64 encoder
|
|
|
|
|
var standardB64 = Convert.ToBase64String(input);
|
|
|
|
|
return TransformToBase64Url(standardB64);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Transforms a Base64 standard formatted string to a Base64 URL formatted string.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">Base64 standard formatted string</param>
|
|
|
|
|
/// <returns>Base64 URL formatted string</returns>
|
|
|
|
|
public static string TransformToBase64Url(string input)
|
|
|
|
|
{
|
|
|
|
|
var output = input
|
2017-08-11 16:04:59 +02:00
|
|
|
|
.Replace('+', '-')
|
|
|
|
|
.Replace('/', '_')
|
|
|
|
|
.Replace("=", string.Empty);
|
|
|
|
|
return output;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 13:59:16 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Decodes a Base64 URL formatted string.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">Base64 URL formatted string</param>
|
|
|
|
|
/// <returns>Data as bytes</returns>
|
2020-03-27 19:36:37 +01:00
|
|
|
|
public static byte[] Base64UrlDecode(string input)
|
2024-01-10 13:59:16 +01:00
|
|
|
|
{
|
|
|
|
|
var standardB64 = TransformFromBase64Url(input);
|
|
|
|
|
// Standard base64 decoder
|
|
|
|
|
return Convert.FromBase64String(standardB64);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Transforms a Base64 URL formatted string to a Base64 standard formatted string.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input">Base64 URL formatted string</param>
|
|
|
|
|
/// <returns>Base64 standard formatted string</returns>
|
|
|
|
|
public static string TransformFromBase64Url(string input)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
var output = input;
|
|
|
|
|
// 62nd char of encoding
|
|
|
|
|
output = output.Replace('-', '+');
|
|
|
|
|
// 63rd char of encoding
|
|
|
|
|
output = output.Replace('_', '/');
|
|
|
|
|
// Pad with trailing '='s
|
2020-03-27 19:36:37 +01:00
|
|
|
|
switch (output.Length % 4)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
|
|
|
|
case 0:
|
2017-08-11 16:04:59 +02:00
|
|
|
|
// No pad chars in this case
|
2022-08-29 22:06:55 +02:00
|
|
|
|
break;
|
|
|
|
|
case 2:
|
2017-08-11 16:04:59 +02:00
|
|
|
|
// Two pad chars
|
|
|
|
|
output += "=="; break;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
case 3:
|
2017-08-11 16:04:59 +02:00
|
|
|
|
// One pad char
|
|
|
|
|
output += "="; break;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
default:
|
2017-08-11 16:04:59 +02:00
|
|
|
|
throw new InvalidOperationException("Illegal base64url string!");
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-10 13:59:16 +01:00
|
|
|
|
// Standard base64 string output
|
|
|
|
|
return output;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-08-31 05:49:11 +02:00
|
|
|
|
public static string PunyEncode(string text)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-08-31 05:49:11 +02:00
|
|
|
|
if (text == "")
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2019-03-12 04:31:45 +01:00
|
|
|
|
return "";
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
2022-08-29 21:53:48 +02:00
|
|
|
|
|
2019-03-12 04:31:45 +01:00
|
|
|
|
if (text == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-11 16:04:59 +02:00
|
|
|
|
if (!text.Contains("@"))
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
// Assume domain name or non-email address
|
|
|
|
|
var idn = new IdnMapping();
|
|
|
|
|
return idn.GetAscii(text);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-08-11 16:04:59 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Assume email address
|
|
|
|
|
return MailboxAddress.EncodeAddrspec(text);
|
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-08-11 16:04:59 +02:00
|
|
|
|
|
|
|
|
|
public static string FormatLicenseSignatureValue(object val)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
if (val == null)
|
|
|
|
|
{
|
|
|
|
|
return string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (val.GetType() == typeof(DateTime))
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
return ToEpocSeconds((DateTime)val).ToString();
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (val.GetType() == typeof(bool))
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-11 16:04:59 +02:00
|
|
|
|
return val.ToString().ToLowerInvariant();
|
|
|
|
|
}
|
2017-08-16 19:55:01 +02:00
|
|
|
|
|
2021-08-31 05:49:11 +02:00
|
|
|
|
if (val is PlanType planType)
|
|
|
|
|
{
|
2020-08-21 23:44:45 +02:00
|
|
|
|
return planType switch
|
2021-08-31 05:49:11 +02:00
|
|
|
|
{
|
|
|
|
|
PlanType.Free => "Free",
|
2020-08-21 23:44:45 +02:00
|
|
|
|
PlanType.FamiliesAnnually2019 => "FamiliesAnnually",
|
|
|
|
|
PlanType.TeamsMonthly2019 => "TeamsMonthly",
|
|
|
|
|
PlanType.TeamsAnnually2019 => "TeamsAnnually",
|
|
|
|
|
PlanType.EnterpriseMonthly2019 => "EnterpriseMonthly",
|
|
|
|
|
PlanType.EnterpriseAnnually2019 => "EnterpriseAnnually",
|
|
|
|
|
PlanType.Custom => "Custom",
|
|
|
|
|
_ => ((byte)planType).ToString(),
|
2021-08-31 05:49:11 +02:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return val.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
public static string SanitizeForEmail(string value, bool htmlEncode = true)
|
2017-08-16 19:55:01 +02:00
|
|
|
|
{
|
|
|
|
|
var cleanedValue = value.Replace("@", "[at]");
|
|
|
|
|
var regexOptions = RegexOptions.CultureInvariant |
|
2021-07-21 18:43:28 +02:00
|
|
|
|
RegexOptions.Singleline |
|
2017-08-16 19:55:01 +02:00
|
|
|
|
RegexOptions.IgnoreCase;
|
2021-07-21 18:43:28 +02:00
|
|
|
|
cleanedValue = Regex.Replace(cleanedValue, @"(\.\w)",
|
2017-08-16 19:55:01 +02:00
|
|
|
|
m => string.Concat("[dot]", m.ToString().Last()), regexOptions);
|
|
|
|
|
while (Regex.IsMatch(cleanedValue, @"((^|\b)(\w*)://)", regexOptions))
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-07-21 18:43:28 +02:00
|
|
|
|
cleanedValue = Regex.Replace(cleanedValue, @"((^|\b)(\w*)://)",
|
|
|
|
|
string.Empty, regexOptions);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-08-16 19:55:01 +02:00
|
|
|
|
return htmlEncode ? HttpUtility.HtmlEncode(cleanedValue) : cleanedValue;
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
2017-08-16 19:55:01 +02:00
|
|
|
|
|
2020-03-27 19:36:37 +01:00
|
|
|
|
public static string DateTimeToTableStorageKey(DateTime? date = null)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (date.HasValue)
|
2017-08-16 19:55:01 +02:00
|
|
|
|
{
|
|
|
|
|
date = date.Value.ToUniversalTime();
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-08-16 19:55:01 +02:00
|
|
|
|
date = DateTime.UtcNow;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 23:44:45 +02:00
|
|
|
|
return _max.Subtract(date.Value).TotalMilliseconds.ToString(CultureInfo.InvariantCulture);
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-16 19:55:01 +02:00
|
|
|
|
// ref: https://stackoverflow.com/a/27545010/1090359
|
|
|
|
|
public static Uri ExtendQuery(Uri uri, IDictionary<string, string> values)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-08-16 19:55:01 +02:00
|
|
|
|
var baseUri = uri.ToString();
|
2018-03-22 18:18:18 +01:00
|
|
|
|
var queryString = string.Empty;
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (baseUri.Contains("?"))
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2018-03-22 18:18:18 +01:00
|
|
|
|
var urlSplit = baseUri.Split('?');
|
|
|
|
|
baseUri = urlSplit[0];
|
|
|
|
|
queryString = urlSplit.Length > 1 ? urlSplit[1] : string.Empty;
|
2017-08-16 19:55:01 +02:00
|
|
|
|
}
|
2017-08-25 14:57:43 +02:00
|
|
|
|
|
2017-09-07 05:57:14 +02:00
|
|
|
|
var queryCollection = HttpUtility.ParseQueryString(queryString);
|
|
|
|
|
foreach (var kvp in values ?? new Dictionary<string, string>())
|
2017-08-25 14:57:43 +02:00
|
|
|
|
{
|
|
|
|
|
queryCollection[kvp.Key] = kvp.Value;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-07 05:57:14 +02:00
|
|
|
|
var uriKind = uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative;
|
|
|
|
|
if (queryCollection.Count == 0)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-09-07 05:57:14 +02:00
|
|
|
|
return new Uri(baseUri, uriKind);
|
2017-08-25 14:57:43 +02:00
|
|
|
|
}
|
2018-03-22 18:18:18 +01:00
|
|
|
|
return new Uri(string.Format("{0}?{1}", baseUri, queryCollection), uriKind);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-20 04:27:45 +01:00
|
|
|
|
public static string CustomProviderName(TwoFactorProviderType type)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2018-12-20 04:27:45 +01:00
|
|
|
|
return string.Concat("Custom_", type.ToString());
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-09-12 05:08:08 +02:00
|
|
|
|
|
Auth/PM-3275 - Changes to support TDE User without MP being able to Set a Password + misc refactoring (#3242)
* PM-3275 - Add new GetMasterPasswordPolicy endpoint which will allow authenticated clients to get an enabled MP org policy if it exists for the purposes of enforcing those policy requirements when setting a password.
* PM-3275 - AccountsController.cs - PostSetPasswordAsync - (1) Convert UserService.setPasswordAsync into new SetInitialMasterPasswordCommand (2) Refactor SetInitialMasterPasswordCommand to only accept post SSO users who are in the invited state
(3) Add TODOs for more cleanup work and more commands
* PM-3275 - Update AccountsControllerTests.cs to add new SetInitialMasterPasswordCommand
* PM-3275 - UserService.cs - Remove non implemented ChangePasswordAsync method
* PM-3275 - The new SetInitialMasterPasswordCommand leveraged the OrganizationService.cs AcceptUserAsync method so while I was in here I converted the AcceptUserAsync methods into a new AcceptOrgUserCommand.cs and turned the private method which accepted an existing org user public for use in the SetInitialMasterPasswordCommand
* PM-3275 - Dotnet format
* PM-3275 - Test SetInitialMasterPasswordCommand
* Dotnet format
* PM-3275 - In process AcceptOrgUserCommandTests.cs
* PM-3275 - Migrate changes from AC-244 / #3199 over into new AcceptOrgUserCommand
* PM-3275 - AcceptOrgUserCommand.cs - create data protector specifically for this command
* PM-3275 - Add TODO for renaming / removing overloading of methods to improve readability / clarity
* PM-3275 - AcceptOrgUserCommand.cs - refactor AcceptOrgUserAsync by OrgId to retrieve orgUser with _organizationUserRepository.GetByOrganizationAsync which gets a single user instead of a collection
* PM-3275 - AcceptOrgUserCommand.cs - update name in TODO for evaluation later
* PM-3275 / PM-1196 - (1) Slightly refactor SsoEmail2faSessionTokenable to provide public static GetTokenLifeTime() method for testing (2) Add missed tests to SsoEmail2faSessionTokenable in preparation for building tests for new OrgUserInviteTokenable.cs
* PM-3275 / PM-1196 - Removing SsoEmail2faSessionTokenable.cs changes + tests as I've handled that separately in a new PR (#3270) for newly created task PM-3925
* PM-3275 - ExpiringTokenable.cs - add clarifying comments to help distinguish between the Valid property and the TokenIsValid method.
* PM-3275 - Create OrgUserInviteTokenable.cs and add tests in OrgUserInviteTokenableTests.cs
* PM-3275 - OrganizationService.cs - Refactor Org User Invite methods to use new OrgUserInviteTokenable instead of manual creation of a token
* PM-3275 - OrgUserInviteTokenable.cs - clarify backwards compat note
* PM-3275 - AcceptOrgUserCommand.cs - Add TODOs + minor name refactor
* PM-3275 - AcceptOrgUserCommand.cs - replace method overloading with more easily readable names.
* PM-3275 - AcceptOrgUserCommand.cs - Update ValidateOrgUserInviteToken to add new token validation while maintaining backwards compatibility for 1 release.
* dotnet format
* PM-3275 - AcceptOrgUserCommand.cs - Move private method below where it is used
* PM-3275 - ServiceCollectionExtensions.cs - Must register IDataProtectorTokenFactory<OrgUserInviteTokenable> for new tokenable
* PM-3275 - OrgUserInviteTokenable needed access to global settings to set its token lifetime to the _globalSettings.OrganizationInviteExpirationHours value. Creating a factory seemed the most straightforward way to encapsulate the desired creation logic. Unsure if in the correct location in ServiceCollectionExtensions.cs but will figure that out later.
* PM-3275 - In process work of creating AcceptOrgUserCommandTests.cs
* PM-3275 - Remove no longer relevant AcceptOrgUser tests from OrganizationServiceTests.cs
* PM-3275 - Register OrgUserInviteTokenableFactory alongside tokenizer
* PM-3275 - AcceptOrgUserCommandTests.cs - AcceptOrgUserAsync basic test suite completed.
* PM-3275 - AcceptOrgUserCommandTests.cs - tweak test names
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Remove old tests from OrganizationServiceTests as no longer needed to reference (2) Add summary for SetupCommonAcceptOrgUserMocks (3) Get AcceptOrgUserByToken_OldToken_AcceptsUserAndVerifiesEmail passing
* PM-3275 - Create interface for OrgUserInviteTokenableFactory b/c that's the right thing to do + enables test substitution
* PM-3275 - AcceptOrgUserCommandTests.cs - (1) Start work on AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail (2) Create and use SetupCommonAcceptOrgUserByTokenMocks() (3) Create generic FakeDataProtectorTokenFactory for tokenable testing
* PM-3275 - (1) Get AcceptOrgUserByToken_NewToken_AcceptsUserAndVerifiesEmail test passing (2) Move FakeDataProtectorTokenFactory to own file
* PM-3275 - AcceptOrgUserCommandTests.cs - Finish up tests for AcceptOrgUserByTokenAsync
* PM-3275 - Add pseudo section comments
* PM-3275 - Clean up unused params on AcceptOrgUserByToken_EmailMismatch_ThrowsBadRequest test
* PM-3275 - (1) Tests written for AcceptOrgUserByOrgSsoIdAsync (2) Refactor happy path assertions into helper function AssertValidAcceptedOrgUser to reduce code duplication
* PM-3275 - Finish up testing AcceptOrgUserCommandTests.cs by adding tests for AcceptOrgUserByOrgIdAsync
* PM-3275 - Tweaking test naming to ensure consistency.
* PM-3275 - Bugfix - OrgUserInviteTokenableFactory implementation required when declaring singleton service in ServiceCollectionExtensions.cs
* PM-3275 - Resolve failing OrganizationServiceTests.cs
* dotnet format
* PM-3275 - PoliciesController.cs - GetMasterPasswordPolicy bugfix - for orgs without a MP policy, policy comes back as null and we should return notFound in that case.
* PM-3275 - Add PoliciesControllerTests.cs specifically for new GetMasterPasswordPolicy(...) endpoint.
* PM-3275 - dotnet format PoliciesControllerTests.cs
* PM-3275 - PoliciesController.cs - (1) Add tech debt task number (2) Properly flag endpoint as deprecated
* PM-3275 - Add new hasManageResetPasswordPermission property to ProfileResponseModel.cs primarily for sync so that we can condition client side if TDE user obtains elevated permissions
* PM-3275 - Fix AccountsControllerTests.cs
* PM-3275 - OrgUserInviteTokenable.cs - clarify TODO
* PM-3275 - AcceptOrgUserCommand.cs - Refactor token validation to use short circuiting to only run old token validation if new token validation fails.
* PM-3275 - OrgUserInviteTokenable.cs - (1) Add new static methods to centralize validation logic to avoid repetition (2) Add new token validation method so we can avoid having to pass in a full org user (and hitting the db to do so)
* PM-3275 - Realized that the old token validation was used in the PoliciesController.cs (existing user clicks invite link in email and goes to log in) and UserService.cs (user clicks invite link in email and registers for a new acct). Added tech debt item for cleaning up backwards compatibility in future.
* dotnet format
* PM-3275 - (1) AccountsController.cs - Update PostSetPasswordAsync SetPasswordRequestModel to allow null keys for the case where we have a TDE user who obtains elevated permissions - they already have a user public and user encrypted private key saved in the db. (2) AccountsControllerTests.cs - test PostSetPasswordAsync scenarios to ensure changes will work as expected.
* PM-3275 - PR review feedback - (1) set CurrentContext to private (2) Refactor GetProfile to use variables to improve clarity and simplify debugging.
* PM-3275 - SyncController.cs - PR Review Feedback - Set current context as private instead of protected.
* PM-3275 - CurrentContextExtensions.cs - PR Feedback - move parenthesis up from own line.
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - Replace unnecessary variable
* PM-3275 - SetInitialMasterPasswordCommandTests.cs - PR Feedback - Add expected outcome statement to test name
* PM-3275 - Set Initial Password command and tests - PR Feedback changes - (1) Rename orgIdentifier --> OrgSsoIdentifier for clarity (2) Update SetInitialMasterPasswordAsync to not allow null orgSsoId with explicit message saying this vs letting null org trigger invalid organization (3) Add test to cover this new scenario.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Move summary from implementation to interface to better respect standards and the fact that the interface is the more seen piece of code.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, rename AcceptOrgUserByTokenAsync -> AcceptOrgUserByEmailTokenAsync + replace generic name token with emailToken
* PM-3275 - OrganizationService.cs - Per PR feedback, remove dupe line
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove new lines in error messages for consistency.
* PM-3275 - SetInitialMasterPasswordCommand.cs - Per PR feedback, adjust formatting of constructor for improved readability.
* PM-3275 - CurrentContextExtensions.cs - Refactor AnyOrgUserHasManageResetPasswordPermission per PR feedback to remove unnecessary var.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, remove completed TODO
* PM-3275 - PoliciesController.cs - Per PR feedback, update GetByInvitedUser param to be guid instead of string.
* PM-3275 - OrgUserInviteTokenable.cs - per PR feedback, add tech debt item info.
* PM-3275 - AcceptOrgUserCommand.cs - Per PR feedback, use const purpose from tokenable instead of magic string.
* PM-3275 - Restore non duplicate line to fix tests
* PM-3275 - Per PR feedback, revert all sync controller changes as the ProfileResponseModel.organizations array has org objects which have permissions which have the ManageResetPassword permission. So, I have the information that I need clientside already to determine if the user has the ManageResetPassword in any org.
* PM-3275 - PoliciesControllerTests.cs - Update imports as the PoliciesController was moved under the admin console team's domain.
* PM-3275 - Resolve issues from merge conflict resolutions to get solution building.
* PM-3275 / PM-4633 - PoliciesController.cs - use orgUserId to look up user instead of orgId. Oops.
* Fix user service tests
* Resolve merge conflict
2023-11-02 16:02:25 +01:00
|
|
|
|
// TODO: PM-4142 - remove old token validation logic once 3 releases of backwards compatibility are complete
|
2021-09-23 12:36:08 +02:00
|
|
|
|
public static bool UserInviteTokenIsValid(IDataProtector protector, string token, string userEmail,
|
2021-07-21 18:43:28 +02:00
|
|
|
|
Guid orgUserId, IGlobalSettings globalSettings)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-07-21 18:43:28 +02:00
|
|
|
|
return TokenIsValid("OrganizationUserInvite", protector, token, userEmail, orgUserId,
|
2021-07-21 20:42:06 +02:00
|
|
|
|
globalSettings.OrganizationInviteExpirationHours);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-21 18:43:28 +02:00
|
|
|
|
public static bool TokenIsValid(string firstTokenPart, IDataProtector protector, string token, string userEmail,
|
|
|
|
|
Guid id, double expirationInHours)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-07-21 18:43:28 +02:00
|
|
|
|
var invalid = true;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
try
|
2021-07-21 18:43:28 +02:00
|
|
|
|
{
|
|
|
|
|
var unprotectedData = protector.Unprotect(token);
|
|
|
|
|
var dataParts = unprotectedData.Split(' ');
|
|
|
|
|
if (dataParts.Length == 4 && dataParts[0] == firstTokenPart &&
|
2019-06-11 23:17:23 +02:00
|
|
|
|
new Guid(dataParts[1]) == id &&
|
2021-07-21 18:43:28 +02:00
|
|
|
|
dataParts[2].Equals(userEmail, StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
var creationTime = FromEpocMilliseconds(Convert.ToInt64(dataParts[3]));
|
|
|
|
|
var expTime = creationTime.AddHours(expirationInHours);
|
|
|
|
|
invalid = expTime < DateTime.UtcNow;
|
|
|
|
|
}
|
2017-09-27 18:45:57 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
catch
|
|
|
|
|
{
|
2019-06-11 23:17:23 +02:00
|
|
|
|
invalid = true;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-11 23:17:23 +02:00
|
|
|
|
return !invalid;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-11-29 04:21:47 +01:00
|
|
|
|
|
2023-05-17 12:14:36 +02:00
|
|
|
|
public static string GetApplicationCacheServiceBusSubscriptionName(GlobalSettings globalSettings)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2017-11-29 04:21:47 +01:00
|
|
|
|
var subName = globalSettings.ServiceBus.ApplicationCacheSubscriptionName;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(subName))
|
|
|
|
|
{
|
2023-08-07 15:57:18 +02:00
|
|
|
|
var websiteInstanceId = Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID") ??
|
|
|
|
|
globalSettings.ServiceBus.WebSiteInstanceId;
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(websiteInstanceId))
|
2017-12-15 21:23:57 +01:00
|
|
|
|
{
|
|
|
|
|
throw new Exception("No service bus subscription name available.");
|
|
|
|
|
}
|
|
|
|
|
else
|
2017-11-29 04:21:47 +01:00
|
|
|
|
{
|
|
|
|
|
subName = $"{globalSettings.ProjectName.ToLower()}_{websiteInstanceId}";
|
2020-03-27 19:36:37 +01:00
|
|
|
|
if (subName.Length > 50)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-06-13 06:10:37 +02:00
|
|
|
|
subName = subName.Substring(0, 50);
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2017-11-29 04:21:47 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-13 06:10:37 +02:00
|
|
|
|
return subName;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2018-03-22 18:18:18 +01:00
|
|
|
|
|
|
|
|
|
public static string GetIpAddress(this Microsoft.AspNetCore.Http.HttpContext httpContext,
|
|
|
|
|
GlobalSettings globalSettings)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2018-03-22 18:18:18 +01:00
|
|
|
|
if (httpContext == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2018-05-24 22:53:07 +02:00
|
|
|
|
|
2023-08-29 15:25:47 +02:00
|
|
|
|
if (!globalSettings.SelfHosted && httpContext.Request.Headers.ContainsKey(RealConnectingIp))
|
2018-12-20 04:27:45 +01:00
|
|
|
|
{
|
2023-08-29 15:25:47 +02:00
|
|
|
|
return httpContext.Request.Headers[RealConnectingIp].ToString();
|
2018-12-20 04:27:45 +01:00
|
|
|
|
}
|
2021-02-11 20:39:13 +01:00
|
|
|
|
|
2019-06-11 23:17:23 +02:00
|
|
|
|
return httpContext.Connection?.RemoteIpAddress?.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool IsCorsOriginAllowed(string origin, GlobalSettings globalSettings)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-06-11 23:17:23 +02:00
|
|
|
|
return
|
|
|
|
|
// Web vault
|
2020-06-27 21:08:50 +02:00
|
|
|
|
origin == globalSettings.BaseServiceUri.Vault ||
|
|
|
|
|
// Safari extension origin
|
|
|
|
|
origin == "file://" ||
|
|
|
|
|
// Product website
|
2019-06-11 23:17:23 +02:00
|
|
|
|
(!globalSettings.SelfHosted && origin == "https://bitwarden.com");
|
|
|
|
|
}
|
2019-06-13 06:10:37 +02:00
|
|
|
|
|
|
|
|
|
public static X509Certificate2 GetIdentityServerCertificate(GlobalSettings globalSettings)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2019-06-13 06:10:37 +02:00
|
|
|
|
if (globalSettings.SelfHosted &&
|
|
|
|
|
SettingHasValue(globalSettings.IdentityServer.CertificatePassword)
|
2020-08-25 19:15:59 +02:00
|
|
|
|
&& File.Exists("identity.pfx"))
|
2019-06-13 06:10:37 +02:00
|
|
|
|
{
|
|
|
|
|
return GetCertificate("identity.pfx",
|
|
|
|
|
globalSettings.IdentityServer.CertificatePassword);
|
|
|
|
|
}
|
2019-09-03 20:08:08 +02:00
|
|
|
|
else if (SettingHasValue(globalSettings.IdentityServer.CertificateThumbprint))
|
|
|
|
|
{
|
|
|
|
|
return GetCertificate(
|
2020-03-27 19:36:37 +01:00
|
|
|
|
globalSettings.IdentityServer.CertificateThumbprint);
|
2019-09-03 20:08:08 +02:00
|
|
|
|
}
|
2020-06-27 21:08:50 +02:00
|
|
|
|
else if (!globalSettings.SelfHosted &&
|
|
|
|
|
SettingHasValue(globalSettings.Storage?.ConnectionString) &&
|
|
|
|
|
SettingHasValue(globalSettings.IdentityServer.CertificatePassword))
|
|
|
|
|
{
|
|
|
|
|
return GetBlobCertificateAsync(globalSettings.Storage.ConnectionString, "certificates",
|
|
|
|
|
"identity.pfx", globalSettings.IdentityServer.CertificatePassword).GetAwaiter().GetResult();
|
|
|
|
|
}
|
2020-08-25 19:15:59 +02:00
|
|
|
|
return null;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2020-08-25 19:15:59 +02:00
|
|
|
|
|
|
|
|
|
public static Dictionary<string, object> AdjustIdentityServerConfig(Dictionary<string, object> configDict,
|
|
|
|
|
string publicServiceUri, string internalServiceUri)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2020-08-25 19:15:59 +02:00
|
|
|
|
var dictReplace = new Dictionary<string, object>();
|
|
|
|
|
foreach (var item in configDict)
|
|
|
|
|
{
|
|
|
|
|
if (item.Key == "authorization_endpoint" && item.Value is string val)
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri(val);
|
|
|
|
|
dictReplace.Add(item.Key, string.Concat(publicServiceUri, uri.LocalPath));
|
|
|
|
|
}
|
|
|
|
|
else if ((item.Key == "jwks_uri" || item.Key.EndsWith("_endpoint")) && item.Value is string val2)
|
|
|
|
|
{
|
|
|
|
|
var uri = new Uri(val2);
|
|
|
|
|
dictReplace.Add(item.Key, string.Concat(internalServiceUri, uri.LocalPath));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-09-01 13:38:36 +02:00
|
|
|
|
foreach (var replace in dictReplace)
|
|
|
|
|
{
|
|
|
|
|
configDict[replace.Key] = replace.Value;
|
|
|
|
|
}
|
|
|
|
|
return configDict;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2020-11-10 21:15:29 +01:00
|
|
|
|
|
2023-08-28 02:20:01 +02:00
|
|
|
|
public static List<KeyValuePair<string, string>> BuildIdentityClaims(User user, ICollection<CurrentContextOrganization> orgs,
|
|
|
|
|
ICollection<CurrentContextProvider> providers, bool isPremium)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2020-11-11 16:56:22 +01:00
|
|
|
|
var claims = new List<KeyValuePair<string, string>>()
|
2020-11-10 21:15:29 +01:00
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
new(Claims.Premium, isPremium ? "true" : "false"),
|
|
|
|
|
new(JwtClaimTypes.Email, user.Email),
|
|
|
|
|
new(JwtClaimTypes.EmailVerified, user.EmailVerified ? "true" : "false"),
|
|
|
|
|
new(Claims.SecurityStamp, user.SecurityStamp),
|
2020-11-10 21:15:29 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(user.Name))
|
|
|
|
|
{
|
2020-11-11 16:56:22 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(JwtClaimTypes.Name, user.Name));
|
2020-11-10 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Orgs that this user belongs to
|
|
|
|
|
if (orgs.Any())
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2020-11-10 21:15:29 +01:00
|
|
|
|
foreach (var group in orgs.GroupBy(o => o.Type))
|
|
|
|
|
{
|
|
|
|
|
switch (group.Key)
|
|
|
|
|
{
|
|
|
|
|
case Enums.OrganizationUserType.Owner:
|
|
|
|
|
foreach (var org in group)
|
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.OrganizationOwner, org.Id.ToString()));
|
2020-11-10 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Enums.OrganizationUserType.Admin:
|
|
|
|
|
foreach (var org in group)
|
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.OrganizationAdmin, org.Id.ToString()));
|
2020-11-10 21:15:29 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
2021-01-12 17:02:39 +01:00
|
|
|
|
case Enums.OrganizationUserType.Manager:
|
|
|
|
|
foreach (var org in group)
|
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.OrganizationManager, org.Id.ToString()));
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
2020-11-10 21:15:29 +01:00
|
|
|
|
case Enums.OrganizationUserType.User:
|
|
|
|
|
foreach (var org in group)
|
2022-08-29 21:53:48 +02:00
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.OrganizationUser, org.Id.ToString()));
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
2020-11-10 21:15:29 +01:00
|
|
|
|
case Enums.OrganizationUserType.Custom:
|
|
|
|
|
foreach (var org in group)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.OrganizationCustom, org.Id.ToString()));
|
2021-10-05 18:12:05 +02:00
|
|
|
|
foreach (var (permission, claimName) in org.Permissions.ClaimsMap)
|
2022-08-29 21:53:48 +02:00
|
|
|
|
{
|
2021-10-05 18:12:05 +02:00
|
|
|
|
if (!permission)
|
2021-01-12 17:02:39 +01:00
|
|
|
|
{
|
2021-10-05 18:12:05 +02:00
|
|
|
|
continue;
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2021-10-05 18:12:05 +02:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(claimName, org.Id.ToString()));
|
2021-01-12 17:02:39 +01:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2021-01-12 17:02:39 +01:00
|
|
|
|
break;
|
2020-11-10 21:15:29 +01:00
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-01-31 18:38:53 +01:00
|
|
|
|
|
|
|
|
|
// Secrets Manager
|
|
|
|
|
foreach (var org in group)
|
|
|
|
|
{
|
|
|
|
|
if (org.AccessSecretsManager)
|
|
|
|
|
{
|
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.SecretsManagerAccess, org.Id.ToString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-10 21:15:29 +01:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2021-12-16 15:35:09 +01:00
|
|
|
|
|
2021-06-30 09:35:26 +02:00
|
|
|
|
if (providers.Any())
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-06-30 09:35:26 +02:00
|
|
|
|
foreach (var group in providers.GroupBy(o => o.Type))
|
|
|
|
|
{
|
|
|
|
|
switch (group.Key)
|
|
|
|
|
{
|
|
|
|
|
case ProviderUserType.ProviderAdmin:
|
|
|
|
|
foreach (var provider in group)
|
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.ProviderAdmin, provider.Id.ToString()));
|
2021-06-30 09:35:26 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ProviderUserType.ServiceUser:
|
|
|
|
|
foreach (var provider in group)
|
|
|
|
|
{
|
2023-01-13 15:02:53 +01:00
|
|
|
|
claims.Add(new KeyValuePair<string, string>(Claims.ProviderServiceUser, provider.Id.ToString()));
|
2021-06-30 09:35:26 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-01-12 17:02:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return claims;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-12 17:02:39 +01:00
|
|
|
|
public static T LoadClassFromJsonData<T>(string jsonData) where T : new()
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-01-12 17:02:39 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(jsonData))
|
|
|
|
|
{
|
|
|
|
|
return new T();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var options = new JsonSerializerOptions
|
2022-08-29 21:53:48 +02:00
|
|
|
|
{
|
2021-01-12 17:02:39 +01:00
|
|
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
|
|
|
};
|
2021-02-10 18:00:12 +01:00
|
|
|
|
|
2021-11-09 16:37:32 +01:00
|
|
|
|
return System.Text.Json.JsonSerializer.Deserialize<T>(jsonData, options);
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-11-09 16:37:32 +01:00
|
|
|
|
public static string ClassToJsonData<T>(T data)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-11-09 16:37:32 +01:00
|
|
|
|
var options = new JsonSerializerOptions
|
|
|
|
|
{
|
|
|
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return System.Text.Json.JsonSerializer.Serialize(data, options);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 18:00:12 +01:00
|
|
|
|
public static ICollection<T> AddIfNotExists<T>(this ICollection<T> list, T item)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-02-10 18:00:12 +01:00
|
|
|
|
if (list.Contains(item))
|
|
|
|
|
{
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
list.Add(item);
|
|
|
|
|
return list;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2021-07-07 16:49:59 +02:00
|
|
|
|
|
|
|
|
|
public static string DecodeMessageText(this QueueMessage message)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
2021-07-07 16:49:59 +02:00
|
|
|
|
var text = message?.MessageText;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(text))
|
2021-11-08 21:55:42 +01:00
|
|
|
|
{
|
2021-07-07 16:49:59 +02:00
|
|
|
|
return text;
|
2021-11-08 21:55:42 +01:00
|
|
|
|
}
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return Base64DecodeString(text);
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return text;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool FixedTimeEquals(string input1, string input2)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
return CryptographicOperations.FixedTimeEquals(
|
|
|
|
|
Encoding.UTF8.GetBytes(input1), Encoding.UTF8.GetBytes(input2));
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
|
|
|
|
|
public static string ObfuscateEmail(string email)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
if (email == null)
|
|
|
|
|
{
|
|
|
|
|
return email;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var emailParts = email.Split('@', StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
if (emailParts.Length != 2)
|
2022-08-29 20:53:16 +02:00
|
|
|
|
{
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
return email;
|
2022-08-29 20:53:16 +02:00
|
|
|
|
}
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
|
|
|
|
|
var username = emailParts[0];
|
2022-08-29 20:53:16 +02:00
|
|
|
|
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
if (username.Length < 2)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
return email;
|
2022-08-29 22:06:55 +02:00
|
|
|
|
}
|
2022-08-29 20:53:16 +02:00
|
|
|
|
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
|
sb.Append(emailParts[0][..2]);
|
|
|
|
|
for (var i = 2; i < emailParts[0].Length; i++)
|
2022-08-29 22:06:55 +02:00
|
|
|
|
{
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
sb.Append('*');
|
2022-08-29 21:53:48 +02:00
|
|
|
|
}
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
Families for Enterprise (#1714)
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Create common test infrastructure project
* Add helpers to further type PlanTypes
* Enable testing of ASP.net MVC controllers
Controller properties have all kinds of validations in the background.
In general, we don't user properties on our Controllers, so the easiest
way to allow for Autofixture-based testing of our Controllers is to just
omit setting all properties on them.
* Workaround for broken MemberAutoDataAttribute
https://github.com/AutoFixture/AutoFixture/pull/1164 shows that only
the first test case is pulled for this attribute.
This is a workaround that populates the provided parameters, left to
right, using AutoFixture to populate any remaining.
* WIP: Organization sponsorship flow
* Add Attribute to use the Bit Autodata dependency chain
BitAutoDataAttribute is used to mark a Theory as autopopulating
parameters.
Extract common attribute methods to to a helper class. Cannot
inherit a common base, since both require inheriting from different
Xunit base classes to work.
* WIP: scaffolding for families for enterprise sponsorship flow
* Fix broken tests
* Create sponsorship offer (#1688)
* Initial db work (#1687)
* Add organization sponsorship databases to all providers
* Generalize create and update for database, specialize in code
* Add PlanSponsorshipType to db model
* Write valid json for test entries
* Initial scaffolding of emails (#1686)
* Initial scaffolding of emails
* Work on adding models for FamilyForEnterprise emails
* Switch verbage
* Put preliminary copy in emails
* Skip test
* Families for enterprise/stripe integrations (#1699)
* Add PlanSponsorshipType to static store
* Add sponsorship type to token and creates sponsorship
* PascalCase properties
* Require sponsorship for remove
* Create subscription sponsorship helper class
* Handle Sponsored subscription changes
* Add sponsorship id to subscription metadata
* Make sponsoring references nullable
This state indicates that a sponsorship has lapsed, but was not able to
be reverted for billing reasons
* WIP: Validate and remove subscriptions
* Update sponsorships on organization and org user delete
* Add friendly name to organization sponsorship
* Add sponsorship available boolean to orgDetails
* Add sponsorship service to DI
* Use userId to find org users
* Send f4e offer email
* Simplify names of f4e mail messages
* Fix Stripe org default tax rates
* Universal sponsorship redeem api
* Populate user in current context
* Add product type to organization details
* Use upgrade path to change sponsorship
Sponsorships need to be annual to match the GB add-on charge rate
* Use organization and auth to find organization sponsorship
* Add resend sponsorship offer api endpoint
* Fix double email send
* Fix sponsorship upgrade options
* Add is sponsored item to subscription response
* Add sponsorship validation to upcoming invoice webhook
* Add sponsorship validation to upcoming invoice webhook
* Fix organization delete sponsorship hooks
* Test org sponsorship service
* Fix sproc
* Fix build error
* Update emails
* Fix tests
* Skip local test
* Add newline
* Fix stripe subscription update
* Finish emails
* Skip test
* Fix unit tests
* Remove unused variable
* Fix unit tests
* Switch to handlebars ifs
* Remove ending email
* Remove reconfirmation template
* Switch naming convention
* Switch naming convention
* Fix migration
* Update copy and links
* Switch to using Guid in the method
* Remove unneeded css styles
* Add sql files to Sql.sqlproj
* Removed old comments
* Made name more verbose
* Fix SQL error
* Move unit tests to service
* Fix sp
* Revert "Move unit tests to service"
This reverts commit 1185bf3ec8ca36ccd75717ed2463adf8885159a6.
* Do repository validation in service layer
* Fix tests
* Fix merge conflicts and remove TODO
* Remove unneeded models
* Fix spacing and formatting
* Switch Org -> Organization
* Remove single use variables
* Switch method name
* Fix Controller
* Switch to obfuscating email
* Fix unit tests
Co-authored-by: Justin Baur <admin@justinbaur.com>
2021-11-19 23:25:06 +01:00
|
|
|
|
return sb.Append('@')
|
|
|
|
|
.Append(emailParts[1])
|
|
|
|
|
.ToString();
|
2022-08-29 22:06:55 +02:00
|
|
|
|
|
2016-05-21 23:16:22 +02:00
|
|
|
|
}
|
2023-08-30 08:23:45 +02:00
|
|
|
|
|
|
|
|
|
public static string GetEmailDomain(string email)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(email))
|
|
|
|
|
{
|
|
|
|
|
var emailParts = email.Split('@', StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
if (emailParts.Length == 2)
|
|
|
|
|
{
|
|
|
|
|
return emailParts[1].Trim();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-02-06 19:30:37 +01:00
|
|
|
|
|
|
|
|
|
public static string ReplaceWhiteSpace(string input, string newValue)
|
|
|
|
|
{
|
|
|
|
|
return _whiteSpaceRegex.Replace(input, newValue);
|
|
|
|
|
}
|
2016-05-21 23:16:22 +02:00
|
|
|
|
}
|