Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
DatabaseConfiguration.cs
1using System;
3using System.IO;
4using System.Threading.Tasks;
5using Waher.Content;
10using Waher.Events;
19
21{
26 {
27 private static DatabaseConfiguration instance = null;
28 private static string[] repairedCollections = null;
29
30 private HttpResource selectDatabase = null;
31 private HttpResource testDatabase = null;
32
33 private IDatabasePlugin databasePlugin = null;
34 private string databasePluginName = null;
35 private DatabaseSettings databasePluginSettings = null;
36
37 private SniffableDatabase sniffableDatabase = null;
38 private SniffableLedger sniffableLedger = null;
39
43 [DefaultValueNull]
44 public string DatabasePluginName
45 {
46 get => this.databasePluginName;
47 set => this.databasePluginName = value;
48 }
49
53 [DefaultValueNull]
55 {
56 get => this.databasePluginSettings;
57 set => this.databasePluginSettings = value;
58 }
59
64 {
65 get
66 {
67 if (this.databasePlugin is null)
68 {
69 if (this.databasePluginName is null)
70 return null;
71
72 Type T = Types.GetType(this.databasePluginName);
73 if (!(T is null))
74 this.databasePlugin = Types.Instantiate(T) as IDatabasePlugin;
75 }
76
77 return this.databasePlugin;
78 }
79 }
80
85 {
86 get
87 {
88 this.sniffableDatabase ??= new SniffableDatabase();
89 return this.sniffableDatabase;
90 }
91 }
92
97 {
98 get
99 {
100 this.sniffableLedger ??= new SniffableLedger();
101 return this.sniffableLedger;
102 }
103 }
104
108 public static DatabaseConfiguration Instance => instance;
109
113 public static string[] RepairedCollections
114 {
115 get => repairedCollections;
116 internal set => repairedCollections = value;
117 }
118
122 public override string Resource => "/Settings/Database.md";
123
127 public override int Priority => 0;
128
134 public override Task<string> Title(Language Language)
135 {
136 return Language.GetStringAsync(typeof(Gateway), 1, "Database");
137 }
138
142 public override async Task ConfigureSystem()
143 {
145
146 if (!(Plugin is null))
147 await Plugin.ConfigureSettings(this.databasePluginSettings);
148 }
149
154 public override void SetStaticInstance(ISystemConfiguration Configuration)
155 {
156 instance = Configuration as DatabaseConfiguration;
157 }
158
163 public override Task InitSetup(HttpServer WebServer)
164 {
165 this.selectDatabase = WebServer.Register("/Settings/SelectDatabase", null, this.SelectDatabase, true, false, true);
166 this.testDatabase = WebServer.Register("/Settings/TestDatabase", null, this.TestDatabase, true, false, true);
167
168 return base.InitSetup(WebServer);
169 }
170
175 public override Task UnregisterSetup(HttpServer WebServer)
176 {
177 WebServer.Unregister(this.selectDatabase);
178 WebServer.Unregister(this.testDatabase);
179
180 return base.UnregisterSetup(WebServer);
181 }
182
186 protected override string ConfigPrivilege => "Admin.Data.Database";
187
188 private async Task SelectDatabase(HttpRequest Request, HttpResponse Response)
189 {
190 Gateway.AssertUserAuthenticated(Request, this.ConfigPrivilege);
191
192 if (!Request.HasData)
193 {
194 await Response.SendResponse(new BadRequestException());
195 return;
196 }
197
198 ContentResponse Content = await Request.DecodeDataAsync();
199 if (Content.HasError || !(Content.Decoded is string PluginName))
200 {
201 await Response.SendResponse(new BadRequestException());
202 return;
203 }
204
205 Type PluginType = Types.GetType(PluginName);
206 if (PluginType is null)
207 {
208 await Response.SendResponse(new NotFoundException("Database plugin not found: " + PluginName));
209 return;
210 }
211
212 if (!(Types.Instantiate(PluginType) is IDatabasePlugin Plugin))
213 {
214 await Response.SendResponse(new BadRequestException());
215 return;
216 }
217
218 if (this.databasePluginName != PluginName)
219 {
220 this.databasePlugin = Plugin;
221 this.databasePluginName = PluginName;
222 this.databasePluginSettings = Plugin.CreateNewSettings();
223
224 if (string.IsNullOrEmpty(Plugin.SettingsResource))
225 this.Step = 1;
226 else
227 {
228 this.Step = 0;
229 this.Complete = false;
230 }
231 }
232
233 Response.ContentType = JsonCodec.DefaultContentType;
234
235 string Html = string.Empty;
236 bool HasSettings = false;
237 string ResourceName = Plugin?.SettingsResource;
238 if (!string.IsNullOrEmpty(ResourceName))
239 {
240 if (ResourceName.StartsWith("/"))
241 ResourceName = ResourceName[1..];
242
243 ResourceName = ResourceName.Replace('/', Path.DirectorySeparatorChar);
244 ResourceName = Path.Combine(Gateway.RootFolder, ResourceName);
245 if (File.Exists(ResourceName))
246 {
247 string Markdown = await Files.ReadAllTextAsync(ResourceName);
248 MarkdownSettings Settings = new MarkdownSettings()
249 {
250 Variables = Request.Session
251 };
252 MarkdownDocument Doc = await MarkdownDocument.CreateAsync(Markdown, Settings);
253
254 Html = await Doc.GenerateHTML();
255 Html = HtmlDocument.GetBody(Html);
256 HasSettings = true;
257 }
258 }
259
260 await Response.Write(JSON.Encode(new Dictionary<string, object>()
261 {
262 { "html", Html },
263 { "isDone", this.Step >= 1 },
264 { "hasSettings", HasSettings },
265 { "restart", Database.Locked }
266 }, false));
267 }
268
269 private async Task TestDatabase(HttpRequest Request, HttpResponse Response)
270 {
271 Gateway.AssertUserAuthenticated(Request, this.ConfigPrivilege);
272
273 if (!Request.HasData)
274 {
275 await Response.SendResponse(new BadRequestException());
276 return;
277 }
278
279 ContentResponse Content = await Request.DecodeDataAsync();
280 if (Content.HasError || !(Content.Decoded is Dictionary<string, object> Form))
281 {
282 await Response.SendResponse(new BadRequestException());
283 return;
284 }
285
286 if (!Form.TryGetValue("save", out object Obj) ||
287 !(Obj is bool Save) ||
288 !Form.TryGetValue("Plugin", out Obj) ||
289 !(Obj is string PluginName) ||
290 this.databasePluginName != PluginName ||
291 this.databasePlugin is null ||
292 this.databasePluginSettings is null)
293 {
294 await Response.SendResponse(new BadRequestException());
295 return;
296 }
297
298 await this.databasePlugin.Test(Form, Save, this.databasePluginSettings);
299
300 if (Save)
301 {
302 this.Step = 1;
303 await Gateway.InternalDatabase.Update(this);
304 }
305
306 Response.ContentType = PlainTextCodec.DefaultContentType;
307
308 if (Database.Locked)
309 await Response.Write("2");
310 else
311 await Response.Write("1");
312
313 await Response.SendResponse();
314 }
315
320 public override Task<bool> SimplifiedConfiguration()
321 {
323
324 this.databasePlugin = Plugin;
325 this.databasePluginName = Plugin.GetType().FullName;
326 this.databasePluginSettings = Plugin.CreateNewSettings();
327 this.Step = 1;
328
329 return Task.FromResult(true);
330 }
331
335 public const string GATEWAY_DB_PROVIDER = nameof(GATEWAY_DB_PROVIDER);
336
341 public override async Task<bool> EnvironmentConfiguration()
342 {
343 string ProviderType = Environment.GetEnvironmentVariable(GATEWAY_DB_PROVIDER);
344 if (string.IsNullOrEmpty(ProviderType))
345 return false;
346
347 Type T = Types.GetType(ProviderType);
348 if (T is null)
349 {
350 this.LogEnvironmentError("Database plugin not found.", GATEWAY_DB_PROVIDER, ProviderType);
351 return false;
352 }
353
355
356 try
357 {
359 }
360 catch (Exception ex)
361 {
362 this.LogEnvironmentError(ex.Message, GATEWAY_DB_PROVIDER, ProviderType);
363 return false;
364 }
365
366 if (Plugin is null)
367 {
368 this.LogEnvironmentError("Unable to instantiate database plugin.", GATEWAY_DB_PROVIDER, ProviderType);
369 return false;
370 }
371
372 DatabaseSettings Settings = Plugin.CreateNewSettings();
373
374 try
375 {
376 if (!await Plugin.TestEnvironmentVariables(this, Settings))
377 return false;
378 }
379 catch (Exception ex)
380 {
381 Log.Exception(ex);
382 return false;
383 }
384
385 this.databasePlugin = Plugin;
386 this.databasePluginName = ProviderType;
387 this.databasePluginSettings = Settings;
388 this.Step = 1;
389
390 return true;
391 }
392
393 }
394}
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
Helps with common JSON-related tasks.
Definition: JSON.cs:16
static string Encode(string s)
Encodes a string for inclusion in JSON.
Definition: JSON.cs:537
const string DefaultContentType
application/json
Definition: JsonCodec.cs:20
Contains a markdown document. This markdown document class supports original markdown,...
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Plain text encoder/decoder.
const string DefaultContentType
text/plain
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
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.
Definition: Log.cs:1657
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
static IUser AssertUserAuthenticated(HttpRequest Request, string Privilege)
Makes sure a request is being made from a session with a successful user login.
Definition: Gateway.cs:3868
static IDatabaseProvider InternalDatabase
Local Internal Encrypted Object Database provider.
Definition: Gateway.cs:3176
static string RootFolder
Web root folder.
Definition: Gateway.cs:3142
static DatabaseConfiguration Instance
Current instance of configuration.
SniffableLedger SniffableLedger
Makes ledger activity sniffable.
override string ConfigPrivilege
Minimum required privilege for a user to be allowed to change the configuration defined by the class.
override int Priority
Priority of the setting. Configurations are sorted in ascending order.
IDatabasePlugin DatabasePlugin
Current database plugin, if defined, null otherwise.
override Task InitSetup(HttpServer WebServer)
Initializes the setup object.
override async Task< bool > EnvironmentConfiguration()
Environment configuration by configuring values available in environment variables.
override async Task ConfigureSystem()
Is called during startup to configure the system.
static string[] RepairedCollections
Collections repaired during startup.
string DatabasePluginName
Full name of database plugin class.
override void SetStaticInstance(ISystemConfiguration Configuration)
Sets the static instance of the configuration.
SniffableDatabase SniffableDatabase
Makes database activity sniffable.
override Task< bool > SimplifiedConfiguration()
Simplified configuration by configuring simple default values.
override Task UnregisterSetup(HttpServer WebServer)
Unregisters the setup object.
override Task< string > Title(Language Language)
Gets a title for the system configuration.
DatabaseSettings DatabasePluginSettings
Settings for database plugin.
Class that can be used to sniff on database updates.
Class that can be used to sniff on ledger activity.
Abstract base class for multi-step system configurations.
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Represents an HTTP request.
Definition: HttpRequest.cs:22
bool HasData
If the request has data.
Definition: HttpRequest.cs:113
async Task< ContentResponse > DecodeDataAsync()
Decodes data sent in request.
Definition: HttpRequest.cs:139
Base class for all HTTP resources.
Definition: HttpResource.cs:23
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:23
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
Task Write(byte[] Data)
Returns binary data in the response.
Implements an HTTP server.
Definition: HttpServer.cs:41
HttpResource Register(HttpResource Resource)
Registers a resource with the server.
Definition: HttpServer.cs:1568
bool Unregister(HttpResource Resource)
Unregisters a resource from the server.
Definition: HttpServer.cs:1743
The server has not found anything matching the Request-URI. No indication is given of whether the con...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static bool Locked
If the datbase provider has been locked for the rest of the run-time of the application.
Definition: Database.cs:89
Contains static methods
Definition: Files.cs:14
static async Task< string > ReadAllTextAsync(string FileName)
Reads a text file asynchronously.
Definition: Files.cs:84
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
static Type GetType(string FullName)
Gets a type, given its full name.
Definition: Types.cs:42
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...
Definition: Types.cs:1454
Contains information about a language.
Definition: Language.cs:17
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
Definition: Language.cs:209
Interface for system configurations. The gateway will scan all module for system configuration classe...
Task Update(object Object)
Updates an object in the database.