Skip to content

Commit 817607b

Browse files
committed
Reimplement license with protobuf
1 parent 8019d07 commit 817607b

File tree

5 files changed

+71
-80
lines changed

5 files changed

+71
-80
lines changed

TIKSN.Framework.Core.Tests/Licensing/TestEntitlementsConverter.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Collections.Generic;
2+
using System.Linq;
3+
using Google.Protobuf;
24
using LanguageExt;
35
using LanguageExt.Common;
46
using TIKSN.Licensing;
@@ -61,7 +63,7 @@ public Validation<Error, TestLicenseEntitlements> Convert(
6163
}
6264
else
6365
{
64-
result.Salt = entitlements.Salt.ToArray();
66+
result.Salt = ByteString.CopyFrom([.. entitlements.Salt]);
6567
}
6668
}
6769

@@ -104,7 +106,7 @@ public Validation<Error, TestEntitlements> Convert(
104106
errors.Add(Error.New(314894957, "EmployeeId is invalid"));
105107
}
106108

107-
if (entitlementsData.Salt.Count == 0)
109+
if (entitlementsData.Salt.Length == 0)
108110
{
109111
errors.Add(Error.New(139152695, "Salt is missing"));
110112
}

TIKSN.Framework.Core/Licensing/ILicenseFactory.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
using System.Security.Cryptography.X509Certificates;
2+
using Google.Protobuf;
23
using LanguageExt;
34
using LanguageExt.Common;
45

56
namespace TIKSN.Licensing;
67

7-
#pragma warning disable S2326 // Unused type parameters should be removed
8-
9-
public interface ILicenseFactory<TEntitlements, TEntitlementsData>
10-
#pragma warning restore S2326 // Unused type parameters should be removed
8+
public interface ILicenseFactory<TEntitlements, TEntitlementsData> where TEntitlementsData : IMessage<TEntitlementsData>
119
{
1210
Validation<Error, License<TEntitlements>> Create(
1311
LicenseTerms terms,

TIKSN.Framework.Core/Licensing/LicenseFactory.cs

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
11
using System.Security.Cryptography.X509Certificates;
2+
using Google.Protobuf;
23
using LanguageExt;
34
using LanguageExt.Common;
45
using Microsoft.Extensions.DependencyInjection;
5-
using TIKSN.Serialization.Bond;
66
using static LanguageExt.Prelude;
77

88
namespace TIKSN.Licensing;
99

10-
public class LicenseFactory<TEntitlements, TEntitlementsData> : ILicenseFactory<TEntitlements, TEntitlementsData>
10+
public class LicenseFactory<TEntitlements, TEntitlementsData> : ILicenseFactory<TEntitlements, TEntitlementsData> where TEntitlementsData : IMessage<TEntitlementsData>
1111
{
12-
private readonly CompactBinaryBondDeserializer deserializer;
1312
private readonly IEntitlementsConverter<TEntitlements, TEntitlementsData> entitlementsConverter;
1413
private readonly ILicenseDescriptor<TEntitlements> licenseDescriptor;
15-
private readonly CompactBinaryBondSerializer serializer;
1614
private readonly IServiceProvider serviceProvider;
1715
private readonly TimeProvider timeProvider;
1816

1917
public LicenseFactory(
20-
CompactBinaryBondSerializer serializer,
21-
CompactBinaryBondDeserializer deserializer,
2218
ILicenseDescriptor<TEntitlements> licenseDescriptor,
2319
IEntitlementsConverter<TEntitlements, TEntitlementsData> entitlementsConverter,
2420
TimeProvider timeProvider,
2521
IServiceProvider serviceProvider)
2622
{
27-
this.serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
28-
this.deserializer = deserializer ?? throw new ArgumentNullException(nameof(deserializer));
2923
this.licenseDescriptor = licenseDescriptor ?? throw new ArgumentNullException(nameof(licenseDescriptor));
3024
this.entitlementsConverter = entitlementsConverter ?? throw new ArgumentNullException(nameof(entitlementsConverter));
3125
this.timeProvider = timeProvider ?? throw new ArgumentNullException(nameof(timeProvider));
@@ -49,8 +43,7 @@ public Validation<Error, License<TEntitlements>> Create(
4943

5044
_ = this.entitlementsConverter.Convert(entitlements)
5145
.Match(
52-
succ => envelope.Message.Entitlements =
53-
new ArraySegment<byte>(this.serializer.Serialize(succ)),
46+
succ => envelope.Message.Entitlements = succ.ToByteString(),
5447
fail => errors.AddRange(fail));
5548

5649
if (!privateCertificate.HasPrivateKey)
@@ -63,15 +56,15 @@ public Validation<Error, License<TEntitlements>> Create(
6356
return errors.ToSeq();
6457
}
6558

66-
var messageData = this.serializer.Serialize(envelope.Message);
59+
var messageData = envelope.Message.ToByteString();
6760

6861
var keyAlgorithm = privateCertificate.GetKeyAlgorithm();
6962
envelope.SignatureAlgorithm = keyAlgorithm;
7063
var signatureService = this.serviceProvider.GetRequiredKeyedService<ICertificateSignatureService>(keyAlgorithm);
71-
var signature = signatureService.Sign(messageData, privateCertificate);
72-
envelope.Signature = new ArraySegment<byte>(signature);
64+
var signature = signatureService.Sign(messageData.ToByteArray(), privateCertificate);
65+
envelope.Signature = ByteString.CopyFrom(signature);
7366

74-
var envelopeData = this.serializer.Serialize(envelope);
67+
var envelopeData = envelope.ToByteString();
7568

7669
return new License<TEntitlements>(
7770
terms,
@@ -93,10 +86,14 @@ public Validation<Error, License<TEntitlements>> Create(
9386
return errors.ToSeq();
9487
}
9588

96-
var envelope = this.deserializer.Deserialize<LicenseEnvelope>([.. data]);
89+
var envelope = LicenseEnvelope.Parser.ParseFrom([.. data]);
9790

9891
var licenseTermsValidation = this.GetTerms(envelope, this.timeProvider);
99-
var entitlementsValidation = this.entitlementsConverter.Convert(this.deserializer.Deserialize<TEntitlementsData>([.. envelope.Message.Entitlements]));
92+
93+
var entitlementsData = Activator.CreateInstance<TEntitlementsData>();
94+
entitlementsData.MergeFrom(envelope.Message.Entitlements.CreateCodedInput());
95+
96+
var entitlementsValidation = this.entitlementsConverter.Convert(entitlementsData);
10097

10198
var keyAlgorithm = publicCertificate.GetKeyAlgorithm();
10299

@@ -107,9 +104,9 @@ public Validation<Error, License<TEntitlements>> Create(
107104

108105
var signatureService = this.serviceProvider.GetRequiredKeyedService<ICertificateSignatureService>(keyAlgorithm);
109106

110-
var messageData = this.serializer.Serialize(envelope.Message);
107+
var messageData = envelope.Message.ToByteArray();
111108

112-
if (!signatureService.Verify(messageData, [.. envelope.Signature], publicCertificate))
109+
if (!signatureService.Verify(messageData, envelope.Signature.ToByteArray(), publicCertificate))
113110
{
114111
errors.Add(Error.New(1311896038, "License signature is invalid"));
115112
}
@@ -133,12 +130,7 @@ private Validation<Error, LicenseTerms> GetTerms(
133130
{
134131
ArgumentNullException.ThrowIfNull(envelope);
135132

136-
if (envelope.Message.VersionNumber != 1)
137-
{
138-
return Error.New(2129266854, "License version is invalid");
139-
}
140-
141-
if (envelope.Message.Discriminator.Count != Guid.Empty.ToByteArray().Length ||
133+
if (envelope.Message.Discriminator.Count() != Guid.Empty.ToByteArray().Length ||
142134
envelope.Message.Discriminator.All(x => x == byte.MinValue) ||
143135
!envelope.Message.Discriminator.SequenceEqual(this.licenseDescriptor.Discriminator.ToByteArray()))
144136
{
@@ -193,14 +185,15 @@ private Validation<Error, LicenseEnvelope> Populate(
193185

194186
var errors = new List<Error>();
195187

196-
envelope.Message.VersionNumber = 1;
197-
198188
if (this.licenseDescriptor.Discriminator == Guid.Empty)
199189
{
200190
errors.Add(Error.New(13127674, "'Discriminator' should not be empty GUID"));
201191
}
202192

203-
envelope.Message.Discriminator = new ArraySegment<byte>(this.licenseDescriptor.Discriminator.ToByteArray());
193+
envelope.Message = new LicenseMessage
194+
{
195+
Discriminator = ByteString.CopyFrom(this.licenseDescriptor.Discriminator.ToByteArray()),
196+
};
204197

205198
if (terms.NotAfter < terms.NotBefore)
206199
{

TIKSN.Framework.Core/Licensing/LicenseFactoryTermsValidation.cs

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using System.Net.Mail;
2-
using Bond;
2+
using Google.Protobuf;
33
using LanguageExt;
44
using LanguageExt.Common;
55
using static LanguageExt.Prelude;
6+
using static TIKSN.Licensing.LicenseParty;
67

78
namespace TIKSN.Licensing;
89

@@ -40,19 +41,19 @@ internal static Validation<Error, DateTimeOffset> ConvertToDate(long dateTicks)
4041
private static readonly Seq<Ulid> InvalidSerialNumbers =
4142
Seq(Ulid.Empty, Ulid.MinValue, Ulid.MaxValue);
4243

43-
internal static Validation<Error, ArraySegment<byte>> ConvertFromUlid(Ulid serialNumber)
44+
internal static Validation<Error, ByteString> ConvertFromUlid(Ulid serialNumber)
4445
{
4546
if (InvalidSerialNumbers.Contains(serialNumber))
4647
{
4748
return Error.New(877535586, "Invalid serial number");
4849
}
4950

50-
return new ArraySegment<byte>(serialNumber.ToByteArray());
51+
return ByteString.CopyFrom(serialNumber.ToByteArray());
5152
}
5253

53-
internal static Validation<Error, Ulid> ConvertToUlid(ArraySegment<byte> serialNumberBytes)
54+
internal static Validation<Error, Ulid> ConvertToUlid(ByteString serialNumberBytes)
5455
{
55-
var serialNumber = new Ulid(serialNumberBytes);
56+
var serialNumber = new Ulid(serialNumberBytes.ToByteArray());
5657

5758
if (InvalidSerialNumbers.Contains(serialNumber))
5859
{
@@ -129,34 +130,31 @@ internal static Validation<Error, MailAddress> ConvertToMailAddress(string addre
129130

130131
#region Party
131132

132-
internal static Validation<Error, IBonded<LicenseParty>> ConvertFromParty(Party party) => party switch
133+
internal static Validation<Error, LicenseParty> ConvertFromParty(Party party) => party switch
133134
{
134-
IndividualParty individualParty => ConvertFromIndividual(individualParty).Map<IBonded<LicenseParty>>(x => new Bonded<LicenseIndividualParty>(x)),
135-
OrganizationParty organizationParty => ConvertFromOrganization(organizationParty).Map<IBonded<LicenseParty>>(x => new Bonded<LicenseOrganizationParty>(x)),
135+
IndividualParty individualParty => ConvertFromIndividual(individualParty),
136+
OrganizationParty organizationParty => ConvertFromOrganization(organizationParty),
136137
_ => Error.New(2143629281, "Invalid party type"),
137138
};
138139

139-
internal static Validation<Error, Party> ConvertToParty(IBonded<LicenseParty> licenseParty)
140-
{
141-
var licensePartyBase = licenseParty.Deserialize();
142-
return licensePartyBase.Kind switch
140+
internal static Validation<Error, Party> ConvertToParty(LicenseParty licenseParty) =>
141+
licenseParty.PartyKindCase switch
143142
{
144-
LicensePartyKind.Unknown => Error.New(2084794372, "Unknown party type"),
145-
LicensePartyKind.Individual => ConvertToIndividual(licenseParty.Deserialize<LicenseIndividualParty>()).Map<Party>(x => x),
146-
LicensePartyKind.Organization => ConvertToOrganization(licenseParty.Deserialize<LicenseOrganizationParty>()).Map<Party>(x => x),
143+
PartyKindOneofCase.None => Error.New(2084794372, "Unknown or No party type"),
144+
PartyKindOneofCase.IndividualParty => ConvertToIndividual(licenseParty).Map<Party>(x => x),
145+
PartyKindOneofCase.OrganizationParty => ConvertToOrganization(licenseParty).Map<Party>(x => x),
147146
_ => Error.New(103216125, "Invalid party type"),
148147
};
149-
}
150148

151-
private static Validation<Error, LicenseIndividualParty> ConvertFromIndividual(
149+
private static Validation<Error, LicenseParty> ConvertFromIndividual(
152150
IndividualParty individualParty)
153151
{
154152
ArgumentNullException.ThrowIfNull(individualParty);
155153

156154
var errors = new List<Error>();
157-
var result = new LicenseIndividualParty
155+
var result = new LicenseParty
158156
{
159-
Kind = LicensePartyKind.Individual,
157+
IndividualParty = new LicenseIndividualParty()
160158
};
161159

162160
if (string.IsNullOrWhiteSpace(individualParty.FirstName))
@@ -165,7 +163,7 @@ private static Validation<Error, LicenseIndividualParty> ConvertFromIndividual(
165163
}
166164
else
167165
{
168-
result.FirstName = individualParty.FirstName;
166+
result.IndividualParty.FirstName = individualParty.FirstName;
169167
}
170168

171169
if (string.IsNullOrWhiteSpace(individualParty.LastName))
@@ -174,16 +172,16 @@ private static Validation<Error, LicenseIndividualParty> ConvertFromIndividual(
174172
}
175173
else
176174
{
177-
result.LastName = individualParty.LastName;
175+
result.IndividualParty.LastName = individualParty.LastName;
178176
}
179177

180178
if (string.IsNullOrWhiteSpace(individualParty.FullName))
181179
{
182-
result.FullName = $"{individualParty.FirstName} {individualParty.LastName}";
180+
result.IndividualParty.FullName = $"{individualParty.FirstName} {individualParty.LastName}";
183181
}
184182
else
185183
{
186-
result.FullName = individualParty.FullName;
184+
result.IndividualParty.FullName = individualParty.FullName;
187185
}
188186

189187
SetBasePartyProperties(individualParty, errors, result);
@@ -196,15 +194,15 @@ private static Validation<Error, LicenseIndividualParty> ConvertFromIndividual(
196194
return result;
197195
}
198196

199-
private static Validation<Error, LicenseOrganizationParty> ConvertFromOrganization(
197+
private static Validation<Error, LicenseParty> ConvertFromOrganization(
200198
OrganizationParty organizationParty)
201199
{
202200
ArgumentNullException.ThrowIfNull(organizationParty);
203201

204202
var errors = new List<Error>();
205-
var result = new LicenseOrganizationParty
203+
var result = new LicenseParty
206204
{
207-
Kind = LicensePartyKind.Organization,
205+
OrganizationParty = new LicenseOrganizationParty()
208206
};
209207

210208
if (string.IsNullOrWhiteSpace(organizationParty.LongName))
@@ -213,7 +211,7 @@ private static Validation<Error, LicenseOrganizationParty> ConvertFromOrganizati
213211
}
214212
else
215213
{
216-
result.LongName = organizationParty.LongName;
214+
result.OrganizationParty.LongName = organizationParty.LongName;
217215
}
218216

219217
if (string.IsNullOrWhiteSpace(organizationParty.ShortName))
@@ -222,7 +220,7 @@ private static Validation<Error, LicenseOrganizationParty> ConvertFromOrganizati
222220
}
223221
else
224222
{
225-
result.ShortName = organizationParty.ShortName;
223+
result.OrganizationParty.ShortName = organizationParty.ShortName;
226224
}
227225

228226
SetBasePartyProperties(organizationParty, errors, result);
@@ -236,27 +234,27 @@ private static Validation<Error, LicenseOrganizationParty> ConvertFromOrganizati
236234
}
237235

238236
private static Validation<Error, IndividualParty> ConvertToIndividual(
239-
LicenseIndividualParty licenseIndividualParty)
237+
LicenseParty licenseParty)
240238
{
241-
ArgumentNullException.ThrowIfNull(licenseIndividualParty);
239+
ArgumentNullException.ThrowIfNull(licenseParty);
242240

243241
var errors = new List<Error>();
244242

245-
if (string.IsNullOrWhiteSpace(licenseIndividualParty.FirstName))
243+
if (string.IsNullOrWhiteSpace(licenseParty.IndividualParty.FirstName))
246244
{
247245
errors.Add(Error.New(1348133387, "First Name is missing"));
248246
}
249247

250-
if (string.IsNullOrWhiteSpace(licenseIndividualParty.LastName))
248+
if (string.IsNullOrWhiteSpace(licenseParty.IndividualParty.LastName))
251249
{
252250
errors.Add(Error.New(946047972, "Last Name is missing"));
253251
}
254252

255-
var fullName = string.IsNullOrWhiteSpace(licenseIndividualParty.FullName)
256-
? $"{licenseIndividualParty.FirstName} {licenseIndividualParty.LastName}"
257-
: licenseIndividualParty.FullName;
253+
var fullName = string.IsNullOrWhiteSpace(licenseParty.IndividualParty.FullName)
254+
? $"{licenseParty.IndividualParty.FirstName} {licenseParty.IndividualParty.LastName}"
255+
: licenseParty.IndividualParty.FullName;
258256

259-
var basePartyProperties = GetBasePartyProperties(licenseIndividualParty);
257+
var basePartyProperties = GetBasePartyProperties(licenseParty);
260258

261259
if (errors.Count != 0)
262260
{
@@ -265,31 +263,31 @@ private static Validation<Error, IndividualParty> ConvertToIndividual(
265263

266264
return basePartyProperties
267265
.Map(x => new IndividualParty(
268-
licenseIndividualParty.FirstName,
269-
licenseIndividualParty.LastName,
266+
licenseParty.IndividualParty.FirstName,
267+
licenseParty.IndividualParty.LastName,
270268
fullName,
271269
x.email,
272270
x.website));
273271
}
274272

275273
private static Validation<Error, OrganizationParty> ConvertToOrganization(
276-
LicenseOrganizationParty licenseOrganizationParty)
274+
LicenseParty licenseParty)
277275
{
278-
ArgumentNullException.ThrowIfNull(licenseOrganizationParty);
276+
ArgumentNullException.ThrowIfNull(licenseParty);
279277

280278
var errors = new List<Error>();
281279

282-
if (string.IsNullOrWhiteSpace(licenseOrganizationParty.LongName))
280+
if (string.IsNullOrWhiteSpace(licenseParty.OrganizationParty.LongName))
283281
{
284282
errors.Add(Error.New(1625517012, "Long Name is missing"));
285283
}
286284

287-
if (string.IsNullOrWhiteSpace(licenseOrganizationParty.ShortName))
285+
if (string.IsNullOrWhiteSpace(licenseParty.OrganizationParty.ShortName))
288286
{
289287
errors.Add(Error.New(280436811, "Short Name is missing"));
290288
}
291289

292-
var basePartyProperties = GetBasePartyProperties(licenseOrganizationParty);
290+
var basePartyProperties = GetBasePartyProperties(licenseParty);
293291

294292
if (errors.Count != 0)
295293
{
@@ -298,8 +296,8 @@ private static Validation<Error, OrganizationParty> ConvertToOrganization(
298296

299297
return basePartyProperties
300298
.Map(x => new OrganizationParty(
301-
licenseOrganizationParty.LongName,
302-
licenseOrganizationParty.ShortName,
299+
licenseParty.OrganizationParty.LongName,
300+
licenseParty.OrganizationParty.ShortName,
303301
x.email,
304302
x.website));
305303
}

0 commit comments

Comments
 (0)