5using System.Threading.Tasks;
43 : base(
"Legal/AddIdAttachment",
44 new KeyValuePair<Type,
Expression>(typeof(Dictionary<string, object>), new
Expression(jsonPattern)),
64 string KeyId = (string)Parameters[
"PKeyId"].AssociatedObjectValue;
65 string Nonce = (string)Parameters[
"PNonce"].AssociatedObjectValue;
66 string KeySignature = (string)Parameters[
"PKeySignature"].AssociatedObjectValue;
67 string RequestSignature = (string)Parameters[
"PRequestSignature"].AssociatedObjectValue;
69 string AttachmentBase64 = (string)Parameters[
"PAttachmentBase64"].AssociatedObjectValue;
70 string AttachmentFileName = (string)Parameters[
"PAttachmentFileName"].AssociatedObjectValue;
71 string AttachmentContentType = (string)Parameters[
"PAttachmentContentType"].AssociatedObjectValue;
72 StringBuilder sb =
new StringBuilder();
74 object DecodedAttachment;
76 if (
string.IsNullOrEmpty(KeyId))
82 if (
string.IsNullOrEmpty(Nonce) || Nonce.Length < 32)
96 if (Identity.Account != User.
UserName)
102 if (Identity.
State != IoTBroker.Legal.Identity.IdentityState.Created)
104 await Response.
SendResponse(
new ForbiddenException(Request,
"Attachments can only be added to newly created identities before they are approved."));
144 sb.Append(KeySignature);
146 string s2 = sb.ToString();
151 sb.Append(AttachmentBase64);
153 sb.Append(AttachmentFileName);
155 sb.Append(AttachmentContentType);
157 sb.Append(LegalId.
Value);
159 string s3 = sb.ToString();
161 string s = Convert.ToBase64String(
164 Encoding.UTF8.GetBytes(s3)));
166 if (s != RequestSignature)
168 string Msg =
"Request Signature invalid.";
175 string Msg =
"Nonce value has already been used.";
184 Attachment = Convert.FromBase64String(AttachmentBase64);
208 string AttachmentSignatureBase64 = Convert.ToBase64String(AttachmentSignature);
212 if (Convert.ToBase64String(Ref.
Signature) == s)
220 bool IncNrPeerReviews =
false;
221 List<LegalIdentity> Reviewers =
null;
222 string LegalNamespace = NamespaceLegalIdentity(Identity.Version);
224 if (DecodedAttachment is XmlDocument Doc)
226 if (Doc.DocumentElement.LocalName ==
"identityReview" &&
227 Doc.DocumentElement.NamespaceURI == LegalNamespace)
232 else if (Doc.DocumentElement.LocalName ==
"peerReview" &&
233 Doc.DocumentElement.NamespaceURI == LegalNamespace)
239 bool ReviewedHasStatus =
false;
240 bool ReviewerHasStatus =
false;
241 byte[] PeerSignature = Convert.FromBase64String(
XML.
Attribute(Doc.DocumentElement,
"s"));
242 DateTime TP =
XML.
Attribute(Doc.DocumentElement,
"tp", DateTime.Now);
243 byte[] SignedIdentity =
null;
244 DateTime UtcNow = DateTime.UtcNow;
246 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
248 if (!(N is XmlElement
E) || N.NamespaceURI != LegalNamespace)
251 foreach (XmlNode N2
in E.ChildNodes)
253 if (N2 is XmlElement E2 &&
254 E2.LocalName ==
"identity" &&
255 E2.NamespaceURI == LegalNamespace)
260 ReviewedIdentity =
LegalIdentity.Parse(E2, out ReviewedHasStatus,
261 out Dictionary<string, string> ReviewedIdentityAttachmentsUrls);
264 ReviewedIdentity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
XmppServerModule.Legal);
265 string s1 = sb.ToString();
268 Identity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
XmppServerModule.Legal);
278 ReviewedIdentity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true, ReviewedIdentityAttachmentsUrls,
XmppServerModule.Legal);
279 SignedIdentity = Encoding.UTF8.GetBytes(sb.ToString());
283 ReviewerIdentity =
LegalIdentity.Parse(E2, out ReviewerHasStatus,
284 out Dictionary<string, string> ReviewerIdentityAttachmentsUrls);
287 ReviewerIdentity.Serialize(sb,
false,
false,
false,
false,
false,
false,
false,
null,
XmppServerModule.Legal);
288 byte[] Data = Encoding.UTF8.GetBytes(sb.ToString());
293 (ReviewerIdentity,
_) = await
XmppServerModule.Legal.ValidateSignature(
new XmppAddress(ReviewerJid), TP, Data, ReviewerIdentity.ClientSignature);
301 if (ReviewerIdentity.State != IoTBroker.Legal.Identity.IdentityState.Approved)
307 if (UtcNow < ReviewerIdentity.From.ToUniversalTime() ||
308 UtcNow > ReviewerIdentity.To.ToUniversalTime())
320 if (
string.IsNullOrEmpty(ReviewerIdentity.ClientKeyName) ||
321 ReviewerIdentity.ClientPubKey is
null ||
322 ReviewerIdentity.ClientPubKey.Length == 0)
328 if (ReviewerIdentity.ClientSignature is
null ||
329 ReviewerIdentity.ClientSignature.Length == 0)
347 if (ReviewedIdentity is
null || !ReviewedHasStatus ||
348 ReviewerIdentity is
null || !ReviewerHasStatus ||
349 SignedIdentity is
null)
363 if (!ReviewerIdentity.ValidateSignature(SignedIdentity, PeerSignature))
389 global::Paiwise.PersonalInformation RI = GetPersonalInformation(ReviewerIdentity);
467 if (Valid.HasValue && !Valid.Value)
565 if (!await CheckPeerReviewFields(ReviewedIdentity, Response))
568 global::Paiwise.PersonalInformation PI = GetPersonalInformation(ReviewedIdentity);
578 if (PI.OrgName != RI.OrgName ||
579 PI.OrgNumber != RI.OrgNumber ||
580 PI.OrgCountry != RI.OrgCountry)
589 LegalIdentity[] Reviewers2 = await GetPeerReviewers(Identity);
600 Reviewers ??=
new List<LegalIdentity>();
601 Reviewers.AddRange(Reviewers2);
605 Reviewers ??=
new List<LegalIdentity>();
606 Reviewers.Add(ReviewerIdentity);
607 IncNrPeerReviews =
true;
619 KeyValuePair<Attachment, AttachmentReference> A =
620 await CreateAttachment(AttachmentFileName, Identity, AttachmentSignature,
621 TempFile, AttachmentContentType, User.
Account,
null,
623 Identity.
To.ToUniversalTime(),
false);
627 List<AttachmentReference> References =
new List<AttachmentReference>();
628 bool Approved =
false;
633 References.Add(A.Value);
634 Identity.Attachments = References.ToArray();
637 if (IncNrPeerReviews)
639 Identity.NrPeerReviews++;
643 Identity.
State == IoTBroker.Legal.Identity.IdentityState.Created)
645 Identity.State = IoTBroker.Legal.Identity.IdentityState.Approved;
652 StringBuilder Markdown =
new StringBuilder();
654 Markdown.AppendLine(
"Peer reviewed Legal ID approved");
655 Markdown.AppendLine(
"===================================");
656 Markdown.AppendLine();
665 XmppServerModule.Legal.AppendMarkdown(Markdown, Reviewer,
"Reviewer " + Index.ToString());
676 if (Identity.
State == IoTBroker.Legal.Identity.IdentityState.Approved)
677 await CopyPropertiesFromApprovedIdentity(Identity,
Account as DataStorage.
Account);
682 Identity.
Id.
Value, BareJid,
"LegalIdUpdated", Identity.GetTags());
685 Identity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true,
null,
XmppServerModule.Legal);
686 string IdentityXml = sb.ToString();
691 if (Approved || Identity.
State == IoTBroker.Legal.Identity.IdentityState.Approved)
695 string JidDomain = i < 0 ? XmppServerModule.Server.Domain : IdentityAddress.
Domain.
Substring(i + 1);
701 XmlDocument IdentityDoc =
XML.
ParseXml(IdentityXml,
true);
705 {
"Identity", IdentityDoc },
712 await DisposableAsync.DisposeAsync();
713 else if (DecodedAttachment is IDisposable Disposable)
714 Disposable.Dispose();
722 global::Paiwise.PersonalInformation PI = GetPersonalInformation(ReviewedIdentity);
797 if (Valid.HasValue && !Valid.Value)
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
Static class managing encoding and decoding of internet content.
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
A Named dictionary is a dictionary, with a local name and a namespace. Use it to return content that ...
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static XmlDocument ParseXml(string Xml)
Parses an XML Document from its string representation.
Static class managing the application event log. Applications and services log events on this static ...
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Static class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static Task< bool > HasNonceBeenUsed(string Nonce)
Checks if a Nonce value has been used.
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
static Task RegisterNonceValue(string Nonce)
Registers a nonce value.
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.
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...
Task Return(Exception ex)
Returns an error to the client.
The server has not found anything matching the Request-URI. No indication is given of whether the con...
Abstract base class for Elliptic Curve endpoints.
override byte[] Sign(byte[] Data)
Signs binary data using the local private key.
XmppAddress MainDomain
Main/principal domain address
Contains information about one XMPP address.
CaseInsensitiveString Domain
Domain
static readonly XmppAddress Empty
Empty address.
Task< bool > SendMessage(string Type, string Id, string From, string To, string Language, string ContentXml)
Sends a Message stanza to a recipient.
CaseInsensitiveString Domain
Domain name.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
string LowerCase
Lower-case representation of the case-insensitive string.
int IndexOf(CaseInsensitiveString value, StringComparison comparisonType)
Reports the zero-based index of the first occurrence of the specified string in the current System....
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
CaseInsensitiveString Substring(int startIndex, int length)
Retrieves a substring from this instance. The substring starts at a specified character position and ...
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.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
Static class managing persistent counters.
static Task< long > IncrementCounter(CaseInsensitiveString Key)
Increments a counter.
Static class managing loading of resources stored as embedded resources or in content files.
static string LoadResourceAsText(string ResourceName)
Loads a text resource from an embedded resource.
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Class managing a script expression.
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.
Contains information about a broker account.
bool Enabled
If account is enabled
string Password
Password of account
Account()
Contains information about a broker account.
Account Account
Account object.
string UserName
User Name.
Represents an attachment to a document.
Represents an attachment to a document.
string ContentType
Internet Content Type of binary attachment.
byte[] Signature
Binary signature of the attachment, generated by an approved legal identity of the account-holder....
Data in accordance with ISO 3166
static bool TryGetCountry(string Code, out string Country)
Tries to get the Country Name from a ISO 3166-1 Country Code. String comparisons are case-insensitive...
CaseInsensitiveString Id
ID of the legal identity
AttachmentReference[] Attachments
Attachments assigned to the legal identity.
DateTime To
To what point in time the legal identity is valid.
IdentityState State
Current state of identity
Personal Number Schemes available in different countries.
static async Task< bool?> IsValid(string CountryCode, string PersonalNumber)
Checks if a personal number is valid, in accordance with registered personal number schemes.
Legal (digital identities, smart contracts) service component.
static DateTime UtcNowSecond
Current Date & Time (in UTC), to a precision of one second.
string AttachmentsFolder
Attachments folder.
Provides the user with options to control notifications from the Broker.
static BrokerNotificationConfiguration Instance
Current instance of configuration.
bool PeerReviewApproved
If a notification should be sent when a peer review of a Legal ID has been approved.
Provides the user configuration options regarding peer-review of new legal identities.
bool AllowPeerReview
If peer-review is allowed on the broker.
bool RequireFirstName
If first name is required in applications for them to be peer-reviewable.
int NrReviewersToApprove
Number of peers required to review and approve a legal identity application before it can be approved...
bool RequireBirthDate
If birth date is required in applications for them to be peer-reviewable.
int NrPhotosRequired
Number of photos required in an application for it to be peer-reviewable.
bool RequirePostalCode
If postal code is required in applications for them to be peer-reviewable.
bool IsReviewerAllowed(string Jid, string LegalId)
Checks if a reviewer is allowed to perform peer review, based on the white-list, if configured.
bool RequireCity
If city is required in applications for them to be peer-reviewable.
static PeerReviewConfiguration Instance
Current instance of configuration.
bool RequireNationality
If nationality is required in applications for them to be peer-reviewable.
bool RequireMiddleName
If middle name(s) is/are required in applications for them to be peer-reviewable.
bool RequireRegion
If region is required in applications for them to be peer-reviewable.
bool RequireIso3166Compliance
If country codes are required to be ISO 3166 compliant in applications for them to be peer-reviewable...
bool RequireCountry
If country is required in applications for them to be peer-reviewable.
bool RequirePersonalNumber
If personal number is required in applications for them to be peer-reviewable.
bool RequireAddress
If address is required in applications for them to be peer-reviewable.
bool RequireLastName
If last names is/are is required in applications for them to be peer-reviewable.
bool RequireArea
If area is required in applications for them to be peer-reviewable.
bool RequireGender
If gender is required in applications for them to be peer-reviewable.
Abstract base class for agent resources supporting the POST method.
static AccountUser AssertUserAuthenticated(HttpRequest Request)
Makes sure the request is made by an authenticated API user.
const string AgentNamespace
https://waher.se/Schema/BrokerAgent.xsd
Contains an encrypted key for an agent.
string Namespace
Namespace of algorithm
string LocalName
Local Name of algorithm
Adds an attachment to a new Legal ID
AddIdAttachment()
Adds an attachment to a new Legal ID
override async Task POST(HttpRequest Request, HttpResponse Response, Dictionary< string, IElement > Parameters)
Executes the POST method on the resource.
Applies for a new Legal ID
Service Module hosting the XMPP broker and its components.
Interface for asynchronously disposable objects.
Interface for XMPP user accounts.