Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PetitionSignatureViewModel.cs
1using CommunityToolkit.Mvvm.ComponentModel;
2using CommunityToolkit.Mvvm.Input;
9using System.Collections.ObjectModel;
10using System.ComponentModel;
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? signatoryIdentityId;
26 private readonly string? petitionId;
27 private readonly byte[]? contentToSign;
28
34 : base()
35 {
36 this.photosLoader = new PhotosLoader(this.Photos);
37
38 if (Args is null)
39 return;
40
41 this.RequestorIdentity = Args.RequestorIdentity;
42 this.requestorFullJid = Args.RequestorFullJid;
43 this.signatoryIdentityId = Args.SignatoryIdentityId;
44 this.contentToSign = Args.ContentToSign;
45 this.petitionId = Args.PetitionId;
46 this.Purpose = Args.Purpose;
47 }
48
50 public override async Task OnInitializeAsync()
51 {
52 await base.OnInitializeAsync();
53
54 this.AssignProperties();
55
56 if (this.RequestorIdentity?.Attachments is not null)
57 _ = this.photosLoader.LoadPhotos(this.RequestorIdentity.Attachments, SignWith.LatestApprovedId);
58 }
59
61 public override async Task OnDisposeAsync()
62 {
63 this.photosLoader.CancelLoadPhotos();
64
65 await base.OnDisposeAsync();
66 }
67
71 public ObservableCollection<Photo> Photos { get; } = [];
72
76 public LegalIdentity? RequestorIdentity { get; private set; }
77
78 [RelayCommand]
79 private async Task Accept()
80 {
81 if (!await this.authenticationService.AuthenticateUserAsync(AuthenticationPurpose.AcceptPetitionRequest, true))
82 return;
83
84 bool Succeeded = await ServiceRef.NetworkService.TryRequest(async () =>
85 {
86 byte[] Signature = await ServiceRef.XmppService.Sign(this.contentToSign!, SignWith.LatestApprovedId);
87
88 await ServiceRef.XmppService.SendPetitionSignatureResponse(this.signatoryIdentityId, this.contentToSign!, Signature,
89 this.petitionId!, this.requestorFullJid!, true);
90 });
91
92 if (Succeeded)
93 await this.GoBack();
94 }
95
96 [RelayCommand]
97 private async Task Decline()
98 {
99 bool Succeeded = await ServiceRef.NetworkService.TryRequest(() =>
100 {
101 return ServiceRef.XmppService.SendPetitionSignatureResponse(this.signatoryIdentityId,
102 this.contentToSign!, [], this.petitionId!, this.requestorFullJid!, false);
103 });
104
105 if (Succeeded)
106 await this.GoBack();
107 }
108
109 [RelayCommand]
110 private async Task Ignore()
111 {
112 await this.GoBack();
113 }
114
118 public override Task<string> Title => Task.FromResult(this.FullName);
119
120 // Full name of requesting entity.
121 public string FullName => ContactInfo.GetFullName(this.FirstName, this.MiddleNames, this.LastNames);
122
123 // The display name of the identity. If organization name is available, it is used, otherwise the full name.
124 public string? DisplayName => string.IsNullOrEmpty(this.Domain) ? (this.HasOrg ? this.OrgName : this.FullName) : this.Domain;
125
126
130 [ObservableProperty]
131 [DefaultValue(false)]
132 private bool hasDomain;
133
134 #region Properties
135
139 [ObservableProperty]
140 private DateTime? created;
141
145 [ObservableProperty]
146 private DateTime? updated;
147
151 [ObservableProperty]
152 private DateTime? expires;
153
157 [ObservableProperty]
158 private string? legalId;
159
163 [ObservableProperty]
164 private string? networkId;
165
169 [ObservableProperty]
170 private IdentityState? state;
171
175 [ObservableProperty]
176 private DateTime? from;
177
181 [ObservableProperty]
182 private DateTime? to;
183
187 [ObservableProperty]
188 [NotifyPropertyChangedFor(nameof(FullName))]
189 [NotifyPropertyChangedFor(nameof(DisplayName))]
190
191 private string? firstName;
192
196 [ObservableProperty]
197 [NotifyPropertyChangedFor(nameof(FullName))]
198 [NotifyPropertyChangedFor(nameof(DisplayName))]
199
200 private string? middleNames;
201
205 [ObservableProperty]
206 [NotifyPropertyChangedFor(nameof(FullName))]
207 [NotifyPropertyChangedFor(nameof(DisplayName))]
208 private string? lastNames;
209
210 [ObservableProperty]
211 [NotifyPropertyChangedFor(nameof(DisplayName))]
212 private string? domain;
213
217 [ObservableProperty]
218 private string? personalNumber;
219
223 [ObservableProperty]
224 private string? address;
225
229 [ObservableProperty]
230 private string? address2;
231
235 [ObservableProperty]
236 private string? zipCode;
237
241 [ObservableProperty]
242 private string? area;
243
247 [ObservableProperty]
248 private string? city;
249
253 [ObservableProperty]
254 private string? region;
255
259 [ObservableProperty]
260 private string? countryCode;
261
265 [ObservableProperty]
266 private string? nationalityCode;
267
271 [ObservableProperty]
272 private string? gender;
273
277 [ObservableProperty]
278 private DateTime? birthDate;
279
283 [ObservableProperty]
284 [NotifyPropertyChangedFor(nameof(DisplayName))]
285 private string? orgName;
286
290 [ObservableProperty]
291 private string? orgNumber;
292
296 [ObservableProperty]
297 private string? orgDepartment;
298
302 [ObservableProperty]
303 private string? orgRole;
304
308 [ObservableProperty]
309 private string? orgAddress;
310
314 [ObservableProperty]
315 private string? orgAddress2;
316
320 [ObservableProperty]
321 private string? orgZipCode;
322
326 [ObservableProperty]
327 private string? orgArea;
328
332 [ObservableProperty]
333 private string? orgCity;
334
338 [ObservableProperty]
339 private string? orgRegion;
340
344 [ObservableProperty]
345 private string? orgCountryCode;
346
350 [ObservableProperty]
351 [NotifyPropertyChangedFor(nameof(DisplayName))]
352 private bool hasOrg;
353
357 [ObservableProperty]
358 private bool hasPhotos;
359
363 [ObservableProperty]
364 private string? phoneNr;
365
369 [ObservableProperty]
370 private string? eMail;
371
375 [ObservableProperty]
376 private string? deviceId;
377
381 [ObservableProperty]
382 private bool isApproved;
383
387 [ObservableProperty]
388 private string? purpose;
389
393 [ObservableProperty]
394 private ImageSource? firstPhotoSource;
395
399 [ObservableProperty]
400 private int firstPhotoRotation;
401
402 #endregion
403
404 private void AssignProperties()
405 {
406 if (this.RequestorIdentity is not null)
407 {
408 this.Created = this.RequestorIdentity.Created;
409 this.Updated = this.RequestorIdentity.Updated.GetDateOrNullIfMinValue();
410 this.Expires = this.RequestorIdentity.To.GetDateOrNullIfMinValue();
411 this.LegalId = this.RequestorIdentity.Id;
412 this.NetworkId = this.RequestorIdentity.GetJid();
413 this.State = this.RequestorIdentity.State;
414 this.From = this.RequestorIdentity.From.GetDateOrNullIfMinValue();
415 this.To = this.RequestorIdentity.To.GetDateOrNullIfMinValue();
417 this.MiddleNames = this.RequestorIdentity[Constants.XmppProperties.MiddleNames];
419 this.PersonalNumber = this.RequestorIdentity[Constants.XmppProperties.PersonalNumber];
426 this.CountryCode = this.RequestorIdentity[Constants.XmppProperties.Country];
427 this.NationalityCode = this.RequestorIdentity[Constants.XmppProperties.Nationality];
430 this.HasDomain = !string.IsNullOrEmpty(this.Domain);
431
432 string BirthDayStr = this.RequestorIdentity[Constants.XmppProperties.BirthDay];
433 string BirthMonthStr = this.RequestorIdentity[Constants.XmppProperties.BirthMonth];
434 string BirthYearStr = this.RequestorIdentity[Constants.XmppProperties.BirthYear];
435
436 if (!string.IsNullOrEmpty(BirthDayStr) && int.TryParse(BirthDayStr, out int BirthDay) &&
437 !string.IsNullOrEmpty(BirthMonthStr) && int.TryParse(BirthMonthStr, out int BirthMonth) &&
438 !string.IsNullOrEmpty(BirthYearStr) && int.TryParse(BirthYearStr, out int BirthYear))
439 {
440 try
441 {
442 this.BirthDate = new DateTime(BirthYear, BirthMonth, BirthDay);
443 }
444 catch (Exception ex)
445 {
446 ServiceRef.LogService.LogException(ex);
447 this.BirthDate = null;
448 }
449 }
450
453 this.OrgDepartment = this.RequestorIdentity[Constants.XmppProperties.OrgDepartment];
456 this.OrgAddress2 = this.RequestorIdentity[Constants.XmppProperties.OrgAddress2];
461 this.OrgCountryCode = this.RequestorIdentity[Constants.XmppProperties.OrgCountry];
462 this.HasOrg =
463 !string.IsNullOrEmpty(this.OrgName) ||
464 !string.IsNullOrEmpty(this.OrgNumber) ||
465 !string.IsNullOrEmpty(this.OrgDepartment) ||
466 !string.IsNullOrEmpty(this.OrgRole) ||
467 !string.IsNullOrEmpty(this.OrgAddress) ||
468 !string.IsNullOrEmpty(this.OrgAddress2) ||
469 !string.IsNullOrEmpty(this.OrgZipCode) ||
470 !string.IsNullOrEmpty(this.OrgArea) ||
471 !string.IsNullOrEmpty(this.OrgCity) ||
472 !string.IsNullOrEmpty(this.OrgRegion) ||
473 !string.IsNullOrEmpty(this.OrgCountryCode);
474 this.HasPhotos = this.Photos.Count > 0;
475 this.PhoneNr = this.RequestorIdentity[Constants.XmppProperties.Phone];
478 this.IsApproved = this.RequestorIdentity.State == IdentityState.Approved;
479 }
480 else
481 {
482 this.Created = DateTime.MinValue;
483 this.Updated = null;
484 this.LegalId = Constants.NotAvailableValue;
485 this.NetworkId = Constants.NotAvailableValue;
486 this.State = IdentityState.Compromised;
487 this.From = null;
488 this.To = null;
489 this.FirstName = Constants.NotAvailableValue;
490 this.MiddleNames = Constants.NotAvailableValue;
491 this.LastNames = Constants.NotAvailableValue;
492 this.PersonalNumber = Constants.NotAvailableValue;
493 this.Address = Constants.NotAvailableValue;
494 this.Address2 = Constants.NotAvailableValue;
495 this.ZipCode = Constants.NotAvailableValue;
496 this.Area = Constants.NotAvailableValue;
497 this.City = Constants.NotAvailableValue;
498 this.Region = Constants.NotAvailableValue;
499 this.CountryCode = Constants.NotAvailableValue;
500 this.NationalityCode = Constants.NotAvailableValue;
501 this.Gender = Constants.NotAvailableValue;
502 this.BirthDate = null;
503 this.OrgName = Constants.NotAvailableValue;
504 this.OrgNumber = Constants.NotAvailableValue;
505 this.OrgDepartment = Constants.NotAvailableValue;
506 this.OrgRole = Constants.NotAvailableValue;
507 this.OrgAddress = Constants.NotAvailableValue;
508 this.OrgAddress2 = Constants.NotAvailableValue;
509 this.OrgZipCode = Constants.NotAvailableValue;
510 this.OrgArea = Constants.NotAvailableValue;
511 this.OrgCity = Constants.NotAvailableValue;
512 this.OrgRegion = Constants.NotAvailableValue;
513 this.OrgCountryCode = Constants.NotAvailableValue;
514 this.HasOrg = false;
515 this.HasPhotos = false;
516 this.PhoneNr = Constants.NotAvailableValue;
517 this.EMail = Constants.NotAvailableValue;
518 this.DeviceId = Constants.NotAvailableValue;
519 this.IsApproved = false;
520 }
521
522 // QR
523 if (this.RequestorIdentity is null)
524 this.RemoveQrCode();
525 else
526 this.GenerateQrCode(Constants.UriSchemes.CreateIdUri(this.RequestorIdentity.Id));
527
528 if (this.IsConnected)
529 this.ReloadPhotos();
530 }
531
533 protected override Task XmppService_ConnectionStateChanged(object? Sender, XmppState NewState)
534 {
535 return MainThread.InvokeOnMainThreadAsync(async () =>
536 {
537 await base.XmppService_ConnectionStateChanged(Sender, NewState);
538
539 if (this.IsConnected)
540 {
541 await Task.Delay(Constants.Timeouts.XmppInit);
542 this.ReloadPhotos();
543 }
544 });
545 }
546
547 private async void ReloadPhotos()
548 {
549 try
550 {
551 this.photosLoader.CancelLoadPhotos();
552
553 Attachment[]? Attachments = this.RequestorIdentity?.Attachments;
554
555 if (Attachments is not null)
556 {
557 Photo? First = await this.photosLoader.LoadPhotos(Attachments, SignWith.LatestApprovedIdOrCurrentKeys);
558
559 this.FirstPhotoSource = First?.Source;
560 this.FirstPhotoRotation = First?.Rotation ?? 0;
561 }
562 }
563 catch (Exception ex)
564 {
565 ServiceRef.LogService.LogException(ex);
566 }
567 }
568
572 [RelayCommand]
573 private async Task Copy(object Item)
574 {
575 try
576 {
577 if (Item is string Label)
578 {
579 if (Label == this.LegalId)
580 {
581 await Clipboard.SetTextAsync(Constants.UriSchemes.IotId + ":" + this.LegalId);
582 await ServiceRef.UiService.DisplayAlert(
585 }
586 else
587 {
588 await Clipboard.SetTextAsync(Label);
589 await ServiceRef.UiService.DisplayAlert(
592 }
593 }
594 }
595 catch (Exception ex)
596 {
597 ServiceRef.LogService.LogException(ex);
598 await ServiceRef.UiService.DisplayException(ex);
599 }
600 }
601 }
602}
static readonly TimeSpan XmppInit
XMPP Init timeout
Definition: Constants.cs:707
static string CreateIdUri(string id)
Generates a IoT ID Uri form the specified id.
Definition: Constants.cs:252
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 Domain
Domain name.
Definition: Constants.cs:534
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 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 SuccessTitle
Looks up a localized string similar to Success.
Contains information about a contact.
Definition: ContactInfo.cs:22
static string GetFullName(LegalIdentity? Identity)
Gets the full name of a person.
Definition: ContactInfo.cs:578
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 IReportingStringLocalizer Localizer
Localization service
Definition: ServiceRef.cs:370
static IXmppService XmppService
The XMPP service for XMPP communication.
Definition: ServiceRef.cs:190
virtual async Task GoBack()
Method called when user wants to navigate to the previous screen.
Holds navigation parameters specific to views displaying a petition of a signature.
The view model to bind to when displaying petitioning of a signature in a view or page.
ObservableCollection< Photo > Photos
The list of photos related to the identity being petitioned.
override async Task OnDisposeAsync()
Method called when the view is disposed, and will not be used more. Use this method to unregister eve...
override async Task OnInitializeAsync()
Method called when view is initialized for the first time. Use this method to implement registration ...
PetitionSignatureViewModel(PetitionSignatureNavigationArgs? Args)
Creates a new instance of the PetitionSignatureViewModel class.
override Task XmppService_ConnectionStateChanged(object? Sender, XmppState NewState)
Listens to connection state changes from the XMPP server.
A view model that holds the XMPP state.
void RemoveQrCode()
Removes the QR-code
void GenerateQrCode(string Uri)
Generates a QR-code
Contains a reference to an attachment assigned to a legal object.
Definition: Attachment.cs:10
Abstract base class of signatures
Definition: Signature.cs:10
Definition: ImplTypes.g.cs:58
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
XmppState
State of XMPP connection.
Definition: XmppState.cs:7