Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
LegalModel.cs
3using System;
4using System.Collections.Generic;
5using System.Text;
6using System.Threading.Tasks;
7using System.Windows;
8using System.Windows.Input;
16
18{
22 [Singleton]
23 public class LegalModel : PersistedModel, IDisposable
24 {
25 private readonly PersistedProperty<string> firstName;
26 private readonly PersistedProperty<string> middleName;
27 private readonly PersistedProperty<string> lastName;
28 private readonly PersistedProperty<string> personalNumber;
29 private readonly PersistedProperty<string> address;
30 private readonly PersistedProperty<string> address2;
31 private readonly PersistedProperty<string> zip;
32 private readonly PersistedProperty<string> area;
33 private readonly PersistedProperty<string> city;
34 private readonly PersistedProperty<string> region;
35 private readonly PersistedProperty<string> country;
36 private readonly PersistedProperty<string> nationality;
37 private readonly PersistedProperty<string> gender;
38 private readonly PersistedProperty<string> eMail;
39 private readonly PersistedProperty<DateTime?> birthDate;
40
41 private readonly PersistedProperty<string> orgName;
42 private readonly PersistedProperty<string> orgDepartment;
43 private readonly PersistedProperty<string> orgRole;
44 private readonly PersistedProperty<string> orgNumber;
45 private readonly PersistedProperty<string> orgAddress;
46 private readonly PersistedProperty<string> orgAddress2;
47 private readonly PersistedProperty<string> orgZip;
48 private readonly PersistedProperty<string> orgArea;
49 private readonly PersistedProperty<string> orgCity;
50 private readonly PersistedProperty<string> orgRegion;
51 private readonly PersistedProperty<string> orgCountry;
52
53 private readonly Property<Contract> template;
54 private readonly Property<TemplateReferenceModel[]> templates;
55 private readonly Property<string> contractTemplateName;
56
57 private readonly Dictionary<string, IdentityWrapper> identities = new();
58
59 private readonly Command apply;
60
61 private readonly ContractsClient contracts;
62 private readonly HttpFileUploadClient httpFileUploadClient;
63 private ContractModel currentContract;
64
72 public LegalModel(XmppClient Client, string ComponentJid, string FileUploadJid, long? MaxFileSize)
73 : base()
74 {
75 this.Add(this.firstName = new PersistedProperty<string>("Legal", nameof(this.FirstName), true, string.Empty, this));
76 this.Add(this.middleName = new PersistedProperty<string>("Legal", nameof(this.MiddleName), true, string.Empty, this));
77 this.Add(this.lastName = new PersistedProperty<string>("Legal", nameof(this.LastName), true, string.Empty, this));
78 this.Add(this.personalNumber = new PersistedProperty<string>("Legal", nameof(this.PersonalNumber), true, string.Empty, this));
79 this.Add(this.address = new PersistedProperty<string>("Legal", nameof(this.Address), true, string.Empty, this));
80 this.Add(this.address2 = new PersistedProperty<string>("Legal", nameof(this.Address2), true, string.Empty, this));
81 this.Add(this.zip = new PersistedProperty<string>("Legal", nameof(this.Zip), true, string.Empty, this));
82 this.Add(this.area = new PersistedProperty<string>("Legal", nameof(this.Area), true, string.Empty, this));
83 this.Add(this.city = new PersistedProperty<string>("Legal", nameof(this.City), true, string.Empty, this));
84 this.Add(this.region = new PersistedProperty<string>("Legal", nameof(this.Region), true, string.Empty, this));
85 this.Add(this.country = new PersistedProperty<string>("Legal", nameof(this.Country), true, string.Empty, this));
86 this.Add(this.nationality = new PersistedProperty<string>("Legal", nameof(this.Nationality), true, string.Empty, this));
87 this.Add(this.gender = new PersistedProperty<string>("Legal", nameof(this.Gender), true, string.Empty, this));
88 this.Add(this.eMail = new PersistedProperty<string>("Legal", nameof(this.EMail), true, string.Empty, this));
89 this.Add(this.birthDate = new PersistedProperty<DateTime?>("Legal", nameof(this.BirthDate), true, null, this));
90
91 this.Add(this.orgName = new PersistedProperty<string>("Legal", nameof(this.OrgName), true, string.Empty, this));
92 this.Add(this.orgDepartment = new PersistedProperty<string>("Legal", nameof(this.OrgDepartment), true, string.Empty, this));
93 this.Add(this.orgRole = new PersistedProperty<string>("Legal", nameof(this.OrgRole), true, string.Empty, this));
94 this.Add(this.orgNumber = new PersistedProperty<string>("Legal", nameof(this.OrgNumber), true, string.Empty, this));
95 this.Add(this.orgAddress = new PersistedProperty<string>("Legal", nameof(this.OrgAddress), true, string.Empty, this));
96 this.Add(this.orgAddress2 = new PersistedProperty<string>("Legal", nameof(this.OrgAddress2), true, string.Empty, this));
97 this.Add(this.orgZip = new PersistedProperty<string>("Legal", nameof(this.OrgZip), true, string.Empty, this));
98 this.Add(this.orgArea = new PersistedProperty<string>("Legal", nameof(this.OrgArea), true, string.Empty, this));
99 this.Add(this.orgCity = new PersistedProperty<string>("Legal", nameof(this.OrgCity), true, string.Empty, this));
100 this.Add(this.orgRegion = new PersistedProperty<string>("Legal", nameof(this.OrgRegion), true, string.Empty, this));
101 this.Add(this.orgCountry = new PersistedProperty<string>("Legal", nameof(this.OrgCountry), true, string.Empty, this));
102
103 this.template = new Property<Contract>(nameof(this.Template), null, this);
104 this.templates = new Property<TemplateReferenceModel[]>(nameof(this.Templates), Array.Empty<TemplateReferenceModel>(), this);
105 this.contractTemplateName = new Property<string>(nameof(this.ContractTemplateName), string.Empty, this);
106
107 this.apply = new Command(this.CanExecuteApply, this.ExecuteApply);
108
109 this.contracts = new ContractsClient(Client, ComponentJid);
110 this.contracts.EnableE2eEncryption(true);
111 this.contracts.IdentityUpdated += this.Contracts_IdentityUpdated;
112 this.contracts.PetitionForIdentityReceived += this.Contracts_PetitionForIdentityReceived;
113
114 this.httpFileUploadClient = new HttpFileUploadClient(Client, FileUploadJid, MaxFileSize);
115 }
116
118 public void Dispose()
119 {
120 this.contracts.Dispose();
121 }
122
126 public ContractsClient Contracts => this.contracts;
127
131 public HttpFileUploadClient FileUpload => this.httpFileUploadClient;
132
136 public ContractModel CurrentContract => this.currentContract;
137
139 public override async Task Start()
140 {
142 {
143 MainWindow.currentInstance.LegalIdTab.DataContext = this;
144 MainWindow.currentInstance.ContractsTab.DataContext = this;
145 MainWindow.currentInstance.ContractsTab.ContractCommands.DataContext = this;
146
147 return Task.CompletedTask;
148 });
149
150 await this.contracts.LoadKeys(true);
151
152 LegalIdentity[] Identities = await this.contracts.GetLegalIdentitiesAsync();
153
154 lock (this.identities)
155 {
156 foreach (LegalIdentity Identity in Identities)
157 this.identities[Identity.Id] = new IdentityWrapper(this.contracts.Client.Domain, Identity);
158 }
159
160 this.RaisePropertyChanged(nameof(this.Identities));
161
162 Dictionary<string, object> Settings = await RuntimeSettings.GetWhereKeyLikeAsync("Contract.Template.*", "*");
163 List<TemplateReferenceModel> Templates = new();
164
165 foreach (KeyValuePair<string, object> Setting in Settings)
166 {
167 if (Setting.Value is string ContractId)
168 Templates.Add(new TemplateReferenceModel(Setting.Key[18..], ContractId));
169 }
170
171 this.Templates = Templates.ToArray();
172
173 await base.Start();
174 }
175
176 #region Legal Identity properties
177
181 public string FirstName
182 {
183 get => this.firstName.Value;
184 set => this.firstName.Value = value;
185 }
186
190 public string MiddleName
191 {
192 get => this.middleName.Value;
193 set => this.middleName.Value = value;
194 }
195
199 public string LastName
200 {
201 get => this.lastName.Value;
202 set => this.lastName.Value = value;
203 }
204
208 public string PersonalNumber
209 {
210 get => this.personalNumber.Value;
211 set => this.personalNumber.Value = value;
212 }
213
217 public string Address
218 {
219 get => this.address.Value;
220 set => this.address.Value = value;
221 }
222
226 public string Address2
227 {
228 get => this.address2.Value;
229 set => this.address2.Value = value;
230 }
231
235 public string Zip
236 {
237 get => this.zip.Value;
238 set => this.zip.Value = value;
239 }
240
244 public string Area
245 {
246 get => this.area.Value;
247 set => this.area.Value = value;
248 }
249
253 public string City
254 {
255 get => this.city.Value;
256 set => this.city.Value = value;
257 }
258
262 public string Region
263 {
264 get => this.region.Value;
265 set => this.region.Value = value;
266 }
267
271 public string Country
272 {
273 get => this.country.Value;
274 set => this.country.Value = value;
275 }
276
281
286
290 public string Nationality
291 {
292 get => this.nationality.Value;
293 set => this.nationality.Value = value;
294 }
295
299 public string Gender
300 {
301 get => this.gender.Value;
302 set => this.gender.Value = value;
303 }
304
308 public DateTime? BirthDate
309 {
310 get => this.birthDate.Value;
311 set => this.birthDate.Value = value;
312 }
313
317 public string EMail
318 {
319 get => this.eMail.Value;
320 set => this.eMail.Value = value;
321 }
322
326 public string OrgName
327 {
328 get => this.orgName.Value;
329 set => this.orgName.Value = value;
330 }
331
335 public string OrgDepartment
336 {
337 get => this.orgDepartment.Value;
338 set => this.orgDepartment.Value = value;
339 }
340
344 public string OrgRole
345 {
346 get => this.orgRole.Value;
347 set => this.orgRole.Value = value;
348 }
349
353 public string OrgNumber
354 {
355 get => this.orgNumber.Value;
356 set => this.orgNumber.Value = value;
357 }
358
362 public string OrgAddress
363 {
364 get => this.orgAddress.Value;
365 set => this.orgAddress.Value = value;
366 }
367
371 public string OrgAddress2
372 {
373 get => this.orgAddress2.Value;
374 set => this.orgAddress2.Value = value;
375 }
376
380 public string OrgZip
381 {
382 get => this.orgZip.Value;
383 set => this.orgZip.Value = value;
384 }
385
389 public string OrgArea
390 {
391 get => this.orgArea.Value;
392 set => this.orgArea.Value = value;
393 }
394
398 public string OrgCity
399 {
400 get => this.orgCity.Value;
401 set => this.orgCity.Value = value;
402 }
403
407 public string OrgRegion
408 {
409 get => this.orgRegion.Value;
410 set => this.orgRegion.Value = value;
411 }
412
416 public string OrgCountry
417 {
418 get => this.orgCountry.Value;
419 set => this.orgCountry.Value = value;
420 }
421
422 #endregion
423
424 #region Legal Identities
425
430 {
431 get
432 {
433 lock (this.identities)
434 {
435 IdentityWrapper[] Result = new IdentityWrapper[this.identities.Count];
436 this.identities.Values.CopyTo(Result, 0);
437 return Result;
438 }
439 }
440 }
441
442 private Task Contracts_IdentityUpdated(object Sender, LegalIdentityEventArgs e)
443 {
444 lock (this.identities)
445 {
446 this.identities[e.Identity.Id] = new IdentityWrapper(this.contracts.Client.Domain, e.Identity);
447 }
448
449 this.RaisePropertyChanged(nameof(this.Identities));
450
451 return Task.CompletedTask;
452 }
453
454 #endregion
455
456 #region Apply for new Legal Identity
457
461 public ICommand Apply => this.apply;
462
463 private bool CanExecuteApply()
464 {
465 return this.contracts.Client.State == XmppState.Connected;
466 }
467
468 private async Task ExecuteApply()
469 {
470 try
471 {
472 LegalIdentity[] Identities = await this.contracts.GetLegalIdentitiesAsync();
473
474 foreach (LegalIdentity OldIdentity in Identities)
475 {
476 if (OldIdentity.State == IdentityState.Approved)
477 await this.contracts.ObsoleteLegalIdentityAsync(OldIdentity.Id);
478 }
479
480 List<Property> Properties = new();
481
482 AddProperty(Properties, "FIRST", this.FirstName);
483 AddProperty(Properties, "MIDDLE", this.MiddleName);
484 AddProperty(Properties, "LAST", this.LastName);
485 AddProperty(Properties, "PNR", this.PersonalNumber);
486 AddProperty(Properties, "ADDR", this.Address);
487 AddProperty(Properties, "ADDR2", this.Address2);
488 AddProperty(Properties, "ZIP", this.Zip);
489 AddProperty(Properties, "AREA", this.Area);
490 AddProperty(Properties, "CITY", this.City);
491 AddProperty(Properties, "REGION", this.Region);
492 AddProperty(Properties, "COUNTRY", this.Country);
493 AddProperty(Properties, "NATIONALITY", this.Nationality);
494 AddProperty(Properties, "GENDER", this.Gender);
495 AddProperty(Properties, "EMAIL", this.EMail);
496
497 if (this.BirthDate.HasValue)
498 {
499 AddProperty(Properties, "BDAY", this.BirthDate.Value.Day.ToString());
500 AddProperty(Properties, "BMONTH", this.BirthDate.Value.Month.ToString());
501 AddProperty(Properties, "BYEAR", this.BirthDate.Value.Year.ToString());
502 }
503
504 AddProperty(Properties, "ORGNAME", this.OrgName);
505 AddProperty(Properties, "ORGDEPT", this.OrgDepartment);
506 AddProperty(Properties, "ORGROLE", this.OrgRole);
507 AddProperty(Properties, "ORGNR", this.OrgNumber);
508 AddProperty(Properties, "ORGADDR", this.OrgAddress);
509 AddProperty(Properties, "ORGADDR2", this.OrgAddress2);
510 AddProperty(Properties, "ORGZIP", this.OrgZip);
511 AddProperty(Properties, "ORGAREA", this.OrgArea);
512 AddProperty(Properties, "ORGCITY", this.OrgCity);
513 AddProperty(Properties, "ORGREGION", this.OrgRegion);
514 AddProperty(Properties, "ORGCOUNTRY", this.OrgCountry);
515
516 AddProperty(Properties, "JID", this.contracts.Client.BareJID);
517
518 LegalIdentity Identity = await this.contracts.ApplyAsync(Properties.ToArray());
519
520 lock (this.identities)
521 {
522 this.identities[Identity.Id] = new IdentityWrapper(this.contracts.Client.Domain, Identity);
523 }
524
525 this.RaisePropertyChanged(nameof(this.Identities));
526 }
527 catch (Exception ex)
528 {
529 MainWindow.ErrorBox(ex.Message);
530 }
531 }
532
533 private static void AddProperty(List<Property> Properties, string Name, string Value)
534 {
535 if (!string.IsNullOrEmpty(Value))
536 Properties.Add(new Property(Name, Value));
537 }
538
539 #endregion
540
541 #region Legal Identity Petitions
542
543 private Task Contracts_PetitionForIdentityReceived(object Sender, LegalIdentityPetitionEventArgs e)
544 {
545 StringBuilder Question = new();
546
547 Question.Append("A petition for your legal identity has been received for the following purpose: ");
548 Question.Append(e.Purpose);
549 Question.Append(" The petition was sent by");
550
551 Append(Question, e.RequestorIdentity["FIRST"], " ", string.Empty);
552 Append(Question, e.RequestorIdentity["MIDDLE"], " ", string.Empty);
553 Append(Question, e.RequestorIdentity["LAST"], " ", string.Empty);
554 Append(Question, e.RequestorIdentity["PNR"], " (", ")");
555
556 Question.Append(", at");
557
558 Append(Question, e.RequestorIdentity["ADDR"], " ", string.Empty);
559 Append(Question, e.RequestorIdentity["ADDR2"], " ", string.Empty);
560 Append(Question, e.RequestorIdentity["ZIP"], " ", string.Empty);
561 Append(Question, e.RequestorIdentity["AREA"], " ", string.Empty);
562 Append(Question, e.RequestorIdentity["CITY"], " ", string.Empty);
563 Append(Question, e.RequestorIdentity["REGION"], " ", string.Empty);
564
565 string s = e.RequestorIdentity["COUNTRY"];
566 if (!string.IsNullOrEmpty(s))
567 {
568 if (Iso_3166_1.CodeToCountry(s, out string Country))
569 s = Country;
570
571 Append(Question, s, " ", string.Empty);
572 }
573
574 Append(Question, e.RequestorFullJid, ", from ", string.Empty);
575
576 Question.Append(". Do you want to return your identity information?");
577
579 {
580 switch (MessageBox.Show(Question.ToString(), "Petition received", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.No))
581 {
582 case MessageBoxResult.Yes:
583 Task.Run(() => this.contracts.PetitionIdentityResponseAsync(e.RequestedIdentityId, e.PetitionId, e.RequestorFullJid, true));
584 break;
585
586 case MessageBoxResult.No:
587 Task.Run(() => this.contracts.PetitionIdentityResponseAsync(e.RequestedIdentityId, e.PetitionId, e.RequestorFullJid, false));
588 break;
589 }
590
591 return Task.CompletedTask;
592 });
593
594 return Task.CompletedTask;
595 }
596
597 private static void Append(StringBuilder Question, string Value, string PrefixIfNotEmpty, string SuffixIfNotEmpty)
598 {
599 if (!string.IsNullOrEmpty(Value))
600 {
601 Question.Append(PrefixIfNotEmpty);
602 Question.Append(Value);
603 Question.Append(SuffixIfNotEmpty);
604 }
605 }
606
607 #endregion
608
609 #region Create Contracts
610
615 {
616 get => this.templates.Value;
617 set => this.templates.Value = value;
618 }
619
624 {
625 get => this.contractTemplateName.Value;
626 set
627 {
628 this.contractTemplateName.Value = value;
629 MainWindow.UpdateGui(() => this.LoadTemplate(value, null));
630 }
631 }
632
638 public async Task SetContractTemplateName(string Name, Dictionary<CaseInsensitiveString, object> PresetValues)
639 {
640 this.contractTemplateName.Value = Name;
642 await this.LoadTemplate(Name, PresetValues);
643 }
644
649 {
650 get => this.template.Value;
651 set => this.template.Value = value;
652 }
653
659 public void ContractTemplateAdded(string TemplateName, Contract Contract)
660 {
661 SortedDictionary<string, TemplateReferenceModel> Templates = new();
662
663 foreach (TemplateReferenceModel Ref in this.Templates)
664 Templates[Ref.TemplateName] = Ref;
665
666 Templates[TemplateName] = new TemplateReferenceModel(TemplateName, Contract.ContractId);
667
668 this.Templates = Templates.ToValueArray();
669 }
670
671 private async Task LoadTemplate(string TemplateName, Dictionary<CaseInsensitiveString, object> PresetValues)
672 {
673 try
674 {
675 string ContractId = await RuntimeSettings.GetAsync("Contract.Template." + TemplateName, string.Empty);
676 if (string.IsNullOrEmpty(ContractId))
677 return;
678
680 this.Template = await this.contracts.GetContractAsync(ContractId);
682
683 if (this.currentContract is not null)
684 await this.currentContract.Stop();
685
686 this.currentContract = await ContractModel.CreateAsync(this.contracts, this.Template, MainWindow.DesignModel,
687 MainWindow.currentInstance.ContractsTab.MachineReadableXmlEditor);
688
689 await this.currentContract.Start();
690
691 await this.currentContract.PopulateParameters(
692 MainWindow.currentInstance.ContractsTab.LanguageOptions,
693 MainWindow.currentInstance.ContractsTab.CreateParameters,
694 MainWindow.currentInstance.ContractsTab.CreateCommands,
695 PresetValues);
696
697 await this.currentContract.PopulateContract(
698 MainWindow.currentInstance.ContractsTab.ContractToCreate,
699 MainWindow.currentInstance.ContractsTab.ContractToCreateHumanReadable);
700 }
701 catch (Exception ex)
702 {
703 MainWindow.ErrorBox(ex.Message);
704 }
705 }
706
707 #endregion
708 }
709}
Contains the definition of a contract
Definition: Contract.cs:22
string ContractId
Contract identity
Definition: Contract.cs:65
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Class managing HTTP File uploads, as defined in XEP-0363.
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:59
Static class managing persistent settings.
static Task< Dictionary< string, object > > GetWhereKeyLikeAsync(string Key, string Wildcard)
Gets available settings, matching a search filter.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
IdentityState
Lists recognized legal identity states.
XmppState
State of XMPP connection.
Definition: XmppState.cs:7