7using System.Reflection;
10using System.Threading.Tasks;
12using System.Xml.Schema;
188 private readonly Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, CaseInsensitiveString>> petitionsByBareJid =
new Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, CaseInsensitiveString>>();
193 private readonly
string attachmentsFolder;
214 this.pubsub = PubSub;
217 if (!Directory.Exists(
this.attachmentsFolder))
218 Directory.CreateDirectory(this.attachmentsFolder);
221 this.httpServer.Register(this.attachmentsResource);
223 #region Neuro-Foundation V1 handlers
225 this.
RegisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityNeuroFoundationV1, this.GetPublicKeyHandler,
true);
226 this.
RegisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityNeuroFoundationV1, this.IdApplicationAttributesHandler,
false); ;
227 this.
RegisterIqSetHandler(
"apply", NamespaceLegalIdentityNeuroFoundationV1, this.ApplyHandler,
false);
228 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentitiesHandler,
false);
229 this.
RegisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentityHandler,
false);
230 this.
RegisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityNeuroFoundationV1, this.ValidateSignatureHandler,
false);
231 this.
RegisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.ObsoleteLegalIdentityHandler,
false);
232 this.
RegisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.CompromiseLegalIdentityHandler,
false);
233 this.
RegisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityHandler,
false);
234 this.
RegisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityResponseHandler,
false);
235 this.
RegisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.AddLegalIdAttachmentHandler,
false);
236 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.RemoveLegalIdAttachmentHandler,
false);
237 this.
RegisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureHandler,
false);
238 this.
RegisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureResponseHandler,
false);
239 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityNeuroFoundationV1, this.AuthorizeAccessToIdHandler,
false);
240 this.
RegisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkLegalIdentityHandler,
false);
241 this.
RegisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityNeuroFoundationV1, this.CanSignAsHandler,
false);
242 this.
RegisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityNeuroFoundationV1, this.ReadyForApprovalHandler,
false);
243 this.
RegisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityNeuroFoundationV1, this.GetReviewIdProvidersHandler,
false);
244 this.
RegisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityNeuroFoundationV1, this.SelectReviewServiceHandler,
false);
250 this.
RegisterIqSetHandler(
"createContract", NamespaceSmartContractsNeuroFoundationV1, this.CreateContractHandler,
true);
251 this.
RegisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetCreatedContractsHandler,
false);
252 this.
RegisterIqSetHandler(
"signContract", NamespaceSmartContractsNeuroFoundationV1, this.SignContractHandler,
false);
253 this.
RegisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetSignedContractsHandler,
false);
254 this.
RegisterIqGetHandler(
"getContract", NamespaceSmartContractsNeuroFoundationV1, this.GetContractHandler,
false);
255 this.
RegisterIqGetHandler(
"getContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetContractsHandler,
false);
256 this.
RegisterIqGetHandler(
"isPart", NamespaceSmartContractsNeuroFoundationV1, this.IsPartHandler,
false);
257 this.
RegisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsNeuroFoundationV1, this.ObsoleteContractHandler,
false);
258 this.
RegisterIqSetHandler(
"deleteContract", NamespaceSmartContractsNeuroFoundationV1, this.DeleteContractHandler,
false);
259 this.
RegisterIqSetHandler(
"updateContract", NamespaceSmartContractsNeuroFoundationV1, this.UpdateContractHandler,
false);
260 this.
RegisterIqGetHandler(
"getSchemas", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemasHandler,
false);
261 this.
RegisterIqGetHandler(
"getSchema", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemaHandler,
false);
262 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetLegalIdentitiesOfContractHandler,
false);
263 this.
RegisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetNetworkIdentitiesHandler,
false);
264 this.
RegisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsNeuroFoundationV1, this.SearchPublicContractsHandler,
false);
265 this.
RegisterIqSetHandler(
"petitionContract", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractHandler,
false);
266 this.
RegisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseHandler,
false);
267 this.
RegisterIqSetHandler(
"addAttachment", NamespaceSmartContractsNeuroFoundationV1, this.AddContractAttachmentHandler,
false);
268 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsNeuroFoundationV1, this.RemoveContractAttachmentHandler,
false);
269 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsNeuroFoundationV1, this.AuthorizeAccessToContractHandler,
false);
270 this.
RegisterIqSetHandler(
"contractSigned", NamespaceSmartContractsNeuroFoundationV1, this.ContractSignedHandler,
false);
271 this.
RegisterMessageHandler(
"failContract", NamespaceSmartContractsNeuroFoundationV1, this.FailContractHandler,
false);
275 #region IEEE V1 handlers
277 this.
RegisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityIeeeV1, this.GetPublicKeyHandler,
true);
278 this.
RegisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityIeeeV1, this.IdApplicationAttributesHandler,
false); ;
280 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentitiesHandler,
false);
281 this.
RegisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentityHandler,
false);
282 this.
RegisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityIeeeV1, this.ValidateSignatureHandler,
false);
283 this.
RegisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityIeeeV1, this.ObsoleteLegalIdentityHandler,
false);
284 this.
RegisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityIeeeV1, this.CompromiseLegalIdentityHandler,
false);
285 this.
RegisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityHandler,
false);
286 this.
RegisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityResponseHandler,
false);
287 this.
RegisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityIeeeV1, this.AddLegalIdAttachmentHandler,
false);
288 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityIeeeV1, this.RemoveLegalIdAttachmentHandler,
false);
289 this.
RegisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureHandler,
false);
290 this.
RegisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureResponseHandler,
false);
291 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityIeeeV1, this.AuthorizeAccessToIdHandler,
false);
292 this.
RegisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityIeeeV1, this.GetNetworkLegalIdentityHandler,
false);
293 this.
RegisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityIeeeV1, this.CanSignAsHandler,
false);
294 this.
RegisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityIeeeV1, this.ReadyForApprovalHandler,
false);
295 this.
RegisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityIeeeV1, this.GetReviewIdProvidersHandler,
false);
296 this.
RegisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityIeeeV1, this.SelectReviewServiceHandler,
false);
302 this.
RegisterIqSetHandler(
"createContract", NamespaceSmartContractsIeeeV1, this.CreateContractHandler,
true);
303 this.
RegisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsIeeeV1, this.GetCreatedContractsHandler,
false);
304 this.
RegisterIqSetHandler(
"signContract", NamespaceSmartContractsIeeeV1, this.SignContractHandler,
false);
305 this.
RegisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsIeeeV1, this.GetSignedContractsHandler,
false);
306 this.
RegisterIqGetHandler(
"getContract", NamespaceSmartContractsIeeeV1, this.GetContractHandler,
false);
307 this.
RegisterIqGetHandler(
"getContracts", NamespaceSmartContractsIeeeV1, this.GetContractsHandler,
false);
309 this.
RegisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsIeeeV1, this.ObsoleteContractHandler,
false);
310 this.
RegisterIqSetHandler(
"deleteContract", NamespaceSmartContractsIeeeV1, this.DeleteContractHandler,
false);
311 this.
RegisterIqSetHandler(
"updateContract", NamespaceSmartContractsIeeeV1, this.UpdateContractHandler,
false);
312 this.
RegisterIqGetHandler(
"getSchemas", NamespaceSmartContractsIeeeV1, this.GetSchemasHandler,
false);
313 this.
RegisterIqGetHandler(
"getSchema", NamespaceSmartContractsIeeeV1, this.GetSchemaHandler,
false);
314 this.
RegisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsIeeeV1, this.GetLegalIdentitiesOfContractHandler,
false);
315 this.
RegisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsIeeeV1, this.GetNetworkIdentitiesHandler,
false);
316 this.
RegisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsIeeeV1, this.SearchPublicContractsHandler,
false);
317 this.
RegisterIqSetHandler(
"petitionContract", NamespaceSmartContractsIeeeV1, this.PetitionContractHandler,
false);
318 this.
RegisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseHandler,
false);
319 this.
RegisterIqSetHandler(
"addAttachment", NamespaceSmartContractsIeeeV1, this.AddContractAttachmentHandler,
false);
320 this.
RegisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsIeeeV1, this.RemoveContractAttachmentHandler,
false);
321 this.
RegisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsIeeeV1, this.AuthorizeAccessToContractHandler,
false);
322 this.
RegisterIqSetHandler(
"contractSigned", NamespaceSmartContractsIeeeV1, this.ContractSignedHandler,
false);
323 this.
RegisterMessageHandler(
"failContract", NamespaceSmartContractsIeeeV1, this.FailContractHandler,
false);
329 Security.Users.User.UpdatingUserLegalId += this.User_UpdatingUserLegalId;
331 this.Server.OnPresenceLocalSender += this.Server_OnPresenceLocalSender;
332 this.petitions.Removed += this.Petitions_Removed;
333 this.remoteComponents.Removed += this.RemoteComponents_Removed;
344 this.Server.OnPresenceLocalSender -= this.Server_OnPresenceLocalSender;
346 if (!(this.petitions is
null))
348 this.petitions.Removed -= this.Petitions_Removed;
349 this.remoteComponents.Removed -= this.RemoteComponents_Removed;
351 this.petitions =
null;
354 this.transientParameters?.
Dispose();
355 this.transientParameters =
null;
357 this.httpServer.Unregister(this.attachmentsResource);
359 #region Neuro-Foundation V1 handlers
361 this.
UnregisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityNeuroFoundationV1, this.GetPublicKeyHandler,
true);
362 this.
UnregisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityNeuroFoundationV1, this.IdApplicationAttributesHandler,
false); ;
364 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentitiesHandler,
false);
365 this.
UnregisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetLegalIdentityHandler,
false);
366 this.
UnregisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityNeuroFoundationV1, this.ValidateSignatureHandler,
false);
367 this.
UnregisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.ObsoleteLegalIdentityHandler,
false);
368 this.
UnregisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.CompromiseLegalIdentityHandler,
false);
369 this.
UnregisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityHandler,
false);
370 this.
UnregisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionIdentityResponseHandler,
false);
371 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.AddLegalIdAttachmentHandler,
false);
372 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityNeuroFoundationV1, this.RemoveLegalIdAttachmentHandler,
false);
373 this.
UnregisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureHandler,
false);
374 this.
UnregisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityNeuroFoundationV1, this.PetitionSignatureResponseHandler,
false);
375 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityNeuroFoundationV1, this.AuthorizeAccessToIdHandler,
false);
376 this.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkLegalIdentityHandler,
false);
377 this.
UnregisterIqGetHandler(
"canSignAs", NamespaceLegalIdentityNeuroFoundationV1, this.CanSignAsHandler,
false);
378 this.
UnregisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityNeuroFoundationV1, this.ReadyForApprovalHandler,
false);
379 this.
UnregisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityNeuroFoundationV1, this.GetReviewIdProvidersHandler,
false);
380 this.
UnregisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityNeuroFoundationV1, this.SelectReviewServiceHandler,
false);
382 this.
Server.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityNeuroFoundationV1, this.GetNetworkXmppIdentityHandler,
false);
384 this.
Server.
UnregisterIqGetHandler(
"getIdentityReferences", NamespaceLegalIdentityNeuroFoundationV1, this.GetIdentityReferencesHandler,
false);
386 this.
UnregisterIqSetHandler(
"createContract", NamespaceSmartContractsNeuroFoundationV1, this.CreateContractHandler,
true);
387 this.
UnregisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetCreatedContractsHandler,
false);
388 this.
UnregisterIqSetHandler(
"signContract", NamespaceSmartContractsNeuroFoundationV1, this.SignContractHandler,
false);
389 this.
UnregisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetSignedContractsHandler,
false);
390 this.
UnregisterIqGetHandler(
"getContract", NamespaceSmartContractsNeuroFoundationV1, this.GetContractHandler,
false);
391 this.
UnregisterIqGetHandler(
"getContracts", NamespaceSmartContractsNeuroFoundationV1, this.GetContractsHandler,
false);
392 this.
UnregisterIqGetHandler(
"isPart", NamespaceSmartContractsNeuroFoundationV1, this.IsPartHandler,
false);
393 this.
UnregisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsNeuroFoundationV1, this.ObsoleteContractHandler,
false);
394 this.
UnregisterIqSetHandler(
"deleteContract", NamespaceSmartContractsNeuroFoundationV1, this.DeleteContractHandler,
false);
395 this.
UnregisterIqSetHandler(
"updateContract", NamespaceSmartContractsNeuroFoundationV1, this.UpdateContractHandler,
false);
396 this.
UnregisterIqGetHandler(
"getSchemas", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemasHandler,
false);
397 this.
UnregisterIqGetHandler(
"getSchema", NamespaceSmartContractsNeuroFoundationV1, this.GetSchemaHandler,
false);
398 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetLegalIdentitiesOfContractHandler,
false);
399 this.
UnregisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsNeuroFoundationV1, this.GetNetworkIdentitiesHandler,
false);
400 this.
UnregisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsNeuroFoundationV1, this.SearchPublicContractsHandler,
false);
401 this.
UnregisterIqSetHandler(
"petitionContract", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractHandler,
false);
402 this.
UnregisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseHandler,
false);
403 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceSmartContractsNeuroFoundationV1, this.AddContractAttachmentHandler,
false);
404 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsNeuroFoundationV1, this.RemoveContractAttachmentHandler,
false);
405 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsNeuroFoundationV1, this.AuthorizeAccessToContractHandler,
false);
406 this.
UnregisterIqSetHandler(
"contractSigned", NamespaceSmartContractsNeuroFoundationV1, this.ContractSignedHandler,
false);
407 this.
UnregisterMessageHandler(
"failContract", NamespaceSmartContractsNeuroFoundationV1, this.FailContractHandler,
false);
411 #region IEEE V1 handlers
413 this.
UnregisterIqGetHandler(
"getPublicKey", NamespaceLegalIdentityIeeeV1, this.GetPublicKeyHandler,
true);
414 this.
UnregisterIqGetHandler(
"applicationAttributes", NamespaceLegalIdentityIeeeV1, this.IdApplicationAttributesHandler,
false); ;
416 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentitiesHandler,
false);
417 this.
UnregisterIqGetHandler(
"getLegalIdentity", NamespaceLegalIdentityIeeeV1, this.GetLegalIdentityHandler,
false);
418 this.
UnregisterIqGetHandler(
"validateSignature", NamespaceLegalIdentityIeeeV1, this.ValidateSignatureHandler,
false);
419 this.
UnregisterIqSetHandler(
"obsoleteLegalIdentity", NamespaceLegalIdentityIeeeV1, this.ObsoleteLegalIdentityHandler,
false);
420 this.
UnregisterIqSetHandler(
"compromisedLegalIdentity", NamespaceLegalIdentityIeeeV1, this.CompromiseLegalIdentityHandler,
false);
421 this.
UnregisterIqSetHandler(
"petitionIdentity", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityHandler,
false);
422 this.
UnregisterIqSetHandler(
"petitionIdentityResponse", NamespaceLegalIdentityIeeeV1, this.PetitionIdentityResponseHandler,
false);
423 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceLegalIdentityIeeeV1, this.AddLegalIdAttachmentHandler,
false);
424 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceLegalIdentityIeeeV1, this.RemoveLegalIdAttachmentHandler,
false);
425 this.
UnregisterIqSetHandler(
"petitionSignature", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureHandler,
false);
426 this.
UnregisterIqSetHandler(
"petitionSignatureResponse", NamespaceLegalIdentityIeeeV1, this.PetitionSignatureResponseHandler,
false);
427 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceLegalIdentityIeeeV1, this.AuthorizeAccessToIdHandler,
false);
428 this.
UnregisterIqGetHandler(
"getNetworkIdentity", NamespaceLegalIdentityIeeeV1, this.GetNetworkLegalIdentityHandler,
false);
430 this.
UnregisterIqSetHandler(
"readyForApproval", NamespaceLegalIdentityIeeeV1, this.ReadyForApprovalHandler,
false);
431 this.
UnregisterIqGetHandler(
"reviewIdProviders", NamespaceLegalIdentityIeeeV1, this.GetReviewIdProvidersHandler,
false);
432 this.
UnregisterIqSetHandler(
"selectReviewService", NamespaceLegalIdentityIeeeV1, this.SelectReviewServiceHandler,
false);
438 this.
UnregisterIqSetHandler(
"createContract", NamespaceSmartContractsIeeeV1, this.CreateContractHandler,
true);
439 this.
UnregisterIqGetHandler(
"getCreatedContracts", NamespaceSmartContractsIeeeV1, this.GetCreatedContractsHandler,
false);
440 this.
UnregisterIqSetHandler(
"signContract", NamespaceSmartContractsIeeeV1, this.SignContractHandler,
false);
441 this.
UnregisterIqGetHandler(
"getSignedContracts", NamespaceSmartContractsIeeeV1, this.GetSignedContractsHandler,
false);
442 this.
UnregisterIqGetHandler(
"getContract", NamespaceSmartContractsIeeeV1, this.GetContractHandler,
false);
443 this.
UnregisterIqGetHandler(
"getContracts", NamespaceSmartContractsIeeeV1, this.GetContractsHandler,
false);
445 this.
UnregisterIqSetHandler(
"obsoleteContract", NamespaceSmartContractsIeeeV1, this.ObsoleteContractHandler,
false);
446 this.
UnregisterIqSetHandler(
"deleteContract", NamespaceSmartContractsIeeeV1, this.DeleteContractHandler,
false);
447 this.
UnregisterIqSetHandler(
"updateContract", NamespaceSmartContractsIeeeV1, this.UpdateContractHandler,
false);
450 this.
UnregisterIqGetHandler(
"getLegalIdentities", NamespaceSmartContractsIeeeV1, this.GetLegalIdentitiesOfContractHandler,
false);
451 this.
UnregisterIqGetHandler(
"getNetworkIdentities", NamespaceSmartContractsIeeeV1, this.GetNetworkIdentitiesHandler,
false);
452 this.
UnregisterIqGetHandler(
"searchPublicContracts", NamespaceSmartContractsIeeeV1, this.SearchPublicContractsHandler,
false);
453 this.
UnregisterIqSetHandler(
"petitionContract", NamespaceSmartContractsIeeeV1, this.PetitionContractHandler,
false);
454 this.
UnregisterIqSetHandler(
"petitionContractResponse", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseHandler,
false);
455 this.
UnregisterIqSetHandler(
"addAttachment", NamespaceSmartContractsIeeeV1, this.AddContractAttachmentHandler,
false);
456 this.
UnregisterIqSetHandler(
"removeAttachment", NamespaceSmartContractsIeeeV1, this.RemoveContractAttachmentHandler,
false);
457 this.
UnregisterIqSetHandler(
"authorizeAccess", NamespaceSmartContractsIeeeV1, this.AuthorizeAccessToContractHandler,
false);
458 this.
UnregisterIqSetHandler(
"contractSigned", NamespaceSmartContractsIeeeV1, this.ContractSignedHandler,
false);
465 Security.Users.User.UpdatingUserLegalId -= this.User_UpdatingUserLegalId;
467 this.remoteComponents?.
Dispose();
468 this.remoteComponents =
null;
480 Gateway.ContractsClient.PetitionForPeerReviewIDReceived += this.ContractsClient_PetitionForPeerReviewIDReceived;
489 Gateway.ContractsClient.PetitionForPeerReviewIDReceived -= this.ContractsClient_PetitionForPeerReviewIDReceived;
511 if (this.eDaler is
null)
513 else if (this.eDaler != value)
514 throw new InvalidOperationException(
"Not allowed to change component reference.");
528 internal byte[] Sign(
byte[]
Data)
533 internal byte[] Sign(Stream
Data)
552 #region Legal Identities
554 private Task GetPublicKeyHandler(
object Sender,
IqEventArgs e)
556 StringBuilder Xml =
new StringBuilder();
562 Xml.Append(
"<publicKey xmlns='");
564 Xml.Append(
"'><ed448 pub='");
566 Xml.Append(
"' xmlns='");
568 Xml.Append(
"'/></publicKey>");
572 return Task.CompletedTask;
581 public static Tuple<IE2eEndpoint, DateTime?, DateTime?>
GetPublicKey(DateTime? Timestamp)
587 if (!Timestamp.HasValue ||
603 return new Tuple<IE2eEndpoint, DateTime?, DateTime?>(Endpoint, From, To);
606 private Task IdApplicationAttributesHandler(
object Sender,
IqEventArgs e)
608 StringBuilder Xml =
new StringBuilder();
611 Xml.Append(
"<idApplicationAttributes xmlns='");
616 Xml.Append(
"' peerReview='true' nrReviewers='");
618 Xml.Append(
"' nrPhotos='");
620 Xml.Append(
"' iso3166='");
625 Xml.Append(
"<required>FIRST</required>");
628 Xml.Append(
"<required>MIDDLE</required>");
631 Xml.Append(
"<required>LAST</required>");
634 Xml.Append(
"<required>PNR</required>");
637 Xml.Append(
"<required>ADDR</required>");
640 Xml.Append(
"<required>ZIP</required>");
643 Xml.Append(
"<required>AREA</required>");
646 Xml.Append(
"<required>CITY</required>");
649 Xml.Append(
"<required>REGION</required>");
652 Xml.Append(
"<required>COUNTRY</required>");
655 Xml.Append(
"<required>NATIONALITY</required>");
658 Xml.Append(
"<required>GENDER</required>");
662 Xml.Append(
"<required>BDAY</required>");
663 Xml.Append(
"<required>BMONTH</required>");
664 Xml.Append(
"<required>BYEAR</required>");
667 Xml.Append(
"</idApplicationAttributes>");
670 Xml.Append(
"' peerReview='false'/>");
674 return Task.CompletedTask;
677 private async Task ApplyHandler(
object Sender,
IqEventArgs e)
683 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
693 StringBuilder sb =
new StringBuilder();
694 DateTime TP = Next.Value;
695 DateTime Today = DateTime.Today;
697 if (Next.Value == DateTime.MaxValue)
699 sb.Append(
"This endpoint (");
701 sb.Append(
") has been blocked from the system.");
705 sb.Append(
"Too many failed identity applications in a row registered. Try again after ");
706 sb.Append(TP.ToLongTimeString());
708 if (TP.Date != Today)
710 if (TP.Date == Today.AddDays(1))
711 sb.Append(
" tomorrow");
715 sb.Append(TP.ToShortDateString());
719 sb.Append(
". Remote Endpoint: ");
731 foreach (XmlNode N
in e.
Query.ChildNodes)
733 if (N is XmlElement E && E.LocalName ==
"identity" && E.NamespaceURI == e.
Query.NamespaceURI)
738 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when applying for a legal identity.",
"en");
744 if (Identity is
null)
774 if (!Identity.ValidateClientSignature(
this))
787 if (!
string.IsNullOrEmpty(JID) && JID != e.
From.
BareJid)
795 if (!CheckNameWhitespace(
P.Value))
821 if (!
string.IsNullOrEmpty(Domain))
824 string.IsNullOrEmpty(Connection.RemoteEndPoint))
830 if (!IPAddress.TryParse(Connection.RemoteEndPoint.RemovePortNumber(), out IPAddress RemoteAddress))
832 await e.
IqErrorForbidden(e.
To,
"Requests for a DOMAIN identity requires a connection using TCP/IP.",
"en");
836 if (IPAddress.TryParse(Domain, out IPAddress
_))
842 switch (RemoteAddress.AddressFamily)
849 if (Ip4Addresses is
null || Array.IndexOf(Ip4Addresses, RemoteAddress) < 0)
851 await e.
IqErrorForbidden(e.
To,
"Request did not come from the domain specified in DOMAIN.",
"en");
857 await e.
IqErrorForbidden(e.
To,
"Unable to lookup IPv4 address(es) of " + Domain +
".",
"en");
867 if (Ip6Addresses is
null || Array.IndexOf(Ip6Addresses, RemoteAddress) < 0)
869 await e.
IqErrorForbidden(e.
To,
"Request did not come from the domain specified in DOMAIN.",
"en");
875 await e.
IqErrorForbidden(e.
To,
"Unable to lookup IPv6 address(es) of " + Domain +
".",
"en");
881 await e.
IqErrorForbidden(e.
To,
"Requests for a DOMAIN identity requires a connection using TCP/IP.",
"en");
888 Identity.State = Legal.Identity.IdentityState.Created;
890 Identity.Updated = DateTime.MinValue;
891 Identity.From = Identity.
Created.Date;
895 Identity.ObjectId = Guid.NewGuid().ToString();
904 "LegalIdDeleted", ToRemove.GetTags());
910 Identity.Id = Identity.ObjectId +
"@" + this.SubdomainSuffixed + e.
From.
Domain;
916 KeyValuePair<string, object>[] Tags = Identity.GetTags();
921 "LegalIdRegistered", Tags);
926 StringBuilder Xml =
new StringBuilder();
927 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
928 string IdentityXml = Xml.ToString();
935 await AddPreview(Identity);
943 StringBuilder Markdown =
new StringBuilder();
945 Markdown.Append(
"Legal identity application received: [`");
946 Markdown.Append(Identity.
Id);
947 Markdown.Append(
"`](");
949 Markdown.Append(Identity.
Id);
950 Markdown.AppendLine(
")");
951 Markdown.AppendLine();
966 case Legal.Identity.IdentityState.Created:
967 case Legal.Identity.IdentityState.Approved:
972 Markdown.AppendLine(
"Other identities registered for the same account:");
979 Markdown.Append(
"[`");
980 Markdown.Append(ID.
Id);
981 Markdown.Append(
"`](");
983 Markdown.Append(ID.
Id);
984 Markdown.AppendLine(
")");
985 Markdown.AppendLine();
987 Output(Markdown, ID.GetTags());
1005 internal static bool CheckNameWhitespace(
string FullName)
1007 bool LastWhiteSpace =
true;
1009 foreach (
char ch
in FullName)
1011 if (
char.IsWhiteSpace(ch))
1013 if (LastWhiteSpace || ch !=
' ')
1016 LastWhiteSpace =
true;
1019 LastWhiteSpace =
false;
1022 return !LastWhiteSpace;
1032 return GetPersonalInformation(Identity.
Properties);
1040 internal static PersonalInformation GetPersonalInformation(IEnumerable<Property> Properties)
1049 Result.FirstName =
P.Value;
1053 Result.MiddleNames =
P.Value;
1057 Result.LastNames =
P.Value;
1061 Result.FullName =
P.Value;
1065 Result.Address =
P.Value;
1069 Result.Address2 =
P.Value;
1073 Result.PostalCode =
P.Value;
1077 Result.Area =
P.Value;
1081 Result.City =
P.Value;
1085 Result.Region =
P.Value;
1089 Result.Country =
P.Value;
1093 Result.Nationality =
P.Value;
1097 switch (
P.Value.LowerCase)
1100 Result.Gender =
Gender.Male;
1104 Result.Gender =
Gender.Female;
1108 Result.Gender =
Gender.Other;
1114 if (
int.TryParse(
P.Value, out
int i) && i >= 1 && i <= 31)
1115 Result.BirthDay = i;
1119 if (
int.TryParse(
P.Value, out i) && i >= 1 && i <= 12)
1120 Result.BirthMonth = i;
1124 if (
int.TryParse(
P.Value, out i) && i >= 1900 && i <= 2100)
1125 Result.BirthYear = i;
1129 if (
int.TryParse(
P.Value.
ToString(), out i) && i >= 0)
1130 Result.AgeAbove = i;
1134 Result.PersonalNumber =
P.Value;
1138 Result.OrgName =
P.Value;
1139 Result.HasOrg =
true;
1143 Result.OrgDepartment =
P.Value;
1144 Result.HasOrg =
true;
1148 Result.OrgRole =
P.Value;
1149 Result.HasOrg =
true;
1153 Result.OrgAddress =
P.Value;
1154 Result.HasOrg =
true;
1158 Result.OrgAddress2 =
P.Value;
1159 Result.HasOrg =
true;
1163 Result.OrgPostalCode =
P.Value;
1164 Result.HasOrg =
true;
1168 Result.OrgArea =
P.Value;
1169 Result.HasOrg =
true;
1173 Result.OrgCity =
P.Value;
1174 Result.HasOrg =
true;
1178 Result.OrgRegion =
P.Value;
1179 Result.HasOrg =
true;
1183 Result.OrgCountry =
P.Value;
1184 Result.HasOrg =
true;
1188 Result.OrgNumber =
P.Value;
1189 Result.HasOrg =
true;
1193 Result.Phone =
P.Value;
1197 Result.EMail =
P.Value;
1201 Result.Jid =
P.Value;
1206 Result.HasBirthDate =
1207 Result.BirthDay.HasValue &&
1208 Result.BirthMonth.HasValue &&
1209 Result.BirthYear.HasValue &&
1210 Result.BirthDay.Value <= DateTime.DaysInMonth(Result.
BirthYear.Value, Result.
BirthMonth.Value);
1214 Result.BirthDay =
null;
1215 Result.BirthMonth =
null;
1216 Result.BirthYear =
null;
1231 internal static async Task<KeyValuePair<IPhoto[], XmlDocument[]>> GetPhotosAndDocuments(
LegalIdentity Identity,
bool Review)
1241 int i = s.IndexOf(
';');
1243 s = s[..i].TrimEnd();
1248 if (!IsImage && !IsXml)
1254 Bin = await GetPreviewAttachment(Ref);
1262 Aes Aes = Aes.Create();
1264 Aes.BlockSize = 128;
1266 Aes.Mode = CipherMode.CBC;
1267 Aes.Padding = PaddingMode.Zeros;
1269 byte[] Key =
new byte[32];
1270 byte[] IV =
new byte[16];
1275 using ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV);
1276 using CryptoStream DecryptedAttachmentFile =
new CryptoStream(AttachmentFile, Decryptor, CryptoStreamMode.Read);
1279 Bin = await DecryptedAttachmentFile.ReadAllAsync(c);
1286 XmlDocument Doc =
new XmlDocument();
1290 Doc.Load(
new MemoryStream(Bin));
1292 catch (Exception ex)
1303 return new KeyValuePair<IPhoto[], XmlDocument[]>(Photos.
ToArray(), Documents.
ToArray());
1313 DateTime TP = DateTime.UtcNow;
1314 TP =
new DateTime(TP.Year, TP.Month, TP.Day, TP.Hour, TP.Minute, TP.Second, DateTimeKind.Utc);
1319 internal static void Output(StringBuilder Markdown, KeyValuePair<string, object>[] Tags)
1321 Output(Markdown, Tags,
true);
1324 internal static void Output(StringBuilder Markdown, KeyValuePair<string, object>[] Tags,
bool IncludeHeader)
1328 Markdown.AppendLine(
"| Key | Value |");
1329 Markdown.AppendLine(
"|:----|:------|");
1332 foreach (KeyValuePair<string, object> Tag
in Tags)
1334 Markdown.Append(
"| ");
1335 Markdown.Append(
MarkdownDocument.
Encode(Tag.Key).Replace(
"\r\n",
"\n").Replace(
"\n",
"<br/>").Replace(
"\r",
"<br/>"));
1336 Markdown.Append(
" | ");
1338 if (!(Tag.Value is
null))
1339 Markdown.Append(
MarkdownDocument.
Encode(Tag.Value.ToString()).Replace(
"\r\n",
"\n").Replace(
"\n",
"<br/>").Replace(
"\r",
"<br/>"));
1341 Markdown.AppendLine(
" |");
1345 private async Task GetLegalIdentitiesHandler(
object Sender,
IqEventArgs e)
1351 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
1361 catch (Exception ex)
1367 private string SerializeIdentities(IEnumerable<LegalIdentity> Identities, IEnumerable<Dictionary<string, string>> AttachmentUrls,
1370 using IEnumerator<Dictionary<string, string>> e = AttachmentUrls?.GetEnumerator();
1371 StringBuilder Xml =
new StringBuilder();
1373 Xml.Append(
"<identities xmlns='");
1378 Identity.Serialize(Xml, Identity.Version != Version,
true,
true,
true,
true,
true,
true, (e?.MoveNext() ??
false) ? e.Current :
null,
this);
1380 Xml.Append(
"</identities>");
1382 return Xml.ToString();
1385 internal static async Task<LegalIdentity> GetLocalLegalIdentity(
string LegalId)
1387 KeyValuePair<LegalIdentity, bool>
P = await GetLocalLegalIdentity(LegalId,
false);
1398 string Folder = Gateway.AppDataFolder is
null ?
"Previews" :
1401 if (!Directory.Exists(Folder))
1402 Directory.CreateDirectory(Folder);
1407 internal static string GetPreviewFileName(
string Id,
string Extension)
1410 int i = Id.IndexOf(
'@');
1414 string FileName = Path.Combine(Folder, Id + Extension);
1415 FileName = Path.GetFullPath(FileName);
1420 internal static string GetPreviewKey(
string FileName)
1422 StringBuilder sb =
new StringBuilder();
1423 sb.Append(FileName);
1427 string Key = sb.ToString();
1433 internal static async Task<byte[]> CreatePreviewSalt(
string FileName,
string UserName)
1435 string Key = GetPreviewKey(FileName);
1436 return await
XmppServerModule.CreateSalt(Key, Encoding.UTF8.GetBytes(UserName));
1439 internal static async Task<KeyValuePair<byte[], string>> GetPreviewSalt(
string FileName)
1441 string Key = GetPreviewKey(FileName);
1442 KeyValuePair<byte[], byte[]>
P = await
XmppServerModule.GetSaltWithAdditionalData(Key);
1443 string UserName = Encoding.UTF8.GetString(
P.Value);
1444 return new KeyValuePair<byte[], string>(
P.Key, UserName);
1447 internal static async Task<bool> RemovePreviewSalt(
string FileName)
1449 string Key = GetPreviewKey(FileName);
1453 private static async Task AddPreview(
LegalIdentity Identity)
1455 string FileName = GetPreviewFileName(Identity.
Id,
".id");
1456 byte[] Salt = await CreatePreviewSalt(FileName, Identity.Account.
Value);
1458 StringBuilder sb =
new StringBuilder();
1459 Identity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true,
null,
XmppServerModule.Legal);
1461 byte[]
Data = Encoding.UTF8.GetBytes(sb.ToString());
1468 internal static async Task<KeyValuePair<LegalIdentity, bool>> GetLocalLegalIdentity(
string LegalId,
bool IncludePreviews)
1471 if (!(Identity is
null))
1472 return new KeyValuePair<LegalIdentity, bool>(Identity,
false);
1474 if (!IncludePreviews)
1475 return new KeyValuePair<LegalIdentity, bool>(
null,
false);
1477 string FileName = GetPreviewFileName(LegalId,
".id");
1478 if (!File.Exists(FileName))
1479 return new KeyValuePair<LegalIdentity, bool>(
null,
false);
1481 Identity = await GetPreviewIdentity(FileName);
1482 return new KeyValuePair<LegalIdentity, bool>(Identity, !(Identity is
null));
1485 internal static async Task<LegalIdentity> GetPreviewIdentity(
string FileName)
1487 KeyValuePair<byte[], string>
P = await GetPreviewSalt(FileName);
1491 byte[] Salt =
P.Key;
1492 string UserName =
P.Value;
1495 string s = Encoding.UTF8.GetString(
Data);
1497 XmlDocument Doc =
new XmlDocument();
1501 Identity.Account = UserName;
1506 internal static async Task<byte[]> GetPreviewAttachment(
string AttachmentId)
1508 string AttachmentFileName = GetPreviewFileName(AttachmentId,
".att");
1509 KeyValuePair<byte[], string>
P = await GetPreviewSalt(AttachmentFileName);
1510 byte[] Salt =
P.Key;
1515 return await Decoded.ReadAllAsync();
1528 internal async Task<int> DeleteOldPreviewApplications(
int KeepDays)
1531 string[] FileNames = Directory.GetFiles(Folder,
"*.*", SearchOption.TopDirectoryOnly);
1532 DateTime Limit = DateTime.UtcNow.AddDays(-KeepDays);
1535 foreach (
string FileName
in FileNames)
1539 if (File.GetCreationTimeUtc(FileName) > Limit)
1542 bool IsPreviewIdFile =
string.Compare(Path.GetExtension(FileName),
".id",
true) == 0;
1544 if (IsPreviewIdFile)
1548 LegalIdentity Identity = await GetPreviewIdentity(FileName);
1550 if (!(Identity is
null))
1552 await this.UpdateState(Identity, Legal.Identity.IdentityState.Obsoleted,
1553 Array.Empty<
string>(),
null,
true,
false,
null);
1556 catch (Exception ex)
1562 File.Delete(FileName);
1565 if (IsPreviewIdFile)
1568 catch (Exception ex)
1577 private async Task GetLegalIdentityHandler(
object Sender,
IqEventArgs e)
1583 KeyValuePair<LegalIdentity, bool>
P = await GetLocalLegalIdentity(Id,
true);
1585 bool Preview =
P.Value;
1587 if (Identity is
null)
1594 this.Server.IsServerDomain(e.
From.
Domain,
true)) ||
1595 (!Preview &&
this.IsAccessToIdentityAuthorized(e.
From.
BareJid, Identity.
Id)))
1599 StringBuilder Xml =
new StringBuilder();
1600 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
1607 await e.
IqErrorForbidden(e.
To,
"A client can only access its own legal identities, and the legal identities of parts in smart contracts to which the client is part.",
"en");
1610 catch (Exception ex)
1616 private async Task PetitionIdentityHandler(
object Sender,
IqEventArgs e)
1625 byte[]
Data = Encoding.UTF8.GetBytes(PetitionId +
":" + LegalId +
":" + Purpose +
":" + Nonce +
":" + e.
From.
BareJid.
LowerCase);
1627 if (!TryGetContext(e.
Query, out XmlElement ContextXml, out
string _,
1628 out
string[] Properties, out
string[] Attachments))
1634 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
1635 if (Identity is
null)
1643 string JidDomain = i < 0 ? this.Server.Domain : LegalIdAddr.
Domain.
Substring(i + 1);
1645 (
LegalIdentity RequestorIdentity, Dictionary<string, string> RequestorAttachmentUrls) = await this.ValidateSenderSignature(
1648 if (RequestorIdentity is
null)
1651 StringBuilder Msg =
new StringBuilder();
1653 Msg.Append(
"<petitionIdentityMsg id=\"");
1655 Msg.Append(
"\" pid=\"");
1657 Msg.Append(
"\" from=\"");
1659 Msg.Append(
"\" purpose=\"");
1663 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
1665 Msg.Append(
"\" clientEp=\"");
1666 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
1670 ClientInformation ClientInfo = await this.GetNetworkIdentity(RequestorIdentity.
Id,
true,
false, Identity.Version);
1671 if (!(ClientInfo is
null))
1673 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
1675 if (!
string.IsNullOrEmpty(ClientEndpoint))
1677 Msg.Append(
"\" clientEp=\"");
1683 Msg.Append(
"\" xmlns=\"");
1687 this.Append(Msg, Properties, Attachments, ContextXml,
null, RequestorIdentity,
1688 Identity.Version, RequestorAttachmentUrls);
1690 Msg.Append(
"</petitionIdentityMsg>");
1697 catch (Exception ex)
1703 private void Append(StringBuilder Msg,
string[] Properties,
string[] Attachments,
1705 NamespaceSet RequestNamespace, Dictionary<string, string> RequestorAttachmentUrls)
1707 if (!(Properties is
null))
1709 Msg.Append(
"<properties>");
1711 foreach (
string Property in Properties)
1713 Msg.Append(
"<property>");
1715 Msg.Append(
"</property>");
1718 Msg.Append(
"</properties>");
1721 if (!(Attachments is
null))
1723 Msg.Append(
"<attachments>");
1727 Msg.Append(
"<attachment>");
1729 Msg.Append(
"</attachment>");
1732 Msg.Append(
"</attachments>");
1735 RequestorIdentity?.Serialize(Msg, RequestorIdentity.Version != RequestNamespace,
1736 true,
true,
true,
true,
true,
true, RequestorAttachmentUrls,
this);
1738 if (!
string.IsNullOrEmpty(
Content))
1740 Msg.Append(
"<content>");
1742 Msg.Append(
"</content>");
1745 if (!(ContextXml is
null))
1746 Msg.Append(ContextXml.OuterXml);
1749 private static bool TryGetContext(XmlElement Query, out XmlElement Context,
1750 out
string Content, out
string[] Properties, out
string[] Attachments)
1761 foreach (XmlNode N
in Query)
1763 if (!(N is XmlElement E))
1766 if (IsIdentityNamespace)
1771 else if (IsContractNamespace)
1778 if (E.NamespaceURI != Query.NamespaceURI)
1782 switch (E.LocalName)
1785 if (
string.IsNullOrEmpty(
Content))
1794 foreach (XmlNode N2
in E.ChildNodes)
1796 if (!(N2 is XmlElement E2))
1799 if (E2.LocalName ==
"property")
1802 PropertyList.
Add(E2.InnerText);
1810 foreach (XmlNode N2
in E.ChildNodes)
1812 if (!(N2 is XmlElement E2))
1815 if (E2.LocalName ==
"attachment")
1818 AttachmentList.
Add(E2.InnerText);
1826 if (Context is
null)
1833 Properties = PropertyList?.
ToArray();
1834 Attachments = AttachmentList?.
ToArray();
1839 private async Task PetitionIdentityResponseHandler(
object Sender,
IqEventArgs e)
1848 XmlElement ContextXml =
null;
1850 foreach (XmlNode N
in e.
Query)
1852 if (!(N is XmlElement E))
1855 if (ContextXml is
null)
1864 Identity = await GetLocalLegalIdentity(LegalId);
1865 if (Identity is
null)
1871 StringBuilder Msg =
new StringBuilder();
1873 Msg.Append(
"<petitionIdentityResponseMsg pid=\"");
1875 Msg.Append(
"\" response=\"");
1879 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
1881 Msg.Append(
"\" clientEp=\"");
1882 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
1885 Msg.Append(
"\" xmlns=\"");
1891 this.IdentityAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, LegalId, Response);
1893 Identity.Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
1896 if (!(ContextXml is
null))
1897 Msg.Append(ContextXml.OuterXml);
1899 Msg.Append(
"</petitionIdentityResponseMsg>");
1905 catch (Exception ex)
1914 this.Authorization(
"I:", ToBareJid, FromBareJid, LegalId, Authorized ? 1 : 0);
1939 this.petitions?.
Add(Key2, Value);
1941 lock (this.petitionsByBareJid)
1943 if (!this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
1945 ByLegalId =
new Dictionary<CaseInsensitiveString, CaseInsensitiveString>();
1946 this.petitionsByBareJid[ToBareJid] = ByLegalId;
1949 ByLegalId[Key1] = FromBareJid;
1954 this.petitions?.
Remove(Key2);
1956 lock (this.petitionsByBareJid)
1958 if (this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId) &&
1959 ByLegalId.Remove(Key1) &&
1960 ByLegalId.Count == 0)
1962 this.petitionsByBareJid.
Remove(ToBareJid);
1973 int i1 = Key.IndexOf(
':');
1976 int i2 = Key.IndexOf(
':', i1 + 1);
1982 lock (this.petitionsByBareJid)
1984 if (this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId) &&
1985 ByLegalId.Remove(Key1) &&
1986 ByLegalId.Count == 0)
1988 this.petitionsByBareJid.
Remove(ToBareJid);
1995 return Task.CompletedTask;
2001 return DisposableAsync.DisposeAsync();
2003 if (e.
Value is IDisposable Disposable)
2004 Disposable.Dispose();
2006 return Task.CompletedTask;
2012 return (this.petitions?.TryGetValue(Key, out
int i) ??
false) && (i > 0);
2015 private async Task Server_OnPresenceLocalSender(
object Sender,
PresenceEventArgs e)
2026 if (N is XmlElement E && E.LocalName ==
"identity" && E.NamespaceURI == Namespace)
2029 if (!(Identity is
null))
2033 if (Identity is
null)
2041 Log.
Warning(
"Client tried to forward someone else's identity in a presence subscription request.",
2044 new KeyValuePair<string, object>(
"ID", Identity.
Id.
Value),
2045 new KeyValuePair<string, object>(
"ID Account", Identity.Account.
Value));
2052 StringBuilder Id1 =
new StringBuilder();
2053 Identity.Serialize(Id1,
true,
true,
true,
true,
true,
true,
false,
null,
this);
2054 string Id1Xml = Id1.ToString();
2056 StringBuilder Id2 =
new StringBuilder();
2057 Identity.Serialize(Id2,
true,
true,
true,
true,
true,
true,
false,
null,
this);
2058 string Id2Xml = Id2.ToString();
2060 if (Id1Xml == Id2Xml)
2064 Log.
Warning(
"Client tried to forward invalid ID in a presence subscription request.",
2067 new KeyValuePair<string, object>(
"ID", Identity.
Id.
Value),
2068 new KeyValuePair<string, object>(
"Attempt", Id1Xml),
2069 new KeyValuePair<string, object>(
"Actual", Id2Xml));
2080 case "unsubscribed":
2081 LinkedList<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> ToRemove =
null;
2083 lock (this.petitionsByBareJid)
2085 if (this.petitionsByBareJid.
TryGetValue(e.
To.
BareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
2087 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>
P in ByLegalId)
2091 ToRemove ??=
new LinkedList<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>>();
2092 ToRemove.AddLast(
P);
2098 if (!(ToRemove is
null))
2100 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>
P in ToRemove)
2101 this.Authorization(
P.Key.Substring(0, 2), e.
To.
BareJid,
P.Value,
P.Key.Substring(2), 0);
2108 private async Task PetitionSignatureHandler(
object Sender,
IqEventArgs e)
2118 if (!TryGetContext(e.
Query, out XmlElement ContextXml, out
string ContentStr,
2119 out
string[] Properties, out
string[] Attachments))
2125 if (ContentStr is
null)
2127 if (ContextXml is
null)
2128 ContentStr = e.
Query.InnerText;
2136 byte[]
Content = Convert.FromBase64String(ContentStr);
2137 string DataStr = PetitionId +
":" + LegalId +
":" + Purpose +
":" + Nonce +
":" + e.From.BareJid.LowerCase +
":" + ContentStr;
2138 byte[]
Data = Encoding.UTF8.GetBytes(DataStr);
2139 string s = Encoding.UTF8.GetString(
Content);
2141 Dictionary<string, string> ReqAttachmentUrls =
null;
2142 bool PeerReview =
false;
2144 if (s.StartsWith(
"<identity") && s.EndsWith(
"</identity>"))
2150 if (Doc.DocumentElement.LocalName ==
"identity")
2156 TempId.
State == Legal.Identity.IdentityState.Created &&
2159 ReqIdentity = TempId;
2164 await e.
IqErrorForbidden(e.
To,
"Signature of identity proving access to private keys not valid.",
"en");
2176 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
2177 if (Identity is
null)
2185 string JidDomain = i < 0 ? this.Server.Domain : LegalIdAddr.
Domain.
Substring(i + 1);
2187 if (ReqIdentity is
null)
2189 (ReqIdentity, ReqAttachmentUrls) = await this.ValidateSenderSignature(e.
From,
new ExternalRequest(e), DateTime.Now,
Data,
Signature, Identity.Account +
"@" + JidDomain);
2190 if (ReqIdentity is
null)
2194 StringBuilder Msg =
new StringBuilder();
2196 Msg.Append(
"<petitionSignatureMsg id=\"");
2198 Msg.Append(
"\" pid=\"");
2200 Msg.Append(
"\" from=\"");
2202 Msg.Append(
"\" purpose=\"");
2206 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
2208 Msg.Append(
"\" clientEp=\"");
2209 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
2213 ClientInformation ClientInfo = await this.GetNetworkIdentity(ReqIdentity.
Id,
true,
false, Identity.Version);
2214 if (!(ClientInfo is
null))
2216 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
2218 if (!
string.IsNullOrEmpty(ClientEndpoint))
2220 Msg.Append(
"\" clientEp=\"");
2226 Msg.Append(
"\" xmlns=\"");
2230 this.Append(Msg, Properties, Attachments, ContextXml,
2231 ContentStr, PeerReview ?
null : ReqIdentity,
2232 Identity.Version, ReqAttachmentUrls);
2236 if (!(ContextXml is
null) &&
2237 ContextXml.LocalName ==
"agentApi" &&
2241 int Timeout =
XML.
Attribute(ContextXml,
"timeout", 3600);
2243 if (Timeout < 1 || Timeout > 3600)
2258 await e.
IqErrorBadRequest(e.
To,
"Requestor lacks DOMAIN property in its legal identity.",
"en");
2262 if (ReqDomain != Domain)
2264 await e.
IqErrorBadRequest(e.
To,
"Requestor domain does not match stated domain in agent API context.",
"en");
2268 this.AgentApiLoginCorrelation(e.
From.
BareJid, ClientBareJid.
Address, PetitionId, Timeout);
2271 Msg.Append(
"</petitionSignatureMsg>");
2277 catch (Exception ex)
2286 this.Authorization(
"A:", ToBareJid, FromBareJid, PetitionId, Timeout);
2294 if (!(this.petitions?.TryGetValue(Key2, out Timeout) ??
false))
2300 lock (this.petitionsByBareJid)
2302 if (!this.petitionsByBareJid.
TryGetValue(ToBareJid, out Dictionary<CaseInsensitiveString, CaseInsensitiveString> ByLegalId))
2308 if (!ByLegalId.TryGetValue(Key1, out
CaseInsensitiveString FromBareJid2) || FromBareJid != FromBareJid2)
2318 private async Task PetitionSignatureResponseHandler(
object Sender,
IqEventArgs e)
2326 string ContentStr =
null;
2327 string SignatureStr =
null;
2331 XmlElement ContextXml =
null;
2333 foreach (XmlNode N
in e.
Query.ChildNodes)
2335 if (!(N is XmlElement E))
2338 if (E.NamespaceURI == e.
Query.NamespaceURI)
2340 switch (E.LocalName)
2343 ContentStr = E.InnerText;
2344 Content = Convert.FromBase64String(ContentStr);
2349 Signature = Convert.FromBase64String(SignatureStr);
2353 else if (ContextXml is
null)
2362 Identity = await GetLocalLegalIdentity(LegalId);
2363 if (Identity is
null)
2369 StringBuilder Msg =
new StringBuilder();
2371 Msg.Append(
"<petitionSignatureResponseMsg pid=\"");
2373 Msg.Append(
"\" response=\"");
2377 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
2379 Msg.Append(
"\" clientEp=\"");
2380 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
2383 Msg.Append(
"\" xmlns=\"");
2407 Msg.Append(
"<signature>");
2408 Msg.Append(SignatureStr);
2409 Msg.Append(
"</signature>");
2410 Identity.Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
2412 this.IdentityAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, LegalId, Response);
2414 if (ContextXml is
null &&
2415 this.IsAgentApiLoginCorrelated(RequestorFullJid.
BareJid, e.
From.
BareJid, PetitionId, out
int Timeout) &&
2419 string RemoteEndPoint;
2424 RemoteEndPoint = XmppServerConnection.RemoteEndPoint;
2426 RemoteEndPoint =
string.Empty;
2428 if (!
string.IsNullOrEmpty(RemoteEndPoint))
2431 int IssuedAt = (int)Math.Round(DateTime.UtcNow.Subtract(
JSON.
UnixEpoch).TotalSeconds);
2432 int Expires = IssuedAt + Timeout;
2441 Msg.Append(
"<agentApiToken xmlns='");
2445 Msg.Append(
"</agentApiToken>");
2449 if (!(ContextXml is
null))
2450 Msg.Append(ContextXml.OuterXml);
2452 Msg.Append(
"</petitionSignatureResponseMsg>");
2459 catch (Exception ex)
2465 private async Task ValidateSignatureHandler(
object Sender,
IqEventArgs e)
2473 string ForBareJid =
null;
2475 foreach (XmlAttribute Attr
in e.
Query.Attributes)
2484 BareJid = Attr.
Value;
2488 Data = Convert.FromBase64String(Attr.Value);
2492 Signature = Convert.FromBase64String(Attr.Value);
2496 ForBareJid = Attr.Value;
2509 await e.
IqErrorBadRequest(e.
To,
"Both the id and bareJid attributes cannot be specified at the same time.",
"en");
2519 Identity = await GetLocalLegalIdentity(Id);
2520 if (Identity is
null)
2541 await e.
IqErrorForbidden(e.
To,
"Bare JID does not correspond to this Trust Provider.",
"en");
2553 DateTime UtcNow = DateTime.UtcNow;
2568 if (Identity is
null)
2570 await e.
IqErrorForbidden(e.
To,
"No matching legal identity found that can validate the signature.",
"en");
2575 if (!
string.IsNullOrEmpty(ForBareJid))
2576 this.IdentityAuthorization(ForBareJid, BareJid, Identity.
Id,
true);
2578 this.IdentityAuthorization(e.
From.
BareJid, BareJid, Identity.
Id,
true);
2580 StringBuilder Xml =
new StringBuilder();
2581 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2585 catch (Exception ex)
2591 private Task ObsoleteLegalIdentityHandler(
object Sender,
IqEventArgs e)
2593 return this.ChangeStateLegalIdentityHandler(e, Identity.IdentityState.Obsoleted,
true);
2596 private Task CompromiseLegalIdentityHandler(
object Sender,
IqEventArgs e)
2598 return this.ChangeStateLegalIdentityHandler(e, Identity.IdentityState.Compromised,
false);
2601 private async Task ChangeStateLegalIdentityHandler(
IqEventArgs e, Identity.IdentityState State,
bool IncludePreviews)
2610 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can apply for registering legal identities.",
"en");
2614 KeyValuePair<LegalIdentity, bool>
P = await GetLocalLegalIdentity(Id, IncludePreviews);
2616 bool IsPreview =
P.Value;
2618 if (Identity is
null)
2626 await e.
IqErrorForbidden(e.
To,
"Only allowed to obsolete your own legal identities.",
"en");
2643 if (Identity.
State != State)
2645 switch (Identity.
State)
2647 case Legal.Identity.IdentityState.Created:
2648 State = Legal.Identity.IdentityState.Rejected;
2651 case Legal.Identity.IdentityState.Rejected:
2652 await e.
IqErrorForbidden(e.
To,
"Legal identity has been rejected, and cannot be changed.",
"en");
2655 case Legal.Identity.IdentityState.Compromised:
2656 await e.
IqErrorForbidden(e.
To,
"Legal identity has been flagged as compromised, and cannot be changed.",
"en");
2660 await this.UpdateState(Identity, State,
new string[] { e.From.Address },
2664 StringBuilder Xml =
new StringBuilder();
2665 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2669 catch (Exception ex)
2682 Account.LatestIdentity = Identity.
Id;
2683 Account.LatestIdentityState = Identity.
State;
2701 switch (
P.Name.Value.ToUpper())
2707 Account.EMailVerified =
null;
2714 Account.PhoneNr = s;
2715 Account.PhoneNrVerified =
null;
2720 Account.FirstName = s;
2724 Account.MiddleNames = s;
2728 Account.LastNames = s;
2736 Account.FirstName = FirstName;
2737 Account.MiddleNames = MiddleNames;
2738 Account.LastNames = LastNames;
2742 Account.PersonalNumber = s;
2746 Account.Country = s;
2750 Account.OrgName = s;
2754 Account.OrgNumber = s;
2758 Account.OrgDepartment = s;
2762 Account.OrgRole = s;
2766 Account.OrgCountry = s;
2771 Account.Updated = DateTime.UtcNow;
2776 internal Task UpdateState(
LegalIdentity Identity, Identity.IdentityState State,
2779 return this.UpdateState(Identity, State,
new string[] { Actor },
Account,
2780 Preview, Save, Application);
2783 internal async Task UpdateState(
LegalIdentity Identity, Identity.IdentityState State,
2786 if (Identity.
State != State)
2788 bool ApprovedBefore = Identity.State == Legal.Identity.IdentityState.Approved;
2790 Identity.State = State;
2792 Identity.Sign(
this);
2797 await AddPreview(Identity);
2807 string Msg = Preview
2808 ?
"Legal Identity preview registration updated."
2809 :
"Legal Identity registration updated.";
2811 if (Actors.Length == 0)
2814 "LegalIdUpdated", Identity.GetTags(Preview));
2818 foreach (
string Actor
in Actors)
2821 "LegalIdUpdated", Identity.GetTags(Preview));
2825 bool ApprovedAfter = Identity.State == Legal.Identity.IdentityState.Approved;
2827 if (!Preview && Save)
2829 if (ApprovedBefore && ApprovedAfter)
2830 await UpdateLegalIdentityReference(Identity);
2831 else if (ApprovedBefore)
2832 await DeleteLegalIdentityReference(Identity.
Id);
2833 else if (ApprovedAfter)
2834 await AddLegalIdentityReference(Identity);
2837 StringBuilder Xml =
new StringBuilder();
2838 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
2843 if (!(
Account is
null) && !Preview && Save)
2845 if (State == Legal.Identity.IdentityState.Approved)
2846 await CopyPropertiesFromApprovedIdentity(Identity,
Account);
2849 Account.LatestIdentityState = State;
2850 Account.Updated = DateTime.UtcNow;
2856 if (Application is
null)
2858 KeyValuePair<IPhoto[], XmlDocument[]>
P = await GetPhotosAndDocuments(Identity, Preview);
2861 GetPersonalInformation(Identity), Identity.GetTags(
true, Preview),
2866 if (StatefulServices.Length > 0)
2869 (Security.IdentityState)(
int)Identity.
State);
2877 catch (Exception ex)
2906 Timestamp = Timestamp.ToUniversalTime();
2912 if (ID.
From.ToUniversalTime() <= Timestamp &&
2913 ID.
To.ToUniversalTime() >= Timestamp &&
2914 (Result is
null || ID.
Created.ToUniversalTime() > Result.Created.ToUniversalTime()))
2923 private async Task AddLegalIdAttachmentHandler(
object Sender,
IqEventArgs e)
2937 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can add attachments.",
"en");
2941 if (!Uri.TryCreate(GetUrl, UriKind.Absolute, out Uri GetUri))
2966 KeyValuePair<LegalIdentity, bool>
P = await GetLocalLegalIdentity(Id,
true);
2968 bool Preview =
P.Value;
2970 if (Identity is
null)
2978 await e.
IqErrorForbidden(e.
To,
"Only allowed to add attachments to your own legal identities.",
"en");
2982 string PreapprovedAttachment =
null;
2983 string PreapprovedAttachmentKey =
null;
2984 bool PreapprovedAttachmentValid =
false;
2985 string ReviewKey = Identity.Id +
"|identityReview";
2990 if (!(P2.Encoded is
null))
2991 await P2.Encoded.DisposeAsync();
3000 if (this.remoteComponents.
TryGetValue(ReviewKey, out
object Obj) &&
3001 Obj is
string IdentityReview &&
3007 PreapprovedAttachment = IdentityReview;
3008 PreapprovedAttachmentKey = ReviewKey;
3009 PreapprovedAttachmentValid =
true;
3013 if (Identity.
State != Legal.Identity.IdentityState.Created)
3015 if (!PreapprovedAttachmentValid)
3017 await e.
IqErrorForbidden(e.
To,
"Attachments can only be added to newly created identities before they are approved.",
"en");
3024 string s = Convert.ToBase64String(
Signature);
3028 if (Convert.ToBase64String(Ref.
Signature) == s)
3037 if (!Identity.ValidateSignature(File,
Signature))
3044 bool IncNrPeerReviews =
false;
3045 StringBuilder sb =
new StringBuilder();
3046 List<LegalIdentity> Reviewers =
null;
3053 Doc =
new XmlDocument()
3055 PreserveWhitespace =
true
3059 if (Doc.DocumentElement.LocalName ==
"identityReview" &&
3060 Doc.DocumentElement.NamespaceURI == Namespace)
3062 if (
string.IsNullOrEmpty(PreapprovedAttachment))
3074 this.remoteComponents?.
Remove(PreapprovedAttachmentKey);
3076 else if (Doc.DocumentElement.LocalName ==
"peerReview" &&
3077 Doc.DocumentElement.NamespaceURI == Namespace)
3083 bool ReviewedHasStatus =
false;
3084 bool ReviewerHasStatus =
false;
3085 byte[] PeerSignature = Convert.FromBase64String(
XML.
Attribute(Doc.DocumentElement,
"s"));
3086 DateTime TP =
XML.
Attribute(Doc.DocumentElement,
"tp", DateTime.Now);
3087 byte[] SignedIdentity =
null;
3088 DateTime UtcNow = DateTime.UtcNow;
3090 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
3092 if (!(N is XmlElement E) || N.NamespaceURI != Namespace)
3095 foreach (XmlNode N2
in E.ChildNodes)
3097 if (N2 is XmlElement E2 &&
3098 E2.LocalName ==
"identity" &&
3099 E2.NamespaceURI == Namespace)
3101 switch (E.LocalName)
3104 ReviewedIdentity =
LegalIdentity.Parse(E2, out ReviewedHasStatus,
3105 out Dictionary<string, string> ReviewedIdentityAttachmentsUrls);
3108 ReviewedIdentity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
this);
3109 string s1 = sb.ToString();
3112 Identity.Serialize(sb,
true,
true,
true,
false,
false,
false,
false,
null,
this);
3113 string s2 = sb.ToString();
3122 ReviewedIdentity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true, ReviewedIdentityAttachmentsUrls,
this);
3123 SignedIdentity = Encoding.UTF8.GetBytes(sb.ToString());
3127 ReviewerIdentity =
LegalIdentity.Parse(E2, out ReviewerHasStatus,
3128 out Dictionary<string, string> ReviewerIdentityAttachmentsUrls);
3131 ReviewerIdentity.Serialize(sb,
false,
false,
false,
false,
false,
false,
false,
null,
this);
3132 byte[]
Data = Encoding.UTF8.GetBytes(sb.ToString());
3137 (ReviewerIdentity,
_) = await this.ValidateSignature(
new XmppAddress(ReviewerJid), TP,
Data,
3147 if (ReviewerIdentity.
State != Legal.Identity.IdentityState.Approved)
3153 if (UtcNow < ReviewerIdentity.
From.ToUniversalTime() ||
3154 UtcNow > ReviewerIdentity.
To.ToUniversalTime())
3167 ReviewerIdentity.ClientPubKey is
null ||
3168 ReviewerIdentity.ClientPubKey.Length == 0)
3183 await e.
IqErrorForbidden(e.
To,
"Reviewer identity not trusted for reviewing.",
"en");
3192 if (ReviewedIdentity is
null || !ReviewedHasStatus ||
3193 ReviewerIdentity is
null || !ReviewerHasStatus ||
3194 SignedIdentity is
null)
3196 await e.
IqErrorForbidden(e.
To,
"Attachment not a correctly formed peer-review document.",
"en");
3204 await e.
IqErrorForbidden(e.
To,
"Reviewer cannot be the same person as the reviewed person.",
"en");
3208 if (!ReviewerIdentity.ValidateSignature(SignedIdentity, PeerSignature))
3229 await e.
IqErrorForbidden(e.
To,
"Peer review not accepted: Identity lacks sufficient photos (" +
3238 await e.
IqErrorBadRequest(e.
To,
"Reviewer not white-listed. Peer review not accepted.",
"en");
3244 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a First name. Peer review not accepted.",
"en");
3250 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Middle name. Peer review not accepted.",
"en");
3256 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Last name. Peer review not accepted.",
"en");
3262 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Personal number. Peer review not accepted.",
"en");
3268 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an address. Peer review not accepted.",
"en");
3274 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Postal Code (ZIP). Peer review not accepted.",
"en");
3280 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an Area. Peer review not accepted.",
"en");
3286 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a City. Peer review not accepted.",
"en");
3292 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Region. Peer review not accepted.",
"en");
3298 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Country. Peer review not accepted.",
"en");
3306 await e.
IqErrorBadRequest(e.
To,
"Reviewer Country is not an ISO 3166-1 Country Code. Peer review not accepted.",
"en");
3313 if (Valid.HasValue && !Valid.Value)
3315 await e.
IqErrorBadRequest(e.
To,
"The personal number format used by the reviewer does not comply with regulations.",
"en");
3323 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Nationality. Peer review not accepted.",
"en");
3329 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Gender. Peer review not accepted.",
"en");
3337 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a Birth Date. Peer review not accepted.",
"en");
3341 DateTime BirthDate = RI.
BirthDate.Value;
3345 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity too young. Peer review not accepted.",
"en");
3354 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization name. Peer review not accepted.",
"en");
3360 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a department. Peer review not accepted.",
"en");
3366 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks a role. Peer review not accepted.",
"en");
3372 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization number. Peer review not accepted.",
"en");
3378 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization address. Peer review not accepted.",
"en");
3384 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Postal Code (ZIP). Peer review not accepted.",
"en");
3390 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Area. Peer review not accepted.",
"en");
3396 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization City. Peer review not accepted.",
"en");
3402 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Region. Peer review not accepted.",
"en");
3408 await e.
IqErrorBadRequest(e.
To,
"Reviewer identity lacks an organization Country. Peer review not accepted.",
"en");
3416 await e.
IqErrorBadRequest(e.
To,
"Reviewer organization Country is not an ISO 3166-1 Country Code. Peer review not accepted.",
"en");
3422 if (!await CheckPeerReviewFields(e, ReviewedIdentity))
3431 await e.
IqErrorBadRequest(e.
To,
"Peer reviewer lacks organization information. Peer review not accepted.",
"en");
3439 await e.
IqErrorBadRequest(e.
To,
"Peer reviewer must be from same company. Peer review not accepted.",
"en");
3446 LegalIdentity[] Reviewers2 = await GetPeerReviewers(Identity);
3452 await e.
IqErrorBadRequest(e.
To,
"A reviewer can only review the application once.",
"en");
3457 Reviewers ??=
new List<LegalIdentity>();
3458 Reviewers.AddRange(Reviewers2);
3462 Reviewers ??=
new List<LegalIdentity>();
3463 Reviewers.Add(ReviewerIdentity);
3464 IncNrPeerReviews =
true;
3472 if (Identity.
State != Legal.Identity.IdentityState.Created)
3474 await e.
IqErrorForbidden(e.
To,
"Attachments can only be added to newly created identities before they are approved.",
"en");
3479 List<AttachmentReference> References =
new List<AttachmentReference>();
3480 bool Approved =
false;
3485 KeyValuePair<Attachment, AttachmentReference>
A = await this.CreateAttachment(
3486 GetUri, Identity,
Signature, File, ContentType, Account2,
null,
3487 Identity.
To.ToUniversalTime(), Preview);
3489 References.Add(
A.Value);
3491 Identity.Attachments = References.ToArray();
3494 if (IncNrPeerReviews)
3496 Identity.NrPeerReviews++;
3500 Identity.
State == Legal.Identity.IdentityState.Created)
3502 Identity.State = Legal.Identity.IdentityState.Approved;
3508 StringBuilder Markdown =
new StringBuilder();
3510 Markdown.AppendLine(
"Peer reviewed Legal ID approved");
3511 Markdown.AppendLine(
"===================================");
3512 Markdown.AppendLine();
3514 this.AppendMarkdown(Markdown, Identity,
"Applicant");
3521 this.AppendMarkdown(Markdown, Reviewer,
"Reviewer " + Index.ToString());
3529 Identity.Sign(
this);
3533 await AddPreview(Identity);
3541 if (Identity.
State == Legal.Identity.IdentityState.Approved)
3542 await CopyPropertiesFromApprovedIdentity(Identity,
Account as
Account);
3546 "LegalIdUpdated", Identity.GetTags());
3550 Identity.Serialize(sb,
true,
true,
true,
true,
true,
true,
true,
null,
this);
3551 string Xml = sb.ToString();
3553 if (!Preview && Approved)
3554 await AddLegalIdentityReference(Identity);
3556 if (Approved || Identity.
State == Legal.Identity.IdentityState.Approved)
3560 string JidDomain = i < 0 ? this.Server.Domain : IdentityAddress.
Domain.
Substring(i + 1);
3563 new XmppAddress(Identity.Account +
"@" +
this.Server.Domain),
string.
Empty, Xml);
3568 catch (Exception ex)
3651 if (Valid.HasValue && !Valid.Value)
3653 await e.
IqErrorBadRequest(e.
To,
"The personal number format does not comply with regulations in your country.",
"en");
3681 await e.
IqErrorBadRequest(e.
To,
"Organization name is a required field for work identities.",
"en");
3687 await e.
IqErrorBadRequest(e.
To,
"Department is a required field for work identities.",
"en");
3699 await e.
IqErrorBadRequest(e.
To,
"Organization Number is a required field for work identites.",
"en");
3705 await e.
IqErrorBadRequest(e.
To,
"Organization Address is a required field for work identites.",
"en");
3711 await e.
IqErrorBadRequest(e.
To,
"Organization Postal Code (ZIP) is a required field for work identites.",
"en");
3717 await e.
IqErrorBadRequest(e.
To,
"Organization Area is a required field for work identites.",
"en");
3723 await e.
IqErrorBadRequest(e.
To,
"Organization City is a required field for work identites.",
"en");
3729 await e.
IqErrorBadRequest(e.
To,
"Organization Region is a required field for work identites.",
"en");
3735 await e.
IqErrorBadRequest(e.
To,
"Organization Country is a required field for work identites.",
"en");
3743 await e.
IqErrorBadRequest(e.
To,
"Organization Country must be a ISO 3166-1 Country Code.",
"en");
3753 internal static async Task<LegalIdentity[]> GetPeerReviewers(
LegalIdentity Identity)
3755 List<LegalIdentity> Result =
new List<LegalIdentity>();
3758 if (!(Identity?.Attachments is
null))
3770 Aes Aes = Aes.Create();
3772 Aes.BlockSize = 128;
3774 Aes.Mode = CipherMode.CBC;
3775 Aes.Padding = PaddingMode.Zeros;
3777 byte[] Key =
new byte[32];
3778 byte[] IV =
new byte[16];
3783 using ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV);
3784 using CryptoStream DecryptedAttachmentFile =
new CryptoStream(AttachmentFile, Decryptor, CryptoStreamMode.Read);
3785 XmlDocument Doc =
new XmlDocument()
3787 PreserveWhitespace =
true
3789 Doc.Load(DecryptedAttachmentFile);
3791 if (Doc.DocumentElement.LocalName ==
"peerReview" &&
3792 Doc.DocumentElement.NamespaceURI == Namespace)
3794 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
3796 if (N is XmlElement E &&
3797 E.LocalName ==
"reviewer" &&
3798 E.NamespaceURI == Namespace)
3800 foreach (XmlNode N2
in E.ChildNodes)
3802 if (N2 is XmlElement E2 &&
3803 E2.LocalName ==
"identity" &&
3804 E2.NamespaceURI == Namespace)
3807 Result.Add(ReviewerID);
3817 return Result.ToArray();
3820 internal void AppendMarkdown(StringBuilder Markdown,
LegalIdentity Identity,
string Title)
3822 Markdown.AppendLine(
Title);
3823 Markdown.AppendLine(
new string(
'-',
Title.Length + 3));
3824 Markdown.AppendLine();
3826 Markdown.Append(
"| `");
3827 Markdown.Append(Identity.
Id);
3828 Markdown.AppendLine(
"` ||");
3829 Markdown.AppendLine(
"|:----|:----|");
3833 Markdown.Append(
"| `");
3834 Markdown.Append(
P.Name);
3835 Markdown.Append(
"` | ");
3837 Markdown.AppendLine(
" |");
3840 Markdown.AppendLine();
3843 private Task<KeyValuePair<Attachment, AttachmentReference>> CreateAttachment(Uri GetUri,
3847 return CreateAttachment(Path.GetFileName(GetUri.AbsolutePath), UploadingIdentity,
3848 Signature, File, ContentType,
Account, ContractId,
this.attachmentsFolder, ExpiresUtc, Preview);
3851 internal static string GetFolderName(
string AttachmentsFolder, out DateTime Timestamp)
3853 Timestamp = DateTime.UtcNow;
3855 Timestamp.Month.ToString(
"D2"), Timestamp.Day.ToString(
"D2"));
3857 if (!Directory.Exists(Folder))
3858 Directory.CreateDirectory(Folder);
3863 internal static async Task<KeyValuePair<Attachment, AttachmentReference>> CreateAttachment(
string RemoteFileName,
3866 DateTime ExpiresUtc,
bool Preview)
3874 Timestamp = DateTime.UtcNow;
3888 ContractId = ContractId,
3889 RemoteFileName = RemoteFileName,
3891 Timestamp = Timestamp,
3892 UploaderLegalId = UploadingIdentity.
Id,
3898 Attachment.ObjectId = Guid.NewGuid().ToString();
3903 string FileName = Preview ? GetPreviewFileName(AttachmentId,
".att") :
3904 Path.Combine(Folder, AttachmentId +
".bin");
3906 Attachment.Id = AttachmentId +
"@" + UploadingIdentity.
Provider;
3907 Attachment.LocalFileName = FileName;
3914 Attachment.Salt = Salt;
3924 byte[] Key =
new byte[32];
3925 byte[] IV =
new byte[16];
3927 Buffer.BlockCopy(Salt, 0, Key, 0, 32);
3928 Buffer.BlockCopy(Salt, 32, IV, 0, 16);
3930 using FileStream AttachmentFile =
System.IO.File.Create(FileName);
3931 Aes Aes = Aes.Create();
3933 Aes.BlockSize = 128;
3935 Aes.Mode = CipherMode.CBC;
3936 Aes.Padding = PaddingMode.Zeros;
3938 using ICryptoTransform Encryptor = Aes.CreateEncryptor(Key, IV);
3939 using CryptoStream EncryptedAttachmentFile =
new CryptoStream(AttachmentFile, Encryptor, CryptoStreamMode.Write);
3942 EncryptedAttachmentFile.FlushFinalBlock();
3947 Created = DateTime.UtcNow,
3948 Expires = ExpiresUtc,
3966 Timestamp = Timestamp,
3970 return new KeyValuePair<Attachment, AttachmentReference>(
Attachment, Ref);
3973 private async Task RemoveLegalIdAttachmentHandler(
object Sender,
IqEventArgs e)
3981 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can remove attachments.",
"en");
4000 if (Identity is
null)
4008 await e.
IqErrorForbidden(e.
To,
"Only allowed to remove attachments from your own legal identities.",
"en");
4012 if (Identity.
State != Legal.Identity.IdentityState.Created)
4014 await e.
IqErrorForbidden(e.
To,
"Attachments can only be removed from newly created identities before they are approved.",
"en");
4023 List<AttachmentReference> Attachments =
new List<AttachmentReference>();
4027 if (Ref.
Id != AttachmentId)
4028 Attachments.Add(Ref);
4031 Identity.Attachments = Attachments.ToArray();
4032 Identity.Sign(
this);
4039 StringBuilder Xml =
new StringBuilder();
4040 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
4044 catch (Exception ex)
4050 internal async Task<KeyValuePair<byte[], string>> GetAttachment(
string AttachmentId,
4051 string AttachmentUrl, DateTime Expires)
4053 Expires = Expires.ToUniversalTime();
4059 if (!(Item is
null))
4063 Item.Expires = Expires;
4071 int i = AttachmentId.IndexOf(
'@');
4075 string AttachmentDomain = AttachmentId[(i + 1)..];
4076 AttachmentId = AttachmentId[..i];
4081 Networking.XMPP.Contracts.SignWith.LatestApprovedId, 30000);
4087 Data = await File.ReadAllAsync();
4090 Expires,
Data, ContentType,
this);
4092 return new KeyValuePair<byte[], string>(
Data, ContentType);
4102 Aes Aes = Aes.Create();
4104 Aes.BlockSize = 128;
4106 Aes.Mode = CipherMode.CBC;
4107 Aes.Padding = PaddingMode.Zeros;
4109 byte[] Key =
new byte[32];
4110 byte[] IV =
new byte[16];
4115 using ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV);
4116 using (CryptoStream DecryptedAttachmentFile =
new CryptoStream(AttachmentFile, Decryptor, CryptoStreamMode.Read))
4123 return new KeyValuePair<byte[], string>(
Data, ContentType);
4141 throw new Exception(
"Expected server domain, not a component domain: " +
Address.Domain);
4144 ??
throw new Exception(
"Legal Identity not found: " + Id.
Value);
4150 if (
Address.Domain.StartsWith(
this.SubdomainSuffixed, StringComparison.CurrentCultureIgnoreCase))
4159 return new ClientInformation()
4162 Connections = this.RemoveDisconnected(Connections)
4168 throw new Exception(
"Expected legal component domain, not server domain: " +
Address.Domain);
4187 return new ClientInformation()
4190 Connections = this.RemoveDisconnected(Connections)
4195 TaskCompletionSource<ClientInformation> Result =
new TaskCompletionSource<ClientInformation>();
4196 StringBuilder Xml =
new StringBuilder();
4199 Xml.Append(
"<getNetworkIdentity xmlns='");
4200 Xml.Append(Namespace);
4201 Xml.Append(
"' id='");
4209 XmlElement E = e2.FirstElement;
4211 if (!(E is null) && E.LocalName ==
"networkIdentity" && E.NamespaceURI == Namespace)
4213 string Jid = XML.Attribute(E,
"jid");
4214 List<ClientConnectionInformation> Connections = new List<ClientConnectionInformation>();
4216 foreach (XmlNode N in E.ChildNodes)
4218 if (N is XmlElement E2 &&
4219 E2.LocalName ==
"connection" &&
4220 E2.NamespaceURI == Namespace)
4222 Connections.Add(new ClientConnectionInformation()
4224 Endpoint = XML.Attribute(E2,
"clientEp"),
4225 LastPresenceTimestamp = XML.Attribute(E2,
"ts", DateTimeOffset.MinValue)
4230 Result.TrySetResult(new ClientInformation()
4233 Connections = Connections.ToArray()
4237 Result.TrySetException(new Exception(
"Unexpected response received."));
4240 Result.TrySetException(
new Exception(
string.IsNullOrEmpty(e2.ErrorText) ?
"Unable to get network identity." : e2.ErrorText));
4242 return Task.CompletedTask;
4245 return await Result.Task;
4249 private ClientConnectionInformation[] RemoveDisconnected(
IClientConnection[] Connections)
4251 if (Connections is
null)
4252 return Array.Empty<ClientConnectionInformation>();
4254 List<ClientConnectionInformation> Result =
new List<ClientConnectionInformation>();
4267 Result.Add(
new ClientConnectionInformation()
4270 LastPresenceTimestamp = Connection.LastPresence.Timestamp
4274 return Result.ToArray();
4277 internal class ClientInformation
4280 public ClientConnectionInformation[] Connections {
get;
set; }
4282 public string MostRecentEndpoint
4286 DateTimeOffset Best = DateTimeOffset.MinValue;
4287 string Endpoint =
null;
4289 if (!(this.Connections is
null))
4291 foreach (ClientConnectionInformation Info
in this.Connections)
4293 if (Info.LastPresenceTimestamp > Best)
4295 Best = Info.LastPresenceTimestamp;
4296 Endpoint = Info.Endpoint;
4306 internal class ClientConnectionInformation
4308 public string Endpoint {
get;
set; }
4309 public DateTimeOffset LastPresenceTimestamp {
get;
set; }
4312 private Task GetNetworkLegalIdentityHandler(
object Sender,
IqEventArgs e)
4314 return this.GetNetworkIdentityHandler(e,
true);
4317 private Task GetNetworkXmppIdentityHandler(
object Sender,
IqEventArgs e)
4319 return this.GetNetworkIdentityHandler(e,
false);
4322 private async Task GetNetworkIdentityHandler(
IqEventArgs e,
bool ToLegalComponent)
4343 if (this.IsComponentDomain(IdAddress.
Domain,
true))
4345 if (!ToLegalComponent)
4359 if (Identity is
null)
4365 if (IdAddress.
Domain.
StartsWith(
this.SubdomainSuffixed, StringComparison.CurrentCultureIgnoreCase))
4366 NetworkIdentity = Identity.Account +
"@" + IdAddress.
Domain.
Substring(this.SubdomainSuffixed.Length);
4368 NetworkIdentity = Identity.Account +
"@" + this.Server.Domain;
4370 if (!this.Server.TryGetClientConnections(NetworkIdentity, out Connections))
4373 else if (this.Server.IsServerDomain(IdAddress.
Domain,
true))
4375 if (ToLegalComponent)
4383 NetworkIdentity = IdAddress.
Address;
4385 if (!this.Server.TryGetClientConnections(NetworkIdentity, out Connections))
4390 NetworkIdentity = IdAddress.
BareJid;
4410 StringBuilder Xml =
new StringBuilder();
4412 Xml.Append(
"<networkIdentity xmlns='");
4413 Xml.Append(NamespaceLegalIdentity(QueryVersion));
4414 Xml.Append(
"' jid='");
4415 Xml.Append(
XML.
Encode(NetworkIdentity));
4418 foreach (ClientConnectionInformation ClientInfo
in this.RemoveDisconnected(Connections))
4420 Xml.Append(
"<connection clientEp='");
4421 Xml.Append(
XML.
Encode(ClientInfo.Endpoint));
4422 Xml.Append(
"' ts='");
4423 Xml.Append(
XML.
Encode(ClientInfo.LastPresenceTimestamp));
4427 Xml.Append(
"</networkIdentity>");
4431 catch (Exception ex)
4437 private async Task GetIdentityReferencesHandler(
object Sender,
IqEventArgs e)
4461 if (!this.Server.IsServerDomain(
Address.Domain,
true))
4463 await e.
IqErrorForbidden(e.
To,
"JID domain part not a domain name of the broker.",
"en");
4475 StringBuilder Xml =
new StringBuilder();
4476 DateTime UtcNow = DateTime.UtcNow;
4478 Xml.Append(
"<identityReferences xmlns='");
4479 Xml.Append(NamespaceLegalIdentity(QueryVersion));
4488 Xml.Append(
"<identityReference>");
4490 Xml.Append(
"</identityReference>");
4493 Xml.Append(
"</identityReferences>");
4497 catch (Exception ex)
4508 internal async Task<string[]> GetIdentityReferences(
XmppAddress Jid)
4511 string Key = BareJid +
"|idRefs";
4513 if (this.remoteComponents.
TryGetValue(Key, out
object Obj) && Obj is
string[] CachedResult)
4514 return CachedResult;
4518 if (this.Server.IsServerDomain(Jid.
Domain,
true))
4520 DateTime UtcNow = DateTime.UtcNow;
4528 References.
Add(ID.
Id);
4531 CachedResult = References.
ToArray();
4532 this.remoteComponents[Key] = CachedResult;
4534 return CachedResult;
4538 return Array.Empty<
string>();
4540 TaskCompletionSource<string[]> Result =
new TaskCompletionSource<string[]>();
4541 StringBuilder Xml =
new StringBuilder();
4543 Xml.Append(
"<identityReferences xmlns='");
4544 Xml.Append(NamespaceLegalIdentity(
NamespaceSet.Current));
4545 Xml.Append(
"' jid='");
4549 await this.Server.SendIqRequest(
"get", this.Server.Domain, Jid.
Domain,
null,
4555 Result.TrySetException(XmppClient.GetExceptionObject(e.ErrorElement));
4556 else if ((E = e.FirstElement) is null ||
4557 E.LocalName !=
"identityReferences" ||
4558 !IsNamespaceLegalIdentity(E.NamespaceURI))
4560 Result.TrySetException(new Exception(
"Unable to get the legal identity references for " +
4561 BareJid +
". Invalid response returned."));
4565 foreach (XmlNode N in E.ChildNodes)
4567 if (N is XmlElement E2 &&
4568 E2.LocalName ==
"identityReference" &&
4569 IsNamespaceLegalIdentity(E2.NamespaceURI))
4571 References.Add(E2.InnerText);
4575 CachedResult = References.
ToArray();
4576 this.remoteComponents[Key] = CachedResult;
4577 Result.TrySetResult(CachedResult);
4580 return Task.CompletedTask;
4583 return await Result.Task;
4592 internal bool TryGetItemFromCache(
string Key, out
object Obj)
4594 return this.remoteComponents.
TryGetValue(Key, out Obj);
4602 internal void AddItemToCache(
string Key,
object Obj)
4604 this.remoteComponents[Key] = Obj;
4612 internal bool RemoveItemFromCache(
string Key)
4614 return this.remoteComponents.
Remove(Key);
4617 private async Task CanSignAsHandler(
object Sender,
IqEventArgs e)
4638 if (ReferenceAddress.
Domain != SignatoryAddress.
Domain)
4646 if (!this.IsComponentDomain(ReferenceAddress.
Domain,
true))
4648 await e.
IqErrorBadRequest(e.
To, IncludeDetailedErrorMessage ?
"Reference identity not hosted by broker." :
string.
Empty,
"en");
4652 LegalIdentity ReferenceIdentity = await GetLocalLegalIdentity(ReferenceId);
4653 if (ReferenceIdentity is
null)
4659 switch (ReferenceIdentity.
State)
4661 case Legal.Identity.IdentityState.Created:
4662 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID never approved." :
string.
Empty,
"en");
4665 case Legal.Identity.IdentityState.Approved:
4666 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID still approved." :
string.
Empty,
"en");
4673 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded JID." :
string.
Empty,
"en");
4680 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded Personal Number." :
string.
Empty,
"en");
4687 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Reference ID lacks encoded Country." :
string.
Empty,
"en");
4691 LegalIdentity SignatoryIdentity = await GetLocalLegalIdentity(SignatoryId);
4692 if (SignatoryIdentity is
null)
4698 if (SignatoryIdentity.
State != Legal.Identity.IdentityState.Approved)
4700 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Signatory ID not in an approved state." :
string.
Empty,
"en");
4712 await e.
IqErrorForbidden(e.
To, IncludeDetailedErrorMessage ?
"Personal Number mismatch." :
string.
Empty,
"en");
4724 catch (Exception ex)
4742 if (ReferenceAddress.
Domain != SignatoryAddress.
Domain)
4745 if (this.IsComponentDomain(ReferenceAddress.
Domain,
true))
4747 LegalIdentity ReferenceIdentity = await GetLocalLegalIdentity(ReferenceId);
4748 if (ReferenceIdentity is
null)
4751 switch (ReferenceIdentity.
State)
4753 case Legal.Identity.IdentityState.Created:
4754 case Legal.Identity.IdentityState.Approved:
4769 LegalIdentity SignatoryIdentity = await GetLocalLegalIdentity(SignatoryId);
4770 if (SignatoryIdentity is
null)
4773 if (SignatoryIdentity.
State != Legal.Identity.IdentityState.Approved)
4787 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
4788 StringBuilder Xml =
new StringBuilder();
4789 string Namespace = NamespaceLegalIdentity(
NamespaceSet.Current);
4791 Xml.Append(
"<canSignAs xmlns='");
4792 Xml.Append(Namespace);
4793 Xml.Append(
"' referenceId='");
4795 Xml.Append(
"' signatoryId='");
4799 await this.Server.SendIqRequest(
"get", this.MainDomain.Address, ReferenceAddress.
Domain,
string.
Empty, Xml.
ToString(),
true, (sender2, e2) =>
4801 Result.TrySetResult(e2.Ok);
4802 return Task.CompletedTask;
4805 return await Result.Task;
4809 private async Task AuthorizeAccessToIdHandler(
object Sender,
IqEventArgs e)
4813 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
4835 if (!this.IsComponentDomain(IdAddress.
Domain,
true))
4859 if (Identity is
null)
4871 ClientInformation ClientInfo = await this.GetNetworkIdentity(RemoteId,
true,
true, Identity.Version);
4873 this.IdentityAuthorization(RemoteJid, e.
From.
BareJid, Id, Authorized);
4877 catch (Exception ex)
4883 private async Task ReadyForApprovalHandler(
object Sender,
IqEventArgs e)
4903 KeyValuePair<LegalIdentity, bool>
P = await GetLocalLegalIdentity(Id,
true);
4905 bool Preview =
P.Value;
4907 if (Identity is
null)
4915 await e.
IqErrorForbidden(e.
To,
"You can only mark your own identity applications for approval.",
"en");
4921 this.CheckAuthenticityOfIdentity(Identity, Identity.GetTags(), e.
To, e.
From,
4927 this.remoteComponents?.Add(Identity2.Id +
"|identityReview", IdentityReviewXml);
4929 return Task.FromResult(Identity2);
4932 catch (Exception ex)
4938 internal async
void CheckAuthenticityOfIdentity(
LegalIdentity Identity,
4939 KeyValuePair<string, object>[] Claims,
XmppAddress ComponentAddress,
4941 Func<
string,
LegalIdentity, Task<LegalIdentity>> IdentityReviewCallback)
4945 KeyValuePair<IPhoto[], XmlDocument[]>
P = await GetPhotosAndDocuments(Identity, Preview);
4947 NamespaceLegalIdentity(Identity.Version), Preview,
4948 GetPersonalInformation(Identity), Claims,
4951 foreach (KeyValuePair<string, object> Claim
in Claims)
4956 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string EMail) &&
4961 Application.ClaimValid(Claim.Key,
this);
4966 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string Phone) &&
4971 Application.ClaimValid(Claim.Key,
this);
4976 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string Id))
4978 if (Id == Identity.
Id)
4979 Application.ClaimValid(Claim.Key,
this);
4982 Application.ClaimInvalid(Claim.Key,
4983 "Identifier does not correspond to created identifier.",
4984 "en",
"IdMismatch",
this);
4990 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string Jid))
4993 Application.ClaimValid(Claim.Key,
this);
4996 Application.ClaimInvalid(Claim.Key,
4997 "JID does not correspond to client JID.",
4998 "en",
"JidMismatch",
this);
5006 Application.ClaimValid(Claim.Key,
this);
5010 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string AccountName))
5013 Application.ClaimValid(Claim.Key,
this);
5016 Application.ClaimInvalid(Claim.Key,
5017 "Account name does not match account.",
5018 "en",
"AccountMismatch",
this);
5024 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out
string Provider))
5026 if (this.IsComponentDomain(Provider,
true))
5027 Application.ClaimValid(Claim.Key,
this);
5030 Application.ClaimInvalid(Claim.Key,
5031 "Provider does not match legal component address.",
5032 "en",
"ProviderMismatch",
this);
5038 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out Legal.Identity.IdentityState State))
5040 if (State == Identity.
State)
5041 Application.ClaimValid(Claim.Key,
this);
5044 Application.ClaimInvalid(Claim.Key,
5045 "State does not match identity state.",
5046 "en",
"StateMismatch",
this);
5052 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out DateTime Created))
5054 if (Created == Identity.
Created)
5055 Application.ClaimValid(Claim.Key,
this);
5058 Application.ClaimInvalid(Claim.Key,
5059 "Created does not match identity creation timestamp.",
5060 "en",
"CreatedMismatch",
this);
5066 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out DateTime Updated))
5068 if (Updated == Identity.
Updated)
5069 Application.ClaimValid(Claim.Key,
this);
5072 Application.ClaimInvalid(Claim.Key,
5073 "Updated does not match identity update timestamp.",
5074 "en",
"UpdatedMismatch",
this);
5080 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out DateTime From))
5082 if (From == Identity.
From)
5083 Application.ClaimValid(Claim.Key,
this);
5086 Application.ClaimInvalid(Claim.Key,
5087 "From does not match identity creation timestamp.",
5088 "en",
"FromMismatch",
this);
5094 if (Application.TryGetValue(Claim.Key, Claim.Value,
this, out DateTime To))
5096 if (To == Identity.
To)
5097 Application.ClaimValid(Claim.Key,
this);
5100 Application.ClaimInvalid(Claim.Key,
5101 "To does not match identity creation timestamp.",
5102 "en",
"ToMismatch",
this);
5110 if (Authenticators.Length == 0 && !Application.IsValid.HasValue)
5115 if (Application.IsValid.HasValue)
5120 await Authenticator.
Validate(Application);
5123 catch (Exception ex)
5125 Application.ReportError(ex.Message,
string.Empty,
string.Empty,
5130 if (!Application.Preview)
5131 Application.LogResults();
5133 if ((!Application.IsValid.HasValue &&
5134 (Application.HasValidatedClaims || Application.HasValidatedPhotos)) ||
5135 (Application.IsValid.HasValue && Application.IsValid.Value))
5137 string Xml = Application.GetIdentityReviewXml();
5139 Identity = await IdentityReviewCallback(Xml, Identity);
5141 await this.Server.SendMessage(
string.Empty,
string.Empty, ComponentAddress,
5145 if (!Application.IsValid.HasValue)
5147 string Xml = Application.GetClientErrorMessageXml(out
string Language,
5148 "Unable to validate application automatically. The application needs to be validated manually, or by peer review.",
5149 "ManualReview",
"en");
5151 await this.Server.SendMessage(
string.Empty,
string.Empty, ComponentAddress,
5156 KeyValuePair<string, object>[] Tags = Application.Tags;
5158 StringBuilder Name =
new StringBuilder();
5161 int c = Application.NrServices;
5163 foreach (
object Service
in Application.Services)
5168 Name.Append(
" and ");
5182 Name.Append(Service.GetType().FullName);
5186 Actors.
Add(Service.GetType().FullName);
5189 if (Application.IsValid.Value)
5204 await this.UpdateState(Identity, Legal.Identity.IdentityState.Approved,
5207 if (!Application.Preview &&
5210 StringBuilder Markdown =
new StringBuilder();
5212 Markdown.Append(
"Legal identity application has been automatically approved: [`");
5213 Markdown.Append(Identity.
Id);
5214 Markdown.Append(
"`](");
5215 Markdown.Append(Url);
5216 Markdown.Append(
") (by ");
5217 Markdown.Append(Name.ToString());
5218 Markdown.AppendLine(
")");
5219 Markdown.AppendLine();
5229 if (!Application.Preview)
5231 if (Application.HasErrors)
5254 await this.UpdateState(Identity, Legal.Identity.IdentityState.Rejected,
5257 string Xml = Application.GetClientErrorMessageXml(out
string Language,
5258 "Unable to validate application automatically. The application needs to be validated manually, or by peer review.",
5259 "ManualReview",
"en");
5261 await this.Server.SendMessage(
string.Empty,
string.Empty, ComponentAddress,
5267 if (!Application.Preview &&
5270 StringBuilder Markdown =
new StringBuilder();
5272 Markdown.Append(
"Legal identity application has been automatically rejected: [`");
5273 Markdown.Append(Identity.
Id);
5274 Markdown.Append(
"`](");
5275 Markdown.Append(Url);
5276 Markdown.Append(
") (by ");
5277 Markdown.Append(Name.ToString());
5278 Markdown.AppendLine(
")");
5279 Markdown.AppendLine();
5287 catch (Exception ex)
5293 private async Task GetTrustChainHandler(
object Sender,
IqEventArgs e)
5297 StringBuilder Xml =
new StringBuilder();
5299 Xml.Append(
"<trustChain xmlns='");
5307 Xml.Append(
"<broker domain='");
5314 Xml.Append(
"<broker domain='");
5319 Xml.Append(
"<broker domain='");
5323 Xml.Append(
"</trustChain>");
5327 catch (Exception ex)
5340 string Key = Domain +
"|trustChain";
5342 if (this.remoteComponents.
TryGetValue(Key, out
object Obj) && Obj is
string[] CachedResult)
5343 return CachedResult;
5346 return Array.Empty<
string>();
5348 TaskCompletionSource<string[]> Result =
new TaskCompletionSource<string[]>();
5351 "<getTrustChain xmlns='" + NamespaceLegalIdentity(
NamespaceSet.Current) +
"'/>",
5357 Result.TrySetException(XmppClient.GetExceptionObject(e2.ErrorElement));
5358 else if ((E = e2.FirstElement) is null ||
5359 E.LocalName !=
"trustChain" ||
5360 !IsNamespaceLegalIdentity(E.NamespaceURI))
5362 Result.TrySetException(new Exception(
"Unable to get the trust chain from " +
5363 Domain +
". Invalid response returned."));
5367 ChunkedList<string> Brokers = new ChunkedList<string>();
5369 foreach (XmlNode N in E.ChildNodes)
5371 if (N is XmlElement E2 &&
5372 E2.LocalName ==
"broker" &&
5373 IsNamespaceLegalIdentity(E2.NamespaceURI))
5375 Brokers.Add(XML.Attribute(E2,
"domain"));
5379 CachedResult = Brokers.ToArray();
5380 this.remoteComponents[Key] = CachedResult;
5381 Result.TrySetResult(CachedResult);
5384 return Task.CompletedTask;
5387 return await Result.Task;
5390 public async Task<string> GetTrustAnchor(
string Domain)
5392 string[] Chain = await this.GetTrustChainAsync(Domain);
5393 if ((Chain?.Length ?? 0) == 0)
5412 string Anchor2 = await this.GetTrustAnchor(Domain);
5414 if (Anchor1 is
null || Anchor2 is
null)
5417 return Anchor1 == Anchor2;
5422 #region Legal Identity references
5424 internal static async Task CheckLegalIdentityReferences()
5428 if (Array.IndexOf(CollectionNames,
"LegalIdentityReferences") < 0)
5433 await UpdateLegalIdentityReference(Identity);
5438 internal static async Task AddLegalIdentityReference(
LegalIdentity Identity)
5444 LegalId = Identity.
Id,
5446 ArchiveDays = CalcRefArchiveDays(Identity)
5478 private static async Task UpdateLegalIdentityReference(
LegalIdentity Identity)
5483 await AddLegalIdentityReference(Identity);
5487 bool Updated =
false;
5513 private static Task DeleteLegalIdentityReference(
string LegalId)
5518 private static int CalcRefArchiveDays(
LegalIdentity Identity)
5520 DateTime Expires = Identity.
To;
5521 if (Expires.Year >= 9999)
5522 return int.MaxValue;
5524 TimeSpan
Span = Expires - DateTime.Now;
5525 double Days = Math.Ceiling(
Span.TotalDays);
5529 else if (Days >
int.MaxValue)
5530 return int.MaxValue;
5537 #region Remote Legal Identity References
5539 private async Task LegalIdReferenceAddedHandler(
object Sender,
IqEventArgs e)
5548 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
5550 if (Identity is
null)
5568 private async Task LegalIdReferenceRemovedHandler(
object Sender,
IqEventArgs e)
5577 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
5579 if (Identity is
null)
5596 private async Task User_UpdatingUserLegalId(
object Sender, Security.Users.UpdatingLegalIdEventArgs e)
5598 if (!
string.IsNullOrEmpty(e.OldLegalId))
5601 StringBuilder Xml =
new StringBuilder();
5603 Xml.Append(
"<legalIdReferenceRemoved xmlns='");
5605 Xml.Append(
"' legalId='");
5609 await this.Server.SendMessage(
string.Empty,
string.Empty,
Gateway.
Domain,
5613 if (!
string.IsNullOrEmpty(e.NewLegalId))
5616 StringBuilder Xml =
new StringBuilder();
5618 Xml.Append(
"<legalIdReferenceAdded xmlns='");
5620 Xml.Append(
"' legalId='");
5624 await this.Server.SendMessage(
string.Empty,
string.Empty,
Gateway.
Domain,
5631 #region Smart Contracts
5633 internal async Task<KeyValuePair<Contract, IqResultEventArgs>> GetContract(
CaseInsensitiveString ContractId)
5635 TaskCompletionSource<IqResultEventArgs> T =
new TaskCompletionSource<IqResultEventArgs>();
5638 if (this.Server.IsServerDomain(ContractAddress.
Domain,
true) ||
5639 this.IsComponentDomain(ContractAddress.
Domain,
true))
5642 return new KeyValuePair<Contract, IqResultEventArgs>(
Contract,
null);
5646 if (!await this.Server.SendIqRequest(
"get",
this.MainDomain,
new XmppAddress(ContractAddress.
Domain),
string.
Empty,
5647 "<getContract xmlns='" + NamespaceSmartContracts(
NamespaceSet.Current) +
"' id='" +
XML.
Encode(ContractId) +
"'/>",
true,
5651 return Task.CompletedTask;
5654 return new KeyValuePair<Contract, IqResultEventArgs>(
null,
null);
5661 return new KeyValuePair<Contract, IqResultEventArgs>(
null, e3);
5664 return new KeyValuePair<Contract, IqResultEventArgs>(Parsed?.
Contract, e3);
5668 private async Task PetitionContractHandler(
object Sender,
IqEventArgs e)
5677 byte[]
Data = Encoding.UTF8.GetBytes(PetitionId +
":" + ContractId +
":" + Purpose +
":" + Nonce +
":" + e.
From.
BareJid.
LowerCase);
5679 if (!TryGetContext(e.
Query, out XmlElement ContextXml, out
string _,
5680 out
string[] Properties, out
string[] Attachments))
5686 (
LegalIdentity ReqIdentity, Dictionary<string, string> ReqAttachmentUrls) = await this.ValidateSenderSignature(
5689 if (ReqIdentity is
null)
5699 StringBuilder Msg =
new StringBuilder();
5701 Msg.Append(
"<petitionContractMsg id=\"");
5703 Msg.Append(
"\" pid=\"");
5705 Msg.Append(
"\" from=\"");
5707 Msg.Append(
"\" purpose=\"");
5711 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
5713 Msg.Append(
"\" clientEp=\"");
5714 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
5718 ClientInformation ClientInfo = await this.GetNetworkIdentity(ReqIdentity.
Id,
true,
false,
Contract.Version);
5719 if (!(ClientInfo is
null))
5721 string ClientEndpoint = ClientInfo.MostRecentEndpoint;
5723 if (!
string.IsNullOrEmpty(ClientEndpoint))
5725 Msg.Append(
"\" clientEp=\"");
5731 Msg.Append(
"\" xmlns=\"");
5732 Msg.Append(NamespaceSmartContracts(
Contract.Version));
5735 this.Append(Msg, Properties, Attachments, ContextXml,
5736 null, ReqIdentity,
Contract.Version, ReqAttachmentUrls);
5738 Msg.Append(
"</petitionContractMsg>");
5740 string Xml = Msg.ToString();
5742 if (!(
Contract.ClientSignatures is
null))
5753 catch (Exception ex)
5759 private async Task PetitionContractResponseHandler(
object Sender,
IqEventArgs e)
5768 XmlElement ContextXml =
null;
5770 foreach (XmlNode N
in e.
Query)
5772 if (!(N is XmlElement E))
5775 if (ContextXml is
null)
5791 this.ContractAuthorization(RequestorFullJid.
BareJid, e.
From.
BareJid, ContractId, Response);
5793 StringBuilder Msg =
new StringBuilder();
5795 Msg.Append(
"<petitionContractResponseMsg pid=\"");
5797 Msg.Append(
"\" response=\"");
5801 !
string.IsNullOrEmpty(Connection.RemoteEndPoint))
5803 Msg.Append(
"\" clientEp=\"");
5804 Msg.Append(
XML.
Encode(Connection.RemoteEndPoint));
5807 Msg.Append(
"\" xmlns=\"");
5808 Msg.Append(NamespaceSmartContracts(
Contract.Version));
5812 await
Contract.
Serialize(Msg,
false,
true,
true,
true,
true,
true,
true,
null,
this);
5814 if (!(ContextXml is
null))
5815 Msg.Append(ContextXml.OuterXml);
5817 Msg.Append(
"</petitionContractResponseMsg>");
5819 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To, RequestorFullJid,
string.
Empty, Msg.
ToString());
5823 catch (Exception ex)
5832 this.Authorization(
"C:", ToBareJid, FromBareJid, ContractId, Authorized ? 1 : 0);
5838 return (this.petitions?.TryGetValue(Key, out
int i) ??
false) && (i > 0);
5841 private async Task CreateContractHandler(
object Sender,
IqEventArgs e)
5849 CreateContractThread.
Start();
5850 ParametersThread.
Start();
5853 CreateContractThread.
NewState(
"Parsing");
5855 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
5857 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can create new contracts.",
"en");
5861 LinkedList<ClientSignature> SignaturesToTransfer =
null;
5862 XmlElement E =
null;
5864 Dictionary<CaseInsensitiveString, Parameter> Parameters =
new Dictionary<CaseInsensitiveString, Parameter>();
5865 LinkedList<CaseInsensitiveString> ParameterOrder =
new LinkedList<CaseInsensitiveString>();
5866 Dictionary<CaseInsensitiveString, Parameter> TransientParameters =
null;
5867 bool ParametersChecked =
false;
5868 bool HasTransientParameters =
false;
5870 foreach (XmlNode N
in e.
Query.ChildNodes)
5872 E = N as XmlElement;
5876 switch (E.LocalName ??
string.Empty)
5893 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when creating new contract.",
"en");
5903 if (!(
Contract.ClientSignatures is
null) &&
Contract.ClientSignatures.Length > 0)
5909 if (!(
Contract.ServerSignature is
null))
5928 ParametersChecked =
true;
5941 KeyValuePair<Contract, IqResultEventArgs> P2 = await this.GetContract(TemplateId);
5945 if (
string.IsNullOrEmpty(P2.Value?.ErrorText))
5953 TemplateId +
": " + P2.Value.ErrorText,
"en");
5981 if (!(
Contract.ClientSignatures is
null))
5987 SignaturesToTransfer ??=
new LinkedList<ClientSignature>();
5988 SignaturesToTransfer.AddLast(
Signature);
5995 Version = QueryVersion,
5996 ForMachines =
Contract.ForMachines,
5997 ForMachinesLocalName =
Contract.ForMachinesLocalName,
5998 ForMachinesNamespace =
Contract.ForMachinesNamespace,
6009 if (HasSecondaryName(
Contract, out
string SecondaryName,
6012 Contract.SecondaryType = NameType;
6013 Contract.SecondaryLocalName = SecondaryName;
6014 Contract.SecondaryNamespace = SecondaryNamespace;
6019 Contract.SecondaryLocalName =
null;
6020 Contract.SecondaryNamespace =
null;
6023 bool HasVisibility =
false;
6024 bool HasDuration =
false;
6025 bool HasArchiveReq =
false;
6026 bool HasArchiveOpt =
false;
6027 bool WellDefined =
true;
6029 foreach (XmlAttribute Attr
in E.Attributes)
6036 Contract.Visibility = Visibility;
6037 HasVisibility =
true;
6040 WellDefined =
false;
6046 Contract.Duration = D;
6050 WellDefined =
false;
6056 Contract.ArchiveRequired = D;
6057 HasArchiveReq =
true;
6060 WellDefined =
false;
6066 Contract.ArchiveOptional = D;
6067 HasArchiveOpt =
true;
6070 WellDefined =
false;
6077 WellDefined =
false;
6084 WellDefined =
false;
6087 case "canActAsTemplate":
6090 Contract.CanActAsTemplate = b;
6091 HasArchiveOpt =
true;
6094 WellDefined =
false;
6100 Contract.Nonce = Convert.FromBase64String(Attr.Value);
6114 if (Attr.Prefix !=
"xmlns")
6115 WellDefined =
false;
6120 if (!(WellDefined && HasVisibility && HasDuration && HasArchiveReq && HasArchiveOpt))
6132 foreach (XmlNode N2
in E.ChildNodes)
6134 if (N2 is XmlElement E2)
6136 switch (E2.LocalName)
6139 List<Part> Parts =
null;
6142 foreach (XmlNode N3
in E2.ChildNodes)
6144 if (N3 is XmlElement E3)
6146 switch (E3.LocalName)
6158 case "templateOnly":
6183 foreach (XmlAttribute Attr
in E3.Attributes)
6188 LegalId = Attr.
Value;
6192 RoleRef = Attr.
Value;
6199 if (Attr.Prefix !=
"xmlns")
6200 WellDefined =
false;
6211 bool RoleFound =
false;
6217 if (Role2.
Name == RoleRef)
6231 Parts ??=
new List<Part>();
6232 Parts.Add(
new Part()
6241 WellDefined =
false;
6247 if (!WellDefined || !Mode.HasValue)
6253 Contract.PartsMode = Mode.Value;
6254 Contract.Parts = Parts?.ToArray();
6266 if (!Parameters.ContainsKey(P3.
Name))
6268 Parameters[P3.
Name] = P3;
6269 ParameterOrder.AddLast(P3.
Name);
6273 foreach (XmlNode N3
in E2.ChildNodes)
6275 if (N3 is XmlElement E3)
6284 if (!Parameters.TryGetValue(Name, out
Parameter OrgParameter))
6286 await e.
IqErrorBadRequest(e.
To,
"Parameter does not exist in original contract: " + Name,
"en");
6290 Parameter ParameterDefinition = await this.TryParseParameter(E3, e, Name, OrgParameter);
6291 if (ParameterDefinition is
null)
6294 Parameters[Name] = ParameterDefinition;
6300 CreateContractThread.
NewState(
"Parameters");
6302 ParametersChecked =
true;
6307 if (!(FailingParameter is
null))
6314 int c = Parameters.Count;
6318 foreach (
string Name
in ParameterOrder)
6319 NewParameters[i++] = Parameters[Name];
6321 Contract.Parameters = NewParameters;
6339 if (ParameterOrder.First is
null)
6343 if (!Parameters.ContainsKey(P3.
Name))
6345 Parameters[P3.
Name] = P3;
6346 ParameterOrder.AddLast(P3.
Name);
6351 foreach (XmlNode N3
in E.ChildNodes)
6353 if (N3 is XmlElement E3)
6362 if (!Parameters.TryGetValue(Name, out
Parameter OrgParameter))
6364 await e.
IqErrorBadRequest(e.
To,
"Parameter does not exist in original contract: " + Name,
"en");
6368 Parameter ParameterDefinition = await this.TryParseParameter(E3, e, Name, OrgParameter);
6369 if (ParameterDefinition is
null)
6372 TransientParameters ??=
new Dictionary<CaseInsensitiveString, Parameter>();
6373 TransientParameters[Name] = ParameterDefinition;
6377 if (!(TransientParameters is
null))
6379 foreach (
Parameter TransientParameter
in TransientParameters.Values)
6383 ContractParamteter.StringValue = TransientParameter.
StringValue;
6384 ContractParamteter.ProtectedValue = TransientParameter.
ProtectedValue;
6391 CreateContractThread.
NewState(
"Parameters");
6397 if (!(FailingParameter2 is
null))
6404 ParametersChecked =
true;
6405 HasTransientParameters =
true;
6426 if (!ParametersChecked)
6428 CreateContractThread.
NewState(
"Parameters");
6434 if (!(FailingParameter3 is
null))
6443 Contract.Created = UtcNowSecond;
6444 Contract.Updated = DateTime.MinValue;
6446 CreateContractThread.
NewState(
"Integrity");
6449 string IntegrityParameter =
P.Value;
6465 await e.
IqErrorBadRequest(e.
To,
"Role counts are incorrect for role " + IntegrityParameter,
"en");
6469 await e.
IqErrorBadRequest(e.
To,
"Duplicate role definition for role " + IntegrityParameter,
"en");
6473 await e.
IqErrorBadRequest(e.
To,
"Duplicate parameter definition for parameter " + IntegrityParameter,
"en");
6477 await e.
IqErrorBadRequest(e.
To,
"Invalid Legal ID reference: " + IntegrityParameter,
"en");
6493 await e.
IqErrorBadRequest(e.
To,
"Role index is invalid for role reference parameter " + IntegrityParameter,
"en");
6497 await e.
IqErrorBadRequest(e.
To,
"Missing property reference for role reference parameter " + IntegrityParameter,
"en");
6501 await e.
IqErrorBadRequest(e.
To,
"Machine-readable information is missing or is invalid.",
"en");
6505 await e.
IqErrorBadRequest(e.
To,
"Missing human-readable information for role " + IntegrityParameter,
"en");
6509 await e.
IqErrorBadRequest(e.
To,
"Missing human-readable information for parameter " + IntegrityParameter,
"en");
6513 await e.
IqErrorBadRequest(e.
To,
"Validation expression error for parameter " + IntegrityParameter,
"en");
6517 await e.
IqErrorBadRequest(e.
To,
"An undefined parameter is referenced: " + IntegrityParameter,
"en");
6525 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for contract: " + IntegrityParameter,
"en");
6529 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for role: " + IntegrityParameter,
"en");
6533 await e.
IqErrorBadRequest(e.
To,
"Duplication language reference for human-readable text for parameter: " + IntegrityParameter,
"en");
6541 CreateContractThread.
NewState(
"Legal ID");
6544 if (Identity is
null)
6546 await e.
IqErrorForbidden(e.
To,
"No current approved legal identity found for account.",
"en");
6550 CreateContractThread.
NewState(
"Content");
6553 SchemaProfiler?.
Start();
6557 string Errors = await this.ValidateContent(
Contract, SchemaProfiler);
6558 if (!
string.IsNullOrEmpty(Errors))
6566 SchemaProfiler?.
Idle();
6567 SchemaProfiler?.
Stop();
6570 StringBuilder Xml =
new StringBuilder();
6572 if (!(SignaturesToTransfer is
null))
6574 CreateContractThread.
NewState(
"Signature Transfer");
6576 Dictionary<string, int> RoleCounters =
new Dictionary<string, int>();
6577 List<ClientSignature> Transfered =
null;
6579 await
Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
6580 byte[]
Data = Encoding.UTF8.GetBytes(Xml.ToString());
6584 Dictionary<string, string> AttachmentUrls;
6586 (Identity, AttachmentUrls) = await this.ValidateSenderSignature(
6590 if (!(Identity is
null))
6592 if (!RoleCounters.TryGetValue(
Signature.Role, out
int RoleIndex))
6598 AttachmentUrls,
this) is
null)
6600 Transfered ??=
new List<ClientSignature>();
6602 RoleCounters[
Signature.Role] = RoleIndex;
6607 Contract.ClientSignatures = Transfered?.ToArray();
6612 if (HasTransientParameters)
6614 CreateContractThread.
NewState(
"Transient Parameters");
6618 CreateContractThread.
NewState(
"Object ID");
6622 CreateContractThread.
NewState(
"Sign");
6624 Contract.ContractId = Contract.ObjectId +
"@" + e.
To.
Address;
6632 CreateContractThread.
NewState(
"Store");
6636 if (HasTransientParameters)
6638 CreateContractThread.
NewState(
"Transient");
6642 CreateContractThread.
NewState(
"Tags");
6644 KeyValuePair<string, object>[] Tags =
Contract.GetTags();
6664 CreateContractThread.
NewState(
"Return Response");
6668 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
6669 string ContractXml = Xml.ToString();
6676 CreateContractThread.
NewState(
"Notifications");
6678 StringBuilder Markdown =
new StringBuilder();
6680 Markdown.Append(
"Contract proposal received: [");
6682 Markdown.Append(
"](");
6684 Markdown.AppendLine(
")");
6685 Markdown.AppendLine();
6691 CreateContractThread.
NewState(
"Event");
6693 await this.SendContractUpdatedEvent(
Contract,
true);
6695 catch (Exception ex)
6702 CreateContractThread.
Stop();
6703 ParametersThread.
Stop();
6710 Log.
Debug(
"Slow contract creation:\r\n\r\n```uml\r\n" + Uml +
"```",
6711 new KeyValuePair<string, object>(
"From", e.
From.
Address),
6712 new KeyValuePair<string, object>(
"To", e.
To.
Address),
6714 new KeyValuePair<string, object>(
"TemplateId",
Contract?.TemplateId));
6727 internal static bool HasSecondaryName(
Contract Contract, out
string LocalName,
6734 if (
Contract.ForMachinesLocalName !=
"Create" ||
6736 Contract.ForMachinesParsed.DocumentElement is
null)
6743 foreach (XmlNode N
in Contract.ForMachinesParsed.DocumentElement.ChildNodes)
6745 if (N is XmlElement E &&
6746 E.LocalName ==
"Definition" &&
6749 foreach (XmlNode N2
in E.ChildNodes)
6751 if (N2 is XmlElement E2)
6753 LocalName = E2.LocalName;
6754 Namespace = E2.NamespaceURI;
6764 catch (Exception ex)
6773 Dictionary<CaseInsensitiveString, Parameter> TransientParameters)
6775 this.transientParameters?.
Add(ContractId, TransientParameters);
6780 byte[] ProtectedValue =
null;
6782 if (E3.HasAttribute(
"guide") &&
XML.
Attribute(E3,
"guide") != OrgParameter.
Guide)
6790 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6794 if (E3.HasAttribute(
"protection"))
6798 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter protection rules.",
"en");
6803 if (E3.HasAttribute(
"protected"))
6807 ProtectedValue = Convert.FromBase64String(
XML.
Attribute(E3,
"protected"));
6818 switch (E3.LocalName)
6820 case "stringParameter":
6827 if ((E3.HasAttribute(
"regEx") &&
XML.
Attribute(E3,
"regEx") != OldStringParameter.RegEx) ||
6828 (E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min") != OldStringParameter.Min) ||
6829 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max") != OldStringParameter.Max) ||
6830 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldStringParameter.MinIncluded) ||
6831 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldStringParameter.MaxIncluded) ||
6832 (E3.HasAttribute(
"minLength") &&
XML.
Attribute(E3,
"minLength", 0) != OldStringParameter.MinLength) ||
6833 (E3.HasAttribute(
"maxLength") &&
XML.
Attribute(E3,
"maxLength", 0) != OldStringParameter.MaxLength) ||
6837 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6845 Guide = OrgParameter.
Guide,
6847 RegEx = OldStringParameter.RegEx,
6848 Min = OldStringParameter.Min,
6849 Max = OldStringParameter.Max,
6850 MinIncluded = OldStringParameter.MinIncluded,
6851 MaxIncluded = OldStringParameter.MaxIncluded,
6852 MinLength = OldStringParameter.MinLength,
6853 MaxLength = OldStringParameter.MaxLength,
6856 ProtectedValue = ProtectedValue
6859 case "numericalParameter":
6866 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", 0.0m) != OldNumericalParameter.Min) ||
6867 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", 0.0m) != OldNumericalParameter.Max) ||
6868 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldNumericalParameter.MinIncluded) ||
6869 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldNumericalParameter.MaxIncluded) ||
6873 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6880 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", 0.0m) : (decimal?)
null,
6881 Guide = OrgParameter.
Guide,
6883 Min = OldNumericalParameter.Min,
6884 Max = OldNumericalParameter.Max,
6885 MinIncluded = OldNumericalParameter.MinIncluded,
6886 MaxIncluded = OldNumericalParameter.MaxIncluded,
6889 ProtectedValue = ProtectedValue
6892 case "booleanParameter":
6899 if ((E3.HasAttribute(
"protection") &&
XML.
Attribute(E3,
"protection",
ProtectionLevel.Normal) != OldBooleanParameter.Protection) ||
6902 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6909 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value",
false) : (
bool?)
null,
6910 Guide = OrgParameter.
Guide,
6914 ProtectedValue = ProtectedValue
6917 case "dateParameter":
6924 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", DateTime.MinValue) != OldDateParameter.Min) ||
6925 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", DateTime.MinValue) != OldDateParameter.Max) ||
6926 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDateParameter.MinIncluded) ||
6927 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDateParameter.MaxIncluded) ||
6931 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6938 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", DateTime.MinValue).Date : (DateTime?)
null,
6939 Guide = OrgParameter.
Guide,
6941 Min = OldDateParameter.Min,
6942 Max = OldDateParameter.Max,
6943 MinIncluded = OldDateParameter.MinIncluded,
6944 MaxIncluded = OldDateParameter.MaxIncluded,
6947 ProtectedValue = ProtectedValue
6950 case "dateTimeParameter":
6957 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", DateTime.MinValue) != OldDateTimeParameter.Min) ||
6958 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", DateTime.MinValue) != OldDateTimeParameter.Max) ||
6959 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDateTimeParameter.MinIncluded) ||
6960 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDateTimeParameter.MaxIncluded) ||
6964 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
6971 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", DateTime.MinValue) : (DateTime?)
null,
6972 Guide = OrgParameter.
Guide,
6974 Min = OldDateTimeParameter.Min,
6975 Max = OldDateTimeParameter.Max,
6976 MinIncluded = OldDateTimeParameter.MinIncluded,
6977 MaxIncluded = OldDateTimeParameter.MaxIncluded,
6980 ProtectedValue = ProtectedValue
6983 case "timeParameter":
6990 if ((E3.HasAttribute(
"min") &&
XML.
Attribute(E3,
"min", TimeSpan.Zero) != OldTimeParameter.Min) ||
6991 (E3.HasAttribute(
"max") &&
XML.
Attribute(E3,
"max", TimeSpan.Zero) != OldTimeParameter.Max) ||
6992 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldTimeParameter.MinIncluded) ||
6993 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldTimeParameter.MaxIncluded) ||
6997 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7004 Value = E3.HasAttribute(
"value") ?
XML.
Attribute(E3,
"value", TimeSpan.Zero) : (TimeSpan?)
null,
7005 Guide = OrgParameter.
Guide,
7007 Min = OldTimeParameter.Min,
7008 Max = OldTimeParameter.Max,
7009 MinIncluded = OldTimeParameter.MinIncluded,
7010 MaxIncluded = OldTimeParameter.MaxIncluded,
7013 ProtectedValue = ProtectedValue
7016 case "durationParameter":
7025 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldDurationParameter.MinIncluded) ||
7026 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldDurationParameter.MaxIncluded) ||
7030 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7038 Guide = OrgParameter.
Guide,
7040 Min = OldDurationParameter.Min,
7041 Max = OldDurationParameter.Max,
7042 MinIncluded = OldDurationParameter.MinIncluded,
7043 MaxIncluded = OldDurationParameter.MaxIncluded,
7046 ProtectedValue = ProtectedValue
7049 case "geoParameter":
7056 if ((E3.HasAttribute(
"min") &&
GeoParameter.GeoPositionAttribute(E3,
"min") != OldGeoParameter.Min) ||
7057 (E3.HasAttribute(
"max") &&
GeoParameter.GeoPositionAttribute(E3,
"max") != OldGeoParameter.Max) ||
7058 (E3.HasAttribute(
"minIncluded") &&
XML.
Attribute(E3,
"minIncluded",
true) != OldGeoParameter.MinIncluded) ||
7059 (E3.HasAttribute(
"maxIncluded") &&
XML.
Attribute(E3,
"maxIncluded",
true) != OldGeoParameter.MaxIncluded) ||
7060 (E3.HasAttribute(
"altitude") &&
XML.
Attribute(E3,
"altitude",
AltitudeUse.Optional) != OldGeoParameter.Altitude) ||
7061 (E3.HasAttribute(
"contractLocation") &&
XML.
Attribute(E3,
"contractLocation",
false) != OldGeoParameter.ContractLocation) ||
7065 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7072 Value =
GeoParameter.GeoPositionAttribute(E3,
"value"),
7073 Guide = OrgParameter.
Guide,
7075 Min = OldGeoParameter.Min,
7076 Max = OldGeoParameter.Max,
7077 MinIncluded = OldGeoParameter.MinIncluded,
7078 MaxIncluded = OldGeoParameter.MaxIncluded,
7079 Altitude = OldGeoParameter.Altitude,
7080 ContractLocation = OldGeoParameter.ContractLocation,
7083 ProtectedValue = ProtectedValue
7086 case "calcParameter":
7095 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7102 Guide = OrgParameter.
Guide,
7106 ProtectedValue = ProtectedValue
7109 case "roleParameter":
7116 if ((E3.HasAttribute(
"role") &&
XML.
Attribute(E3,
"role") != OldRoleParameter.Role) ||
7117 (E3.HasAttribute(
"index") &&
XML.
Attribute(E3,
"index", 0) != OldRoleParameter.Index) ||
7118 (E3.HasAttribute(
"property") &&
XML.
Attribute(E3,
"property") != OldRoleParameter.Property) ||
7119 (E3.HasAttribute(
"required") &&
XML.
Attribute(E3,
"required",
false) != OldRoleParameter.Required) ||
7123 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7130 Role = OldRoleParameter.Role,
7131 Index = OldRoleParameter.Index,
7133 Required = OldRoleParameter.Required,
7134 Guide = OrgParameter.
Guide,
7138 ProtectedValue = ProtectedValue
7141 case "contractReferenceParameter":
7148 if ((E3.HasAttribute(
"localName") &&
XML.
Attribute(E3,
"localName") != OldContractReferenceParameter.LocalName) ||
7149 (E3.HasAttribute(
"namespace") &&
XML.
Attribute(E3,
"namespace") != OldContractReferenceParameter.Namespace) ||
7150 (E3.HasAttribute(
"templateId") &&
XML.
Attribute(E3,
"templateId") != OldContractReferenceParameter.TemplateId) ||
7151 (E3.HasAttribute(
"provider") &&
XML.
Attribute(E3,
"provider") != OldContractReferenceParameter.Provider) ||
7152 (E3.HasAttribute(
"creatorRole") &&
XML.
Attribute(E3,
"creatorRole") != OldContractReferenceParameter.CreatorRole) ||
7153 (E3.HasAttribute(
"required") &&
XML.
Attribute(E3,
"required",
false) != OldContractReferenceParameter.Required) ||
7154 (E3.HasAttribute(
"protection") &&
XML.
Attribute(E3,
"protection",
ProtectionLevel.Normal) != OldContractReferenceParameter.Protection) ||
7157 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7165 Guide = OrgParameter.
Guide,
7168 Labels = OldContractReferenceParameter.Labels,
7169 LocalName = OldContractReferenceParameter.LocalName,
7170 Namespace = OldContractReferenceParameter.Namespace,
7171 TemplateId = OldContractReferenceParameter.TemplateId,
7172 Provider = OldContractReferenceParameter.Provider,
7173 CreatorRole = OldContractReferenceParameter.CreatorRole,
7174 Required = OldContractReferenceParameter.Required,
7176 ProtectedValue = ProtectedValue
7179 case "attachmentParameter":
7186 if ((E3.HasAttribute(
"required") &&
XML.
Attribute(E3,
"required",
false) != OldAttachmentParameter.Required) ||
7187 (E3.HasAttribute(
"contentType") &&
XML.
Attribute(E3,
"contentType") != OldAttachmentParameter.ContentType) ||
7188 (E3.HasAttribute(
"minSize") &&
XML.
Attribute(E3,
"minSize", 0) != OldAttachmentParameter.MinSize) ||
7189 (E3.HasAttribute(
"maxSize") &&
XML.
Attribute(E3,
"maxSize", 0) != OldAttachmentParameter.MaxSize) ||
7190 (E3.HasAttribute(
"minWidth") &&
XML.
Attribute(E3,
"minWidth", 0) != OldAttachmentParameter.MinWidth) ||
7191 (E3.HasAttribute(
"maxWidth") &&
XML.
Attribute(E3,
"maxWidth", 0) != OldAttachmentParameter.MaxWidth) ||
7192 (E3.HasAttribute(
"minHeight") &&
XML.
Attribute(E3,
"minHeight", 0) != OldAttachmentParameter.MinHeight) ||
7193 (E3.HasAttribute(
"maxHeight") &&
XML.
Attribute(E3,
"maxHeight", 0) != OldAttachmentParameter.MaxHeight) ||
7194 (E3.HasAttribute(
"protection") &&
XML.
Attribute(E3,
"protection",
ProtectionLevel.Normal) != OldAttachmentParameter.Protection) ||
7197 await e.
IqErrorBadRequest(e.
To,
"Not allowed to change parameter validation rules.",
"en");
7205 Guide = OrgParameter.
Guide,
7207 Required = OldAttachmentParameter.Required,
7209 MinSize = OldAttachmentParameter.MinSize,
7210 MaxSize = OldAttachmentParameter.MaxSize,
7211 MinWidth = OldAttachmentParameter.MinWidth,
7212 MaxWidth = OldAttachmentParameter.MaxWidth,
7213 MinHeight = OldAttachmentParameter.MinHeight,
7214 MaxHeight = OldAttachmentParameter.MaxHeight,
7217 ProtectedValue = ProtectedValue
7229 string IntegrityParameter =
P.Value;
7233 ContentIntegrity.Ok =>
null,
7234 ContentIntegrity.RolesNotDefined =>
"No roles have been defined.",
7235 ContentIntegrity.PartsNotDefined =>
"Part definition expected.",
7236 ContentIntegrity.RoleCountsMismatch =>
"Role counts are incorrect for role " + IntegrityParameter,
7237 ContentIntegrity.DuplicateRoleDefinition =>
"Duplicate role definition for role " + IntegrityParameter,
7238 ContentIntegrity.DuplicateParameterDefinition =>
"Duplicate parameter definition for parameter " + IntegrityParameter,
7239 ContentIntegrity.InvalidLegalIdReference =>
"Invalid Legal ID reference: " + IntegrityParameter,
7240 ContentIntegrity.InvalidRoleReference =>
"Invalid role reference: " + IntegrityParameter,
7241 ContentIntegrity.TooFewPartsOfRole =>
"Too few parts for role " + IntegrityParameter,
7242 ContentIntegrity.TooManyPartsOfRole =>
"Too many parts for role " + IntegrityParameter,
7243 ContentIntegrity.InvalidRoleIndex =>
"Role index is invalid for role reference parameter " + IntegrityParameter,
7244 ContentIntegrity.MissingRoleProperty =>
"Missing property reference for role reference parameter " + IntegrityParameter,
7245 ContentIntegrity.InvalidMachineReadable =>
"Machine-readable information is missing or is invalid.",
7246 ContentIntegrity.MissingRoleHumanReadable =>
"Missing human-readable information for role " + IntegrityParameter,
7247 ContentIntegrity.MissingParameterHumanReadable =>
"Missing human-readable information for parameter " + IntegrityParameter,
7248 ContentIntegrity.ParameterValidationExpressionError =>
"Validation expression error for parameter " + IntegrityParameter,
7249 ContentIntegrity.InvalidParameterReference =>
"An undefined parameter is referenced: " + IntegrityParameter,
7250 ContentIntegrity.MissingHumanReadable =>
"Missing human-readable information.",
7251 ContentIntegrity.DuplicateLocalization =>
"Duplication language reference for human-readable text for contract: " + IntegrityParameter,
7252 ContentIntegrity.DuplicateRoleLocalization =>
"Duplication language reference for human-readable text for role: " + IntegrityParameter,
7253 ContentIntegrity.DuplicateParameterLocalization =>
"Duplication language reference for human-readable text for parameter: " + IntegrityParameter,
7254 _ =>
"Contract integrity check failed for unknown reasons.",
7260 Contract.ContentSchemaDigest =
null;
7261 Contract.ContentSchemaHashFunction =
HashFunction.SHA256;
7263 if (
string.IsNullOrEmpty(
Contract.ForMachines))
7264 return "No machine-readable content.";
7272 if (Doc.DocumentElement is
null)
7273 return "Invalid machine-readable XML: No root element.";
7275 catch (XmlException ex)
7278 return "Invalid machine-readable XML: " + ex.Message;
7280 catch (Exception ex)
7282 return "Invalid machine-readable XML: " + ex.Message;
7285 (
string ErrorMessage, Dictionary<string, ValidationSchema> Schemas) = await this.ValidateContent(Doc,
Profiler);
7286 if (!
string.IsNullOrEmpty(ErrorMessage))
7287 return ErrorMessage;
7289 int NrSchemas = Schemas.Count;
7290 if (NrSchemas == 0 || !Schemas.ContainsKey(
Contract.ForMachinesNamespace))
7291 return "Machine-readable content not defined by schemas.";
7294 int c = Schemas.Count;
7302 Digest = Convert.FromBase64String(Schema2.
HashBase64),
7303 Algorithm = Schema2.Function
7307 Contract.SchemaReferences = References;
7311 Contract.ContentSchemaDigest = Ref.
Digest;
7312 Contract.ContentSchemaHashFunction = Ref.Algorithm;
7315 return "M2M content schema not found.";
7320 internal async Task<(string, Dictionary<string, ValidationSchema>)> ValidateContent(XmlDocument Doc,
ProfilerThread Profiler)
7324 Dictionary<string, ValidationSchema> Schemas =
new Dictionary<string, ValidationSchema>();
7330 string LastNamespace =
null;
7336 Namespace = E.NamespaceURI;
7337 if (!
string.IsNullOrEmpty(Namespace) && Namespace != LastNamespace)
7339 Schemas[Namespace] =
null;
7340 LastNamespace = Namespace;
7343 if (E.HasAttributes)
7345 foreach (XmlAttribute Attr
in E.Attributes)
7347 Namespace = Attr.NamespaceURI;
7349 if (!
string.IsNullOrEmpty(Namespace) &&
7350 Namespace != LastNamespace &&
7351 Namespace !=
"http://www.w3.org/XML/1998/namespace" &&
7352 Namespace !=
"http://www.w3.org/2000/xmlns/")
7354 Schemas[Namespace] =
null;
7359 foreach (XmlNode N
in E.ChildNodes)
7361 if (N is XmlElement E2)
7366 int NrSchemas = Schemas.Count;
7369 Dictionary<string, bool> Loaded =
new Dictionary<string, bool>();
7370 string[] Namespaces;
7377 Namespaces =
new string[NrSchemas];
7378 Schemas.Keys.CopyTo(Namespaces, 0);
7380 foreach (
string Namespace2
in Namespaces)
7382 if (Loaded.ContainsKey(Namespace2))
7391 (Schema, ErrorMsg) = await this.LoadSchema(Namespace2,
null);
7392 if (!
string.IsNullOrEmpty(ErrorMsg))
7393 return (ErrorMsg,
null);
7395 Loaded[Namespace2] =
true;
7398 Schemas[Namespace2] = Schema;
7400 string[] Imports = GetImports(Schema.
Parsed);
7402 foreach (
string Import
in Imports)
7404 if (!Schemas.ContainsKey(Import))
7406 Schemas[Import] =
null;
7417 ErrorMsg = this.ValidateXml(Schemas.Values, Doc);
7418 if (!
string.IsNullOrEmpty(ErrorMsg))
7420 bool Changed =
false;
7422 foreach (
string Namespace2
in Namespaces)
7424 if (Loaded.ContainsKey(Namespace2))
7427 Schema = Schemas[Namespace2];
7428 (
ValidationSchema Schema2,
string ErrorMsg2) = await this.LoadSchema(Namespace2, Schema);
7429 if (!
string.IsNullOrEmpty(ErrorMsg2))
7430 return (ErrorMsg2,
null);
7432 if (Schema2 != Schema)
7434 Schemas[Namespace2] = Schema2;
7440 return (ErrorMsg,
null);
7442 ErrorMsg = this.ValidateXml(Schemas.Values, Doc);
7443 if (!
string.IsNullOrEmpty(ErrorMsg))
7444 return (ErrorMsg,
null);
7447 return (
null, Schemas);
7450 private static string[] GetImports(XmlSchema Schema)
7452 Dictionary<string, bool> Result =
null;
7455 foreach (XmlSchemaObject Obj
in Schema.Includes)
7462 if (Obj is XmlSchemaExternal External)
7464 if (!(External.Schema is
null))
7466 foreach (XmlSchemaObject Obj2
in External.Schema.Includes)
7470 if (Obj is XmlSchemaImport Import)
7472 Result ??=
new Dictionary<string, bool>();
7473 Result[Import.Namespace] =
true;
7479 return Array.Empty<
string>();
7481 string[] Result2 =
new string[Result.Count];
7482 Result.Keys.CopyTo(Result2, 0);
7494 case "http://www.w3.org/XML/1998/namespace":
7495 Type T = typeof(Networking.XMPP.Contracts.ContractsClient);
7496 Assembly
A = T.Assembly;
7497 File =
A.GetManifestResourceStream(T.Namespace +
".Schema.Xml.xsd");
7501 case "http://www.w3.org/2000/xmlns/":
7502 T = typeof(Networking.XMPP.Contracts.ContractsClient);
7504 File =
A.GetManifestResourceStream(T.Namespace +
".Schema.Xmlns.xsd");
7509 Uri Uri =
new Uri(Namespace);
7512 return (
null,
"Schema not downloadable: " + Namespace);
7517 new KeyValuePair<string, string>(
"Accept",
"application/xml, text/xml"),
7518 new KeyValuePair<string, string>(
"Accept-Charset",
"utf-8"));
7521 return (
null,
"Unable to get schema file " + Namespace +
". The following error was reported: " +
P.Error.Message);
7526 catch (Exception ex)
7528 return (
null,
"Unable to get schema file " + Namespace +
". The following error was reported: " + ex.Message);
7535 if (File.Length >
int.MaxValue)
7536 throw new OutOfMemoryException(
"Schema file too large.");
7540 byte[] Bin = await File.ReadAllAsync();
7544 if (!(PrevSchema is
null) && Digest == PrevSchema.
HashBase64)
7545 return (PrevSchema,
null);
7549 Namespace = Namespace,
7551 HashBase64 = Digest,
7552 Created = UtcNowSecond,
7559 return (Schema,
null);
7567 private string ValidateXml(IEnumerable<ValidationSchema> Schemas, XmlDocument Xml)
7569 StringBuilder Errors =
null;
7570 StringBuilder Warnings =
null;
7574 if (Xml.Schemas.Count > 0)
7576 LinkedList<XmlSchema> ToRemove =
new LinkedList<XmlSchema>();
7578 foreach (XmlSchema Schema
in Xml.Schemas.Schemas())
7579 ToRemove.AddLast(Schema);
7581 foreach (XmlSchema Schema
in ToRemove)
7582 Xml.Schemas.Remove(Schema);
7586 Xml.Schemas.Add(Schema.
Parsed);
7588 Xml.Validate((sender2, e2) =>
7590 switch (e2.Severity)
7592 case XmlSeverityType.Error:
7593 Errors ??= new StringBuilder();
7594 Errors.AppendLine(e2.Message);
7597 case XmlSeverityType.Warning:
7598 Warnings ??= new StringBuilder();
7599 Warnings.AppendLine(e2.Message);
7604 catch (Exception ex)
7606 Errors ??=
new StringBuilder();
7607 Errors.AppendLine(ex.Message);
7610 if (!(Errors is
null) || !(Warnings is
null))
7612 StringBuilder Report =
new StringBuilder();
7614 if (!(Errors is
null))
7616 Report.AppendLine(
"Errors found during validation:");
7617 Report.AppendLine(
new string(
'-', 40));
7618 Report.Append(Errors.ToString());
7620 if (!(Warnings is
null))
7621 Report.AppendLine();
7624 if (!(Warnings is
null))
7626 Report.AppendLine(
"Warnings found during validation:");
7627 Report.AppendLine(
new string(
'-', 40));
7628 Report.Append(Warnings.ToString());
7631 return Report.ToString();
7642 public static async Task<Tuple<byte[], XmlSchema>>
LoadSchema(
string Url)
7646 HttpRequestMessage Request =
null;
7647 HttpResponseMessage Response =
null;
7648 HttpClient Client =
new HttpClient();
7652 Client.Timeout = TimeSpan.FromMilliseconds(30000);
7653 Client.DefaultRequestHeaders.ExpectContinue =
false;
7655 Uri Uri =
new Uri(Url);
7656 Request =
new HttpRequestMessage(HttpMethod.Head, Uri);
7657 Request.Headers.Add(
"Accept",
"application/xml, text/xml");
7658 Request.Headers.Add(
"Accept-Charset",
"utf-8");
7660 Response = await Client.SendAsync(Request);
7661 if (!Response.IsSuccessStatusCode)
7667 Request =
new HttpRequestMessage(HttpMethod.Get, Uri);
7668 Request.Headers.Add(
"Accept",
"application/xml, text/xml");
7669 Request.Headers.Add(
"Accept-Charset",
"utf-8");
7671 Response = await Client.SendAsync(Request);
7672 if (!Response.IsSuccessStatusCode)
7675 string ContentType =
null;
7677 if (Response.Headers.TryGetValues(
"Content-Type", out IEnumerable<string> Values))
7679 foreach (
string s
in Values)
7688 byte[]
Data = await Response.Content.ReadAsByteArrayAsync();
7697 if (!(Decoded.
Decoded is XmlDocument Doc))
7700 using XmlReader r = XmlReader.Create(
new MemoryStream(
Data));
7701 XmlSchema Schema = XmlSchema.Read(r,
null);
7702 return new Tuple<byte[], XmlSchema>(
Data, Schema);
7707 Response?.Dispose();
7711 catch (Exception ex)
7719 private async Task GetCreatedContractsHandler(
object Sender,
IqEventArgs e)
7723 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
7737 string Xml = await this.SerializeContractReferences(Contracts, References, QueryVersion);
7741 catch (Exception ex)
7747 internal async Task<string> SerializeContractReferences(IEnumerable<IContractReference> Contracts,
bool References,
NamespaceSet Version)
7749 StringBuilder Xml =
new StringBuilder();
7752 Xml.Append(
"<contractReferences xmlns='");
7754 Xml.Append(
"<contracts xmlns='");
7756 Xml.Append(NamespaceSmartContracts(Version));
7763 Xml.Append(
"<ref id='");
7768 await Contract2.Serialize(Xml, Contract2.Version != Version,
true,
true,
true,
true,
true,
true,
null,
this);
7771 KeyValuePair<Contract, IqResultEventArgs>
P = await this.GetContract(
Contract.
ContractId);
7774 if (Contract2 is
null)
7776 Xml.Append(
"<ref id='");
7781 await Contract2.Serialize(Xml, Contract2.Version != Version,
true,
true,
true,
true,
true,
true,
null,
this);
7786 Xml.Append(
"</contractReferences>");
7788 Xml.Append(
"</contracts>");
7793 public async Task<CaseInsensitiveString> GetComponent(
CaseInsensitiveString ServerDomain,
string Feature)
7795 KeyValuePair<CaseInsensitiveString, string>
P = await this.GetComponent(ServerDomain,
new string[] { Feature });
7799 public async Task<KeyValuePair<CaseInsensitiveString, string>> GetComponent(
CaseInsensitiveString ServerDomain, params
string[] Features)
7805 return new KeyValuePair<CaseInsensitiveString, string>(
P.Key,
P.Value);
7808 foreach (
string Feature
in Features)
7810 string Key = ServerDomain +
"#" + Feature;
7812 if (this.remoteComponents.
TryGetValue(Key, out
object Obj) &&
7815 return new KeyValuePair<CaseInsensitiveString, string>(JID, Feature);
7819 TaskCompletionSource<KeyValuePair<CaseInsensitiveString, string>> Result =
7820 new TaskCompletionSource<KeyValuePair<CaseInsensitiveString, string>>();
7823 "<query xmlns='http://jabber.org/protocol/disco#items'/>",
true, async (Sender, e) =>
7825 if (e.Ok && !(e.FirstElement is
null))
7827 List<CaseInsensitiveString> JIDs =
new List<CaseInsensitiveString>() { ServerDomain };
7828 object SynchObject =
new object();
7830 foreach (XmlNode N
in e.FirstElement)
7832 if (N is XmlElement E && E.LocalName ==
"item")
7840 int Count = JIDs.Count;
7844 await this.Server.SendIqRequest(
"get",
new XmppAddress(this.Server.Domain),
new XmppAddress(JID2),
string.Empty,
7845 "<query xmlns='http://jabber.org/protocol/disco#info'/>",
true, (sender2, e2) =>
7849 foreach (XmlNode N2 in e2.FirstElement)
7851 if (!(N2 is XmlElement E2) || E2.LocalName !=
"feature")
7854 string Var = XML.Attribute(E2,
"var");
7856 foreach (string Feature in Features)
7868 CaseInsensitiveString s = (CaseInsensitiveString)e2.State;
7869 string Key = ServerDomain +
"#" + Feature;
7871 this.remoteComponents[Key] = s;
7872 Result.TrySetResult(new KeyValuePair<CaseInsensitiveString, string>(s, Feature));
7874 return Task.CompletedTask;
7884 return Task.CompletedTask;
7887 Result.TrySetResult(
new KeyValuePair<CaseInsensitiveString, string>(
null,
null));
7889 return Task.CompletedTask;
7894 Result.TrySetResult(
new KeyValuePair<CaseInsensitiveString, string>(
null,
null));
7897 return await Result.Task;
7900 private async Task SignContractHandler(
object Sender,
IqEventArgs e)
7907 bool Transferable =
false;
7909 foreach (XmlAttribute Attr
in e.
Query.Attributes)
7914 ContractId = Attr.
Value;
7922 Signature = Convert.FromBase64String(Attr.Value);
7925 case "transferable":
7937 if (ContractId is
null ||
Role is
null ||
Signature is
null)
7953 await e.
IqErrorForbidden(e.
To,
"Contract is a template only, and cannot be signed.",
"en");
7980 DateTime UtcNow = DateTime.UtcNow;
7981 if (
Contract.SignAfter.HasValue && UtcNow <
Contract.SignAfter.Value.ToUniversalTime())
7983 await e.
IqErrorForbidden(e.
To,
"Contract will be open for signatures after " +
Contract.SignAfter.Value.ToUniversalTime().ToString() +
" (UTC)",
"en");
7987 if (
Contract.SignBefore.HasValue && UtcNow >
Contract.SignBefore.Value.ToUniversalTime())
7989 await e.
IqErrorForbidden(e.
To,
"Contract closed for signatures as of " +
Contract.SignBefore.Value.ToUniversalTime().ToString() +
" (UTC)",
"en");
7998 if (!(FailingParameter is
null))
8005 int NrSignaturesForRole = 0;
8006 bool RoleFound =
false;
8008 if (!(
Contract.ClientSignatures is
null))
8013 NrSignaturesForRole++;
8023 if (NrSignaturesForRole >= Role2.
MaxCount)
8025 await e.
IqErrorForbidden(e.
To,
"No more signatures of specified role allowed.",
"en");
8041 StringBuilder Xml =
new StringBuilder();
8042 await
Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
8043 byte[]
Data = Encoding.UTF8.GetBytes(Xml.ToString());
8045 (
LegalIdentity Identity, Dictionary<string, string> AttachmentUrls) =
8049 if (Identity is
null)
8054 bool InList =
false;
8080 bool HasSigned =
false;
8082 if (!(
Contract.ClientSignatures is
null))
8108 await e.
IqErrorForbidden(e.
To,
"Legal identity not in explicitly defined list of parts in contract.",
"en");
8113 if (!(
Contract.ClientSignatures is
null))
8122 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
8130 DateTime SignatureTimestamp = DateTime.UtcNow;
8132 Identity, SignatureTimestamp,
Signature, AttachmentUrls,
this);
8134 if (!
string.IsNullOrEmpty(s))
8136 await e.
IqErrorForbidden(e.
To,
"Legal identity does not have required property " + s +
" defined.",
"en");
8140 int c = (
Contract.ClientSignatures?.Length ?? 0) + 1;
8143 Contract.ClientSignatures?.CopyTo(Signatures, 0);
8147 LegalId = Identity.
Id,
8150 Timestamp = SignatureTimestamp,
8151 Transferable = Transferable
8154 bool GeoPublish =
false;
8155 bool Signed =
false;
8157 Contract.ClientSignatures = Signatures;
8159 if (
Contract.From == DateTime.MinValue)
8167 Contract.To = Contract.From +
Contract.Duration.Value;
8190 LegalId = Identity.
Id,
8191 BareJid = e.From.BareJid
8199 new KeyValuePair<string, object>(
"Role",
Role.Value),
8200 new KeyValuePair<string, object>(
"Transferable", Transferable));
8203 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
8204 string ContractXml = Xml.ToString();
8207 if (GeoPublish && !(this.geo is
null))
8210 await this.SendContractSignedNotification(
Contract, Identity,
Role, Signed, e.
From, e.
To);
8219 await this.ContractSigned(
Contract,
true, this.eDaler, this.pubsub);
8221 catch (Exception ex)
8226 catch (Exception ex)
8236 throw new Exception(
"Contract is a template only, and cannot be signed.");
8241 throw new Exception(
"Contract is obsoleted.");
8244 throw new Exception(
"Contract is deleted.");
8247 throw new Exception(
"Contract is not yet approved to be signed.");
8250 throw new Exception(
"Contract proposal has been rejected.");
8253 throw new Exception(
"Contract proposal has failed.");
8256 DateTime UtcNow = DateTime.UtcNow;
8257 if (
Contract.SignAfter.HasValue && UtcNow <
Contract.SignAfter.Value.ToUniversalTime())
8258 throw new Exception(
"Contract will be open for signatures after " +
Contract.SignAfter.Value.ToUniversalTime().ToString() +
" (UTC)");
8260 if (
Contract.SignBefore.HasValue && UtcNow >
Contract.SignBefore.Value.ToUniversalTime())
8261 throw new Exception(
"Contract closed for signatures as of " +
Contract.SignBefore.Value.ToUniversalTime().ToString() +
" (UTC)");
8266 if (!(FailingParameter is
null))
8267 throw new Exception(
"Contract parameter " + FailingParameter.
Name +
" contains invalid value: " +
P.Value);
8269 int NrSignaturesForRole = 0;
8270 bool RoleFound =
false;
8272 if (!(
Contract.ClientSignatures is
null))
8277 NrSignaturesForRole++;
8287 if (NrSignaturesForRole >= Role2.
MaxCount)
8288 throw new Exception(
"No more signatures of specified role allowed.");
8297 throw new Exception(
"No such role defined in contract.");
8299 StringBuilder Xml =
new StringBuilder();
8300 await
Contract.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false,
null,
this);
8301 byte[]
Data = Encoding.UTF8.GetBytes(Xml.ToString());
8304 (
LegalIdentity Identity, Dictionary<string, string> AttachmentUrls) =
8305 await this.ValidateSenderSignature(SignerJid, Request, UtcNow,
Data,
8308 if (Identity is
null)
8311 if (
string.IsNullOrEmpty(Msg))
8312 Msg =
"Unable to validate sender signature.";
8314 throw new Exception(Msg);
8319 bool InList =
false;
8334 throw new Exception(
"Legal identity not in explicitly defined list of parts in contract.");
8337 if (!(
Contract.ClientSignatures is
null))
8346 DateTime SignatureTimestamp = DateTime.UtcNow;
8348 Identity, SignatureTimestamp,
Signature, AttachmentUrls,
this);
8350 if (!
string.IsNullOrEmpty(s))
8351 throw new Exception(
"Legal identity does not have required property " + s +
" defined.");
8353 int c = (
Contract.ClientSignatures?.Length ?? 0) + 1;
8356 Contract.ClientSignatures?.CopyTo(Signatures, 0);
8360 LegalId = Identity.
Id,
8363 Timestamp = SignatureTimestamp,
8364 Transferable = Transferable
8367 Contract.ClientSignatures = Signatures;
8369 bool GeoPublish =
false;
8370 bool Signed =
false;
8372 if (
Contract.From == DateTime.MinValue)
8380 Contract.To = Contract.From +
Contract.Duration.Value;
8403 LegalId = Identity.
Id,
8404 BareJid = SignerJid.BareJid
8411 new KeyValuePair<string, object>(
"BareJid", SignerJid.
BareJid.
Value),
8412 new KeyValuePair<string, object>(
"Role",
Role.Value),
8413 new KeyValuePair<string, object>(
"Transferable", Transferable));
8415 if (GeoPublish && !(this.geo is
null))
8418 await this.SendContractSignedNotification(
Contract, Identity,
Role, Signed, SignerJid, this.MainDomain);
8427 await this.ContractSigned(
Contract, ContractIsLocked, this.eDaler, this.pubsub);
8429 catch (Exception ex)
8442 string ContractNamespace = NamespaceSmartContracts(
Contract.Version);
8443 Dictionary<CaseInsensitiveString, KeyValuePair<string, bool>> StatusRecipients =
new Dictionary<CaseInsensitiveString, KeyValuePair<string, bool>>()
8445 { Contract.Account +
"@" + this.Server.Domain,
new KeyValuePair<string, bool>(ContractNamespace,
false) }
8450 if (!this.Server.IsServerDomain(Addr.
Domain,
true))
8452 KeyValuePair<CaseInsensitiveString, string> P2 = await this.GetComponent(Addr.
Domain, NamespacesSmartContracts);
8455 StatusRecipients[
Component] =
new KeyValuePair<string, bool>(P2.Value,
true);
8458 if (!(
Contract.Parameters is
null))
8467 if (!this.Server.IsServerDomain(Addr.
Domain,
true))
8469 KeyValuePair<CaseInsensitiveString, string> P2 = await this.GetComponent(Addr.
Domain, NamespacesSmartContracts);
8472 StatusRecipients[
Component] =
new KeyValuePair<string, bool>(P2.Value,
true);
8478 if (!(
Contract.ClientSignatures is
null))
8486 if (!this.Server.IsServerDomain(Addr.
Domain,
true))
8488 KeyValuePair<CaseInsensitiveString, string> P2 = await this.GetComponent(Addr.
Domain, NamespacesSmartContracts);
8491 StatusRecipients[
Component] =
new KeyValuePair<string, bool>(P2.Value,
true);
8496 if (StatusRecipients.Count > 0)
8498 StringBuilder Xml =
new StringBuilder();
8499 await
Contract.
Serialize(Xml,
false,
true,
true,
true,
true,
true,
true,
null,
this);
8500 string ContractXml = Xml.ToString();
8505 string Namespace = P3.Value.Key;
8506 bool IsComponent = P3.Value.Value;
8509 Xml.Append(
"<contractSigned xmlns='");
8510 Xml.Append(Namespace);
8511 Xml.Append(
"' contractId='");
8513 Xml.Append(
"' legalId='");
8515 Xml.Append(
"' role='");
8519 Xml.Append(
"' signed='true");
8522 Xml.Append(ContractXml);
8523 Xml.Append(
"</contractSigned>");
8531 await this.Server.SendIqRequest(
"set", Sender,
new XmppAddress(StatusRecipient),
8532 string.Empty,
Event,
false, (
_, e) =>
8535 !(e.FirstElement is
null) &&
8536 e.FirstElement.LocalName ==
"authorizeJid" &&
8537 IsNamespaceSmartContract(e.FirstElement.NamespaceURI))
8539 string Jid = XML.Attribute(e.FirstElement,
"jid");
8541 if (!string.IsNullOrEmpty(Jid))
8543 this.ContractAuthorization(Jid, SignerJid.BareJid,
8544 Contract.ContractId, true);
8546 if (!(Contract.ClientSignatures is null))
8548 foreach (ClientSignature Signature in Contract.ClientSignatures)
8550 XmppAddress Addr = new XmppAddress(Signature.LegalId);
8552 if (this.IsComponentDomain(Addr.Domain, true))
8553 this.IdentityAuthorization(Jid, SignerJid.BareJid, Signature.LegalId, true);
8559 return Task.CompletedTask;
8564 this.ContractAuthorization(StatusRecipient, SignerJid.
BareJid,
8567 if (!(
Contract.ClientSignatures is
null))
8573 if (this.IsComponentDomain(Addr2.
Domain,
true))
8574 this.IdentityAuthorization(StatusRecipient, SignerJid.
BareJid,
Signature.LegalId,
true);
8578 await this.Server.SendMessage(
string.Empty,
string.Empty, Sender,
new XmppAddress(StatusRecipient),
8579 string.Empty,
Event);
8582 catch (Exception ex)
8589 catch (Exception ex)
8602 private async Task ContractSigned(
Contract Contract,
bool ContractIsLocked,
8606 out Dictionary<CaseInsensitiveString, Parameter> TransientParameters) ??
false))
8608 TransientParameters =
null;
8611 switch (
Contract.ForMachinesNamespace)
8615 TransientParameters,
this,
EDaler, PubSub);
8620 TransientParameters,
this,
EDaler);
8625 TransientParameters,
this,
EDaler);
8642 if (this.Server.IsServerDomain(Sender.
Domain,
true))
8654 e?.
IqErrorForbidden(e.
To,
"Signature proving access to private keys not correct.",
"en");
8657 e?.
IqErrorForbidden(e.
To,
"Sender must correspond to an account on the local machine.",
"en");
8666 Dictionary<string, string> AttachmentUrls =
null;
8668 if (this.Server.IsServerDomain(Sender.
Domain,
true))
8670 bool IdFound =
false;
8682 if (!
string.IsNullOrEmpty(ForBareJid))
8683 this.IdentityAuthorization(ForBareJid, Sender.
BareJid, ID.
Id,
true);
8686 AttachmentUrls = this.GetAttachmentUrls(ID);
8696 return (
null,
null);
8701 KeyValuePair<CaseInsensitiveString, string>
P = await this.GetComponent(Sender.
Domain, NamespacesLegalIdentity);
8703 string RemoteNamespace =
P.Value;
8708 Request?.
Error(
EDalerUriErrorType.ServiceUnavailable,
this.MainDomain.Address +
" could not find legal component of " + Sender.
Domain +
", to validate signature.",
false);
8709 return (
null,
null);
8715 if (Identity2 is
null)
8717 Request?.
Error(
EDalerUriErrorType.Forbidden,
"Signature does not match any of the approved legal identities of " +
8721 StringBuilder sb =
new StringBuilder();
8722 Identity2.
Serialize(sb,
true,
true,
true,
true,
true,
true,
true);
8724 XmlDocument Doc =
XML.
ParseXml(sb.ToString(),
true);
8726 Identity =
LegalIdentity.Parse(Doc.DocumentElement, out
_, out AttachmentUrls);
8733 Request?.
Error(
EDalerUriErrorType.ServiceUnavailable,
this.MainDomain.Address +
" was unable to validate remote signature.",
false);
8734 return (
null,
null);
8740 return (
null,
null);
8747 if (Identity is
null)
8749 Request?.
Error(
EDalerUriErrorType.Forbidden,
"Signature does not match any of the approved legal identities of " +
8753 return (Identity, AttachmentUrls);
8756 internal Dictionary<string, string> GetAttachmentUrls(
LegalIdentity Identity)
8761 Dictionary<string, string> Urls =
new Dictionary<string, string>();
8769 internal async Task<(
LegalIdentity, Dictionary<string, string>)> ValidateSignature(
XmppAddress Signatory, DateTime Timestamp,
byte[]
Data,
8773 Dictionary<string, string> AttachmentUrls;
8775 if (this.Server.IsServerDomain(Signatory.
Domain,
true))
8786 AttachmentUrls = this.GetAttachmentUrls(ID);
8791 AttachmentUrls =
null;
8795 KeyValuePair<CaseInsensitiveString, string>
P = await this.GetComponent(Signatory.
Domain, NamespacesLegalIdentity);
8799 return (
null,
null);
8805 return (
null,
null);
8810 return (Identity, AttachmentUrls);
8813 private async Task<IqResultEventArgs> ValidateRemoteSignature(
string RemoteLegalComponent,
string BareJid,
byte[]
Data,
byte[]
Signature,
8816 TaskCompletionSource<IqResultEventArgs> T =
new TaskCompletionSource<IqResultEventArgs>();
8817 StringBuilder Xml =
new StringBuilder();
8820 Xml.Append(
"<validateSignature data=\"");
8821 Xml.Append(Convert.ToBase64String(
Data));
8822 Xml.Append(
"\" s=\"");
8823 Xml.Append(Convert.ToBase64String(
Signature));
8824 Xml.Append(
"\" bareJid=\"");
8827 if (!
string.IsNullOrEmpty(ForBareJid))
8829 Xml.Append(
"\" for=\"");
8833 Xml.Append(
"\" xmlns=\"");
8834 Xml.Append(NamespaceLegalIdentity(Version));
8837 if (!await this.Server.SendIqRequest(
"get",
this.MainDomain,
new XmppAddress(RemoteLegalComponent),
string.Empty,
8838 Xml.
ToString(),
true, (sender2, e2) =>
8841 return Task.CompletedTask;
8847 return await T.Task;
8850 private async Task ContractSignedHandler(
object Sender,
IqEventArgs e)
8866 bool LocalLegalId = this.IsComponentDomain(LegalAddress.
Domain,
true);
8870 foreach (XmlNode N
in e.
Query.ChildNodes)
8872 if (N is XmlElement E && E.LocalName ==
"contract" && IsNamespaceSmartContract(E.NamespaceURI))
8889 KeyValuePair<Contract, IqResultEventArgs>
P = await this.GetContract(ContractId);
8894 if (
string.IsNullOrEmpty(
P.Value?.ErrorText))
8903 if (
Contract.ClientSignatures is
null)
8920 if (BareJid is
null)
8922 await e.
IqErrorForbidden(e.
To,
"Legal Identity not in list of client signatures.",
"en");
8928 if (!await this.ValidateServerSignature(
Contract))
8935 await this.ProcessContractSignature(LocalLegalId,
Contract, LegalId, BareJid,
8941 if (ClientContract is
null)
8943 await e.
IqErrorBadRequest(e.
To,
"Unable to prepare embedded contract for validation.",
"en");
8947 StringBuilder sb =
new StringBuilder();
8949 sb.Append(
"<authorizeJid jid='");
8951 sb.Append(
"' xmlns='");
8957 this.ContractSignedHandlerValidateContract(LocalLegalId,
Contract, LegalId,
8958 BareJid,
Role, Signed, ClientContract);
8962 private async Task ProcessContractSignature(
bool LocalLegalId,
Contract Contract,
8984 private async
void ContractSignedHandlerValidateContract(
bool LocalLegalId,
8986 string Role,
bool Signed, Networking.XMPP.Contracts.Contract ClientContract)
9001 await Task.Delay(DelayMs);
9003 if (DelayMs < 1000 * 60 * 60)
9010 while (Status == Networking.XMPP.Contracts.ContractStatus.NoResponse);
9014 case Networking.XMPP.Contracts.ContractStatus.ContractUndefined:
9015 case Networking.XMPP.Contracts.ContractStatus.NotApproved:
9016 case Networking.XMPP.Contracts.ContractStatus.NotValidYet:
9017 case Networking.XMPP.Contracts.ContractStatus.NotValidAnymore:
9018 case Networking.XMPP.Contracts.ContractStatus.TemplateOnly:
9019 case Networking.XMPP.Contracts.ContractStatus.HumanReadableNotWellDefined:
9020 case Networking.XMPP.Contracts.ContractStatus.ParameterValuesNotValid:
9021 case Networking.XMPP.Contracts.ContractStatus.MachineReadableNotWellDefined:
9022 case Networking.XMPP.Contracts.ContractStatus.NoSchemaAccess:
9023 case Networking.XMPP.Contracts.ContractStatus.CorruptSchema:
9024 case Networking.XMPP.Contracts.ContractStatus.FraudulentSchema:
9025 case Networking.XMPP.Contracts.ContractStatus.FraudulentMachineReadable:
9026 case Networking.XMPP.Contracts.ContractStatus.NoClientSignatures:
9027 case Networking.XMPP.Contracts.ContractStatus.ClientSignatureInvalid:
9028 case Networking.XMPP.Contracts.ContractStatus.ClientSignatureNotValidated:
9029 case Networking.XMPP.Contracts.ContractStatus.ClientIdentityInvalid:
9030 case Networking.XMPP.Contracts.ContractStatus.AttachmentLacksUrl:
9031 case Networking.XMPP.Contracts.ContractStatus.AttachmentUnavailable:
9032 case Networking.XMPP.Contracts.ContractStatus.AttachmentInconsistency:
9033 case Networking.XMPP.Contracts.ContractStatus.AttachmentSignatureInvalid:
9034 case Networking.XMPP.Contracts.ContractStatus.NoTrustProvider:
9035 case Networking.XMPP.Contracts.ContractStatus.NoProviderPublicKey:
9036 case Networking.XMPP.Contracts.ContractStatus.NoProviderSignature:
9037 case Networking.XMPP.Contracts.ContractStatus.ProviderSignatureInvalid:
9038 case Networking.XMPP.Contracts.ContractStatus.ProviderKeyNotRecognized:
9039 case Networking.XMPP.Contracts.ContractStatus.NoResponse:
9040 Log.
Warning(
"Client signature message ignored. Contract validation failed.",
9042 new KeyValuePair<string, object>(
"Status", Status),
9044 new KeyValuePair<string, object>(
"LegalId", LegalId.
Value),
9045 new KeyValuePair<string, object>(
"LocalLegalId", LocalLegalId),
9046 new KeyValuePair<string, object>(
"BareJid", BareJid.
Value),
9047 new KeyValuePair<string, object>(
"Role",
Role),
9048 new KeyValuePair<string, object>(
"Signed", Signed)));
9051 case Networking.XMPP.Contracts.ContractStatus.NotLegallyBinding:
9054 Log.
Warning(
"Client signature message ignored. Contract validation failed.",
9056 new KeyValuePair<string, object>(
"Status", Status),
9058 new KeyValuePair<string, object>(
"LegalId", LegalId.
Value),
9059 new KeyValuePair<string, object>(
"LocalLegalId", LocalLegalId),
9060 new KeyValuePair<string, object>(
"BareJid", BareJid.
Value),
9061 new KeyValuePair<string, object>(
"Role",
Role),
9062 new KeyValuePair<string, object>(
"Signed", Signed)));
9067 case Networking.XMPP.Contracts.ContractStatus.Valid:
9068 await this.ProcessContractSignature(LocalLegalId,
Contract, LegalId, BareJid,
9073 catch (Exception ex)
9075 Log.
Warning(
"Client signature message ignored. Contract validation failed: " + ex.Message);
9087 Log.
Warning(
"Contract failure message ignored. Sender not a broker.");
9093 if (!this.IsComponentDomain(ContractAddress.
Domain,
true))
9095 Log.
Warning(
"Contract failure message ignored. Contract not hosted on broker.");
9099 KeyValuePair<Contract, IqResultEventArgs>
P = await this.GetContract(ContractId);
9103 if (
string.IsNullOrEmpty(
P.Value?.ErrorText))
9104 Log.
Warning(
"Contract failure message ignored. Contract not found.");
9106 Log.
Warning(
"Contract failure message ignored: " +
P.Value.ErrorText);
9111 bool LegitimateSender =
false;
9120 if (!LegitimateSender && !(
Contract.Parameters is
null))
9129 LegitimateSender =
true;
9136 if (!LegitimateSender && !(
Contract.ClientSignatures is
null))
9143 LegitimateSender =
true;
9149 if (!LegitimateSender)
9151 Log.
Warning(
"Contract failure message ignored. Not a legitimate sender.");
9163 internal async Task<Networking.XMPP.Contracts.Contract> ToClientContract(
Contract Contract)
9165 StringBuilder sb =
new StringBuilder();
9166 await
Contract.
Serialize(sb,
true,
true,
true,
true,
true,
true,
true,
null,
this);
9168 string ContractXml = sb.ToString();
9169 XmlDocument Xml =
XML.
ParseXml(ContractXml,
true);
9179 if (
Contract.ServerSignature is
null ||
9185 StringBuilder Xml =
new StringBuilder();
9186 await
Contract.
Serialize(Xml,
false,
true,
true,
true,
true,
false,
false,
null,
this);
9187 byte[]
Data = Encoding.UTF8.GetBytes(Xml.ToString());
9190 return await this.ValidateServerSignature(ContractAddress.
Domain,
Data,
9198 if (this.IsComponentDomain(ServerDomain,
true))
9202 IE2eEndpoint PubKey = await this.GetPublicKey(ServerDomain, Timestamp);
9207 public async Task<IE2eEndpoint> GetPublicKey(
string ServerDomain, DateTime Timestamp)
9209 string Key = ServerDomain +
"|pub";
9211 if (this.remoteComponents.
TryGetValue(Key, out
object Obj) &&
9218 TaskCompletionSource<IE2eEndpoint> Result =
new TaskCompletionSource<IE2eEndpoint>();
9219 string Namespace = NamespaceLegalIdentity(
NamespaceSet.Current);
9220 StringBuilder sb =
new StringBuilder();
9222 sb.Append(
"<getPublicKey xmlns=\"");
9223 sb.Append(Namespace);
9224 sb.Append(
"\" ts=\"");
9228 await this.Server.SendIqRequest(
"get", this.MainDomain,
new XmppAddress(ServerDomain),
string.Empty,
9229 sb.
ToString(),
true, (Sender, e) =>
9231 IE2eEndpoint ServerKey = null;
9235 !((E = e.FirstElement) is null) &&
9236 E.LocalName ==
"publicKey" &&
9237 E.NamespaceURI == Namespace)
9239 DateTime From = XML.Attribute(E,
"from", DateTime.MinValue);
9240 DateTime? To = E.HasAttribute(
"to") ?
9241 XML.Attribute(E,
"to", DateTime.MaxValue) : (DateTime?)null;
9243 foreach (XmlNode N in E.ChildNodes)
9245 if (N is XmlElement E2)
9247 ServerKey = EndpointSecurity.ParseE2eKey(E2);
9248 if (!(ServerKey is null))
9250 if (!this.remoteComponents.TryGetValue(Key, out object Obj) ||
9251 !(Obj is PublicKeyRecords Records))
9253 Records = new PublicKeyRecords();
9254 this.remoteComponents[Key] = Records;
9257 Records.Add(From, To ?? DateTime.UtcNow, ServerKey);
9259 Result.TrySetResult(ServerKey);
9260 return Task.CompletedTask;
9266 Result.TrySetResult(
null);
9267 return Task.CompletedTask;
9272 PubKey = Result.Task.Result;
9277 private async Task GetSignedContractsHandler(
object Sender,
IqEventArgs e)
9289 string Xml = await this.SerializeContractReferences(Signatures, References, QueryVersion);
9293 catch (Exception ex)
9299 private async Task GetContractHandler(
object Sender,
IqEventArgs e)
9335 StringBuilder Xml =
new StringBuilder();
9336 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
9340 catch (Exception ex)
9346 private async Task GetContractsHandler(
object Sender,
IqEventArgs e)
9350 StringBuilder Xml =
new StringBuilder();
9352 Xml.Append(
"<contracts xmlns='");
9353 Xml.Append(e.
Query.NamespaceURI);
9356 foreach (XmlNode N
in e.
Query.ChildNodes)
9358 if (N is XmlElement E && E.LocalName ==
"ref" && E.NamespaceURI == e.
Query.NamespaceURI)
9367 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
9374 Xml.Append(
"<ref id='");
9381 Xml.Append(
"</contracts>");
9385 catch (Exception ex)
9391 private async Task IsPartHandler(
object Sender,
IqEventArgs e)
9410 if (!this.Server.IsServerDomain(BareAddress.
Domain,
true))
9423 KeyValuePair<CaseInsensitiveString, string>
P = await this.GetComponent(e.
From.
Address, NamespacesLegalIdentity);
9425 string Namespace =
P.Value;
9433 foreach (XmlNode N
in e.
Query.ChildNodes)
9435 if (N is XmlElement E && E.LocalName ==
"idRef")
9442 if (!this.IsComponentDomain(LegalIdAddress.
Domain,
true))
9446 LegalIdentity Identity = await GetLocalLegalIdentity(LegalId);
9447 if (Identity is
null)
9450 if (Identity.Account == BareAddress.
Account)
9452 await e.
IqResult(
"<part xmlns='" + e.
Query.NamespaceURI +
"'>true</part>", e.
To);
9458 await e.
IqResult(
"<part xmlns='" + e.
Query.NamespaceURI +
"'>false</part>", e.
To);
9460 catch (Exception ex)
9466 private async Task ObsoleteContractHandler(
object Sender,
IqEventArgs e)
9487 await e.
IqErrorForbidden(e.
To,
"Contract is legally binding and cannot be obsoleted.",
"en");
9515 StringBuilder Xml =
new StringBuilder();
9516 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
9519 await this.SendContractUpdatedEvent(
Contract,
false);
9521 if (!(this.geo is
null))
9524 catch (Exception ex)
9530 internal async Task SendContractUpdatedEvent(
Contract Contract,
bool Created)
9532 StringBuilder Xml =
new StringBuilder();
9534 Xml.Append(
"<contract");
9535 Xml.Append(Created ?
"Created" :
"Updated");
9536 Xml.Append(
" xmlns='");
9537 Xml.Append(NamespaceSmartContracts(
Contract.Version));
9538 Xml.Append(
"' contractId='");
9545 await this.Server.SendMessage(
string.Empty,
string.Empty,
Contract.Provider, StatusRecipient,
string.
Empty,
Event);
9548 private async Task DeleteContractHandler(
object Sender,
IqEventArgs e)
9570 await e.
IqErrorForbidden(e.
To,
"Contract is legally binding and cannot be deleted.",
"en");
9576 await e.
IqErrorForbidden(e.
To,
"Contract cannot be deleted before its required archivation period expires.",
"en");
9584 await this.DeleteAttachments(
Contract.Attachments);
9585 Contract.Attachments =
null;
9594 StringBuilder Xml =
new StringBuilder();
9595 await
Contract.
Serialize(Xml,
true,
true,
true,
false,
true,
true,
false,
null,
this);
9598 await this.SendContractDeletedEvent(
Contract);
9600 if (!(this.geo is
null))
9603 catch (Exception ex)
9611 if (!(AttachmentReferences is
null))
9626 catch (Exception ex)
9638 StringBuilder Xml =
new StringBuilder();
9640 Xml.Append(
"<contractDeleted xmlns='");
9641 Xml.Append(NamespaceSmartContracts(
Contract.Version));
9642 Xml.Append(
"' contractId='");
9649 await this.Server.SendMessage(
string.Empty,
string.Empty,
Contract.Provider, StatusRecipient,
string.
Empty,
Event);
9652 private async Task UpdateContractHandler(
object Sender,
IqEventArgs e)
9656 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
9658 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can manage contracts on the broker.",
"en");
9664 string Namespace = NamespaceSmartContracts(QueryVersion);
9666 foreach (XmlNode N
in e.
Query.ChildNodes)
9668 if (N is XmlElement E && E.LocalName ==
"contract" && IsNamespaceSmartContract(E.NamespaceURI))
9671 UpdatedContract = Parsed?.
Contract;
9673 if (UpdatedContract is
null)
9684 await e.
IqErrorBadRequest(e.
To,
"Status element not permitted when updating contract.",
"en");
9688 if (!ParametersValid)
9699 if (UpdatedContract is
null)
9712 if (!(UpdatedContract.ClientSignatures is
null) && UpdatedContract.ClientSignatures.Length > 0)
9718 if (!(UpdatedContract.ServerSignature is
null))
9726 if (PrevContract is
null)
9738 if (!(PrevContract.ClientSignatures is
null) && PrevContract.ClientSignatures.Length > 0)
9744 switch (PrevContract.State)
9757 await e.
IqErrorForbidden(e.
To,
"Current state of the contract does not allow updates.",
"en");
9762 if (Identity is
null)
9764 await e.
IqErrorForbidden(e.
To,
"No current approved legal identity found for account.",
"en");
9768 string Errors = await this.ValidateContent(UpdatedContract,
null);
9769 if (!
string.IsNullOrEmpty(Errors))
9775 UpdatedContract.ObjectId = PrevContract.
ObjectId;
9776 UpdatedContract.TemplateId = PrevContract.TemplateId;
9777 UpdatedContract.Provider = PrevContract.Provider;
9778 UpdatedContract.Account = PrevContract.Account;
9779 UpdatedContract.Created = PrevContract.Created;
9780 UpdatedContract.Nonce = PrevContract.
Nonce;
9781 UpdatedContract.Updated = UtcNowSecond;
9782 UpdatedContract.Version = QueryVersion;
9789 await UpdatedContract.Sign(
this);
9795 StringBuilder Xml =
new StringBuilder();
9796 await UpdatedContract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
9799 await this.SendContractUpdatedEvent(UpdatedContract,
false);
9801 catch (Exception ex)
9807 private async Task GetSchemasHandler(
object Sender,
IqEventArgs e)
9811 StringBuilder Xml =
new StringBuilder();
9814 Xml.Append(
"<schemas xmlns='");
9815 Xml.Append(e.
Query.NamespaceURI);
9822 if (!(LastNamespace is
null))
9823 Xml.Append(
"</schemaRef>");
9827 Xml.Append(
"<schemaRef namespace='");
9832 Xml.Append(
"<digest function='");
9833 Xml.Append(Schema.
Function.ToString());
9836 Xml.Append(
"</digest>");
9839 if (!(LastNamespace is
null))
9840 Xml.Append(
"</schemaRef>");
9842 Xml.Append(
"</schemas>");
9846 catch (Exception ex)
9852 private async Task GetSchemaHandler(
object Sender,
IqEventArgs e)
9857 string DigestBase64 =
null;
9866 foreach (XmlNode N
in e.
Query.ChildNodes)
9868 if (N is XmlElement E && E.LocalName ==
"digest" && E.NamespaceURI == e.
Query.NamespaceURI)
9870 DigestBase64 = E.InnerText;
9871 if (!Enum.TryParse(
XML.
Attribute(E,
"function"), out Function))
9881 if (DigestBase64 is
null)
9898 (Schema, ErrorMsg) = await this.LoadSchema(Namespace,
null);
9899 if (!
string.IsNullOrEmpty(ErrorMsg))
9909 StringBuilder Xml =
new StringBuilder();
9911 Xml.Append(
"<schema xmlns='");
9912 Xml.Append(e.
Query.NamespaceURI);
9914 Xml.Append(Convert.ToBase64String(Schema.
XmlSchema));
9915 Xml.Append(
"</schema>");
9919 catch (Exception ex)
9925 private async Task GetLegalIdentitiesOfContractHandler(
object Sender,
IqEventArgs e)
9933 if (!(Current || Historic))
9935 await e.
IqErrorBadRequest(e.
To,
"Both current and historic attributes cannot both be false.",
"en");
9940 List<LegalIdentity> Identities =
new List<LegalIdentity>();
9941 List<Dictionary<string, string>> AttachmentUrlss =
new List<Dictionary<string, string>>();
9943 DateTime UtcNow = DateTime.UtcNow;
9945 if (this.IsComponentDomain(ContractAddress.
Domain,
true))
9965 if (!(
Contract.ClientSignatures is
null))
9967 Dictionary<string, bool> Domains =
null;
9972 if (this.IsComponentDomain(LegalId.
Domain,
true))
9974 Identity = await GetLocalLegalIdentity(
Signature.LegalId);
9978 Identities.Add(Identity);
9979 AttachmentUrlss.Add(
null);
9984 CurrentIdentity = await this.GetApprovedLegalIdentityAsync(Identity.Account, UtcNow);
9985 if (CurrentIdentity.Id != Identity.Id)
9987 Identities.Add(CurrentIdentity);
9988 AttachmentUrlss.Add(
null);
9994 Domains ??=
new Dictionary<string, bool>();
9995 Domains[LegalId.
Domain] =
true;
9999 if (!(Domains is
null))
10001 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
10002 object SynchObj =
new object();
10003 int Count = Domains.Count;
10004 StringBuilder Xml =
new StringBuilder();
10005 string ContractsNamespace = NamespaceSmartContracts(
Contract.Version);
10007 Xml.Append(
"<getLegalIdentities xmlns='");
10008 Xml.Append(ContractsNamespace);
10009 Xml.Append(
"' contractId='");
10011 Xml.Append(
"' current='");
10013 Xml.Append(
"' historic='");
10017 string Request = Xml.ToString();
10018 bool Responded =
false;
10020 foreach (KeyValuePair<string, bool> ByDomain
in Domains)
10022 await this.Server.SendIqRequest(
"get", this.MainDomain,
10023 new XmppAddress(ByDomain.Key),
string.
Empty, Request,
false, async (sender2, e2) =>
10029 Last = --Count == 0;
10034 XmlElement E = e2.FirstElement;
10036 if (!(E is
null) && E.LocalName ==
"identities")
10038 foreach (XmlNode N
in E.ChildNodes)
10040 if (N is XmlElement E2 && E2.LocalName ==
"identity")
10042 Identity =
LegalIdentity.Parse(E2, out
bool HasStatus, out Dictionary<string, string> AttachmentUrls);
10046 Identities.Add(Identity);
10047 AttachmentUrlss.Add(AttachmentUrls);
10053 Result.TrySetResult(
true);
10057 if (Result.TrySetResult(
false) && !Responded)
10060 await e.
IqError(e2.ErrorTypeString, e2.ErrorElement?.OuterXml ??
string.Empty, e2.To, e2.ErrorText,
string.Empty);
10066 if (!await Result.Task || Responded)
10084 Identity = await GetLocalLegalIdentity(
Signature.LegalId);
10088 Identities.Add(Identity);
10089 AttachmentUrlss.Add(
null);
10094 CurrentIdentity = await this.GetApprovedLegalIdentityAsync(Identity.Account, UtcNow);
10095 if (CurrentIdentity.Id != Identity.Id)
10097 Identities.Add(CurrentIdentity);
10098 AttachmentUrlss.Add(
null);
10109 Response = this.SerializeIdentities(Identities, AttachmentUrlss, QueryVersion);
10114 catch (Exception ex)
10120 private async Task GetNetworkIdentitiesHandler(
object Sender,
IqEventArgs e)
10127 List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> Identities =
new List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>>();
10129 if (this.IsComponentDomain(ContractAddress.
Domain,
true))
10150 if (!(ErrorResponse is
null))
10153 ErrorResponse.
To, ErrorResponse.
ErrorText,
string.Empty);
10169 Identities.Add(
new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(
Signature.LegalId,
Signature.BareJid));
10173 StringBuilder Response =
new StringBuilder();
10175 Response.Append(
"<networkIdentities xmlns='");
10176 Response.Append(NamespaceSmartContracts(QueryVersion));
10177 Response.Append(
"'>");
10181 foreach (KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>
P in Identities)
10183 Response.Append(
"<networkIdentity bareJid='");
10185 Response.Append(
"' legalId='");
10187 Response.Append(
"'/>");
10191 Response.Append(
"</networkIdentities>");
10193 await e.
IqResult(Response.ToString(), e.
To);
10195 catch (Exception ex)
10201 internal async Task<IqResultEventArgs> GetNetworkIdentities(
Contract Contract,
10202 List<KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>> Identities)
10204 if (!(
Contract.ClientSignatures is
null))
10206 Dictionary<string, bool> Domains =
null;
10211 if (this.IsComponentDomain(LegalId.
Domain,
true))
10214 string JidDomain = i < 0 ? this.Server.Domain : LegalId.
Domain.
Substring(i + 1);
10216 Identities.Add(
new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(Identity.
Id, Identity.Account +
"@" + JidDomain));
10220 Domains ??=
new Dictionary<string, bool>();
10221 Domains[LegalId.
Domain] =
true;
10225 if (!(Domains is
null))
10227 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
10228 object SynchObj =
new object();
10229 int Count = Domains.Count;
10230 StringBuilder Xml =
new StringBuilder();
10232 Xml.Append(
"<getNetworkIdentities xmlns='");
10233 Xml.Append(NamespaceSmartContracts(
Contract.Version));
10234 Xml.Append(
"' contractId='");
10238 string Request = Xml.ToString();
10241 foreach (KeyValuePair<string, bool> ByDomain
in Domains)
10243 await this.Server.SendIqRequest(
"get", this.MainDomain,
10244 new XmppAddress(ByDomain.Key),
string.
Empty, Request,
false, (sender2, e2) =>
10250 Last = --Count == 0;
10255 XmlElement E = e2.FirstElement;
10257 if (!(E is null) && E.LocalName ==
"networkIdentities")
10259 foreach (XmlNode N in E.ChildNodes)
10261 if (N is XmlElement E2 && E2.LocalName ==
"networkIdentity")
10265 Identities.Add(new KeyValuePair<CaseInsensitiveString, CaseInsensitiveString>(
10266 XML.Attribute(E2,
"legalId"), XML.Attribute(E2,
"bareJid")));
10272 Result.TrySetResult(
true);
10276 if (ErrorResponse is
null)
10278 ErrorResponse = e2;
10279 Result.TrySetResult(
false);
10283 return Task.CompletedTask;
10287 if (!await Result.Task)
10288 return ErrorResponse;
10295 private async Task SearchPublicContractsHandler(
object Sender,
IqEventArgs e)
10301 List<CustomFilter> CustomFilters =
new List<CustomFilter>();
10302 List<Filter> Filters =
new List<Filter>()
10307 foreach (XmlNode N
in e.
Query.ChildNodes)
10309 if (N is XmlElement E)
10311 switch (E.LocalName)
10314 if (!await this.AddStrFilter(E, e, Filters,
"ForMachinesLocalName"))
10319 if (!await this.AddStrFilter(E, e, Filters,
"ForMachinesNamespace"))
10324 if (!await this.AddStrFilter(E, e, Filters,
"TemplateId"))
10329 if (!await this.AddRoleFilter(E, e, CustomFilters))
10334 if (!await this.AddParameterFilter(E, e, CustomFilters,
XML.
Attribute(E,
"name")))
10339 if (!await this.AddDateTimeFilter(E, e, Filters,
"Created"))
10344 if (!await this.AddDateTimeFilter(E, e, Filters,
"Updated"))
10349 if (!await this.AddDateTimeFilter(E, e, Filters,
"From"))
10354 if (!await this.AddDateTimeFilter(E, e, Filters,
"To"))
10359 if (!await this.AddDurationFilter(E, e, CustomFilters))
10370 List<Contract> Result =
new List<Contract>();
10371 Filter SearchFilter = Filters.Count == 1 ? Filters[0] :
new FilterAnd(Filters.ToArray());
10372 bool HasCustomFilters = CustomFilters.Count > 0;
10373 IEnumerable<Contract> Contracts;
10376 if (HasCustomFilters)
10380 Contracts = await
Database.
Find<
Contract>(Offset, MaxCount == int.MaxValue ? MaxCount : MaxCount + 1, SearchFilter,
"ContractId");
10386 if (HasCustomFilters)
10388 bool Included =
true;
10390 foreach (CustomFilter
Filter in CustomFilters)
10421 StringBuilder Xml =
new StringBuilder();
10423 Xml.Append(
"<searchResult xmlns='");
10424 Xml.Append(NamespaceSmartContracts(QueryVersion));
10425 Xml.Append(
"' more='");
10431 Xml.Append(
"<ref id='");
10436 Xml.Append(
"</searchResult>");
10440 catch (Exception ex)
10446 private async Task<bool> AddStrFilter(XmlElement E,
IqEventArgs e, List<Filter> Filters,
string Field)
10448 foreach (XmlNode N2
in E.ChildNodes)
10450 if (N2 is XmlElement E2)
10452 switch (E2.LocalName)
10472 private async Task<bool> AddRoleFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters)
10474 foreach (XmlNode N2
in E.ChildNodes)
10476 if (N2 is XmlElement E2)
10478 switch (E2.LocalName)
10481 Filters.Add(
new RoleEqFilter()
10483 Value = E2.InnerText
10488 Filters.Add(
new RoleLikeFilter()
10490 Value = E2.InnerText
10504 private async Task<bool> AddParameterFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters,
string Name)
10506 foreach (XmlNode N2
in E.ChildNodes)
10508 if (N2 is XmlElement E2)
10510 switch (E2.LocalName)
10513 Filters.Add(
new StringParameterEqFilter()
10516 Value = E2.InnerText
10521 Filters.Add(
new StringParameterNEqFilter()
10524 Value = E2.InnerText
10529 Filters.Add(
new StringParameterGtFilter()
10532 Value = E2.InnerText
10537 Filters.Add(
new StringParameterGteFilter()
10540 Value = E2.InnerText
10545 Filters.Add(
new StringParameterLtFilter()
10548 Value = E2.InnerText
10553 Filters.Add(
new StringParameterLteFilter()
10556 Value = E2.InnerText
10561 Filters.Add(
new StringParameterLikeFilter()
10564 Value = E2.InnerText
10575 Filters.Add(
new NumericalParameterEqFilter()
10589 Filters.Add(
new NumericalParameterNEqFilter()
10603 Filters.Add(
new NumericalParameterGtFilter()
10617 Filters.Add(
new NumericalParameterGteFilter()
10631 Filters.Add(
new NumericalParameterLtFilter()
10645 Filters.Add(
new NumericalParameterLteFilter()
10659 Filters.Add(
new BooleanParameterEqFilter()
10673 Filters.Add(
new BooleanParameterNEqFilter()
10682 if (!
XML.
TryParse(E2.InnerText, out DateTime TP) || TP.TimeOfDay != TimeSpan.Zero)
10688 Filters.Add(
new DateParameterEqFilter()
10702 Filters.Add(
new DateParameterNEqFilter()
10716 Filters.Add(
new DateParameterGtFilter()
10730 Filters.Add(
new DateParameterGteFilter()
10744 Filters.Add(
new DateParameterLtFilter()
10758 Filters.Add(
new DateParameterLteFilter()
10772 Filters.Add(
new DateTimeParameterEqFilter()
10786 Filters.Add(
new DateTimeParameterNEqFilter()
10800 Filters.Add(
new DateTimeParameterGtFilter()
10814 Filters.Add(
new DateTimeParameterGteFilter()
10828 Filters.Add(
new DateTimeParameterLtFilter()
10842 Filters.Add(
new DateTimeParameterLteFilter()
10850 if (!TimeSpan.TryParse(E2.InnerText, out TimeSpan TS))
10856 Filters.Add(
new TimeParameterEqFilter()
10864 if (!TimeSpan.TryParse(E2.InnerText, out TS))
10870 Filters.Add(
new TimeParameterNEqFilter()
10878 if (!TimeSpan.TryParse(E2.InnerText, out TS))
10884 Filters.Add(
new TimeParameterGtFilter()
10892 if (!TimeSpan.TryParse(E2.InnerText, out TS))
10898 Filters.Add(
new TimeParameterGteFilter()
10906 if (!TimeSpan.TryParse(E2.InnerText, out TS))
10912 Filters.Add(
new TimeParameterLtFilter()
10920 if (!TimeSpan.TryParse(E2.InnerText, out TS))
10926 Filters.Add(
new TimeParameterLteFilter()
10940 Filters.Add(
new DurationParameterEqFilter()
10954 Filters.Add(
new DurationParameterNEqFilter()
10968 Filters.Add(
new DurationParameterGtFilter()
10982 Filters.Add(
new DurationParameterGteFilter()
10996 Filters.Add(
new DurationParameterLtFilter()
11010 Filters.Add(
new DurationParameterLteFilter()
11027 private async Task<bool> AddDateTimeFilter(XmlElement E,
IqEventArgs e, List<Filter> Filters,
string Field)
11029 foreach (XmlNode N2
in E.ChildNodes)
11031 if (N2 is XmlElement E2)
11033 if (!
XML.
TryParse(E2.InnerText, out DateTime TP))
11039 switch (E2.LocalName)
11075 private async Task<bool> AddDurationFilter(XmlElement E,
IqEventArgs e, List<CustomFilter> Filters)
11077 foreach (XmlNode N2
in E.ChildNodes)
11079 if (N2 is XmlElement E2)
11087 switch (E2.LocalName)
11090 Filters.Add(
new DurationEqFilter()
11097 Filters.Add(
new DurationNEqFilter()
11104 Filters.Add(
new DurationGtFilter()
11111 Filters.Add(
new DurationGteFilter()
11118 Filters.Add(
new DurationLtFilter()
11125 Filters.Add(
new DurationLteFilter()
11141 private async Task AddContractAttachmentHandler(
object Sender,
IqEventArgs e)
11149 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
11151 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can add attachments.",
"en");
11155 if (!Uri.TryCreate(GetUrl, UriKind.Absolute, out Uri GetUri))
11190 await e.
IqErrorForbidden(e.
To,
"Only allowed to add attachments to your own contracts.",
"en");
11196 await e.
IqErrorForbidden(e.
To,
"Attachments can only be added to proposed or approved contracts, before they are signed.",
"en");
11200 if (!(
Contract.Attachments is
null))
11202 string s = Convert.ToBase64String(
Signature);
11206 if (Convert.ToBase64String(Ref.
Signature) == s)
11228 if (UploadingIdentity is
null)
11234 KeyValuePair<Attachment, AttachmentReference>
A = await this.CreateAttachment(GetUri,
11235 UploadingIdentity,
Signature, File, ContentType, Account2, ContractId,
11237 List<AttachmentReference> References =
new List<AttachmentReference>();
11239 if (!(
Contract.Attachments is
null))
11240 References.AddRange(
Contract.Attachments);
11242 References.Add(
A.Value);
11244 Contract.Attachments = References.ToArray();
11249 StringBuilder Xml =
new StringBuilder();
11250 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
11254 catch (Exception ex)
11260 private async Task RemoveContractAttachmentHandler(
object Sender,
IqEventArgs e)
11266 if (!this.Server.IsServerDomain(e.
From.
Domain,
true))
11268 await e.
IqErrorForbidden(e.
To,
"Only accounts on the broker can remove attachments.",
"en");
11295 await e.
IqErrorForbidden(e.
To,
"Only allowed to remove attachments to your own contracts.",
"en");
11301 await e.
IqErrorForbidden(e.
To,
"Attachments can only be removed to proposed or approved contracts, before they are signed.",
"en");
11308 if (!(
Contract.Attachments is
null))
11310 List<AttachmentReference> Attachments =
new List<AttachmentReference>();
11314 if (Ref.
Id != AttachmentId)
11315 Attachments.Add(Ref);
11318 Contract.Attachments = Attachments.ToArray();
11326 StringBuilder Xml =
new StringBuilder();
11327 await
Contract.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null,
this);
11331 catch (Exception ex)
11337 private async Task AuthorizeAccessToContractHandler(
object Sender,
IqEventArgs e)
11357 if (!this.IsComponentDomain(ContractIdAddress.
Domain,
true))
11381 KeyValuePair<Contract, IqResultEventArgs>
P = await this.GetContract(ContractId);
11386 if (
string.IsNullOrEmpty(
P.Value?.ErrorText))
11391 P.Value.ErrorText,
"en");
11403 ClientInformation ClientInfo = await this.GetNetworkIdentity(RemoteId,
true,
true,
Contract.Version);
11406 this.ContractAuthorization(RemoteJid, e.
From.
BareJid, ContractId, Authorized);
11411 catch (Exception ex)
11419 #region Third-party peer reviews
11421 private async Task GetReviewIdProvidersHandler(
object Sender,
IqEventArgs e)
11425 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
11433 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
11445 new FilterFieldEqualTo(
"State", Legal.Identity.IdentityState.Created)),
"-Created");
11454 StringBuilder Xml =
new StringBuilder();
11456 Xml.Append(
"<providers xmlns='");
11457 Xml.Append(e.
Query.NamespaceURI);
11460 foreach (
IPeerReviewService Service
in await this.GetPeerReviewServices(Tags,
true,
true))
11462 Xml.Append(
"<provider id='");
11464 Xml.Append(
"' type='");
11466 Xml.Append(
"' name='");
11468 Xml.Append(
"' legalId='");
11470 Xml.Append(
"' external='");
11473 if (!
string.IsNullOrEmpty(Service.
IconUrl))
11475 Xml.Append(
"' iconUrl='");
11477 Xml.Append(
"' iconWidth='");
11478 Xml.Append(Service.
IconWidth.ToString());
11479 Xml.Append(
"' iconHeight='");
11486 Xml.Append(
"</providers>");
11491 private async Task SelectReviewServiceHandler(
object Sender,
IqEventArgs e)
11495 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
11503 await e.
IqErrorForbidden(e.
To,
"Access to service providers only granted to accounts on broker.",
"en");
11532 new FilterFieldEqualTo(
"State", Legal.Identity.IdentityState.Created)),
"-Created");
11544 if (Service is
null)
11550 this.SelectServiceProvider(AccountName, Service);
11557 lock (this.selectedServicePerAccount)
11559 this.selectedServicePerAccount[AccountName] = Service;
11563 private readonly Dictionary<CaseInsensitiveString, IPeerReviewService> selectedServicePerAccount =
new Dictionary<CaseInsensitiveString, IPeerReviewService>();
11565 internal async Task<IPeerReviewService[]> GetPeerReviewServices(KeyValuePair<string, object>[] Tags,
bool IncludeInternal,
bool IncludeExternal)
11567 List<IPeerReviewService> Result =
new List<IPeerReviewService>();
11570 foreach (Type T
in ServiceTypes)
11583 if (IncludeExternal)
11584 Result.Add(Service);
11588 if (IncludeInternal)
11589 Result.Add(Service);
11594 return Result.ToArray();
11597 private async Task ContractsClient_PetitionForPeerReviewIDReceived(
object Sender,
11598 Networking.XMPP.Contracts.EventArguments.SignaturePetitionEventArgs e)
11605 KeyValuePair<string, object>[] Tags = e.RequestorIdentity.GetTags();
11610 Log.
Warning(
"Peer-review request denied. Access to service providers only granted to accounts on broker.",
11611 e.RequestorIdentity.
Id, e.
From, Tags);
11614 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11624 Log.
Warning(
"Peer-review request denied. Access to service providers only granted to accounts on broker.",
11625 e.RequestorIdentity.
Id, e.
From, Tags);
11628 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11635 Log.
Warning(
"Peer-review request denied. Account has been disabled.",
11636 e.RequestorIdentity.
Id, e.
From, Tags);
11639 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11645 if (!this.IsComponentDomain(RequestorIdentityId.
Domain,
true))
11647 Log.
Warning(
"Peer-review request denied. Requestor legal identity not on the server.",
11648 e.RequestorIdentity.
Id, e.
From, Tags);
11651 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11659 if (LocalRequestorIdentity is
null)
11661 Log.
Warning(
"Peer-review request denied. Proposed identity did not exist on server.",
11662 e.RequestorIdentity.
Id, e.
From, Tags);
11665 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11670 StringBuilder Xml1 =
new StringBuilder();
11671 StringBuilder Xml2 =
new StringBuilder();
11673 LocalRequestorIdentity.Serialize(Xml1,
true,
true,
true,
true,
true,
true,
false,
null,
this);
11674 e.RequestorIdentity.Serialize(Xml2,
true,
true,
true,
true,
true,
true,
false);
11676 if (Xml1.ToString() != Xml2.ToString())
11678 Log.
Warning(
"Peer-review request denied. Requestor legal identity representation not the same as local version.",
11679 e.RequestorIdentity.
Id, e.
From, Tags);
11682 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11687 IPeerReviewService[] PeerReviewServices = await this.GetPeerReviewServices(Tags,
true,
false);
11689 if (PeerReviewServices.Length == 0)
11691 Log.
Warning(
"Peer-review request denied. No local peer review services found.",
11692 e.RequestorIdentity.
Id, e.
From, Tags);
11695 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11702 lock (this.selectedServicePerAccount)
11704 if (!this.selectedServicePerAccount.TryGetValue(AccountName, out PeerReviewService))
11705 PeerReviewService =
null;
11708 if (PeerReviewService is
null)
11710 Log.
Warning(
"Peer-review request denied. No selected peer review service provider.",
11711 e.RequestorIdentity.
Id, e.
From, Tags);
11714 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11719 string Namespace = NamespaceLegalIdentity(LocalRequestorIdentity.Version);
11720 KeyValuePair<IPhoto[], XmlDocument[]>
P = await GetPhotosAndDocuments(LocalRequestorIdentity,
false);
11722 e.RequestorIdentity.
Id, Namespace,
false,
11723 GetPersonalInformation(LocalRequestorIdentity),
11724 LocalRequestorIdentity.GetTags(),
11725 P.Key,
P.Value,
Account, e.Purpose, e.ClientEndpoint);
11729 await PeerReviewService.
Validate(Application, async (sender, e2) =>
11731 StringBuilder Message =
new StringBuilder();
11733 Message.Append(
"<petitionClientUrl xmlns='");
11734 Message.Append(Namespace);
11735 Message.Append(
"' pid='");
11736 Message.Append(
XML.
Encode(e.PetitionId));
11737 Message.Append(
"' url='");
11739 Message.Append(
"'/>");
11741 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To, From.
BareJid,
string.
Empty, Message.
ToString());
11745 catch (Exception ex)
11747 Application.ReportError(ex.Message,
string.Empty,
string.Empty,
11751 if (!Application.IsValid.HasValue)
11753 string Xml = Application.GetClientErrorMessageXml(out
string Language,
11754 "Unable to validate the review.",
"UnableReview",
"en");
11756 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To,
11757 e.RequestorFullJid, Language, Xml);
11761 if (Application.IsValid.Value)
11766 Networking.XMPP.Contracts.SignWith.LatestApprovedId);
11769 Signature, e.PetitionId, e.RequestorFullJid,
true);
11775 if (Application.HasErrors)
11797 string Xml = Application.GetClientErrorMessageXml(out
string Language,
11798 "Unable to validate the review.",
"UnableReview",
"en");
11800 await this.Server.SendMessage(
string.Empty,
string.Empty, e.
To,
11801 e.RequestorFullJid, Language, Xml);
11804 Array.Empty<
byte>(), e.PetitionId, e.RequestorFullJid,
false);
11808 catch (Exception ex)
Contains information about a legal identity application.
Contains information about a legal identity application, including its current state.
Contains information about a legal identity application.
Represents a photo in an identity application.
Contains information about a service provider.
string Name
Displayable name of service provider.
Contains information about a validation error.
string ErrorCode
Machine-readable error code (service-specific).
string ErrorMessage
Error message that can be sent to origin
object Service
Service reporting the error.
KeyValuePair< string, object >[] Tags
Tags annotating the error message.
ValidationErrorType ErrorType
Type of error.
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
Contains information about a stream response to a content request.
string InnerText
Inner Text
override string ToString()
static readonly string[] ImageContentTypes
Image content types.
Static class managing encoding and decoding of internet content.
static bool CanGet(Uri Uri, out Grade Grade, out IContentGetter Getter)
If a resource can be gotten, given its URI.
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
Helps with common JSON-related tasks.
static readonly DateTime UnixEpoch
Unix Date and Time epoch, starting at 1970-01-01T00:00:00Z
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
static readonly string[] XmlContentTypes
XML content types.
const string DefaultContentType
Default content type for XML documents.
const string SchemaContentType
Default content type for XML schema documents.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
static XmlException AnnotateException(XmlException ex)
Creates a new XML Exception object, with reference to the source XML file, for information.
static string NormalizeXml(string Xml)
Normalizes XML in string form.
static XmlDocument ParseXml(string Xml)
Parses an XML Document from its string representation.
static bool IsValidXml(string Xml)
Checks if a string is valid XML
Class representing an event.
override string ToString()
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 Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
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 void Debug(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a debug event.
Static class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static bool IsDomain(string DomainOrHost, bool IncludeAlternativeDomains)
If a domain or host name represents the gateway.
static LoginAuditor LoginAuditor
Current Login Auditor. Should be used by modules accepting user logins, to protect the system from un...
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
static string AppDataFolder
Application data folder.
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
static string GetUrl(string LocalResource)
Gets a URL for a resource.
static ContractsClient ContractsClient
XMPP Contracts Client, if such a compoent is available on the XMPP broker.
static XmppClient XmppClient
XMPP Client connection of gateway.
static bool HasDomain
If a domain name is configured.
Static class that gives access to local content published by the gateway, without having to perform r...
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
DateTime Created
When the object was created.
DNS resolver, as defined in:
static Task< IPAddress[]> TryLookupIP4Addresses(string DomainName)
Tries to look up the IPv4 addresses related to a given domain name.
static Task< IPAddress[]> TryLookupIP6Addresses(string DomainName)
Tries to look up the IPv6 addresses related to a given domain name.
Implements an HTTP 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
Event arguments for identity validation responses
KeyValuePair< string, object >[] Tags
Associated tags with more information.
ContractStatus Status
Validation status of smart contract.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignature, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the identity to XML
Contains information about a parsed contract.
Contract Contract
Contract object
Abstract base class for XMPP client connections
abstract string RemoteEndPoint
Remote endpoint
Base class for components.
bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a message handler.
void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Set handler.
CaseInsensitiveString Subdomain
Subdomain name.
CaseInsensitiveString SubdomainSuffixed
Subdomain name, suffixed with a period (.).
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
string Name
Component name.
XmppAddress MainDomain
Main/principal domain address
bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the component domain, or optionally, an alternative component domain.
XmppServer Server
XMPP Server.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Set handler.
void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a message handler.
Event arguments for IQ queries.
XmppAddress From
From address attribute
Task IqErrorNotAcceptable(XmppAddress From, string ErrorText, string Language)
Returns a not-acceptable error.
Task IqResult(string Xml, string From)
Returns a response to the current request.
Task IqErrorResourceConstraint(XmppAddress From, string ErrorText, string Language)
Returns a resource-constraint error.
Task IqErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns a item-not-found error.
XmlElement Query
Query element, if found, null otherwise.
XmppAddress To
To address attribute
async Task IqError(string ErrorType, string Xml, XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task IqErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Returns a service-unavailable error.
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
ISender Sender
Sender of stanza.
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
string Id
ID of the request.
Event arguments for responses to IQ queries.
string ErrorTypeString
Error Type XML attribute string
XmlElement ErrorElement
Error element.
XmlElement FirstElement
First child element of the Response element.
XmppAddress To
To address attribute
bool Ok
If the response is an OK result response (true), or an error response (false).
string ErrorText
Any error specific text.
Event arguments for Messages.
XmppAddress From
From address attribute
XmlElement Content
Content element, if found, null otherwise.
Presence information event arguments.
string Type
Type attribute.
XmlElement Content
Content element, if found, null otherwise.
Task PresenceErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
XmppAddress To
To attribute.
XmppAddress From
From attribute.
XmlElement StanzaElement
Stanza element.
Contains information about one XMPP address.
override string ToString()
object.ToString()
bool IsBareJID
If the address is a Bare JID.
bool HasAccount
If the address has an account part.
bool IsEmpty
If the address is empty.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
bool IsDomain
If the Address is a domain.
XmppAddress ToBareJID()
Returns the Bare JID as an XmppAddress object.
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
CaseInsensitiveString Account
Account
bool IsFullJID
If the Address is a Full JID.
Manages an XMPP server-to-server connection.
static bool IsRemoteDomainRegistered(CaseInsensitiveString RemoteDomain)
Checks if a remote domain is registered.
Task< bool > SendMessage(string Type, string Id, string From, string To, string Language, string ContentXml)
Sends a Message stanza to a recipient.
bool TryGetClientConnections(string BareJID, out IClientConnection[] Connections)
Tries to get available connections for a given client.
bool TryGetClientConnection(string FullJID, out IClientConnection Connection)
Tries to get an active client connection.
Task< bool > SendIqRequest(string Type, string From, string To, string Language, string ContentXml, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Sends an IQ stanza to a recipient.
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
CaseInsensitiveString Domain
Domain name.
async Task< string > FindComponentAsync(string Jid, string Feature)
Finds a component having a specific feature, servicing a JID.
string Domain
Current Domain.
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
int Length
Gets the number of characters in the current CaseInsensitiveString object.
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.
bool StartsWith(CaseInsensitiveString value)
Determines whether the beginning of this string instance matches the specified string.
override string ToString()
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 Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static Task< string[]> GetCollections()
Gets an array of available collections.
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< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of 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 .
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.
This filter selects objects that have a named field greater or equal to a given value.
This filter selects objects that have a named field greater than a given value.
This filter selects objects that have a named field lesser or equal to a given value.
This filter selects objects that have a named field lesser than a given value.
This filter selects objects that have a named field matching a given regular expression.
This filter selects objects that have a named field not equal to a given value.
Base class for all filter classes.
Implements an in-memory cache.
void Dispose()
IDisposable.Dispose
bool Remove(KeyType Key)
Removes an item from the cache.
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
void Add(KeyType Key, ValueType Value)
Adds an item to the cache.
Event arguments for cache item removal events.
KeyType Key
Key of item that was removed.
ValueType Value
Value of item that was removed.
RemovedReason Reason
Reason for removing the item.
A chunked list is a linked list of chunks of objects of type T .
bool HasFirstItem
If there is a first item in the collection
T RemoveFirst()
Removes the first item in the collection.
void Add(T Item)
Adds an item to the collection.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class managing persistent counters.
static Task< long > IncrementCounter(CaseInsensitiveString Key)
Increments a counter.
Static class that dynamically manages types and interfaces available in the runtime environment.
static Type GetType(string FullName)
Gets a type, given its full name.
static object[] NoParameters
Contains an empty array of parameter values.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
Class that keeps track of events and timing.
void Stop()
Stops measuring time.
ProfilerThread CreateThread(string Name, ProfilerThreadType Type)
Creates a new profiler thread.
void NewState(string State)
Main Thread changes state.
string ExportPlantUml(TimeUnit TimeUnit)
Exports events to PlantUML.
double ElapsedSeconds
Elapsed seconds since start.
void Start()
Starts measuring time.
Class that keeps track of events and timing for one thread.
void Start()
Processing starts.
void Exception(System.Exception Exception)
Exception occurred
void Stop()
Processing starts.
void Idle()
Thread goes idle.
void NewState(string State)
Thread changes state.
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
Class managing the contents of a temporary file. When the class is disposed, the temporary file is de...
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
Asynchronously reads the bytes from the current stream and writes them to another stream,...
override long Length
When overridden in a derived class, gets the length in bytes of the stream.
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 > BeginRead(string Key)
Waits until the semaphore identified by Key is ready for reading. Each call to BeginRead must be fol...
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...
Contains methods for simple hash calculations.
static string ComputeSHA256HashString(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
static byte[] ComputeHash(HashFunction Function, byte[] Data)
Computes a hash of a block of binary data.
Static class containing predefined JWT claim names.
const string Issuer
Issuer of the JWT
const string IssueTime
Time at which the JWT was issued; can be used to determine age of the JWT
const string JwtId
Unique identifier; can be used to prevent the JWT from being replayed (allows a token to be used only...
const string Subject
Subject of the JWT (the user)
const string ExpirationTime
Time after which the JWT expires
string Create(params KeyValuePair< string, object >[] Claims)
Creates a new JWT token.
Class that monitors login events, and help applications determine malicious intent....
async Task< DateTime?> GetEarliestLoginOpportunity(string RemoteEndPoint, string Protocol)
Checks when a remote endpoint can login.
static async void Success(string Message, string UserName, string RemoteEndPoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
static void Fail(string Message, string UserName, string RemoteEndPoint, string Protocol)
Handles a failed login attempt.
Contains information about a broker account.
DateTime? PhoneNrVerified
When Phone Number was verified.
CaseInsensitiveString EMail
E-mail address associated with account.
CaseInsensitiveString UserName
User Name of account
bool Enabled
If account is enabled
DateTime? EMailVerified
When e-Mail was verified.
CaseInsensitiveString PhoneNr
Phone number associated with account.
CaseInsensitiveString LatestIdentity
Last Legal Identity approved for account. Note: Identity object might not be approved any longer.
Manages eDaler on accounts connected to the broker.
virtual void Error(EDalerUriErrorType ErrorType, string ErrorMessage, bool LogAsNotice)
Reports an error with the URI
string ErrorMessage
Error message, or null if no error.
Current state of URI from external source
Current state of URI from internal source
static async Task< bool > AddRemoteAttachment(CaseInsensitiveString AttachmentId, DateTime Expires, byte[] Data, string ContentType, LegalComponent Legal)
Attempts to add an attachment to the cache.
static async Task< AttachmentCacheItem > TryGetAttachment(CaseInsensitiveString AttachmentId)
Tries to get an attachment from the cache.
static async Task< bool > AddLocalAttachment(Attachment Attachment, DateTime Expires)
Attempts to add a local attachment to the cache.
string ContentType
Internet Content-Type of attachment.
async Task< byte[]> LoadContent()
Loads the content of the attachment.
DateTime Expires
When item expires (UTC).
Represents an attachment to a document.
CaseInsensitiveString ContractId
Contract ID, if attachment is associated with a contract, or null otherwise.
CaseInsensitiveString UploaderLegalId
Legal ID of uploader
long Size
Size of attachment, in bytes.
CaseInsensitiveString Id
Attachment ID
string ObjectId
Object ID of attachment.
string LocalFileName
Local Filename of attachment.
byte[] Salt
Salt used for deriving keys for decrypting attachment file.
string ContentType
Internet Content Type of binary attachment.
string RemoteFileName
Remote Filename of attachment.
Represents an attachment to a document.
string FileName
Filename of attachment.
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....
CaseInsensitiveString Id
Attachment ID
Attachment-valued contractual parameter
Boolean contractual parameter
Calculation contractual parameter
Represents a digital signature on a contract.
CaseInsensitiveString BareJid
Bare JID of the client used to generate the signature.
CaseInsensitiveString LegalId
ID of legal identity signing the contract.
CaseInsensitiveString Role
Role of the legal identity in the contract.
Contains the definition of a contract
async Task< int > CanRevoke(XmppAddress Jid, XmppServer Server, LegalComponent LegalComponent)
Checks if an entity can revoke a contract.
IEnumerable< string > GetStakeholders(XmppServer Server)
Gets the JIDs of the stakeholders of the contract (i.e. the creator and signed parties).
async Task Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignatures, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences, Dictionary< string, string > AttachmentsUrls, LegalComponent LegalComponent)
Serializes the Contract, in normalized form.
async Task< KeyValuePair< ContentIntegrity, string > > CheckContentIntegrity(LegalComponent Legal)
Checks content integrity.
static async Task< ParsedContract > Parse(XmlElement Xml, LegalComponent Legal)
Parses a contract from is XML representation.
async Task< bool > IsLegallyBinding(bool CheckCurrentTime, bool ExcludeSigningStage, LegalComponent Legal)
Checks if a contract is legally binding.
bool HasEncryptedParameters
If contract has parameters that require encryption and decryption.
DateTime? FirstSignatureAt
Timestamp of first client signature, if one exists.
bool UpdateRequiresReview(Contract UpdatedContract)
Checks if an updated contract requires review.
Task< KeyValuePair< Parameter, string > > CheckParameters(LegalComponent Legal, bool CheckTransient)
Checks if the parameters in the contract are valid.
bool TryGetParameter(CaseInsensitiveString ParameterName, out Parameter Result)
Tries to get a parameter, given its name.
DateTime Expires
When contract expires.
byte[] Nonce
An optional nonce value that is used when encrypting protected parameter values.
CaseInsensitiveString ContractId
Contract Identity
bool HasTransientParameters
If contract has parameters that are transient.
bool IsCreator(XmppAddress Jid, XmppServer Server)
Checks if an address belongs to the creator of the contract.
async Task< string > TrySetRoleParameters(string Role, int RoleIndex, LegalIdentity Identity, DateTime SignatureTimestamp, byte[] Signature, Dictionary< string, string > AttachmentUrls, LegalComponent Legal)
Tries to set role parameters.
void ProtectTransientParameters()
Protects transient values, by generating GUIDs for those that lack GUIDs.
Task< bool > CanRead(XmppAddress Jid, XmppServer Server, LegalComponent LegalComponent)
Checks if a client with a given Jid is allowed to read the contract.
Contract-reference parameter
CaseInsensitiveString Value
The value of the parameter, containing the ID of the contract that is being referenced.
Contains information about a contract signature.
Date contractual parameter
DateTime contractual parameter
Duration contractual parameter
Geo-spatial contractual parameter
Numerical contractual parameter
Abstract base class for contractual parameters
byte[] ProtectedValue
Protected value, in case Protection is not equal to ProtectionLevel.Normal.
Parameter Clone()
Clones a parameter.
CaseInsensitiveString Name
Parameter name
string Expression
Parameter validation script expression.
HumanReadableText[] Descriptions
Discriptions of the role, in different languages.
string Guide
Parameter guide text
ProtectionLevel Protection
Level of confidentiality of the information provided by the parameter.
abstract string StringValue
String representation of value.
Contains information about a parsed contract.
bool HasStatus
If a status element was found.
Contract Contract
Contract object
CaseInsensitiveString FirstParameterErrorName
Name of first parameter with error.
string FirstParameterError
Error message for first parameter with error.
bool ParametersValid
If parameter values in the contract are valid.
Class defining a part in a contract
CaseInsensitiveString Role
Role of the part in the contract
CaseInsensitiveString LegalId
Legal identity of part
int MaxCount
Largest amount of signatures of this role required for a legally binding contract.
CaseInsensitiveString Name
Name of the role.
Role-reference contractual parameter
Contains an XML schema reference, used to validate a contract.
byte[] Digest
Digest of version used during XML validation.
Abstract base class of signatures
byte[] DigitalSignature
Digital Signature
DateTime Timestamp
Timestamp of signature.
String-valued contractual parameter
Time contractual parameter
byte[] XmlSchema
XML Schema
XmlSchema Parsed
Parsed XML schema.
HashFunction Function
Hash Function used
CaseInsensitiveString Namespace
Namespace of schema
string HashBase64
Hash of schema
Class representing human-readable text.
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...
static void SeparateNames(CaseInsensitiveString FullName, out CaseInsensitiveString FirstName, out CaseInsensitiveString MiddleNames, out CaseInsensitiveString LastName)
Separates a full name into its first, middle and last names.
DateTime Updated
When the identity object was last updated
byte[] ClientSignature
Client signature
Property[] Properties
Properties detailing the legal identity.
static CaseInsensitiveString JoinNames(params CaseInsensitiveString[] Names)
Joins a sequence of names into a full name.
CaseInsensitiveString Id
ID of the legal identity
CaseInsensitiveString Provider
Provider where the identity is maintained.
AttachmentReference[] Attachments
Attachments assigned to the legal identity.
DateTime To
To what point in time the legal identity is valid.
DateTime From
From what point in time the legal identity is valid.
IdentityState State
Current state of identity
bool HasClientSignature
If the identity has a client signature
byte[] ServerSignature
Server signature
DateTime Created
When the identity object was created
bool HasClientPublicKey
If the identity has a client public key
string ClientKeyName
Type of key used for client signatures
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.
A data source for ID Application previews.
Legal (digital identities, smart contracts) service component.
LegalComponent(XmppServer Server, CaseInsensitiveString Subdomain, string Name, HttpServer HttpServer, string AttachmentsFolder, EDalerComponent EDaler, PubSubComponent PubSub, GeoSpatialComponent Geo)
Legal (digital identities, smart contracts) service component.
EDalerComponent EDaler
e-Daler component
static DateTime UtcNowSecond
Current Date & Time (in UTC), to a precision of one second.
async Task< LegalIdentity > GetApprovedLegalIdentityAsync(CaseInsensitiveString Account, DateTime Timestamp)
Gets the approved legal identity for an account for a given point in time.
static async Task< Tuple< byte[], XmlSchema > > LoadSchema(string Url)
Tries to get a schema from the web.
static string NamespaceLegalIdentity(NamespaceSet Version)
Returns the namespace for legal identities.
GeoSpatialComponent Geo
Geo-spatial component
static string NamespaceE2E(NamespaceSet Version)
Returns the namespace for End-to-End Encryption.
void RegisterPeerReviewHandlers()
Registers peer-review handlers.
const string NamespaceSmartContractsNeuroFoundationV1
urn:nf:iot:leg:sc:1.0
static readonly string[] NamespacesLegalIdentity
Supported legal identity namespaces, ordered by preference
static Task< byte[]> GetPreviewAttachment(AttachmentReference Attachment)
Retrieves the attachment associated with a preview id application.
static string NamespaceSmartContracts(NamespaceSet Version)
Returns the namespace for smart contracts.
static readonly string[] NamespacesSmartContracts
Supported smart contract namespaces, ordered by preference
static bool IsNamespaceSmartContract(string Namespace)
If a namespace corresponds to a smart contract namespace.
async Task< bool > InSameTreeOfTrust(string Domain)
Checks if a domain can be trusted for sensitive operations. This is checked by verifying the domain i...
const string NamespaceLegalIdentityIeeeV1
urn:ieee:iot:leg:id:1.0
static async Task< LegalIdentityReference > FindLegalIdentityReference(string LegalId)
Finds the legal identity reference of a legal identity in the federated network, if found in the loca...
static bool IsNamespaceLegalIdentity(string Namespace)
If a namespace corresponds to a legal identity namespace.
const string NamespaceLegalIdentityNeuroFoundationV1
urn:nf:iot:leg:id:1.0
void UnregisterPeerReviewHandlers()
Unregisters peer-review handlers.
static Task< string > GetOnboardingNeuronDomainName()
Gets the domain name of the Nnboarding Neuron.
string AttachmentsFolder
Attachments folder.
const string NamespaceE2ENeuroFoundationV1
urn:nf:iot:e2e:1.0
Task< LegalIdentity > GetCurrentApprovedLegalIdentityAsync(CaseInsensitiveString Account)
Gets the current approved legal identity for an account.
const string NamespaceSmartContractsIeeeV1
urn:ieee:iot:leg:sc:1.0
static string GetPreviewFolder()
Returns the folder where previewed files are stored. If the folder does not exist,...
const string NamespaceE2EIeeeV1
urn:ieee:iot:e2e:1.0
static async Task< IEnumerable< LegalIdentityReference > > FindLegalIdentityReferences(string Country, string PNr)
Finds the legal identity reference objects corresponding to a (COUNTRY,PNR) pair related to a person,...
async Task< string[]> GetTrustChainAsync(string Domain)
Gets the trust chain of a remote domain.
static Tuple< IE2eEndpoint, DateTime?, DateTime?> GetPublicKey(DateTime? Timestamp)
Returns the public key of the legal component, optionally, for a given point in time....
override void Dispose()
IDisposable.Dispose
override bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
Contains a reference to a legal identity, and its related PNR and COUNTRY fields. Allows for distribu...
CaseInsensitiveString Provider
Provider of identity
CaseInsensitiveString PNr
PNR field
CaseInsensitiveString Country
COUNTRY field
Web resource that allows calling applications to enable Quick-Login using legal identities.
const string NamespaceTagSignature
https://tagroot.io/schema/Signature
Contains a reference to a legal identity that is used on a remote neuron for administrative purposes.
Contains a list of public key records for an endpoint.
bool TryGetRecord(DateTime Timestamp, out IE2eEndpoint PubKey)
Tries to get a public key record valid for a given timestamp.
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
const string MarketplaceNamespace
https://paiwise.tagroot.io/Schema/Marketplace.xsd
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
const string NeuroFeaturesNamespace
https://paiwise.tagroot.io/Schema/NeuroFeatures.xsd
Paiwise processor, processing payment instructions defined in smart contracts.
const string PaymentInstructionsNamespace
https://paiwise.tagroot.io/Schema/PaymentInstructions.xsd
Contains information about a payment instruction.
DateTime? Processed
When object was successfully processed.
PubSub component, as defined in XEP-0060. https://xmpp.org/extensions/xep-0060.html
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.
bool OtherLegalIds
If a notification should be sent for every existing valid Legal ID that exists when a new Legal ID ap...
bool LegalIdAutoRejected
If a notification should be sent when a Legal ID application has been automatically rejected.
bool LegalIdAutoApproved
If a notification should be sent when a Legal ID application has been automatically approved.
bool LegalIdReceived
If a notification should be sent when a new a Legal ID application is received.
bool ContractProposalReceived
If a notification should be sent when a contract proposal has been received.
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.
Class representing the current state of a state machine.
Abstract base class for agent resources
static JwtFactory Factory
JWT Factory
Service Module hosting the XMPP broker and its components.
static NamespaceSet GetVersion(string Namespace)
Gets the namespace set version corresponding to a given a namespace.
static async Task< Stream > EncodeBlob(Stream Data)
Encodes a variable-length BLOB by prefixing it with its length. This permits the BLOB to be safely en...
static Task SaveEncryptedFile(string FileName, byte[] Salt, byte[] Data)
Saves an encrypted file.
static Task< byte[]> LoadEncryptedFile(string FileName, byte[] Salt)
Loads an encrypted file.
static async Task< Stream > DecodeBlob(Stream Data)
Decodes a variable-length BLOB encoded by the EncodeBlob method. The length prefix is read first,...
static bool Verify(byte[] Data, byte[] Signature)
Verifies a digital signature, supposedly made by the ledger.
static byte[] Sign(byte[] Data)
Signs data with the private key of the ledger.
static LedgerConfiguration Instance
Current instance of configuration.
byte[] PublicKey
Public key used to validate signatures.
Interface for identity applications.
Interface for identity applications.
Interface for identity application authenticator services.
Task Validate(IIdentityApplication Application)
Validates an identity application.
Interface for stateful identity application services.
Task ApplicationUpdated(IIdentityApplicationState Application)
Called when an Identity application state has been updated.
Interface for currency converter service providers
Task Validate(IIdentityReviewApplication Application, EventHandlerAsync< ClientUrlEventArgs > ClientUrlCallback, object State)
Checks the veracity of identity claims.
IPeerReviewServiceProvider PeerReviewServiceProvider
Reference to service provider.
bool External
If the PeerReviewerLegalId is an external legal identity (true), or represents the neuron itself (fal...
string PeerReviewerLegalId
Legal ID of peer reviewer
Interface for peer-review service providers.
Task< IPeerReviewService > GetServiceForPeerReview(string ServiceId, KeyValuePair< string, object >[] Identity)
Gets a peer-review service.
Interface for information about a service provider.
string Id
ID of service provider.
int IconWidth
Width of icon, if available.
string IconUrl
Optional URL to icon of service provider.
int IconHeight
Height of icon, if available.
string Name
Displayable name of service provider.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
Interface for asynchronously disposable objects.
string RemoteEndPoint
Remote endpoint.
Abstract base class for End-to-End encryption schemes.
bool Verify(byte[] Data, byte[] Signature)
Verifies a signature.
Interface for XMPP user accounts.
Interface for client connections.
PresenceEventArgs LastPresence
Last presence received.
bool CheckLive()
Checks if the connection is live.
Interface for identifiable legal objects
ValidationErrorType
Type of validation error.
Gender
Gender of a person.
ContractStatus
Validation Status of smart contract
RemovedReason
Reason for removing the item.
TimeUnit
Options for presenting time in reports.
ProfilerThreadType
Type of profiler thread.
Prefix
SI prefixes. http://physics.nist.gov/cuu/Units/prefixes.html
ContentType
DTLS Record content type.
Reason
Reason a token is not valid.
HashFunction
Hash method enumeration.
EDalerUriErrorType
Type of URI Error
ContentIntegrity
Result of a contract content integrity check.
ProtectionLevel
Parameter protection levels
SecondaryNameType
What type of secondary name is begin used.
AltitudeUse
How altitudes are managed by a Geo-spatial parameter
ContractState
Recognized contract states
ContractVisibility
Visibility types for contracts.
ContractParts
How the parts of the contract are defined.
NamespaceSet
Namespace versions
Represents a duration value, as defined by the xsd:duration data type: http://www....
static bool TryParse(string s, out Duration Result)
Tries to parse a duration value.
static readonly Duration Zero
Zero value