| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 | using System;using System.Collections.Generic;using System.Diagnostics;using System.Diagnostics.CodeAnalysis;using System.IO;using System.Linq;namespace InABox.Core{    public static class LicenseUtils    {        #region License Generation        /// <summary>        /// Generate a new, out-of-the-box license.        /// </summary>        /// <returns>The new license, valid for 1 month.</returns>        public static LicenseData GenerateNewLicense()        {            return new LicenseData            {                LastRenewal = DateTime.Now,                Expiry = DateTime.Now.AddMonths(1),                CustomerID = Guid.Empty,                RenewalAvailable = DateTime.Now.AddMonths(1).AddDays(-7)            };        }        public static LicenseData RenewLicense(LicenseData oldLicense, DateTime renewed, DateTime newExpiry, DateTime renewAvailable)        {            return new LicenseData            {                LastRenewal = renewed,                Expiry = newExpiry,                CustomerID = oldLicense.CustomerID,                RenewalAvailable = renewAvailable            };        }        private static readonly byte[] LicenseKey = Convert.FromBase64String("dCyTyQkj1o1rqJJQlT+Jcnkxr+OQnO4KCoF/b+6cx54=");        /// <summary>        /// Encrypts the license data.        /// </summary>        /// <param name="license">The license to encrypt.</param>        /// <returns>        /// The encrypted data.        /// </returns>        public static string? EncryptLicense(LicenseData license)        {            return Encryption.EncryptV2(Serialization.Serialize(license), LicenseKey);        }        public static bool TryEncryptLicense(LicenseData license, [NotNullWhen(true)] out string? result, [NotNullWhen(false)] out string? error)        {            return Encryption.TryEncryptV2(Serialization.Serialize(license), LicenseKey, out result, out error);        }        /// <summary>        /// Decrypts <paramref name="license"/>.        /// </summary>        /// <param name="license">The license to decrypt.</param>        /// <returns>        /// The new license data, or <see langword="null"/> if errors occurred.        /// </returns>        public static bool TryDecryptLicense(string data, [NotNullWhen(true)] out LicenseData? result, [NotNullWhen(false)] out string? error)        {            if (!Encryption.TryDecryptV2(data, LicenseKey, out var decrypted, out error))            {                result = null;                return false;            }            result = Serialization.Deserialize<LicenseData>(decrypted);            if(result == null)            {                error = "License deserialization failed";                return false;            }            return true;        }        /// <summary>        /// Decrypts <paramref name="license"/>, throwing an <see cref="Exception"/> on fail.        /// </summary>        /// <param name="license">The license to decrypt.</param>        /// <returns>        /// The new license data.        /// </returns>        public static LicenseData DecryptLicense(string data)        {            if (!TryDecryptLicense(data, out var result, out var error))                throw new Exception(error);            return result;        }        #endregion        #region Fees & Discounts        private static readonly Dictionary<Type, double> _licensefees = new Dictionary<Type, double>();        private static readonly Dictionary<int, double> _periods = new Dictionary<int, double>();        private static readonly Dictionary<int, double> _userDiscounts = new Dictionary<int, double>();        public static double GetLicenseFee(Type type)        {            return _licensefees.GetValueOrDefault(type, 0);        }        public static double GetLicenseFee<T>() where T : LicenseToken        {            return GetLicenseFee(typeof(T));        }        public static IEnumerable<Type> LicenseTypes()        {            return _licensefees.Keys;        }        public static double GetUserDiscount(int users)        {            var key = _userDiscounts.Keys                .Where(x => x <= users)                .DefaultIfEmpty(-1)                .Max();            if (key == -1)                return 0;            return _userDiscounts[key];        }        public static double GetTimeDiscount(int months)        {            var period = _periods.Keys                .Where(x => x <= months)                .DefaultIfEmpty(-1)                .Max();            if (period == -1)                return 0;            return _periods[period];        }        public static IEnumerable<int> TimeDiscountLevels()        {            return _periods.Keys;        }        public static double CalculateLicenseFee(Dictionary<Type, int> licenses, int time)        {            double licensefee = 0.00F;            foreach (var license in licenses.Keys)                if (_licensefees.ContainsKey(license))                    licensefee += _licensefees[license] * licenses[license];            var users = licenses.Values.OrderBy(x => x).LastOrDefault();            var userdiscount = GetUserDiscount(users);            var timediscount = GetTimeDiscount(time);            var result = licensefee * ((100.0F - userdiscount) / 100.0F) * ((100.0F - timediscount) / 100.0F);            return result;        }        public static void LoadSummary(LicenseSummary summary)        {            _licensefees.Clear();            _periods.Clear();            _userDiscounts.Clear();            foreach (var license in summary.LicenseFees)                _licensefees[CoreUtils.GetEntity(license.Key)] = license.Value;            foreach (var (months, period) in summary.TimeDiscounts)                _periods[months] = period;            foreach (var (users, discount) in summary.UserDiscounts)                _userDiscounts[users] = discount;        }        /// <summary>        /// Gets a map from entities to their associated licenses.        /// </summary>        /// <returns>A map of entity types to license types.</returns>        public static Dictionary<Type, Type> LicenseMap()        {            var result = new Dictionary<Type, Type>();            var licenses = CoreUtils.TypeList(                AppDomain.CurrentDomain.GetAssemblies(),                myType =>                    myType.IsClass                    && !myType.IsAbstract                    && !myType.IsGenericType                    && myType.IsSubclassOf(typeof(LicenseToken))            ).ToArray();            var entities = CoreUtils.TypeList(                AppDomain.CurrentDomain.GetAssemblies(),                myType =>                    myType.IsClass                    && !myType.IsAbstract                    && !myType.IsGenericType                    && myType.IsSubclassOf(typeof(Entity))            ).ToArray();            foreach (var entity in entities)            {                var lic = entity.GetInterfaces()                    .FirstOrDefault(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(ILicense<>));                result[entity] = lic?.GenericTypeArguments.FirstOrDefault();            }            return result;        }        public static void SaveLicenseSummary(string filename)        {            var entitymap = LicenseMap();            var summary = new List<string> { "\"License Token\",\"Class Name\"" };            foreach (var mapentry in entitymap.OrderBy(x => x.Value))                summary.Add(string.Format("\"{0}\",\"{1}\"", mapentry.Value?.GetCaption(), mapentry.Value.EntityName()));            File.WriteAllLines(filename, summary.ToArray());        }        public static void Reset()        {            _licensefees.Clear();            _periods.Clear();            _userDiscounts.Clear();        }        #endregion    }    public class LicenseSummary    {        public LicenseSummary()        {            LicenseFees = new Dictionary<string, double>();            TimeDiscounts = new Dictionary<int, double>();            UserDiscounts = new Dictionary<int, double>();        }        public Dictionary<string, double> LicenseFees { get; set; }        public Dictionary<int, double> TimeDiscounts { get; set; }        public Dictionary<int, double> UserDiscounts { get; set; }    }}
 |