4using System.Text.RegularExpressions;
5using System.Threading.Tasks;
31 [CollectionName(
"BrokerAccounts")]
33 [ObsoleteMethod(nameof(ObsoleteProperties))]
36 [Index(
"ApiKey",
"UserName")]
37 [Index(
"EMail",
"UserName")]
38 [Index(
"PhoneNr",
"UserName")]
39 [FullTextSearch(
"FTS_Accounts")]
52 internal static readonly Regex FromSaveUnsaved =
new Regex(
@"Waher[.]Persistence[.]Files[.]ObjectBTreeFile[.+]<?SaveUnsaved>?\w*[.]\w*",
53 RegexOptions.Compiled | RegexOptions.Singleline);
54 internal static readonly Regex FromUpdateObject =
new Regex(
@"Waher[.]Persistence[.]Files[.]ObjectBTreeFile[.+]<?UpdateObject>?\w*[.]\w*",
55 RegexOptions.Compiled | RegexOptions.Singleline);
63 new ApproveAssembly(typeof(Persistence.NeuroLedger.NeuroLedgerProvider).Assembly),
65 new ApproveAssembly(typeof(Networking.SASL.AuthenticationMechanism).Assembly),
66 new ApproveType(typeof(Networking.HTTP.Authentication.BasicAuthentication)),
67 new ApproveType(typeof(Networking.HTTP.Authentication.DigestAlgorithm)),
75 new ApproveType(typeof(Content.Markdown.Web.MarkdownToHtmlConverter))
78 private readonly Dictionary<string, bool> privileges =
new Dictionary<string, bool>();
79 private string objectId =
null;
80 private string apiKey =
string.Empty;
82 private string password =
string.
Empty;
97 private string[] roleIds =
null;
98 private Role[] roles =
null;
99 private string ftpRootFolder =
null;
100 private long? ftpMaxStorage =
null;
101 private bool ftpCanRead =
false;
102 private bool ftpCanWrite =
false;
103 private bool enabled =
true;
104 private bool canRelayMessages =
false;
105 private DateTime created = DateTime.MinValue;
106 private DateTime? updated =
null;
107 private DateTime? eMailVerified =
null;
108 private DateTime? phoneNrVerified =
null;
109 private AccountLogin accountLogin =
null;
124 get => this.objectId;
125 set => this.objectId = value;
134 set => this.apiKey = value;
142 get => this.userName;
143 set => this.userName = value;
155 return this.password;
160 if (!
string.IsNullOrEmpty(this.password))
163 this.password = value;
178 set => this.eMail = value;
187 set => this.phoneNr = value;
194 [DefaultValueStringEmpty]
197 get => this.latestIdentity;
198 set => this.latestIdentity = value;
207 get => this.latestIdentityState;
208 set => this.latestIdentityState = value;
214 [DefaultValueStringEmpty]
217 get => this.firstName;
218 set => this.firstName = value;
224 [DefaultValueStringEmpty]
227 get => this.middleNames;
228 set => this.middleNames = value;
234 [DefaultValueStringEmpty]
237 get => this.lastNames;
238 set => this.lastNames = value;
244 [DefaultValueStringEmpty]
247 get => this.personalNumber;
248 set => this.personalNumber = value;
254 [DefaultValueStringEmpty]
258 set => this.country = value;
264 [DefaultValueStringEmpty]
267 get => this.orgNumber;
268 set => this.orgNumber = value;
274 [DefaultValueStringEmpty]
278 set => this.orgName = value;
284 [DefaultValueStringEmpty]
288 set => this.orgRole = value;
294 [DefaultValueStringEmpty]
297 get => this.orgDepartment;
298 set => this.orgDepartment = value;
304 [DefaultValueStringEmpty]
307 get => this.orgCountry;
308 set => this.orgCountry = value;
314 [DefaultValueDateTimeMinValue]
318 set => this.created = value;
328 set => this.updated = value;
336 get => this.eMailVerified;
337 set => this.eMailVerified = value;
345 get => this.phoneNrVerified;
346 set => this.phoneNrVerified = value;
356 set => this.enabled = value;
362 [DefaultValue(
false)]
365 get => this.canRelayMessages;
366 set => this.canRelayMessages = value;
374 get => this.ftpRootFolder;
375 set => this.ftpRootFolder = value;
383 get => this.ftpCanRead;
384 set => this.ftpCanRead = value;
392 get => this.ftpCanWrite;
393 set => this.ftpCanWrite = value;
402 get => this.ftpMaxStorage;
403 set => this.ftpMaxStorage = value;
415 this.roleIds = value;
417 lock (this.privileges)
420 this.privileges.Clear();
435 string[] Ids = this.roleIds;
436 int i, c = Ids?.Length ?? 0;
439 for (i = 0; i < c; i++)
456 return this.canRelayMessages;
460 return this.ftpCanRead &&
469 return this.ftpCanWrite &&
479 lock (this.privileges)
481 if (this.privileges.TryGetValue(
Privilege, out
bool Result))
498 lock (this.privileges)
529 if (
string.IsNullOrEmpty(Login.RemoteEndPoint) &&
530 Properties.TryGetValue(
"RemoteEndpoint", out
object Obj) &&
531 Obj is
string RemoteEndPoint)
533 Login.RemoteEndPoint = RemoteEndPoint;
537 if (Login.LastLogin == DateTime.MinValue &&
538 Properties.TryGetValue(
"LastLogin", out Obj) &&
539 Obj is DateTime LastLogin)
541 Login.LastLogin = LastLogin;
562 Login.LastLogin = DateTime.Now;
563 Login.RemoteEndPoint = RemoteEndPoint;
574 if (!(this.accountLogin is
null))
575 return this.accountLogin;
578 if (!(this.accountLogin is
null))
579 return this.accountLogin;
584 RemoteEndPoint =
string.
Empty,
585 LastLogin = DateTime.MinValue
590 return this.accountLogin;
596 public string FullName => Concat(
" ", this.firstName, this.middleNames, this.lastNames);
606 public string OrganizationInformation => Concat(
", ", this.orgRole, this.orgDepartment, this.orgName, this.orgNumber, this.orgCountry);
630 StringBuilder sb =
new StringBuilder();
633 foreach (
string Segment
in Segments)
634 Append(sb, ref First, Segment, Delimiter);
636 return sb.ToString();
639 private static void Append(StringBuilder sb, ref
bool First,
CaseInsensitiveString Segment,
string Delimiter)
641 if (!
string.IsNullOrEmpty(Segment))
646 sb.Append(Delimiter);
648 sb.Append(Segment.
Value);
657 internal void AppendAccountXml(StringBuilder sb,
bool IncludeNamespace)
659 sb.Append(
"<Account");
660 if (IncludeNamespace)
661 sb.Append(
" xmlns=\"http://waher.se/schema/Onboarding/v1.xsd\"");
663 sb.Append(
" userName=\"");
665 sb.Append(
"\" password=\"");
667 sb.Append(
"\" domain=\"");
669 sb.Append(
"\" enabled=\"");
671 sb.Append(
"\" created=\"");
674 if (this.updated.HasValue)
676 sb.Append(
"\" updated=\"");
677 sb.Append(
XML.
Encode(
this.updated.Value));
682 sb.Append(
"\" eMail=\"");
685 if (this.eMailVerified.HasValue)
687 sb.Append(
"\" eMailVerified=\"");
688 sb.Append(
XML.
Encode(
this.eMailVerified.Value));
694 sb.Append(
"\" phoneNr=\"");
695 sb.Append(
XML.
Encode(
this.phoneNr.Value));
697 if (this.phoneNrVerified.HasValue)
699 sb.Append(
"\" phoneNrVerified=\"");
700 sb.Append(
XML.
Encode(
this.phoneNrVerified.Value));
706 sb.Append(
"\" latestIdentity=\"");
707 sb.Append(
XML.
Encode(
this.latestIdentity.Value));
712 sb.Append(
"\" firstName=\"");
713 sb.Append(
XML.
Encode(
this.firstName.Value));
718 sb.Append(
"\" middleNames=\"");
719 sb.Append(
XML.
Encode(
this.middleNames.Value));
724 sb.Append(
"\" lastNames=\"");
725 sb.Append(
XML.
Encode(
this.lastNames.Value));
730 sb.Append(
"\" personalNumber=\"");
731 sb.Append(
XML.
Encode(
this.personalNumber.Value));
736 sb.Append(
"\" country=\"");
737 sb.Append(
XML.
Encode(
this.country.Value));
742 sb.Append(
"\" orgNumber=\"");
743 sb.Append(
XML.
Encode(
this.orgNumber.Value));
748 sb.Append(
"\" orgName=\"");
749 sb.Append(
XML.
Encode(
this.orgName.Value));
754 sb.Append(
"\" orgRole=\"");
755 sb.Append(
XML.
Encode(
this.orgRole.Value));
760 sb.Append(
"\" orgDepartment=\"");
761 sb.Append(
XML.
Encode(
this.orgDepartment.Value));
766 sb.Append(
"\" orgCountry=\"");
767 sb.Append(
XML.
Encode(
this.orgCountry.Value));
782 StringBuilder sb =
new StringBuilder();
784 this.AppendAccountXml(sb,
true);
786 byte[] Bin = Encoding.UTF8.GetBytes(sb.ToString());
792 sb.Append(
"<Info xmlns=\"http://waher.se/schema/Onboarding/v1.xsd\" base64=\"");
793 sb.Append(Convert.ToBase64String(Bin));
794 sb.Append(
"\" once=\"true\" expires=\"");
795 sb.Append(
XML.
Encode(Expires.ToUniversalTime()));
800 XmlElement Info = await
Gateway.
XmppClient.IqSetAsync(
"onboarding." + OnboardingDomainName, sb.ToString());
802 foreach (XmlNode N
in Info.ChildNodes)
804 if (N is XmlElement E && E.LocalName ==
"Code")
807 return "obinfo:" + OnboardingDomainName +
":" + Code +
":" +
808 Convert.ToBase64String(Key) +
":" +
809 Convert.ToBase64String(IV);
813 throw new Exception(
"Unexpected response returned: " + Info.OuterXml);
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Converts Web Script-files to desired output, by evaluating the web script and encoding the results in...
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 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 class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
static XmppClient XmppClient
XMPP Client connection of gateway.
Implements a simple FTP Server, as defined in:
const string FtpWritePrivilegePrefix
Prefix of FTP Write Privileges
const string FtpReadPrivilegePrefix
Prefix of FTP Read Privileges
Implements a simple SMTP Server, as defined in:
const string SmtpRelayPrivilegeID
SmtpRelay
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
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static async Task Update(object Object)
Updates an object in the database.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that have a named field equal to a given value.
static byte[] Encrypt(byte[] Data, byte[] Key, byte[] IV, CipherMode CipherMode=CipherMode.CBC, PaddingMode PaddingMode=PaddingMode.PKCS7)
Performs AES encryption of data.
Checks for an approved assembly in the call stack.
Checks for approved sources in the call stack using a regular expression.
Checks for an approved type in the call stack.
Static class containing methods that can be used to make sure calls are made from appropriate locatio...
static void CallFromSource(params string[] Sources)
Makes sure the call is made from one of the listed sources.
Checks for a prohibited assembly in the call stack.
Corresponds to a privilege in the system.
Maintains the collection of all privileges in the system.
static async Task< Privilege > GetPrivilege(string PrivilegeId)
Gets the Privilege object corresponding to a full Privilege ID.
Corresponds to a role in the system.
bool HasPrivilege(string Privilege)
If the user has a given privilege.
Maintains the collection of all roles in the system.
static Task< Role > GetRole(string RoleId)
Gets the Role object corresponding to a Role ID.
Contains information about a broker account.
DateTime? PhoneNrVerified
When Phone Number was verified.
CaseInsensitiveString PersonalNumber
Phone Number associated with account holder.
CaseInsensitiveString EMail
E-mail address associated with account.
CaseInsensitiveString UserName
User Name of account
bool Enabled
If account is enabled
CaseInsensitiveString OrgRole
Organization role associated with account holder.
async void ObsoleteProperties(Dictionary< string, object > Properties)
Method called when loading the object and properties were found that are no longer recognized.
CaseInsensitiveString FirstName
First name associated with account holder.
string PersonalInformation
Personal information of account holder.
async Task< AccountLogin > GetAccountLogin()
Gets the object with the associated account login status information.
bool HasPrivilege(string Privilege)
If account has a certain privilege.
DateTime? EMailVerified
When e-Mail was verified.
string Password
Password of account
CaseInsensitiveString Country
Country code associated with account holder.
string OrganizationInformation
Organizational information of account holder.
IdentityState? LatestIdentityState
State of Last Legal Identity approved for account.
CaseInsensitiveString LastNames
Last name(s) associated with account holder.
CaseInsensitiveString PhoneNr
Phone number associated with account.
async Task< string > GetOnboardingUrl(DateTime Expires)
Generates an oninfo URI for onboarding the account, valid until the specified expiration date.
string FtpRootFolder
FTP Root Folder, if account has access to FTP.
Account()
Contains information about a broker account.
CaseInsensitiveString OrgDepartment
Organization department associated with account holder.
const string AccountDeletedCounterName
Name of counter that counts the number of accounts deleted.
bool FtpCanWrite
If FTP Write access is granted to the root folder and subfolders.
const string AccountCreatedCounterName
Name of counter that counts the number of accounts created.
async Task< Role[]> LoadRoles()
Load role objects.
bool FtpCanRead
If FTP Read access is granted to the root folder and subfolders.
bool CanRelayMessages
If account is allowed to relay e-mail messages
CaseInsensitiveString OrgNumber
Organization number associated with account holder.
string FullName
Full name of account holder.
long? FtpMaxStorage
Maximum storage allowed, in bytes. 0 means no storage. A negative value means unlimited storage.
DateTime? Updated
When account was created associated with account holder.
DateTime Created
When account was created associated with account holder.
async Task LoggedIn(string RemoteEndPoint)
Registers a log-in event on the account.
CaseInsensitiveString OrgName
Organization name associated with account holder.
CaseInsensitiveString OrgCountry
Country code of organization associated with account holder.
CaseInsensitiveString MiddleNames
Middle name(s) associated with account holder.
CaseInsensitiveString LatestIdentity
Last Legal Identity approved for account. Note: Identity object might not be approved any longer.
bool HasExtendedPersonalInformation
If the account has extended personal information associated with it.
string[] EncryptedProperties
Array of properties that are encrypted.
Legal (digital identities, smart contracts) service component.
static Task< string > GetOnboardingNeuronDomainName()
Gets the domain name of the Nnboarding Neuron.
Service Module hosting the XMPP broker and its components.
Interface for XMPP user accounts.
Interface for objects containing encrypted properties. Mark the properties that are encrypted with th...
Interface for call stack checks.
TypeNameSerialization
How the type name should be serialized.
IdentityState
Lists recognized legal identity states.