Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extensions that support JSON serialization/deserialization. #44

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions src/Standard.Licensing.Tests/JsonSerializeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck <d.nauck(at)nauck-it.de>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using NUnit.Framework;

namespace Standard.Licensing.Tests
{
[TestFixture]
public class JsonSerializeTests
{
private string passPhrase;
private string privateKey;
private string publicKey;

[SetUp]
public void Init()
{
passPhrase = Guid.NewGuid().ToString();
var keyGenerator = Security.Cryptography.KeyGenerator.Create();
var keyPair = keyGenerator.GenerateKeyPair();
privateKey = keyPair.ToEncryptedPrivateKeyString(passPhrase);
publicKey = keyPair.ToPublicKeyString();
}

private static DateTime ConvertToRfc1123(DateTime dateTime)
{
return DateTime.ParseExact(
dateTime.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture)
, "r", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}


[Test]
public void Can_Generate_And_Validate_Signature_With_Empty_License()
{
var license = License.New()
.CreateAndSignWithPrivateKey(privateKey, passPhrase);

Assert.That(license, Is.Not.Null);
Assert.That(license.Signature, Is.Not.Null);

// validate json
var jsonText = license.ToJson();
Assert.That(jsonText, Is.Not.Empty);



// validate default values when not set
Assert.That(license.Id, Is.EqualTo(Guid.Empty));
Assert.That(license.Type, Is.EqualTo(LicenseType.Trial));
Assert.That(license.Quantity, Is.EqualTo(0));
Assert.That(license.ProductFeatures, Is.Null);
Assert.That(license.Customer, Is.Null);
Assert.That(license.Expiration, Is.EqualTo(ConvertToRfc1123(DateTime.MaxValue)));

// verify signature
Assert.That(license.VerifySignature(publicKey), Is.True);
}

[Test]
public void Can_Generate_And_Validate_Signature_With_Standard_License()
{
var licenseId = Guid.NewGuid();
var customerName = "Max Mustermann";
var customerEmail = "[email protected]";
var expirationDate = DateTime.Now.AddYears(1);
var productFeatures = new Dictionary<string, string>
{
{"Sales Module", "yes"},
{"Purchase Module", "yes"},
{"Maximum Transactions", "10000"}
};

var additionalAttributes = new Dictionary<string, string>
{
{"Domain", "test.com"},
{"Host", "172.17.0.1"}
};

var license = License.New()
.WithUniqueIdentifier(licenseId)
.As(LicenseType.Standard)
.WithMaximumUtilization(10)
.WithProductFeatures(productFeatures)
.WithAdditionalAttributes(additionalAttributes)
.LicensedTo(customerName, customerEmail)
.ExpiresAt(expirationDate)
.CreateAndSignWithPrivateKey(privateKey, passPhrase);

Assert.That(license, Is.Not.Null);
Assert.That(license.Signature, Is.Not.Null);


// validate json
var jsonText = license.ToJson();
Assert.That(jsonText, Is.Not.Empty);

var parsedLicense = jsonText.ToLicense();
Assert.That(parsedLicense, Is.Not.Null);


// validate default values when not set
Assert.That(parsedLicense.Id, Is.EqualTo(licenseId));
Assert.That(parsedLicense.Type, Is.EqualTo(LicenseType.Standard));
Assert.That(parsedLicense.Quantity, Is.EqualTo(10));
Assert.That(parsedLicense.ProductFeatures, Is.Not.Null);
Assert.That(parsedLicense.ProductFeatures.GetAll(), Is.EquivalentTo(productFeatures));
Assert.That(parsedLicense.Customer, Is.Not.Null);
Assert.That(parsedLicense.Customer.Name, Is.EqualTo(customerName));
Assert.That(parsedLicense.Customer.Email, Is.EqualTo(customerEmail));
Assert.That(parsedLicense.Expiration, Is.EqualTo(ConvertToRfc1123(expirationDate)));

// verify signature
Assert.That(parsedLicense.VerifySignature(publicKey), Is.True);
}



}
}
205 changes: 205 additions & 0 deletions src/Standard.Licensing/JsonSerializeExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck <d.nauck(at)nauck-it.de>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Xml.Linq;

namespace Standard.Licensing
{

/// <summary>
/// serialize as JSON / deserialize from JSON
/// </summary>
public static class JsonSerializeExtension
{
/// <summary>
/// serialize as JSON
/// </summary>
/// <param name="license">License instance</param>
/// <returns>JSON string</returns>
public static string ToJson(this License license)
{
try
{
var jsonObj = new LicenseModel
{
Id = license.Id,
Type = license.Type,
Quantity = license.Quantity,
Signature = license.Signature,
Expiration = license.Expiration
};

if (license.AdditionalAttributes != null)
{
jsonObj.AdditionalAttributes = license.AdditionalAttributes.GetAll();
}
if (license.Customer != null)
{
jsonObj.Customer = new Dictionary<string, string> {
{ "Name", license.Customer.Name },
{ "Company", license.Customer.Company },
{ "Email", license.Customer.Email }
};
}
if (license.ProductFeatures != null)
{
jsonObj.ProductFeatures = license.ProductFeatures.GetAll();
}

return JsonSerializer.Serialize(jsonObj);
}
catch (Exception)
{
return string.Empty;
}
}

/// <summary>
/// deserialize from JSON
/// </summary>
/// <param name="sourceString">JSON string</param>
/// <returns>License instance</returns>
public static License ToLicense(this string sourceString)
{
try
{
var jsonObj = JsonSerializer.Deserialize<LicenseModel>(sourceString);
var xml = new XElement("License");
xml.SetTag("Id", jsonObj.Id.ToString());
xml.SetTag("Type", jsonObj.Type.ToString());
xml.SetTag("Quantity", jsonObj.Quantity.ToString());

if (jsonObj.ProductFeatures != null)
{
var xmlFeatures = xml.Element("ProductFeatures");
if (xmlFeatures == null)
{
xml.Add(new XElement("ProductFeatures"));
}
xmlFeatures = xml.Element("ProductFeatures");
foreach (var item in jsonObj.ProductFeatures)
{
if (!string.IsNullOrEmpty(item.Value))
{
xmlFeatures.SetChildTag("Feature", item.Key, item.Value);
}
}
}





if (jsonObj.AdditionalAttributes != null)
{
var xmlAdditional = xml.Element("LicenseAttributes");
if (xmlAdditional == null)
{
xml.Add(new XElement("LicenseAttributes"));
}
xmlAdditional = xml.Element("LicenseAttributes");
foreach (var item in jsonObj.AdditionalAttributes)
{
if (!string.IsNullOrEmpty(item.Value))
{
xmlAdditional.SetChildTag("Attribute", item.Key, item.Value);
}
}
}

if (jsonObj.Customer != null)
{
var xmlCustomer = xml.Element("Customer");
if (xmlCustomer == null)
{
xml.Add(new XElement("Customer"));
}
xmlCustomer = xml.Element("Customer");
foreach (var item in jsonObj.Customer)
{
if (!string.IsNullOrEmpty(item.Value))
{
var node = new XElement(item.Key);
node.SetValue(item.Value);
xmlCustomer.Add(node);
}
}
}
xml.SetTag("Signature", jsonObj.Signature);
xml.SetTag("Expiration", jsonObj.Expiration.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture));


return new License(xml);
}
catch (Exception ex)
{
return null;
}
}


public static void SetTag(this XElement xmlData, string name, string value)
{
var element = xmlData.Element(name);

if (element == null)
{
element = new XElement(name);
xmlData.Add(element);
}

if (value != null)
element.Value = value;
}

public static string GetTag(this XElement xmlData, string name)
{
var element = xmlData.Element(name);
return element != null ? element.Value : null;
}

public static void SetChildTag(this XElement xmlData, string childName, string name, string value)
{
var element =
xmlData.Elements(childName)
.FirstOrDefault(e => e.Attribute("name") != null && e.Attribute("name").Value == name);

if (element == null)
{
element = new XElement(childName);
element.Add(new XAttribute("name", name));
xmlData.Add(element);
}

if (value != null)
element.Value = value;
}
}
}
44 changes: 44 additions & 0 deletions src/Standard.Licensing/LicenseModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright © 2012 - 2013 Nauck IT KG http://www.nauck-it.de
//
// Author:
// Daniel Nauck <d.nauck(at)nauck-it.de>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;

namespace Standard.Licensing
{
public class LicenseModel
{
public IDictionary<string, string> AdditionalAttributes { get; set; }
public IDictionary<string, string> Customer { get; set; }
public DateTime Expiration { get; set; }
public Guid Id { get; set; }
public IDictionary<string, string> ProductFeatures { get; set; }
public int Quantity { get; set; }
public string Signature { get; set; }
public LicenseType Type { get; set; }


}
}
Loading