2using System.Collections.Generic;
4using System.Runtime.ExceptionServices;
6using System.Text.RegularExpressions;
7using System.Threading.Tasks;
33 internal static readonly Regex FromSaveUnsavedRegex =
new Regex(
@"Waher[.]Persistence[.]Files[.]ObjectBTreeFile[.+]((<SaveUnsaved>\w*[.]\w*)|(SaveUnsavedLocked))",
34 RegexOptions.Compiled | RegexOptions.Singleline);
35 internal static readonly Regex FromUpdateObjectRegex =
new Regex(
@"Waher[.]Persistence[.]Files[.]ObjectBTreeFile[.+]((<UpdateObject>\w*[.]\w*)|(UpdateObjectLocked))",
36 RegexOptions.Compiled | RegexOptions.Singleline);
37 internal static readonly Regex GatewayStartupRegex =
new Regex(
@"Waher[.]IoTGateway[.]Gateway([.]Start|[.+]<Start>\w*[.]\w*)",
38 RegexOptions.Compiled | RegexOptions.Singleline);
39 internal static readonly Regex ApplyLegalIdentityRegex =
new Regex(
@"Waher[.]IoTGateway[.]Setup[.]LegalIdentityConfiguration([.]ApplyLegalIdentity|[.+]<ApplyLegalIdentity>\w*[.]\w*)",
40 RegexOptions.Compiled | RegexOptions.Singleline);
41 internal static readonly Regex ApplyIdRegex =
new Regex(
@"Waher[.]IoTGateway[.]Setup[.]LegalIdentityConfiguration([.]ApplyId|[.+]<ApplyId>\w*[.]\w*)",
42 RegexOptions.Compiled | RegexOptions.Singleline);
43 internal static readonly Regex GenerateNewKeysRegex =
new Regex(
@"Waher[.]Networking[.]XMPP[.]Contracts[.]ContractsClient([.]GenerateNewKeys|[.+]<GenerateNewKeys>\w*[.]\w*)",
44 RegexOptions.Compiled | RegexOptions.Singleline);
45 internal static readonly Regex GetAttachmentRegex =
new Regex(
@"Waher[.]Networking[.]XMPP[.]Contracts[.]ContractsClient[.+]<GetAttachmentAsync>\w*[.]\w*",
46 RegexOptions.Compiled | RegexOptions.Singleline);
47 private static readonly
object[] approvedSources =
new object[]
49 "Waher.Persistence.NeuroLedger.NeuroLedgerProvider",
50 typeof(Content.Markdown.Web.MarkdownToHtmlConverter),
51 "Waher.IoTGateway.Setup.LegalIdentityConfiguration.UpdateClients",
53 FromUpdateObjectRegex,
56 private static readonly
object[] approvedContractClientSources =
new object[]
58 "Waher.Service.IoTBroker.Legal.MFA.QuickLogin",
59 "Waher.Service.IoTBroker.Marketplace.MarketplaceProcessor",
60 "Waher.Service.Abc4Io.Model.Actions.Contract.SignContract",
61 ApplyLegalIdentityRegex,
75 private bool useLegalIdentity =
false;
76 private bool protectWithPassword =
false;
77 private string firstName =
string.Empty;
78 private string middleName =
string.Empty;
79 private string lastName =
string.Empty;
80 private string personalNumber =
string.Empty;
81 private string address =
string.Empty;
82 private string address2 =
string.Empty;
83 private string postalCode =
string.Empty;
84 private string area =
string.Empty;
85 private string city =
string.Empty;
86 private string region =
string.Empty;
87 private string country =
string.Empty;
88 private string nationality =
string.Empty;
89 private string gender =
string.Empty;
90 private string orgName =
string.Empty;
91 private string orgDepartment =
string.Empty;
92 private string orgRole =
string.Empty;
93 private string orgNumber =
string.Empty;
94 private string orgAddress =
string.Empty;
95 private string orgAddress2 =
string.Empty;
96 private string orgPostalCode =
string.Empty;
97 private string orgArea =
string.Empty;
98 private string orgCity =
string.Empty;
99 private string orgRegion =
string.Empty;
100 private string orgCountry =
string.Empty;
103 private DateTime checkApprovedExpiry = DateTime.MinValue;
104 private DateTime? birthDate =
null;
121 [DefaultValue(
false)]
124 get => this.useLegalIdentity;
125 set => this.useLegalIdentity = value;
131 [DefaultValueStringEmpty]
134 get => this.firstName;
135 set => this.firstName = value;
141 [DefaultValueStringEmpty]
144 get => this.middleName;
145 set => this.middleName = value;
151 [DefaultValueStringEmpty]
154 get => this.lastName;
155 set => this.lastName = value;
161 [DefaultValueStringEmpty]
164 get => this.personalNumber;
165 set => this.personalNumber = value;
171 [DefaultValueStringEmpty]
175 set => this.address = value;
181 [DefaultValueStringEmpty]
184 get => this.address2;
185 set => this.address2 = value;
191 [DefaultValueStringEmpty]
194 get => this.postalCode;
195 set => this.postalCode = value;
201 [DefaultValueStringEmpty]
205 set => this.area = value;
211 [DefaultValueStringEmpty]
215 set => this.city = value;
221 [DefaultValueStringEmpty]
225 set => this.region = value;
231 [DefaultValueStringEmpty]
235 set => this.country = value;
241 [DefaultValueStringEmpty]
244 get => this.nationality;
245 set => this.nationality = value;
251 [DefaultValueStringEmpty]
255 set => this.gender = value;
264 get => this.birthDate;
265 set => this.birthDate = value;
271 [DefaultValueStringEmpty]
275 set => this.orgName = value;
281 [DefaultValueStringEmpty]
284 get => this.orgDepartment;
285 set => this.orgDepartment = value;
291 [DefaultValueStringEmpty]
295 set => this.orgRole = value;
301 [DefaultValueStringEmpty]
304 get => this.orgNumber;
305 set => this.orgNumber = value;
311 [DefaultValueStringEmpty]
314 get => this.orgAddress;
315 set => this.orgAddress = value;
321 [DefaultValueStringEmpty]
324 get => this.orgAddress2;
325 set => this.orgAddress2 = value;
331 [DefaultValueStringEmpty]
334 get => this.orgPostalCode;
335 set => this.orgPostalCode = value;
341 [DefaultValueStringEmpty]
345 set => this.orgArea = value;
351 [DefaultValueStringEmpty]
355 set => this.orgCity = value;
361 [DefaultValueStringEmpty]
364 get => this.orgRegion;
365 set => this.orgRegion = value;
371 [DefaultValueStringEmpty]
374 get => this.orgCountry;
375 set => this.orgCountry = value;
384 get => this.altFields;
385 set => this.altFields = value;
391 [DefaultValue(
false)]
394 get => this.protectWithPassword;
397 if (this.protectWithPassword != value)
399 if (this.protectWithPassword)
402 this.protectWithPassword = value;
415 if (!(this.passwordHashes is
null))
418 return this.passwordHashes;
423 if (!(this.passwordHashes is
null))
426 this.passwordHashes = value;
433 public override string Resource =>
"/Settings/LegalIdentity.md";
465 await this.AddHandlers();
468 private async Task AddHandlers()
472 this.handlersAdded =
true;
475 Gateway.XmppClient.OnStateChanged += this.XmppClient_OnStateChanged;
477 Gateway.ContractsClient.ContractDeleted += this.ContractsClient_ContractDeleted;
478 Gateway.ContractsClient.ContractSigned += this.ContractsClient_ContractSigned;
479 Gateway.ContractsClient.ContractUpdated += this.ContractsClient_ContractUpdated;
480 Gateway.ContractsClient.IdentityUpdated += this.ContractsClient_IdentityUpdated;
481 Gateway.ContractsClient.PetitionedIdentityResponseReceived += this.ContractsClient_PetitionedIdentityResponseReceived;
482 Gateway.ContractsClient.PetitionedContractResponseReceived += this.ContractsClient_PetitionedContractResponseReceived;
487 await this.GetLegalIdentities();
491 private bool handlersAdded =
false;
494 private async Task XmppClient_OnStateChanged(
object Sender,
XmppState NewState)
497 await this.GetLegalIdentities();
500 private Task GetLegalIdentities()
503 return Task.CompletedTask;
509 approvedIdentities = this.SetLegalIdentities(e.Identities, null, false);
510 allIdentities = this.SetLegalIdentities(e.Identities, null, true);
513 return Task.CompletedTask;
520 List<LegalIdentity> Result =
new List<LegalIdentity>();
524 if (!(Identities is
null))
528 if (Changed is
null || ID.
Id != Changed.
Id)
544 Result.Sort((i1, i2) => Math.Sign((i2.Created - i1.Created).Ticks));
546 return Result.ToArray();
557 return allIdentities;
568 List<Dictionary<string, object>> Result =
new List<Dictionary<string, object>>();
570 if (!(allIdentities is
null))
574 Dictionary<string, object> ID2 =
new Dictionary<string, object>()
577 {
"Created", ID.Created },
578 {
"Properties", ID.Properties },
579 {
"Attachments", ID.Attachments },
582 {
"State", ID.State },
583 {
"ADDR", string.Empty },
584 {
"ADDR2", string.Empty },
585 {
"ZIP", string.Empty },
586 {
"AREA", string.Empty },
587 {
"CITY", string.Empty },
588 {
"REGION", string.Empty },
589 {
"COUNTRY", string.Empty },
590 {
"NATIONALITY", string.Empty },
591 {
"GENDER", string.Empty },
592 {
"BDAY", string.Empty },
593 {
"BMONTH", string.Empty },
594 {
"BYEAR", string.Empty },
595 {
"FIRST", string.Empty },
596 {
"MIDDLE", string.Empty },
597 {
"LAST", string.Empty },
598 {
"PNR", string.Empty },
599 {
"ORGADDR", string.Empty },
600 {
"ORGADDR2", string.Empty },
601 {
"ORGZIP", string.Empty },
602 {
"ORGAREA", string.Empty },
603 {
"ORGCITY", string.Empty },
604 {
"ORGREGION", string.Empty },
605 {
"ORGCOUNTRY", string.Empty },
606 {
"ORGNAME", string.Empty },
607 {
"ORGDEPT", string.Empty },
608 {
"ORGROLE", string.Empty },
609 {
"ORGNR", string.Empty },
620 return Result.ToArray();
632 return approvedIdentities;
656 if (allIdentities is
null)
661 if (LegalId == ID.
Id)
678 if (approvedIdentities is
null)
683 if (LegalId == ID.
Id)
694 List<KeyValuePair<string, object>> Tags =
new List<KeyValuePair<string, object>>()
696 new KeyValuePair<string, object>(
"State", ID.
State),
697 new KeyValuePair<string, object>(
"Provider", ID.
Provider),
698 new KeyValuePair<string, object>(
"Created", ID.
Created),
699 new KeyValuePair<string, object>(
"Updated", ID.
Updated),
700 new KeyValuePair<string, object>(
"From", ID.
From),
701 new KeyValuePair<string, object>(
"KeyAlgorithm", ID.
ClientKeyName),
702 new KeyValuePair<string, object>(
"PublicKey", Convert.ToBase64String(ID.
ClientPubKey))
706 Tags.Add(
new KeyValuePair<string, object>(P.
Name, P.
Value));
710 await this.UpdateClients(ID);
715 allIdentities = this.SetLegalIdentities(allIdentities, ID,
true);
716 approvedIdentities = this.SetLegalIdentities(approvedIdentities, ID,
false);
718 return this.UpdateClients();
721 private async Task UpdateClients()
730 if (TabIDs.Length > 0)
732 string FileName = Path.Combine(
Gateway.
RootFolder,
"Settings",
"LegalIdentities.md");
733 if (File.Exists(FileName))
751 return Task.CompletedTask;
757 return Task.CompletedTask;
763 return Task.CompletedTask;
772 this.applyLegalIdentity = WebServer.
Register(
"/Settings/ApplyLegalIdentity",
null, this.ApplyLegalIdentity,
true,
false,
true);
773 this.contractAction = WebServer.
Register(
"/Settings/ContractAction",
null, this.ContractAction,
true,
false,
true);
775 this.checkApprovedExpiry =
Gateway.
ScheduleEvent(this.CheckApprovedExpiry, DateTime.Now.AddMinutes(5),
true);
777 return base.InitSetup(WebServer);
786 WebServer.
Unregister(this.applyLegalIdentity);
790 this.checkApprovedExpiry = DateTime.MinValue;
792 return base.UnregisterSetup(WebServer);
795 private async Task CheckApprovedExpiry(
object State)
797 if (!(State is
bool Reschedule))
800 DateTime Now = DateTime.Now;
801 DateTime Today = Now.Date;
804 this.checkApprovedExpiry =
Gateway.
ScheduleEvent(this.CheckApprovedExpiry, Today.AddDays(1).AddMinutes(5),
true);
806 if (!this.useLegalIdentity)
822 int Days = (int)(Expires - Today).TotalDays;
829 await
Gateway.
SendNotification(
"The approved Legal Identity for the gateway **expires today**.",
string.Empty);
833 await
Gateway.
SendNotification(
"The approved Legal Identity for the gateway **expires tomorrow**.",
string.Empty);
837 await
Gateway.
SendNotification(
"The approved Legal Identity for the gateway **expires in " + Days.ToString() +
" days**.",
string.Empty);
857 await this.AddHandlers();
859 return await base.SetupConfiguration(WebServer);
875 if (!(Obj is Dictionary<string, object> Parameters))
878 if (!Parameters.TryGetValue(
"protectWithPassword", out Obj) || !(Obj is
bool ProtectWithPassword) ||
879 !Parameters.TryGetValue(
"password", out Obj) || !(Obj is
string Password) ||
880 !Parameters.TryGetValue(
"password2", out Obj) || !(Obj is
string Password2) ||
881 !Parameters.TryGetValue(
"firstName", out Obj) || !(Obj is
string FirstName) ||
882 !Parameters.TryGetValue(
"middleName", out Obj) || !(Obj is
string MiddleName) ||
883 !Parameters.TryGetValue(
"lastName", out Obj) || !(Obj is
string LastName) ||
884 !Parameters.TryGetValue(
"pNr", out Obj) || !(Obj is
string PNr) ||
885 !Parameters.TryGetValue(
"address", out Obj) || !(Obj is
string Address) ||
886 !Parameters.TryGetValue(
"address2", out Obj) || !(Obj is
string Address2) ||
887 !Parameters.TryGetValue(
"postalCode", out Obj) || !(Obj is
string PostalCode) ||
888 !Parameters.TryGetValue(
"area", out Obj) || !(Obj is
string Area) ||
889 !Parameters.TryGetValue(
"city", out Obj) || !(Obj is
string City) ||
890 !Parameters.TryGetValue(
"region", out Obj) || !(Obj is
string Region) ||
891 !Parameters.TryGetValue(
"country", out Obj) || !(Obj is
string Country) ||
892 !Parameters.TryGetValue(
"nationality", out Obj) || !(Obj is
string Nationality) ||
893 !Parameters.TryGetValue(
"gender", out Obj) || !(Obj is
string Gender) ||
894 !Parameters.TryGetValue(
"birthDate", out Obj) || !(Obj is
string BirthDateStr) ||
895 !Parameters.TryGetValue(
"orgName", out Obj) || !(Obj is
string OrgName) ||
896 !Parameters.TryGetValue(
"orgDepartment", out Obj) || !(Obj is
string OrgDepartment) ||
897 !Parameters.TryGetValue(
"orgRole", out Obj) || !(Obj is
string OrgRole) ||
898 !Parameters.TryGetValue(
"orgNr", out Obj) || !(Obj is
string OrgNr) ||
899 !Parameters.TryGetValue(
"orgAddress", out Obj) || !(Obj is
string OrgAddress) ||
900 !Parameters.TryGetValue(
"orgAddress2", out Obj) || !(Obj is
string OrgAddress2) ||
901 !Parameters.TryGetValue(
"orgPostalCode", out Obj) || !(Obj is
string OrgPostalCode) ||
902 !Parameters.TryGetValue(
"orgArea", out Obj) || !(Obj is
string OrgArea) ||
903 !Parameters.TryGetValue(
"orgCity", out Obj) || !(Obj is
string OrgCity) ||
904 !Parameters.TryGetValue(
"orgRegion", out Obj) || !(Obj is
string OrgRegion) ||
905 !Parameters.TryGetValue(
"orgCountry", out Obj) || !(Obj is
string OrgCountry))
912 if (
string.IsNullOrEmpty(Password))
915 if (Password != Password2)
921 if (Parameters.TryGetValue(
"alternative", out Obj) && Obj is Dictionary<string, object> Alternative)
923 foreach (KeyValuePair<string, object> P
in Alternative)
925 switch (P.Key.ToUpper())
954 throw new BadRequestException(
"The following alternative field name is not allowed: " + P.Key);
963 string TabID = Request.
Header[
"X-TabID"];
964 if (
string.IsNullOrEmpty(TabID))
967 if (!
string.IsNullOrEmpty(BirthDateStr))
969 if (!DateTime.TryParse(BirthDateStr, out DateTime
BirthDate))
975 this.birthDate =
null;
977 this.useLegalIdentity =
true;
981 this.personalNumber = PNr;
994 this.orgNumber = OrgNr;
1006 Response.StatusCode = 200;
1011 private async Task ApplyId(
string Password,
string TabID,
bool ProtectWithPassword, TaskCompletionSource<bool> Response)
1020 object[] P = (
object[])e.
State;
1021 string Password = (
string)P[0];
1022 string TabID = (string)P[1];
1024 TaskCompletionSource<bool> Response = (TaskCompletionSource<bool>)P[3];
1032 Dictionary<string, AlternativeField> ById =
new Dictionary<string, AlternativeField>();
1034 if (!(this.passwordHashes is
null))
1043 ById.Values.CopyTo(
Hashes, 0);
1045 this.passwordHashes =
Hashes;
1051 if (!
string.IsNullOrEmpty(TabID))
1054 await this.UpdateClients(e.
Identity);
1056 Response?.TrySetResult(
true);
1060 if (!
string.IsNullOrEmpty(TabID))
1063 Response?.TrySetResult(
false);
1067 private string CalcPasswordHash(
LegalIdentity ID,
string Password)
1069 StringBuilder sb =
new StringBuilder();
1070 SortedDictionary<string, string> Sorted =
new SortedDictionary<string, string>();
1074 if (Sorted.TryGetValue(P.
Name, out
string s))
1085 foreach (KeyValuePair<string, string> P
in Sorted)
1097 byte[] Digest =
Hashes.
ComputeHMACSHA256Hash(System.Text.Encoding.UTF8.GetBytes(Password), System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
1099 return Convert.ToBase64String(Digest);
1104 List<Property> Properties =
new List<Property>();
1106 if (!
string.IsNullOrEmpty(this.firstName))
1107 Properties.Add(
new Property(
"FIRST", this.firstName));
1109 if (!
string.IsNullOrEmpty(this.middleName))
1110 Properties.Add(
new Property(
"MIDDLE", this.middleName));
1112 if (!
string.IsNullOrEmpty(this.lastName))
1113 Properties.Add(
new Property(
"LAST", this.lastName));
1115 if (!
string.IsNullOrEmpty(this.personalNumber))
1116 Properties.Add(
new Property(
"PNR", this.personalNumber));
1118 if (!
string.IsNullOrEmpty(this.address))
1119 Properties.Add(
new Property(
"ADDR", this.address));
1121 if (!
string.IsNullOrEmpty(this.address2))
1122 Properties.Add(
new Property(
"ADDR2", this.address2));
1124 if (!
string.IsNullOrEmpty(this.postalCode))
1125 Properties.Add(
new Property(
"ZIP", this.postalCode));
1127 if (!
string.IsNullOrEmpty(this.area))
1128 Properties.Add(
new Property(
"AREA", this.area));
1130 if (!
string.IsNullOrEmpty(this.city))
1131 Properties.Add(
new Property(
"CITY", this.city));
1133 if (!
string.IsNullOrEmpty(this.region))
1134 Properties.Add(
new Property(
"REGION", this.region));
1136 if (!
string.IsNullOrEmpty(this.country))
1137 Properties.Add(
new Property(
"COUNTRY", this.country));
1139 if (!
string.IsNullOrEmpty(this.nationality))
1140 Properties.Add(
new Property(
"NATIONALITY", this.nationality));
1142 if (!
string.IsNullOrEmpty(this.gender))
1143 Properties.Add(
new Property(
"GENDER", this.gender));
1145 if (!(this.birthDate is
null))
1147 Properties.Add(
new Property(
"BDAY", this.birthDate.Value.Day.ToString()));
1148 Properties.Add(
new Property(
"BMONTH", this.birthDate.Value.Month.ToString()));
1149 Properties.Add(
new Property(
"BYEAR", this.birthDate.Value.Year.ToString()));
1152 if (!
string.IsNullOrEmpty(this.orgName))
1153 Properties.Add(
new Property(
"ORGNAME", this.orgName));
1155 if (!
string.IsNullOrEmpty(this.orgDepartment))
1156 Properties.Add(
new Property(
"ORGDEPT", this.orgDepartment));
1158 if (!
string.IsNullOrEmpty(this.orgRole))
1159 Properties.Add(
new Property(
"ORGROLE", this.orgRole));
1161 if (!
string.IsNullOrEmpty(this.orgNumber))
1162 Properties.Add(
new Property(
"ORGNR", this.orgNumber));
1164 if (!
string.IsNullOrEmpty(this.orgAddress))
1165 Properties.Add(
new Property(
"ORGADDR", this.orgAddress));
1167 if (!
string.IsNullOrEmpty(this.orgAddress2))
1168 Properties.Add(
new Property(
"ORGADDR2", this.orgAddress2));
1170 if (!
string.IsNullOrEmpty(this.orgPostalCode))
1171 Properties.Add(
new Property(
"ORGZIP", this.orgPostalCode));
1173 if (!
string.IsNullOrEmpty(this.orgArea))
1174 Properties.Add(
new Property(
"ORGAREA", this.orgArea));
1176 if (!
string.IsNullOrEmpty(this.orgCity))
1177 Properties.Add(
new Property(
"ORGCITY", this.orgCity));
1179 if (!
string.IsNullOrEmpty(this.orgRegion))
1180 Properties.Add(
new Property(
"ORGREGION", this.orgRegion));
1182 if (!
string.IsNullOrEmpty(this.orgCountry))
1183 Properties.Add(
new Property(
"ORGCOUNTRY", this.orgCountry));
1185 if (!(this.altFields is
null))
1188 Properties.Add(
new Property(F.Key, F.Value));
1191 return Properties.ToArray();
1203 if (!(Obj is Dictionary<string, object> Parameters))
1206 if (!Parameters.TryGetValue(
"requestId", out Obj) || !(Obj is
string RequestId) ||
1207 !Parameters.TryGetValue(
"sign", out Obj) || !(Obj is
bool Sign) ||
1208 !Parameters.TryGetValue(
"protect", out Obj) || !(Obj is
bool Protect))
1215 if (!Parameters.TryGetValue(
"password", out Obj) || !(Obj is
string s))
1221 Password =
string.Empty;
1224 if (SignatureRequest.
Signed.HasValue)
1230 throw new BadRequestException(
"No approved legal identity found with which to sign the contract.");
1233 if (
string.IsNullOrEmpty(Id))
1236 else if (this.protectWithPassword)
1244 SignatureRequest.Signed = DateTime.Now;
1250 Response.StatusCode = 200;
1261 get => !(approvedIdentities is
null) && approvedIdentities.Length > 0;
1278 if (Latest is
null || Identity.
Created > Latest.Created)
1305 return DateTime.MinValue;
1318 if (approvedIdentities is
null || approvedIdentities.Length == 0)
1323 string H = this.CalcPasswordHash(ID, Password);
1350 EventHandlerAsync<LegalIdentityPetitionResponseEventArgs> Callback, TimeSpan Timeout)
1352 if (this.protectWithPassword)
1353 throw new ForbiddenException(
"Petitioning legal identities is protected using passwords on this machine.");
1369 EventHandlerAsync<LegalIdentityPetitionResponseEventArgs> Callback, TimeSpan Timeout)
1374 if (this.protectWithPassword)
1377 if (
string.IsNullOrEmpty(Id))
1381 lock (this.identityPetitionCallbackMethods)
1383 if (this.identityPetitionCallbackMethods.ContainsKey(PetitionId))
1384 throw new ArgumentException(
"Petition ID already used.", nameof(PetitionId));
1386 this.identityPetitionCallbackMethods[PetitionId] = Callback;
1397 }, DateTime.Now.Add(Timeout), PetitionId);
1399 catch (Exception ex)
1401 lock (this.identityPetitionCallbackMethods)
1403 this.identityPetitionCallbackMethods.Remove(PetitionId);
1406 ExceptionDispatchInfo.Capture(ex).Throw();
1422 EventHandlerAsync<ContractPetitionResponseEventArgs> Callback, TimeSpan Timeout)
1424 if (this.protectWithPassword)
1425 throw new ForbiddenException(
"Petitioning legal identities is protected using passwords on this machine.");
1427 return this.
PetitionContract(ContractId, PetitionId, Purpose,
string.Empty, Callback, Timeout);
1440 public async Task<bool>
PetitionContract(
string ContractId,
string PetitionId,
string Purpose,
string Password,
1441 EventHandlerAsync<ContractPetitionResponseEventArgs> Callback, TimeSpan Timeout)
1446 if (this.protectWithPassword)
1449 if (
string.IsNullOrEmpty(Id))
1453 lock (this.contractPetitionCallbackMethods)
1455 if (this.contractPetitionCallbackMethods.ContainsKey(PetitionId))
1456 throw new ArgumentException(
"Petition ID already used.", nameof(PetitionId));
1458 this.contractPetitionCallbackMethods[PetitionId] = Callback;
1469 }, DateTime.Now.Add(Timeout), PetitionId);
1471 catch (Exception ex)
1473 lock (this.contractPetitionCallbackMethods)
1475 this.contractPetitionCallbackMethods.Remove(PetitionId);
1478 ExceptionDispatchInfo.Capture(ex).Throw();
1484 private readonly Dictionary<string, EventHandlerAsync<LegalIdentityPetitionResponseEventArgs>> identityPetitionCallbackMethods =
new Dictionary<string, EventHandlerAsync<LegalIdentityPetitionResponseEventArgs>>();
1485 private readonly Dictionary<string, EventHandlerAsync<ContractPetitionResponseEventArgs>> contractPetitionCallbackMethods =
new Dictionary<string, EventHandlerAsync<ContractPetitionResponseEventArgs>>();
1489 EventHandlerAsync<LegalIdentityPetitionResponseEventArgs> Callback;
1492 lock (this.identityPetitionCallbackMethods)
1494 if (!this.identityPetitionCallbackMethods.TryGetValue(PetitionId, out Callback))
1495 return Task.CompletedTask;
1497 this.identityPetitionCallbackMethods.Remove(PetitionId);
1500 return Callback.Raise(Sender, e);
1505 EventHandlerAsync<ContractPetitionResponseEventArgs> Callback;
1508 lock (this.contractPetitionCallbackMethods)
1510 if (!this.contractPetitionCallbackMethods.TryGetValue(PetitionId, out Callback))
1511 return Task.CompletedTask;
1513 this.contractPetitionCallbackMethods.Remove(PetitionId);
1516 return Callback.Raise(Sender, e);
1525 return Task.FromResult(
true);
1683 if (!this.useLegalIdentity)
1686 this.firstName = Environment.GetEnvironmentVariable(
GATEWAY_ID_FIRST) ??
string.Empty;
1687 this.middleName = Environment.GetEnvironmentVariable(
GATEWAY_ID_MIDDLE) ??
string.Empty;
1688 this.lastName = Environment.GetEnvironmentVariable(
GATEWAY_ID_LAST) ??
string.Empty;
1689 this.personalNumber = Environment.GetEnvironmentVariable(
GATEWAY_ID_PNR) ??
string.Empty;
1690 this.address = Environment.GetEnvironmentVariable(
GATEWAY_ID_ADDR) ??
string.Empty;
1691 this.address2 = Environment.GetEnvironmentVariable(
GATEWAY_ID_ADDR2) ??
string.Empty;
1692 this.postalCode = Environment.GetEnvironmentVariable(
GATEWAY_ID_ZIP) ??
string.Empty;
1693 this.area = Environment.GetEnvironmentVariable(
GATEWAY_ID_AREA) ??
string.Empty;
1694 this.city = Environment.GetEnvironmentVariable(
GATEWAY_ID_CITY) ??
string.Empty;
1695 this.region = Environment.GetEnvironmentVariable(
GATEWAY_ID_REGION) ??
string.Empty;
1696 this.country = Environment.GetEnvironmentVariable(
GATEWAY_ID_COUNTRY) ??
string.Empty;
1698 this.gender = Environment.GetEnvironmentVariable(
GATEWAY_ID_GENDER) ??
string.Empty;
1699 this.orgName = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGNAME) ??
string.Empty;
1700 this.orgDepartment = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGDEPT) ??
string.Empty;
1701 this.orgRole = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGROLE) ??
string.Empty;
1702 this.orgNumber = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGNR) ??
string.Empty;
1703 this.orgAddress = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGADDR) ??
string.Empty;
1704 this.orgAddress2 = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGADDR2) ??
string.Empty;
1705 this.orgPostalCode = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGZIP) ??
string.Empty;
1706 this.orgArea = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGAREA) ??
string.Empty;
1707 this.orgCity = Environment.GetEnvironmentVariable(
GATEWAY_ID_ORGCITY) ??
string.Empty;
1714 List<AlternativeField> Fields =
new List<AlternativeField>();
1718 string[] Parts = Value.Split(
',');
1720 foreach (
string Part in Parts)
1731 this.altFields = Fields.ToArray();
1735 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
1738 Task _ = Task.Delay(30000).ContinueWith(Prev => Result?.TrySetException(
new TimeoutException()));
1740 await this.ApplyId(Value,
null, !
string.IsNullOrEmpty(Value), Result);
1742 if (await Result.Task)
1747 catch (Exception ex)
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
Helps with common JSON-related tasks.
static string Encode(string s)
Encodes a string for inclusion in JSON.
const string DefaultContentType
application/json
Contains a markdown document. This markdown document class supports original markdown,...
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Static class managing loading of resources stored as embedded resources or in content files.
static async Task< string > ReadAllTextAsync(string FileName)
Reads a text file asynchronously.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
static string[] GetTabIDsForLocation(string Location)
Gets the Tab IDs of all tabs that display a particular resource.
static Task< int > PushEvent(string[] TabIDs, string Type, object Data)
Puses an event to a set of Tabs, given their Tab IDs.
static string[] GetTabIDs()
Gets all open Tab IDs.
Static class managing the runtime environment of the IoT Gateway.
static IUser AssertUserAuthenticated(HttpRequest Request, string Privilege)
Makes sure a request is being made from a session with a successful user login.
static bool Configuring
If the gateway is being configured.
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
static ContractsClient ContractsClient
XMPP Contracts Client, if such a compoent is available on the XMPP broker.
static Emoji1LocalFiles Emoji1_24x24
Emojis.
static DateTime ScheduleEvent(ScheduledEventCallback Callback, DateTime When, object State)
Schedules a one-time event.
static XmppClient XmppClient
XMPP Client connection of gateway.
static string RootFolder
Web root folder.
static bool CancelScheduledEvent(DateTime When)
Cancels a scheduled event.
Represents an alternative field in a legal identity.
string Key
Alternative field name.
Contains information about a contract signature request.
DateTime? Signed
When contract was signed.
async Task< Contract > GetContract()
Gets the parsed contract.
void SetContract(Contract Contract)
Sets a parsed contract.
string Role
Requested role.
Configures legal identity for the gateway.
LegalIdentityConfiguration()
Configures legal identity for the gateway.
static bool TryGetMyIdentity(CaseInsensitiveString LegalId, out LegalIdentity Identity)
Tries to get one of the legal identities belonging to the current instance.
const string GATEWAY_ID_ORGDEPT
Organization department of legal identity.
Task< bool > PetitionLegalIdentity(string LegalId, string PetitionId, string Purpose, EventHandlerAsync< LegalIdentityPetitionResponseEventArgs > Callback, TimeSpan Timeout)
Petitions information about a legal identity from its owner.
const string GATEWAY_ID_NATIONALITY
Nationality of legal identity.
const string GATEWAY_ID_ORGADDR2
Organization address(line 2) of legal identity.
string OrgArea
Organization Area
override async Task< bool > EnvironmentConfiguration()
Environment configuration by configuring values available in environment variables.
string GetPasswordLegalId(string Password)
Gets the legal identity that corresponds to a given password, from the corresponding hash digests.
AlternativeField[] AlternativeFields
Alternative fields.
string Nationality
Nationality
const string GATEWAY_ID_ORGROLE
Organization role of legal identity.
const string GATEWAY_ID_ORGNR
Organization number of legal identity.
const string GATEWAY_ID_AREA
Area of legal identity.
const string GATEWAY_ID_ALT_
Value for alternative field field to send in the identity application.
const string GATEWAY_ID_ADDR2
Address(line 2) of legal identity.
static LegalIdentityConfiguration Instance
Instance of configuration object.
override string Resource
Resource to be redirected to, to perform the configuration.
string OrgAddress2
Organization Address, 2nd row
static bool IsMe(CaseInsensitiveString LegalId)
Checks if a Legal Identity refers to the gateway.
string OrgPostalCode
Organization Postal Code (or zip code)
static DateTime LatestApprovedLegalIdentityExpires
Expiry date of latest approved legal identity.
string OrgName
Organization Name
const string GATEWAY_ID_ORGREGION
Organization region of legal identity.
const string GATEWAY_ID_REGION
Region of legal identity.
const string GATEWAY_ID_ORGAREA
Organization area of legal identity.
string OrgCountry
Organization Country
const string GATEWAY_ID_ORGADDR
Organization address (line 1) of legal identity.
async Task< bool > PetitionContract(string ContractId, string PetitionId, string Purpose, string Password, EventHandlerAsync< ContractPetitionResponseEventArgs > Callback, TimeSpan Timeout)
Petitions information about a smart contract from its owner.
string PersonalNumber
Personal number (or organizational number)
override Task InitSetup(HttpServer WebServer)
Initializes the setup object.
const string GATEWAY_ID_GENDER
Gender of legal identity.
static bool IsMeApproved(CaseInsensitiveString LegalId)
Checks if a Legal Identity refers to an approved ID of the gateway.
string Address2
Address, 2nd row
static LegalIdentity[] ApprovedIdentities
Approved Legal Identities associated with account.
override string ConfigPrivilege
Minimum required privilege for a user to be allowed to change the configuration defined by the class.
string OrgAddress
Organization Address
Task< bool > PetitionContract(string ContractId, string PetitionId, string Purpose, EventHandlerAsync< ContractPetitionResponseEventArgs > Callback, TimeSpan Timeout)
Petitions information about a smart contract from its owner.
const string GATEWAY_ID_MIDDLE
Middle name of legal identity.
DateTime? BirthDate
Birth Date
string MiddleName
Middle Name
const string GATEWAY_ID_FIRST
First name of legal identity.
const string GATEWAY_ID_USE
If a legal identity is to be used by the gateway.If used, the folllowing optional variables can be us...
const string GATEWAY_ID_PNR
Personal number of legal identity.
static Dictionary< string, object >[] AllIdentitiesJSON
Public profile of all Legal Identities associated with account, as dictionaries.
override async Task ConfigureSystem()
Is called during startup to configure the system.
const string GATEWAY_ID_ALT
Comma-separated list of alternative fields to send in identity application.
string PostalCode
Postal Code (or zip code)
override int Priority
Priority of the setting. Configurations are sorted in ascending order.
string OrgRegion
Organization Region
async Task< bool > PetitionLegalIdentity(string LegalId, string PetitionId, string Purpose, string Password, EventHandlerAsync< LegalIdentityPetitionResponseEventArgs > Callback, TimeSpan Timeout)
Petitions information about a legal identity from its owner.
const string GATEWAY_ID_COUNTRY
Country of legal identity.
const string GATEWAY_ID_ORGCITY
Organization city of legal identity.
static bool HasApprovedLegalIdentities
If there are approved legal identities configured.
bool ProtectWithPassword
If the legal identity should be protected with a password.
const string GATEWAY_ID_ZIP
Postal code of legal identity.
override Task< bool > SimplifiedConfiguration()
Simplified configuration by configuring simple default values.
string OrgRole
Organization Role
const string GATEWAY_ID_ORGNAME
Organization name of legal identity.
string OrgDepartment
Organization Department
override Task UnregisterSetup(HttpServer WebServer)
Unregisters the setup object.
string OrgCity
Organization City
const string GATEWAY_ID_LAST
Last name of legal identity.
override async Task< bool > SetupConfiguration(HttpServer WebServer)
Waits for the user to provide configuration.
static LegalIdentity[] AllIdentities
All Legal Identities associated with account.
const string GATEWAY_ID_ORGCOUNTRY
Organization country of legal identity.
static string LatestApprovedLegalIdentityId
Latest approved Legal Identity ID.
string OrgNumber
Organization number
const string GATEWAY_ID_BDATE
Birth Date of legal identity.
const string GATEWAY_ID_CITY
City of legal identity.
const string GATEWAY_ID_ADDR
Address (line 1) of legal identity.
AlternativeField[] PasswordHashes
Password hash, if legal identity is protected by password.
override void SetStaticInstance(ISystemConfiguration Configuration)
Sets the static instance of the configuration.
override Task< string > Title(Language Language)
Gets a title for the system configuration.
const string GATEWAY_ID_ORGZIP
Organization postal code of legal identity.
bool UseLegalIdentity
If the gateway will use a legal identity.
static LegalIdentity LatestApprovedLegalIdentity
Latest approved Legal Identity.
string FirstName
First Name
const string GATEWAY_ID_PASSWORD
Protect legal identity with this password.
bool Complete
If the configuration is complete.
bool TryGetEnvironmentVariable(string VariableName, bool Required, out string Value)
Tries to get a string-valued environment variable.
Abstract base class for multi-step system configurations.
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
The server understood the request, but is refusing to fulfill it. Authorization will not help and the...
Represents an HTTP request.
HttpRequestHeader Header
Request header.
bool HasData
If the request has data.
async Task< object > DecodeDataAsync()
Decodes data sent in request.
Base class for all HTTP resources.
Represets a response of an HTTP client request.
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
async Task Write(byte[] Data)
Returns binary data in the response.
Implements an HTTP server.
static Variables CreateVariables()
Creates a new collection of variables, that contains access to the global set of variables.
HttpResource Register(HttpResource Resource)
Registers a resource with the server.
bool Unregister(HttpResource Resource)
Unregisters a resource from the server.
The server has not found anything matching the Request-URI. No indication is given of whether the con...
Contains the definition of a contract
Adds support for legal identities, smart contracts and signatures to an XMPP client.
async Task GenerateNewKeys()
Generates new keys for the contracts clients.
Task PetitionIdentityAsync(string LegalId, string PetitionId, string Purpose)
Sends a petition to the owner of a legal identity, to access the information in the identity....
void SetAllowedSources(object[] ApprovedSources)
If access to sensitive methods is only accessible from a set of approved sources.
Task PetitionContractAsync(string ContractId, string PetitionId, string Purpose)
Sends a petition to the parts of a smart contract, to access the information in the contract....
Task< Contract > SignContractAsync(Contract Contract, string Role, bool Transferable)
Signs a contract
Task GetLegalIdentities(EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets legal identities registered with the account.
Task Apply(Property[] Properties, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Applies for a legal identity to be registered.
Event arguments for smart contract petition responses
string PetitionId
Petition ID
Event arguments for events referencing a contract.
string ContractId
ID of contract being signed.
Event arguments for contract signature events
string Role
Role the legal identity has signed.
string LegalId
ID of legal identity signing the contract.
Event arguments for legal identity responses
LegalIdentity Identity
Legal Identity
Event arguments for legal identity petition responses
string PetitionId
Petition ID
DateTime From
From what point in time the legal identity is valid.
DateTime Updated
When the identity object was last updated
DateTime To
To what point in time the legal identity is valid.
DateTime Created
When the identity object was created
IdentityState State
Current state of identity
string ClientKeyName
Type of key used for client signatures
string Provider
Provider where the identity is maintained.
byte[] ClientPubKey
Client Public key
string Id
ID of the legal identity
Property[] Properties
Properties detailing the legal identity.
Class defining a part in a contract
string Name
Name of property
string Value
Property value
bool Ok
If the response is an OK result response (true), or an error response (false).
object State
State object passed to the original request.
string ErrorText
Any error specific text.
XmppState State
Current state of connection.
Task Connect()
Connects the client.
Represents a case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< object > TryLoadObject(string CollectionName, object ObjectId)
Tries to load an object given its Object ID ObjectId and its collection name CollectionName .
Contains information about a language.
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Static class containing methods that can be used to make sure calls are made from appropriate locatio...
static void CallFromSource(params string[] Sources)
Makes sure the call is made from one of the listed sources.
Contains methods for simple hash calculations.
static byte[] ComputeHMACSHA256Hash(byte[] Key, byte[] Data)
Computes the HMAC-SHA-256 hash of a block of binary data.
Interface for system configurations. The gateway will scan all module for system configuration classe...
IdentityState
Lists recognized legal identity states.
XmppState
State of XMPP connection.