Removed public access to database config
Database connection is now acquired directly via Configuration instead of an object within it.
This commit is contained in:
parent
e9a4e3e726
commit
0401bfce2d
3 changed files with 64 additions and 35 deletions
|
@ -1,56 +1,43 @@
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Npgsql;
|
using Npgsql;
|
||||||
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Noikoio.RegexBot.ConfigItem
|
namespace Noikoio.RegexBot.ConfigItem
|
||||||
{
|
{
|
||||||
class DatabaseConfig
|
class DatabaseConfig
|
||||||
{
|
{
|
||||||
private readonly bool _enabled;
|
|
||||||
private readonly string _host;
|
private readonly string _host;
|
||||||
private readonly string _user;
|
private readonly string _user;
|
||||||
private readonly string _pass;
|
private readonly string _pass;
|
||||||
private readonly string _dbname;
|
private readonly string _dbname;
|
||||||
private readonly string _parsemsg;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether database storage is available.
|
|
||||||
/// </summary>
|
|
||||||
public bool Available => _enabled;
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor error message (only if not enabled)
|
|
||||||
/// </summary>
|
|
||||||
public string ParseMsg => _parsemsg;
|
|
||||||
|
|
||||||
public DatabaseConfig(JToken ctok)
|
public DatabaseConfig(JToken ctok)
|
||||||
{
|
{
|
||||||
if (ctok == null || ctok.Type != JTokenType.Object)
|
if (ctok == null || ctok.Type != JTokenType.Object)
|
||||||
{
|
{
|
||||||
_enabled = false;
|
throw new DatabaseConfigLoadException("");
|
||||||
_parsemsg = "Database configuration not defined.";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
var conf = (JObject)ctok;
|
var conf = (JObject)ctok;
|
||||||
|
|
||||||
_host = conf["hostname"]?.Value<string>() ?? "localhost"; // default to localhost
|
_host = conf["hostname"]?.Value<string>() ?? "localhost"; // default to localhost
|
||||||
|
|
||||||
_user = conf["username"]?.Value<string>();
|
_user = conf["username"]?.Value<string>();
|
||||||
|
if (string.IsNullOrWhiteSpace(_user))
|
||||||
|
throw new DatabaseConfigLoadException("Value for username is not defined.");
|
||||||
|
|
||||||
_pass = conf["password"]?.Value<string>();
|
_pass = conf["password"]?.Value<string>();
|
||||||
|
if (string.IsNullOrWhiteSpace(_pass))
|
||||||
|
throw new DatabaseConfigLoadException(
|
||||||
|
$"Value for password is not defined. {nameof(RegexBot)} only supports password authentication.");
|
||||||
|
|
||||||
_dbname = conf["database"]?.Value<string>();
|
_dbname = conf["database"]?.Value<string>();
|
||||||
|
if (string.IsNullOrWhiteSpace(_dbname))
|
||||||
if (string.IsNullOrWhiteSpace(_user) || string.IsNullOrWhiteSpace(_pass) || string.IsNullOrWhiteSpace(_dbname))
|
throw new DatabaseConfigLoadException("Value for database name is not defined.");
|
||||||
{
|
|
||||||
_parsemsg = "One or more required values are invalid or not defined.";
|
|
||||||
_enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_parsemsg = null;
|
|
||||||
_enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<NpgsqlConnection> GetOpenConnectionAsync()
|
internal async Task<NpgsqlConnection> GetOpenConnectionAsync()
|
||||||
{
|
{
|
||||||
if (!Available) return null;
|
|
||||||
|
|
||||||
var cs = new NpgsqlConnectionStringBuilder()
|
var cs = new NpgsqlConnectionStringBuilder()
|
||||||
{
|
{
|
||||||
Host = _host,
|
Host = _host,
|
||||||
|
@ -63,5 +50,10 @@ namespace Noikoio.RegexBot.ConfigItem
|
||||||
await db.OpenAsync();
|
await db.OpenAsync();
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class DatabaseConfigLoadException : Exception
|
||||||
|
{
|
||||||
|
public DatabaseConfigLoadException(string message) : base(message) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ namespace Noikoio.RegexBot
|
||||||
|
|
||||||
public string BotUserToken => _botToken;
|
public string BotUserToken => _botToken;
|
||||||
public string CurrentGame => _currentGame;
|
public string CurrentGame => _currentGame;
|
||||||
public DatabaseConfig Database => _dbConfig;
|
|
||||||
|
|
||||||
public ServerConfig[] Servers => _servers;
|
public ServerConfig[] Servers => _servers;
|
||||||
|
|
||||||
|
@ -72,22 +71,44 @@ namespace Noikoio.RegexBot
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads essential, unchanging values needed for bot startup. Returns false on failure.
|
/// Loads essential, unchanging values needed for bot startup. Returns false on failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool LoadInitialConfig()
|
internal bool LoadInitialConfig()
|
||||||
{
|
{
|
||||||
var lt = LoadFile();
|
var lt = LoadFile();
|
||||||
lt.Wait();
|
lt.Wait();
|
||||||
JObject conf = lt.Result;
|
JObject conf = lt.Result;
|
||||||
if (conf == null) return false;
|
if (conf == null) return false;
|
||||||
|
|
||||||
|
var log = Logger.GetLogger(LogPrefix);
|
||||||
|
|
||||||
_botToken = conf["bot-token"]?.Value<string>();
|
_botToken = conf["bot-token"]?.Value<string>();
|
||||||
if (String.IsNullOrWhiteSpace(_botToken))
|
if (String.IsNullOrWhiteSpace(_botToken))
|
||||||
{
|
{
|
||||||
Logger.GetLogger(LogPrefix)("Error: Bot token not defined. Cannot continue.").Wait();
|
log("Error: Bot token not defined. Cannot continue.").Wait();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_currentGame = conf["playing"]?.Value<string>();
|
_currentGame = conf["playing"]?.Value<string>();
|
||||||
|
|
||||||
_dbConfig = new DatabaseConfig(conf["database"]);
|
// Database configuration:
|
||||||
|
// Either it exists or it doesn't. Read config, but also attempt to make a database connection
|
||||||
|
// right here, or else make it known that database support is disabled for this instance.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_dbConfig = new DatabaseConfig(conf["database"]);
|
||||||
|
var conn = _dbConfig.GetOpenConnectionAsync().GetAwaiter().GetResult();
|
||||||
|
conn.Dispose();
|
||||||
|
}
|
||||||
|
catch (DatabaseConfig.DatabaseConfigLoadException ex)
|
||||||
|
{
|
||||||
|
if (ex.Message == "") log("Database configuration not found.").Wait();
|
||||||
|
else log("Error within database config: " + ex.Message).Wait();
|
||||||
|
_dbConfig = null;
|
||||||
|
}
|
||||||
|
catch (Npgsql.NpgsqlException ex)
|
||||||
|
{
|
||||||
|
log("An error occurred while establishing initial database connection: " + ex.Message).Wait();
|
||||||
|
_dbConfig = null;
|
||||||
|
}
|
||||||
|
// Modules that will not enable due to lack of database access should say so in their constructors.
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -179,7 +200,23 @@ namespace Noikoio.RegexBot
|
||||||
_servers = newservers.ToArray();
|
_servers = newservers.ToArray();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value stating if database access is available.
|
||||||
|
/// Specifically, indicates if <see cref="GetOpenDatabaseConnectionAsync"/> will return a non-null value.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Ideally, this value remains constant on runtime. It does not take into account
|
||||||
|
/// the possibility of the database connection failing during the program's run time.
|
||||||
|
/// </remarks>
|
||||||
|
public bool DatabaseAvailable => _dbConfig != null;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an opened connection to the SQL database, if available.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// An <see cref="Npgsql.NpgsqlConnection"/> in the opened state,
|
||||||
|
/// or null if an SQL database is not available.
|
||||||
|
/// </returns>
|
||||||
|
public Task<Npgsql.NpgsqlConnection> GetOpenDatabaseConnectionAsync() => _dbConfig?.GetOpenConnectionAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace Noikoio.RegexBot.EntityCache
|
||||||
if (lresult != null) return lresult;
|
if (lresult != null) return lresult;
|
||||||
|
|
||||||
// Database cache search
|
// Database cache search
|
||||||
var db = await RegexBot.Config.Database.GetOpenConnectionAsync();
|
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||||
if (db == null) return null; // Database not available for query.
|
if (db == null) return null; // Database not available for query.
|
||||||
using (db) return await DbQueryAsync(db, guild, user);
|
using (db) return await DbQueryAsync(db, guild, user);
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ namespace Noikoio.RegexBot.EntityCache
|
||||||
if (lresult.Count() != 0) return lresult;
|
if (lresult.Count() != 0) return lresult;
|
||||||
|
|
||||||
// Database cache search
|
// Database cache search
|
||||||
var db = await RegexBot.Config.Database.GetOpenConnectionAsync();
|
var db = await RegexBot.Config.GetOpenDatabaseConnectionAsync();
|
||||||
if (db == null) return null; // Database not available for query.
|
if (db == null) return null; // Database not available for query.
|
||||||
using (db) return await DbQueryAsync(db, guild, name, disc);
|
using (db) return await DbQueryAsync(db, guild, name, disc);
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ namespace Noikoio.RegexBot.EntityCache
|
||||||
{
|
{
|
||||||
var result = new List<CacheUser>();
|
var result = new List<CacheUser>();
|
||||||
|
|
||||||
using (db = await RegexBot.Config.Database.GetOpenConnectionAsync())
|
using (db = await RegexBot.Config.GetOpenDatabaseConnectionAsync())
|
||||||
{
|
{
|
||||||
using (var c = db.CreateCommand())
|
using (var c = db.CreateCommand())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue