Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PetitionIdentityViewModel.cs
1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
9using System.Collections.ObjectModel;
13
15{
20 {
21 private readonly IAuthenticationService authenticationService = ServiceRef.Provider.GetRequiredService<IAuthenticationService>();
22
23 private readonly PhotosLoader photosLoader;
24 private readonly string? requestorFullJid;
25 private readonly string? requestedIdentityId;
26 private readonly string? petitionId;
27 private readonly string? bareJid;
28
33 public PetitionIdentityViewModel(PetitionIdentityNavigationArgs? Args)
34 {
35 this.photosLoader = new PhotosLoader(this.Photos);
36
37 if (Args is not null)
38 {
39 this.RequestorIdentity = Args.RequestorIdentity;
40 this.requestorFullJid = Args.RequestorFullJid;
41 this.requestedIdentityId = Args.RequestedIdentityId;
42 this.petitionId = Args.PetitionId;
43 this.Purpose = Args.Purpose;
44
45 if (!string.IsNullOrEmpty(this.requestorFullJid))
46 this.bareJid = XmppClient.GetBareJID(this.requestorFullJid);
47 else if (Args.RequestorIdentity is not null)
48 this.bareJid = Args.RequestorIdentity.GetJid();
49 else
50 this.bareJid = string.Empty;
51 }
52 }
53
55 public override async Task OnInitializeAsync()
56 {
57 await base.OnInitializeAsync();
58
59 if (!string.IsNullOrEmpty(this.bareJid))
60 {
61 ContactInfo Info = await ContactInfo.FindByBareJid(this.bareJid);
62
63 if (this.RequestorIdentity is not null &&
64 Info is not null &&
65 (Info.LegalIdentity is null || (
66 Info.LegalId != this.RequestorIdentity?.Id &&
67 Info.LegalIdentity is not null &&
68 Info.LegalIdentity.Created < this.RequestorIdentity!.Created &&
69 this.RequestorIdentity.State == IdentityState.Approved)))
70 {
71 Info.LegalId = this.LegalId;
72 Info.LegalIdentity = this.RequestorIdentity;
73 Info.FriendlyName = ContactInfo.GetFriendlyName(this.RequestorIdentity);
74
75 await Database.Update(Info);
76 await Database.Provider.Flush();
77 }
78
79 this.ThirdPartyInContacts = Info is not null;
80 }
81
82 this.AssignProperties();
83 EvaluateAllCommands();
84
85 this.ReloadPhotos();
86 }
87
88 private async void ReloadPhotos()
89 {
90 try
91 {
92 this.photosLoader.CancelLoadPhotos();
93
94 Attachment[]? Attachments = this.RequestorIdentity?.Attachments;
95
96 if (Attachments is not null)
97 {
98 Photo? First = await this.photosLoader.LoadPhotos(Attachments, SignWith.LatestApprovedId);
99
100 this.FirstPhotoSource = First?.Source;
101 this.FirstPhotoRotation = First?.Rotation ?? 0;
102 }
103 }
104 catch (Exception ex)
105 {
106 ServiceRef.LogService.LogException(ex);
107 }
108 }
109
111 public override async Task OnDisposeAsync()
112 {
113 this.photosLoader.CancelLoadPhotos();
114
115 await base.OnDisposeAsync();
116 }
117
118 private static void EvaluateAllCommands()
119 {
120 }
121
125 public ObservableCollection<Photo> Photos { get; } = [];
126
130 public LegalIdentity? RequestorIdentity { get; private set; }
131
132 [RelayCommand]
133 private async Task Accept()
134 {
135 if (!await this.authenticationService.AuthenticateUserAsync(AuthenticationPurpose.PetitionIdentity))
136 return;
137
138 bool Succeeded = await ServiceRef.NetworkService.TryRequest(() =>
139 {
140 return ServiceRef.XmppService.SendPetitionIdentityResponse(this.requestedIdentityId, this.petitionId!,
141 this.requestorFullJid!, true);
142 });
143
144 if (Succeeded)
145 {
146 bool AddContact = false;
147
148 if (!this.ThirdPartyInContacts)
149 {
150 // If the identity is not in contacts, push a popup asking if you would like to add it.
151 AddContact = await ServiceRef.UiService.DisplayAlert(
155
156 if (AddContact)
157 {
158 await this.AddContact();
159 }
160
161 }
162 await ServiceRef.NavigationService.GoBackAsync();
163 }
164 }
165
166 [RelayCommand]
167 private async Task Decline()
168 {
169 bool Succeeded = await ServiceRef.NetworkService.TryRequest(() =>
170 {
171 return ServiceRef.XmppService.SendPetitionIdentityResponse(this.requestedIdentityId, this.petitionId!,
172 this.requestorFullJid!, false);
173 });
174
175 if (Succeeded)
176 await this.GoBack();
177 }
178
179 [RelayCommand]
180 private async Task Ignore()
181 {
182 await this.GoBack();
183 }
184
185 // Full name of requesting entity.
186 public string FullName => ContactInfo.GetFullName(this.FirstName, this.MiddleNames, this.LastNames);
187
188 #region Properties
189
193 [ObservableProperty]
194 private DateTime created;
195
199 [ObservableProperty]
200 private DateTime? updated;
201
205 [ObservableProperty]
206 private DateTime? expires;
207
211 [ObservableProperty]
212 private string? legalId;
213
217 [ObservableProperty]
218 private string? networkId;
219
223 [ObservableProperty]
224 private IdentityState state;
225
229 [ObservableProperty]
230 private DateTime? from;
231
235 [ObservableProperty]
236 private DateTime? to;
237
241 [ObservableProperty]
242 [NotifyPropertyChangedFor(nameof(FullName))]
243 private string? firstName;
244
248 [ObservableProperty]
249 [NotifyPropertyChangedFor(nameof(FullName))]
250 private string? middleNames;
251
255 [ObservableProperty]
256 [NotifyPropertyChangedFor(nameof(FullName))]
257 private string? lastNames;
258
262 [ObservableProperty]
263 private string? personalNumber;
264
268 [ObservableProperty]
269 private string? address;
270
274 [ObservableProperty]
275 private string? address2;
276
280 [ObservableProperty]
281 private string? zipCode;
282
286 [ObservableProperty]
287 private string? area;
288
292 [ObservableProperty]
293 private string? city;
294
298 [ObservableProperty]
299 private string? region;
300
304 [ObservableProperty]
305 private string? countryCode;
306
310 [ObservableProperty]
311 private string? nationalityCode;
312
316 [ObservableProperty]
317 private string? gender;
318
322 [ObservableProperty]
323 private DateTime? birthDate;
324
328 [ObservableProperty]
329 private string? orgName;
330
334 [ObservableProperty]
335 private string? orgNumber;
336
340 [ObservableProperty]
341 private string? orgDepartment;
342
346 [ObservableProperty]
347 private string? orgRole;
348
352 [ObservableProperty]
353 private string? orgAddress;
354
358 [ObservableProperty]
359 private string? orgAddress2;
360
364 [ObservableProperty]
365 private string? orgZipCode;
366
370 [ObservableProperty]
371 private string? orgArea;
372
376 [ObservableProperty]
377 private string? orgCity;
378
382 [ObservableProperty]
383 private string? orgRegion;
384
388 [ObservableProperty]
389 private string? orgCountryCode;
390
394 [ObservableProperty]
395 private bool hasOrg;
396
400 [ObservableProperty]
401 private bool hasPhotos;
402
406 [ObservableProperty]
407 private string? phoneNr;
408
412 [ObservableProperty]
413 private string? eMail;
414
418 [ObservableProperty]
419 private string? deviceId;
420
424 [ObservableProperty]
425 private bool isApproved;
426
430 [ObservableProperty]
431 private string? purpose;
432
436 [ObservableProperty]
437 [NotifyCanExecuteChangedFor(nameof(AddContactCommand))]
438 [NotifyCanExecuteChangedFor(nameof(RemoveContactCommand))]
439 private bool thirdPartyInContacts;
440
444 [ObservableProperty]
445 private ImageSource? firstPhotoSource;
446
450 [ObservableProperty]
451 private int firstPhotoRotation;
452
453 #endregion
454
455 private void AssignProperties()
456 {
457 if (this.RequestorIdentity is not null)
458 {
459 this.Created = this.RequestorIdentity.Created;
460 this.Updated = this.RequestorIdentity.Updated.GetDateOrNullIfMinValue();
461 this.Expires = this.RequestorIdentity.To.GetDateOrNullIfMinValue();
462 this.LegalId = this.RequestorIdentity.Id;
463 this.NetworkId = this.RequestorIdentity.GetJid();
464 this.State = this.RequestorIdentity.State;
465 this.From = this.RequestorIdentity.From.GetDateOrNullIfMinValue();
466 this.To = this.RequestorIdentity.To.GetDateOrNullIfMinValue();
468 this.MiddleNames = this.RequestorIdentity[Constants.XmppProperties.MiddleNames];
470 this.PersonalNumber = this.RequestorIdentity[Constants.XmppProperties.PersonalNumber];
477 this.CountryCode = this.RequestorIdentity[Constants.XmppProperties.Country];
478 this.NationalityCode = this.RequestorIdentity[Constants.XmppProperties.Nationality];
480
481 string BirthDayStr = this.RequestorIdentity[Constants.XmppProperties.BirthDay];
482 string BirthMonthStr = this.RequestorIdentity[Constants.XmppProperties.BirthMonth];
483 string BirthYearStr = this.RequestorIdentity[Constants.XmppProperties.BirthYear];
484
485 if (!string.IsNullOrEmpty(BirthDayStr) && int.TryParse(BirthDayStr, out int BirthDay) &&
486 !string.IsNullOrEmpty(BirthMonthStr) && int.TryParse(BirthMonthStr, out int BirthMonth) &&
487 !string.IsNullOrEmpty(BirthYearStr) && int.TryParse(BirthYearStr, out int BirthYear))
488 {
489 try
490 {
491 this.BirthDate = new DateTime(BirthYear, BirthMonth, BirthDay);
492 }
493 catch (Exception ex)
494 {
495 ServiceRef.LogService.LogException(ex);
496 this.BirthDate = null;
497 }
498 }
499
502 this.OrgDepartment = this.RequestorIdentity[Constants.XmppProperties.OrgDepartment];
505 this.OrgAddress2 = this.RequestorIdentity[Constants.XmppProperties.OrgAddress2];
510 this.OrgCountryCode = this.RequestorIdentity[Constants.XmppProperties.OrgCountry];
511 this.HasOrg =
512 !string.IsNullOrEmpty(this.OrgName) ||
513 !string.IsNullOrEmpty(this.OrgNumber) ||
514 !string.IsNullOrEmpty(this.OrgDepartment) ||
515 !string.IsNullOrEmpty(this.OrgRole) ||
516 !string.IsNullOrEmpty(this.OrgAddress) ||
517 !string.IsNullOrEmpty(this.OrgAddress2) ||
518 !string.IsNullOrEmpty(this.OrgZipCode) ||
519 !string.IsNullOrEmpty(this.OrgArea) ||
520 !string.IsNullOrEmpty(this.OrgCity) ||
521 !string.IsNullOrEmpty(this.OrgRegion) ||
522 !string.IsNullOrEmpty(this.OrgCountryCode);
523 this.HasPhotos = this.Photos.Count > 0;
524 this.PhoneNr = this.RequestorIdentity[Constants.XmppProperties.Phone];
527 this.IsApproved = this.RequestorIdentity.State == IdentityState.Approved;
528 }
529 else
530 {
531 this.Created = DateTime.MinValue;
532 this.Updated = null;
533 this.LegalId = Constants.NotAvailableValue;
534 this.State = IdentityState.Compromised;
535 this.From = null;
536 this.To = null;
537 this.FirstName = Constants.NotAvailableValue;
538 this.MiddleNames = Constants.NotAvailableValue;
539 this.LastNames = Constants.NotAvailableValue;
540 this.PersonalNumber = Constants.NotAvailableValue;
541 this.Address = Constants.NotAvailableValue;
542 this.Address2 = Constants.NotAvailableValue;
543 this.ZipCode = Constants.NotAvailableValue;
544 this.Area = Constants.NotAvailableValue;
545 this.City = Constants.NotAvailableValue;
546 this.Region = Constants.NotAvailableValue;
547 this.CountryCode = Constants.NotAvailableValue;
548 this.NationalityCode = Constants.NotAvailableValue;
549 this.Gender = Constants.NotAvailableValue;
550 this.BirthDate = null;
551 this.OrgName = Constants.NotAvailableValue;
552 this.OrgNumber = Constants.NotAvailableValue;
553 this.OrgDepartment = Constants.NotAvailableValue;
554 this.OrgRole = Constants.NotAvailableValue;
555 this.OrgAddress = Constants.NotAvailableValue;
556 this.OrgAddress2 = Constants.NotAvailableValue;
557 this.OrgZipCode = Constants.NotAvailableValue;
558 this.OrgArea = Constants.NotAvailableValue;
559 this.OrgCity = Constants.NotAvailableValue;
560 this.OrgRegion = Constants.NotAvailableValue;
561 this.OrgCountryCode = Constants.NotAvailableValue;
562 this.HasOrg = false;
563 this.HasPhotos = false;
564 this.PhoneNr = Constants.NotAvailableValue;
565 this.EMail = Constants.NotAvailableValue;
566 this.DeviceId = Constants.NotAvailableValue;
567 this.IsApproved = false;
568 }
569 }
570
574 [RelayCommand]
575 private async Task Copy(object Item)
576 {
577 try
578 {
579 if (Item is string Label)
580 {
581 if (Label == this.LegalId)
582 {
583 await Clipboard.SetTextAsync(Constants.UriSchemes.IotId + ":" + this.LegalId);
584 await ServiceRef.UiService.DisplayAlert(
587 }
588 else
589 {
590 await Clipboard.SetTextAsync(Label);
591 await ServiceRef.UiService.DisplayAlert(
594 }
595 }
596 }
597 catch (Exception ex)
598 {
599 ServiceRef.LogService.LogException(ex);
600 await ServiceRef.UiService.DisplayException(ex);
601 }
602 }
603
607 public bool CanAddContact => !this.ThirdPartyInContacts;
608
612 [RelayCommand(CanExecute = nameof(CanAddContact))]
613 private async Task AddContact()
614 {
615 if (this.RequestorIdentity is null)
616 return;
617
618 try
619 {
620 string FriendlyName = ContactInfo.GetFriendlyName(this.RequestorIdentity);
621 string BareJid = XmppClient.GetBareJID(this.requestorFullJid);
622
623 RosterItem? Item = ServiceRef.XmppService.GetRosterItem(BareJid);
624 if (Item is null)
625 ServiceRef.XmppService.AddRosterItem(new RosterItem(BareJid, FriendlyName));
626
627 ContactInfo Info = await ContactInfo.FindByBareJid(BareJid);
628 if (Info is null)
629 {
630 Info = new ContactInfo()
631 {
632 BareJid = BareJid,
633 LegalId = this.RequestorIdentity.Id,
635 FriendlyName = FriendlyName,
636 IsThing = false
637 };
638
639 await Database.Insert(Info);
640 }
641 else
642 {
643 Info.LegalId = this.requestedIdentityId;
644 Info.LegalIdentity = this.RequestorIdentity;
645 Info.FriendlyName = FriendlyName;
646
647 await Database.Update(Info);
648 }
649
650 await ServiceRef.AttachmentCacheService.MakePermanent(this.LegalId!);
651 await Database.Provider.Flush();
652
653 this.ThirdPartyInContacts = true;
654 }
655 catch (Exception ex)
656 {
657 await ServiceRef.UiService.DisplayException(ex);
658 }
659 }
660
664 public bool CanRemoveContact => this.ThirdPartyInContacts;
665
669 [RelayCommand(CanExecute = nameof(CanRemoveContact))]
670 private async Task RemoveContact()
671 {
672 try
673 {
674 if (!await ServiceRef.UiService.DisplayAlert(ServiceRef.Localizer[nameof(AppResources.Confirm)],
677 {
678 return;
679 }
680
681 string BareJid = XmppClient.GetBareJID(this.requestorFullJid);
682
683 ContactInfo Info = await ContactInfo.FindByBareJid(BareJid);
684 if (Info is not null)
685 {
686 await Database.Delete(Info);
687 await ServiceRef.AttachmentCacheService.MakeTemporary(Info.LegalId);
688 await Database.Provider.Flush();
689 }
690
691 RosterItem? Item = ServiceRef.XmppService.GetRosterItem(BareJid);
692 if (Item is not null)
693 ServiceRef.XmppService.RemoveRosterItem(BareJid);
694
695 this.ThirdPartyInContacts = false;
696 }
697 catch (Exception ex)
698 {
699 await ServiceRef.UiService.DisplayException(ex);
700 }
701 }
702 }
703}
const string IotId
The IoT ID URI Scheme (iotid)
Definition: Constants.cs:153
const string PersonalNumber
Personal number
Definition: Constants.cs:394
const string OrgAddress2
Organization Address line 2
Definition: Constants.cs:474
const string OrgArea
Organization Area
Definition: Constants.cs:479
const string OrgRegion
Organization Region
Definition: Constants.cs:494
const string Nationality
Nationality
Definition: Constants.cs:434
const string BirthYear
Birth Year
Definition: Constants.cs:454
const string OrgCity
Organization City
Definition: Constants.cs:484
const string OrgRole
Organization Role
Definition: Constants.cs:509
const string Phone
Phone number
Definition: Constants.cs:524
const string EMail
e-Mail address
Definition: Constants.cs:529
const string OrgZipCode
Organization Zip Code
Definition: Constants.cs:489
const string MiddleNames
Middle names
Definition: Constants.cs:379
const string OrgCountry
Organization Country
Definition: Constants.cs:499
const string OrgDepartment
Organization Department
Definition: Constants.cs:504
const string Address2
Address line 2
Definition: Constants.cs:404
const string OrgAddress
Organization Address line 1
Definition: Constants.cs:469
const string Address
Address line 1
Definition: Constants.cs:399
const string LastNames
Last names
Definition: Constants.cs:384
const string OrgNumber
Organization number
Definition: Constants.cs:464
const string BirthMonth
Birth Month
Definition: Constants.cs:449
const string FirstName
First name
Definition: Constants.cs:374
const string OrgName
Organization name
Definition: Constants.cs:459
A set of never changing property constants and helpful values.
Definition: Constants.cs:24
const string NotAvailableValue
A generic "no value available" string.
Definition: Constants.cs:28
A strongly-typed resource class, for looking up localized strings, etc.
static string Yes
Looks up a localized string similar to Yes.
static string Cancel
Looks up a localized string similar to Cancel.
static string WouldYouLikeToAddThisIdentityToYourContacts
Looks up a localized string similar to Would you like to add this identity to your contacts?...
static string AreYouSureYouWantToRemoveContact
Looks up a localized string similar to Are you sure you want to remove this contact from your list of...
static string IdCopiedSuccessfully
Looks up a localized string similar to A link to the ID was copied to the clipboard....
static string TagValueCopiedToClipboard
Looks up a localized string similar to Tag value copied to clipboard.
static string Confirm
Looks up a localized string similar to Confirm.
static string AddContact
Looks up a localized string similar to Add Contact.
static string No
Looks up a localized string similar to No.
static string SuccessTitle
Looks up a localized string similar to Success.
Contains information about a contact.
Definition: ContactInfo.cs:22
static async Task< string > GetFriendlyName(CaseInsensitiveString RemoteId)
Gets the friendly name of a remote identity (Legal ID or Bare JID).
Definition: ContactInfo.cs:258
LegalIdentity? LegalIdentity
Legal Identity object.
Definition: ContactInfo.cs:82
static string GetFullName(LegalIdentity? Identity)
Gets the full name of a person.
Definition: ContactInfo.cs:578
static Task< ContactInfo > FindByBareJid(string BareJid)
Finds information about a contact, given its Bare JID.
Definition: ContactInfo.cs:221
CaseInsensitiveString LegalId
Legal ID of contact.
Definition: ContactInfo.cs:72
Base class that references services in the app.
Definition: ServiceRef.cs:43
static IServiceProvider Provider
The service provider for the app. This is set before the app is started, and will be used to resolve ...
Definition: ServiceRef.cs:48
static ILogService LogService
Log service.
Definition: ServiceRef.cs:214
static INetworkService NetworkService
Network service.
Definition: ServiceRef.cs:226
static IUiService UiService
Service serializing and managing UI-related tasks.
Definition: ServiceRef.cs:130
static INavigationService NavigationService
The navigation service for navigating between pages.
Definition: ServiceRef.cs:178
static IAttachmentCacheService AttachmentCacheService
AttachmentCache service.
Definition: ServiceRef.cs:274
static IReportingStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:370
static IXmppService XmppService
The XMPP service for XMPP communication.
Definition: ServiceRef.cs:190
A base class for all view models, inheriting from the BindableObject. NOTE: using this class requir...
virtual async Task GoBack()
Method called when user wants to navigate to the previous screen.
The view model to bind to when displaying petitioning of an identity in a view or page.
ObservableCollection< Photo > Photos
The list of photos related to the identity being petitioned.
override async Task OnInitializeAsync()
Method called when view is initialized for the first time. Use this method to implement registration ...
override async Task OnDisposeAsync()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
PetitionIdentityViewModel(PetitionIdentityNavigationArgs? Args)
Creates a new instance of the PetitionIdentityViewModel class.
Contains a reference to an attachment assigned to a legal object.
Definition: Attachment.cs:10
Maintains information about an item in the roster.
Definition: RosterItem.cs:75
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:58
static string GetBareJID(string JID)
Gets the Bare JID from a JID, which may be a Full JID.
Definition: XmppClient.cs:6958
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static IDatabaseProvider Provider
Registered database provider.
Definition: Database.cs:59
static async Task Update(object Object)
Updates an object in the database.
Definition: Database.cs:1211
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:1291
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Definition: Database.cs:97
Task Flush()
Persists any pending changes.
class Photo(byte[] Binary, int Rotation, Attachment? Attachment)
Class containing information about a photo.
Definition: Photo.cs:10
AuthenticationPurpose
Purpose for requesting the user to authenticate itself.
IdentityState
Lists recognized legal identity states.
SignWith
Options on what keys to use when signing data.
Definition: Enumerations.cs:82