diff --git a/.gitignore b/.gitignore
index fefd0b5b91..504e400b0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ artifacts/
/tests/DMAPI/travistester.int
/tests/DMAPI/travistester.dmb
/src/Tgstation.Server.Host/appsettings.Development.json
+/src/Tgstation.Server.Host/LocalTestDB.sqlite3
/src/Tgstation.Server.Host/wwwroot
/src/Tgstation.Server.Host/ClientApp/node_modules
/src/Tgstation.Server.Host/ClientApp/build
diff --git a/appveyor.yml b/appveyor.yml
index e403ebb358..e355bebd0c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -51,7 +51,7 @@ test_script:
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Client.Tests/Tgstation.Server.Client.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Client.Tests*]*" -output:".\client_coverage.xml" -oldstyle
- ps: $wc = New-Object 'System.Net.WebClient'
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Client.Tests\TestResults\results.trx))
- - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations*" -output:".\host_coverage.xml" -oldstyle
+ - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Tests/Tgstation.Server.Host.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations*" -output:".\host_coverage.xml" -oldstyle
- ps: $wc = New-Object 'System.Net.WebClient'
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Tests\TestResults\results.trx))
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Console.Tests/Tgstation.Server.Host.Console.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Console.Tests*]*" -output:".\console_coverage.xml" -oldstyle
@@ -64,7 +64,7 @@ test_script:
- OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Host.Watchdog.Tests/Tgstation.Server.Host.Watchdog.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Host.Watchdog.Tests*]*" -output:".\watchdog_coverage.xml" -oldstyle
- ps: $wc = New-Object 'System.Net.WebClient'
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Host.Watchdog.Tests\TestResults\results.trx))
- - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations..*" -output:".\server_coverage.xml" -oldstyle
+ - OpenCover.Console.exe -returntargetcode -register:user -target:"C:/Program Files/dotnet/dotnet.exe" -targetargs:"test -c %CONFIGURATION% --logger:trx;LogFileName=results.trx /p:DebugType=full tests/Tgstation.Server.Tests/Tgstation.Server.Tests.csproj" -filter:"+[Tgstation.Server*]* -[Tgstation.Server.Tests*]* -[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations..*" -output:".\server_coverage.xml" -oldstyle
- ps: $wc = New-Object 'System.Net.WebClient'
- ps: $wc.UploadFile("https://ci.appveyor.com/api/testresults/mstest/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\tests\Tgstation.Server.Tests\TestResults\results.trx))
- lint-openapi -c build/OpenApiValidationSettings.json C:/swagger.json
diff --git a/build/test_core.sh b/build/test_core.sh
index 3418f12fe4..a27611b434 100755
--- a/build/test_core.sh
+++ b/build/test_core.sh
@@ -20,7 +20,7 @@ $HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Client.T
cd ../Tgstation.Server.Host.Tests
dotnet build -c $CONFIG /p:CopyLocalLockFileAssemblies=true
-$HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Host.Tests.dll --target "dotnet" --targetargs "test -c $CONFIG --no-build" --format opencover --output "../../TestResults/host.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Host.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations.*"
+$HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Host.Tests.dll --target "dotnet" --targetargs "test -c $CONFIG --no-build" --format opencover --output "../../TestResults/host.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Host.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations.*"
cd ../Tgstation.Server.Host.Watchdog.Tests
@@ -37,7 +37,14 @@ export TGS4_TEST_DATABASE_TYPE=MySql
export TGS4_TEST_CONNECTION_STRING="server=127.0.0.1;uid=root;pwd=;database=tgs_test"
#token set in CI settings
dotnet build -c $CONFIG /p:CopyLocalLockFileAssemblies=true
-$HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Tests.dll --target "dotnet" --targetargs "test -c $CONFIG --no-build" --format opencover --output "../../TestResults/server.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Models.Migrations.*"
+
+$HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Tests.dll --target "dotnet" --targetargs "test -c $CONFIG --no-build" --format opencover --output "../../TestResults/servermy.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations.*"
+
+#Run again for Sqlite
+export TGS4_TEST_DATABASE_TYPE=Sqlite
+export TGS4_TEST_CONNECTION_STRING="Data Source=TravisTestDB.sqlite3;Mode=ReadWriteCreate"
+#Disabled due to upstream issues
+#$HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Tests.dll --target "dotnet" --targetargs "test -c $CONFIG --no-build" --format opencover --output "../../TestResults/serversl.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations.*"
cd ../../TestResults
@@ -46,4 +53,5 @@ bash <(curl -s https://codecov.io/bash) -f client.xml -F unittests
bash <(curl -s https://codecov.io/bash) -f host.xml -F unittests
bash <(curl -s https://codecov.io/bash) -f watchdog.xml -F unittests
bash <(curl -s https://codecov.io/bash) -f console.xml -F unittests
-bash <(curl -s https://codecov.io/bash) -f server.xml -F integration
+bash <(curl -s https://codecov.io/bash) -f servermy.xml -F integration
+# bash <(curl -s https://codecov.io/bash) -f serversl.xml -F integration
diff --git a/src/Tgstation.Server.Host/Configuration/DatabaseType.cs b/src/Tgstation.Server.Host/Configuration/DatabaseType.cs
index c4b5f31d67..d1432ac99c 100644
--- a/src/Tgstation.Server.Host/Configuration/DatabaseType.cs
+++ b/src/Tgstation.Server.Host/Configuration/DatabaseType.cs
@@ -18,6 +18,11 @@
///
/// Use MariaDB
///
- MariaDB
+ MariaDB,
+
+ ///
+ /// Use Sqlite
+ ///
+ Sqlite,
}
}
diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs
index 40c58d0ff6..f7cfa9c27e 100644
--- a/src/Tgstation.Server.Host/Core/Application.cs
+++ b/src/Tgstation.Server.Host/Core/Application.cs
@@ -293,6 +293,9 @@ namespace Tgstation.Server.Host.Core
case DatabaseType.SqlServer:
AddTypedContext();
break;
+ case DatabaseType.Sqlite:
+ AddTypedContext();
+ break;
default:
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid {0}: {1}!", nameof(DatabaseType), dbType));
}
diff --git a/src/Tgstation.Server.Host/Core/SetupWizard.cs b/src/Tgstation.Server.Host/Core/SetupWizard.cs
index d685044ec7..53a7708d58 100644
--- a/src/Tgstation.Server.Host/Core/SetupWizard.cs
+++ b/src/Tgstation.Server.Host/Core/SetupWizard.cs
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Hosting;
+using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MySql.Data.MySqlClient;
@@ -8,6 +9,7 @@ using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
@@ -148,6 +150,157 @@ namespace Tgstation.Server.Host.Core
while (true);
}
+ ///
+ /// Ensure a given works.
+ ///
+ /// The test .
+ /// The may have derived data populated.
+ /// The database name (or path in the case of a database).
+ /// Whether or not the database exists.
+ /// The for the operation.
+ /// A representing the running operation.
+ async Task TestDatabaseConnection(
+ DbConnection testConnection,
+ DatabaseConfiguration databaseConfiguration,
+ string databaseName,
+ bool dbExists,
+ CancellationToken cancellationToken)
+ {
+ bool isSqliteDB = databaseConfiguration.DatabaseType == DatabaseType.Sqlite;
+ using (testConnection)
+ {
+ await console.WriteAsync("Testing connection...", true, cancellationToken).ConfigureAwait(false);
+ await testConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("Connection successful!", true, cancellationToken).ConfigureAwait(false);
+
+ if (databaseConfiguration.DatabaseType == DatabaseType.MariaDB
+ || databaseConfiguration.DatabaseType == DatabaseType.MySql)
+ {
+ await console.WriteAsync("Checking MySQL/MariaDB version...", true, cancellationToken).ConfigureAwait(false);
+ using (var command = testConnection.CreateCommand())
+ {
+ command.CommandText = "SELECT VERSION()";
+ var fullVersion = (string)await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Found {0}", fullVersion), true, cancellationToken).ConfigureAwait(false);
+ var splits = fullVersion.Split('-');
+ databaseConfiguration.MySqlServerVersion = splits.First();
+ }
+ }
+
+ if (!isSqliteDB && !dbExists)
+ {
+ await console.WriteAsync("Testing create DB permission...", true, cancellationToken).ConfigureAwait(false);
+ using (var command = testConnection.CreateCommand())
+ {
+ // I really don't care about user sanitization here, they want to fuck their own DB? so be it
+#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
+ command.CommandText = $"CREATE DATABASE {databaseName}";
+#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
+ await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+ await console.WriteAsync("Success!", true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("Dropping test database...", true, cancellationToken).ConfigureAwait(false);
+ using (var command = testConnection.CreateCommand())
+ {
+#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
+ command.CommandText = $"DROP DATABASE {databaseName}";
+#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
+ try
+ {
+ await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ catch (Exception e)
+ {
+ await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("This should be okay, but you may want to manually drop the database before continuing!", true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("Press any key to continue...", true, cancellationToken).ConfigureAwait(false);
+ await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+
+ if (isSqliteDB && !dbExists)
+ await Task.WhenAll(
+ console.WriteAsync("Deleting test database file...", true, cancellationToken),
+ ioManager.DeleteFile(databaseName, cancellationToken)).ConfigureAwait(false);
+ }
+
+ async Task ValidateNonExistantSqliteDBName(string databaseName, CancellationToken cancellationToken)
+ {
+ var resolvedPath = ioManager.ResolvePath(databaseName);
+ try
+ {
+ var directoryName = ioManager.GetDirectoryName(resolvedPath);
+ bool directoryExisted = await ioManager.DirectoryExists(directoryName, cancellationToken).ConfigureAwait(false);
+ await ioManager.CreateDirectory(directoryName, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await ioManager.WriteAllBytes(resolvedPath, Array.Empty(), cancellationToken).ConfigureAwait(false);
+ }
+ catch
+ {
+ if (!directoryExisted)
+ await ioManager.DeleteDirectory(directoryName, cancellationToken).ConfigureAwait(false);
+ throw;
+ }
+ }
+ catch (IOException)
+ {
+ return null;
+ }
+
+ if (!Path.IsPathRooted(databaseName))
+ {
+ await console.WriteAsync("Note, this relative path (currently) resolves to the following:", true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync(resolvedPath, true, cancellationToken).ConfigureAwait(false);
+ bool writeResolved = await PromptYesNo(
+ "Would you like to save the relative path in the configuration? If not, the full path will be saved. (y/n): ",
+ cancellationToken)
+ .ConfigureAwait(false);
+
+ if (writeResolved)
+ databaseName = resolvedPath;
+ }
+
+ await ioManager.DeleteFile(databaseName, cancellationToken).ConfigureAwait(false);
+ return databaseName;
+ }
+
+ ///
+ /// Prompt the user for the .
+ ///
+ /// The for the operation.
+ /// A resulting in the input .
+ async Task PromptDatabaseType(CancellationToken cancellationToken)
+ {
+ do
+ {
+ await console.WriteAsync(
+ String.Format(
+ CultureInfo.InvariantCulture,
+ "Please enter one of {0}, {1}, or {2}: ",
+ DatabaseType.MariaDB,
+ DatabaseType.MySql,
+ DatabaseType.SqlServer),
+ false,
+ cancellationToken)
+ .ConfigureAwait(false);
+ var databaseTypeString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
+ if (Enum.TryParse(databaseTypeString, out var databaseType))
+ return databaseType;
+
+ await console.WriteAsync("Invalid database type!", true, cancellationToken).ConfigureAwait(false);
+ }
+ while (true);
+ }
+
///
/// Prompts the user to create a
///
@@ -160,69 +313,69 @@ namespace Tgstation.Server.Host.Core
await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
await console.WriteAsync("What SQL database type will you be using?", true, cancellationToken).ConfigureAwait(false);
- var databaseConfiguration = new DatabaseConfiguration();
- do
+ var databaseConfiguration = new DatabaseConfiguration
{
- await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Please enter one of {0}, {1}, or {2}: ", DatabaseType.MariaDB, DatabaseType.SqlServer, DatabaseType.MySql), false, cancellationToken).ConfigureAwait(false);
- var databaseTypeString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
- if (Enum.TryParse(databaseTypeString, out var databaseType))
- {
- databaseConfiguration.DatabaseType = databaseType;
- break;
- }
+ DatabaseType = await PromptDatabaseType(cancellationToken).ConfigureAwait(false)
+ };
- await console.WriteAsync("Invalid database type!", true, cancellationToken).ConfigureAwait(false);
- }
- while (true);
-
- string serverAddress;
+ string serverAddress = null;
uint? mySQLServerPort = null;
- do
- {
- await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Enter the server's address and port [: or ] (blank for local): ", false, cancellationToken).ConfigureAwait(false);
- serverAddress = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
- if (String.IsNullOrWhiteSpace(serverAddress))
+
+ bool isSqliteDB = databaseConfiguration.DatabaseType == DatabaseType.Sqlite;
+ if (!isSqliteDB)
+ do
{
- serverAddress = null;
- break;
- }
- else if (databaseConfiguration.DatabaseType != DatabaseType.SqlServer)
- {
- var m = Regex.Match(serverAddress, @"^(?.+):(?.+)$");
- if (m.Success)
+ await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("Enter the server's address and port [: or ] (blank for local): ", false, cancellationToken).ConfigureAwait(false);
+ serverAddress = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
+ if (!String.IsNullOrWhiteSpace(serverAddress) && databaseConfiguration.DatabaseType == DatabaseType.SqlServer)
{
- serverAddress = m.Groups["server"].Value;
- if (uint.TryParse(m.Groups["port"].Value, out uint port))
+ var match = Regex.Match(serverAddress, @"^(?.+):(?.+)$");
+ if (match.Success)
{
- mySQLServerPort = port;
- break;
- }
- else
- {
- await console.WriteAsync($@"Failed to parse port ""{m.Groups["port"].Value}"", please try again.", true, cancellationToken).ConfigureAwait(false);
+ serverAddress = match.Groups["server"].Value;
+ var portString = match.Groups["port"].Value;
+ if (uint.TryParse(portString, out uint port))
+ mySQLServerPort = port;
+ else
+ {
+ await console.WriteAsync($"Failed to parse port \"{portString}\", please try again.", true, cancellationToken).ConfigureAwait(false);
+ continue;
+ }
}
}
- else break;
+
+ break;
}
- else break;
- }
- while (true);
+ while (true);
await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Enter the database name (Can be from previous installation. Otherwise, should not exist): ", false, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync($"Enter the database {(isSqliteDB ? "file path" : "name")} (Can be from previous installation. Otherwise, should not exist): ", false, cancellationToken).ConfigureAwait(false);
+
string databaseName;
+ bool dbExists = false;
do
{
databaseName = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
if (!String.IsNullOrWhiteSpace(databaseName))
+ {
+ if (isSqliteDB)
+ {
+ dbExists = await ioManager.FileExists(databaseName, cancellationToken).ConfigureAwait(false);
+ if (!dbExists)
+ databaseName = await ValidateNonExistantSqliteDBName(databaseName, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false);
+ }
+
+ if (String.IsNullOrWhiteSpace(databaseName))
+ await console.WriteAsync("Invalid database name!", true, cancellationToken).ConfigureAwait(false);
+ else
break;
- await console.WriteAsync("Invalid database name!", true, cancellationToken).ConfigureAwait(false);
}
while (true);
- var dbExists = await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false);
-
bool useWinAuth;
if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer && platformIdentifier.IsWindows)
useWinAuth = await PromptYesNo("Use Windows Authentication? (y/n): ", cancellationToken).ConfigureAwait(false);
@@ -233,27 +386,28 @@ namespace Tgstation.Server.Host.Core
string username = null;
string password = null;
- if (!useWinAuth)
- {
- await console.WriteAsync("Enter username: ", false, cancellationToken).ConfigureAwait(false);
- username = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Enter password: ", false, cancellationToken).ConfigureAwait(false);
- password = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
- }
- else
- {
- await console.WriteAsync("IMPORTANT: If using the service runner, ensure this computer's LocalSystem account has CREATE DATABASE permissions on the target server!", true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("The account it uses in MSSQL is usually \"NT AUTHORITY\\SYSTEM\" and the role it needs is usually \"dbcreator\".", true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("We'll run a sanity test here, but it won't be indicative of the service's permissions if that is the case", true, cancellationToken).ConfigureAwait(false);
- }
+ if (!isSqliteDB)
+ if (!useWinAuth)
+ {
+ await console.WriteAsync("Enter username: ", false, cancellationToken).ConfigureAwait(false);
+ username = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("Enter password: ", false, cancellationToken).ConfigureAwait(false);
+ password = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ await console.WriteAsync("IMPORTANT: If using the service runner, ensure this computer's LocalSystem account has CREATE DATABASE permissions on the target server!", true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("The account it uses in MSSQL is usually \"NT AUTHORITY\\SYSTEM\" and the role it needs is usually \"dbcreator\".", true, cancellationToken).ConfigureAwait(false);
+ await console.WriteAsync("We'll run a sanity test here, but it won't be indicative of the service's permissions if that is the case", true, cancellationToken).ConfigureAwait(false);
+ }
await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
DbConnection testConnection;
- void CreateTestConnection(string connectionString)
- {
- testConnection = dbConnectionFactory.CreateConnection(connectionString, databaseConfiguration.DatabaseType);
- }
+ void CreateTestConnection(string connectionString) =>
+ testConnection = dbConnectionFactory.CreateConnection(
+ connectionString,
+ databaseConfiguration.DatabaseType);
if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer)
{
@@ -262,6 +416,7 @@ namespace Tgstation.Server.Host.Core
ApplicationName = application.VersionPrefix,
DataSource = serverAddress ?? "(local)"
};
+
if (useWinAuth)
csb.IntegratedSecurity = true;
else
@@ -274,8 +429,20 @@ namespace Tgstation.Server.Host.Core
csb.InitialCatalog = databaseName;
databaseConfiguration.ConnectionString = csb.ConnectionString;
}
+ else if(databaseConfiguration.DatabaseType == DatabaseType.Sqlite)
+ {
+ var csb = new SqliteConnectionStringBuilder
+ {
+ DataSource = databaseName,
+ Mode = dbExists ? SqliteOpenMode.ReadOnly : SqliteOpenMode.ReadWriteCreate
+ };
+
+ CreateTestConnection(csb.ConnectionString);
+ databaseConfiguration.ConnectionString = csb.ConnectionString;
+ }
else
{
+ // MySQL/MariaDB
var csb = new MySqlConnectionStringBuilder
{
Server = serverAddress ?? "127.0.0.1",
@@ -293,63 +460,7 @@ namespace Tgstation.Server.Host.Core
try
{
- using (testConnection)
- {
- await console.WriteAsync("Testing connection...", true, cancellationToken).ConfigureAwait(false);
- await testConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Connection successful!", true, cancellationToken).ConfigureAwait(false);
-
- if (databaseConfiguration.DatabaseType != DatabaseType.SqlServer)
- {
- await console.WriteAsync("Checking MySQL/MariaDB version...", true, cancellationToken).ConfigureAwait(false);
- using (var command = testConnection.CreateCommand())
- {
- command.CommandText = "SELECT VERSION()";
- var fullVersion = (string)await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
- await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Found {0}", fullVersion), true, cancellationToken).ConfigureAwait(false);
- var splits = fullVersion.Split('-');
- databaseConfiguration.MySqlServerVersion = splits[0];
- }
- }
-
- if (!dbExists)
- {
- await console.WriteAsync("Testing create DB permission...", true, cancellationToken).ConfigureAwait(false);
- using (var command = testConnection.CreateCommand())
- {
- // I really don't care about user sanitization here, they want to fuck their own DB? so be it
-#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
- command.CommandText = $"CREATE DATABASE {databaseName}";
-#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
- await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
- }
-
- await console.WriteAsync("Success!", true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Dropping test database...", true, cancellationToken).ConfigureAwait(false);
- using (var command = testConnection.CreateCommand())
- {
-#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
- command.CommandText = $"DROP DATABASE {databaseName}";
-#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
- try
- {
- await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception e)
- {
- await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("This should be okay, but you may want to manually drop the database before continuing!", true, cancellationToken).ConfigureAwait(false);
- await console.WriteAsync("Press any key to continue...", true, cancellationToken).ConfigureAwait(false);
- await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
- }
- }
- }
- }
+ await TestDatabaseConnection(testConnection, databaseConfiguration, databaseName, dbExists, cancellationToken).ConfigureAwait(false);
return databaseConfiguration;
}
diff --git a/src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs b/src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs
index 91ef82de8d..bc0f3f6963 100644
--- a/src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs
+++ b/src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs
@@ -1,7 +1,8 @@
-using MySql.Data.MySqlClient;
-using System;
+using System;
using System.Data.Common;
using System.Data.SqlClient;
+using Microsoft.Data.Sqlite;
+using MySql.Data.MySqlClient;
using Tgstation.Server.Host.Configuration;
namespace Tgstation.Server.Host.Database
@@ -28,6 +29,11 @@ namespace Tgstation.Server.Host.Database
{
ConnectionString = connectionString
};
+ case DatabaseType.Sqlite:
+ return new SqliteConnection
+ {
+ ConnectionString = connectionString
+ };
default:
throw new ArgumentOutOfRangeException(nameof(databaseType), databaseType, "Invalid DatabaseType!");
}
diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs
index 5be860c5a5..d435a228a8 100644
--- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs
+++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs
@@ -10,8 +10,8 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Configuration;
+using Tgstation.Server.Host.Database.Migrations;
using Tgstation.Server.Host.Models;
-using Tgstation.Server.Host.Models.Migrations;
namespace Tgstation.Server.Host.Database
{
@@ -78,6 +78,11 @@ namespace Tgstation.Server.Host.Database
///
protected DatabaseConfiguration DatabaseConfiguration { get; }
+ ///
+ /// Gets a value indicationg whether the MY_ class of migrations should be used instead of the MS_ class
+ ///
+ protected abstract DatabaseType DatabaseType { get; }
+
///
/// The for the
///
@@ -141,7 +146,7 @@ namespace Tgstation.Server.Host.Database
}
///
- public async Task Initialize(CancellationToken cancellationToken)
+ public virtual async Task Initialize(CancellationToken cancellationToken)
{
if (DatabaseConfiguration.DropDatabase)
{
@@ -177,12 +182,6 @@ namespace Tgstation.Server.Host.Database
///
public Task Save(CancellationToken cancellationToken) => SaveChangesAsync(cancellationToken);
- ///
- /// If the MY_ class of migrations should be used instead of the MS_ class
- ///
- /// if the MY_ class of migrations should be used instead of the MS_ class, otherwise
- protected abstract bool UseMySQLMigrations();
-
///
public async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
{
@@ -196,13 +195,52 @@ namespace Tgstation.Server.Host.Database
// Update this with new migrations as they are made
// Always use the MS class
if (version < new Version(4, 0, 2))
+ {
+ // Special handling because this is where SQLite was introduced
+ if (DatabaseType == DatabaseType.Sqlite)
+ throw new NotSupportedException("Cannot migrate below version 4.0.2.0 while using Sqlite!");
+
targetMigration = nameof(MSReattachCompileJobRequired);
+ }
+
+ // Uncomment once next migration/version step happens
+ /*
+ else if (version < new Version(V_NEXT_MIGRATION))
+ {
+ // Special handling because this is where SQLite was introduced
+ if (DatabaseType == DatabaseType.Sqlite)
+ targetMigration = nameof(SLAddSqlite);
+
+ targetMigration = nameof(V_NEXT_LAST_MIGRATION);
+ }
+ */
if (targetMigration == null)
+ {
+ Logger.LogDebug("No down migration required.");
return;
+ }
- if (UseMySQLMigrations())
- targetMigration = String.Format(CultureInfo.InvariantCulture, "MY{0}", targetMigration.Substring(2));
+ string migrationSubstitution;
+ switch (DatabaseType)
+ {
+ case DatabaseType.SqlServer:
+ // already setup
+ migrationSubstitution = null;
+ break;
+ case DatabaseType.MySql:
+ case DatabaseType.MariaDB:
+ migrationSubstitution = "MY{0}";
+ break;
+ case DatabaseType.Sqlite:
+ migrationSubstitution = "SL{0}";
+ break;
+ default:
+ throw new InvalidOperationException($"Invalid DatabaseType: {DatabaseType}");
+ }
+
+ if (migrationSubstitution != null)
+ targetMigration = String.Format(CultureInfo.InvariantCulture, migrationSubstitution, targetMigration.Substring(2));
// even though it clearly implements it in the DatabaseFacade definition this won't work without casting (╯ಠ益ಠ)╯︵ ┻━┻
var dbServiceProvider = ((IInfrastructure)Database).Instance;
diff --git a/src/Tgstation.Server.Host/Database/Design/MySqlDesignTimeDbContextFactory.cs b/src/Tgstation.Server.Host/Database/Design/MySqlDesignTimeDbContextFactory.cs
index 1a48bd319f..56e8711c3f 100644
--- a/src/Tgstation.Server.Host/Database/Design/MySqlDesignTimeDbContextFactory.cs
+++ b/src/Tgstation.Server.Host/Database/Design/MySqlDesignTimeDbContextFactory.cs
@@ -15,7 +15,13 @@ namespace Tgstation.Server.Host.Database.Design
{
using (var loggerFactory = new LoggerFactory())
{
- return new MySqlDatabaseContext(new DbContextOptions(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher())), loggerFactory.CreateLogger());
+ return new MySqlDatabaseContext(
+ new DbContextOptions(),
+ DesignTimeDbContextFactoryHelpers.GetDbContextOptions(),
+ new DatabaseSeeder(
+ new CryptographySuite(
+ new PasswordHasher())),
+ loggerFactory.CreateLogger());
}
}
}
diff --git a/src/Tgstation.Server.Host/Database/Design/SqlServerDesignTimeDbContextFactory.cs b/src/Tgstation.Server.Host/Database/Design/SqlServerDesignTimeDbContextFactory.cs
index a935229be5..93eb51084f 100644
--- a/src/Tgstation.Server.Host/Database/Design/SqlServerDesignTimeDbContextFactory.cs
+++ b/src/Tgstation.Server.Host/Database/Design/SqlServerDesignTimeDbContextFactory.cs
@@ -15,7 +15,13 @@ namespace Tgstation.Server.Host.Database.Design
{
using (var loggerFactory = new LoggerFactory())
{
- return new SqlServerDatabaseContext(new DbContextOptions(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher())), loggerFactory.CreateLogger());
+ return new SqlServerDatabaseContext(
+ new DbContextOptions(),
+ DesignTimeDbContextFactoryHelpers.GetDbContextOptions(),
+ new DatabaseSeeder(
+ new CryptographySuite(
+ new PasswordHasher())),
+ loggerFactory.CreateLogger());
}
}
}
diff --git a/src/Tgstation.Server.Host/Database/Design/SqliteDesignTimeDbContextFactory.cs b/src/Tgstation.Server.Host/Database/Design/SqliteDesignTimeDbContextFactory.cs
new file mode 100644
index 0000000000..501e344bbf
--- /dev/null
+++ b/src/Tgstation.Server.Host/Database/Design/SqliteDesignTimeDbContextFactory.cs
@@ -0,0 +1,28 @@
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Logging;
+using Tgstation.Server.Host.Models;
+using Tgstation.Server.Host.Security;
+
+namespace Tgstation.Server.Host.Database.Design
+{
+ ///
+ sealed class SqliteDesignTimeDbContextFactory : IDesignTimeDbContextFactory
+ {
+ ///
+ public SqliteDatabaseContext CreateDbContext(string[] args)
+ {
+ using (var loggerFactory = new LoggerFactory())
+ {
+ return new SqliteDatabaseContext(
+ new DbContextOptions(),
+ DesignTimeDbContextFactoryHelpers.GetDbContextOptions(),
+ new DatabaseSeeder(
+ new CryptographySuite(
+ new PasswordHasher())),
+ loggerFactory.CreateLogger());
+ }
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.Designer.cs
index f5a3868f47..10c4f58ecc 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20180906135553_MSInitialCreate")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.cs b/src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.cs
index cb61dfd5cc..59917ec1f9 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180906135553_MSInitialCreate.cs
@@ -2,7 +2,7 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// The initial database migration for MSSQL
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.Designer.cs
index fe68368e68..feba7cd191 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180906143029_MYInitialCreate")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.cs b/src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.cs
index 7ceb691436..70372d9875 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180906143029_MYInitialCreate.cs
@@ -2,7 +2,7 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// The initial database migration for MySQL/MariaDB
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs
index dad97d04a0..c911e19dbb 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180918020726_MYAddMinimumSecurity")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.cs
similarity index 96%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.cs
index d2d3149416..638da950cd 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918020726_MYAddMinimumSecurity.cs
@@ -2,7 +2,7 @@
using System;
using Tgstation.Server.Api.Models;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Add the and columns for MySQL/MariaDB
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs
index 7fd4819b71..f984fad66b 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20180918021228_MSAddMinimumSecurity")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.cs
similarity index 96%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.cs
index 67abc2ea84..dbf9ebf569 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918021228_MSAddMinimumSecurity.cs
@@ -2,7 +2,7 @@
using System;
using Tgstation.Server.Api.Models;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Add the and columns for MSSQL
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs
index bd1692cd78..d28f3b4abf 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180918204520_MYNullableAndForeignKeyCleanup")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs
index 2bb9547f3e..b112f3e8f4 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs
@@ -1,7 +1,7 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Cleans up of nullable columns and foreign keys MySQL/MariaDB
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs
index 41e7cd3d22..0570b534ac 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20180918205224_MSNullableAndForeignKeyCleanup")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs b/src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs
index ec767c8e53..b479d8d1a0 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs
@@ -1,7 +1,7 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Cleans up of nullable columns and foreign keys MSSQL
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs
index bb8f71f024..b1248ea1d7 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20180926033145_MSReattachCompileJobRequired")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs
similarity index 91%
rename from src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs
index 8bed2d3671..ca56d5d418 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs
@@ -1,10 +1,10 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
- /// Marks the s of s as non-nullable for MSSQL
+ /// Marks the s of s as non-nullable for MSSQL
///
public partial class MSReattachCompileJobRequired : Migration
{
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs
index 2428009bdc..48a5b58de1 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20180926034014_MYReattachCompileJobRequired")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs
similarity index 91%
rename from src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs
index b51167b1a3..d13c3e7424 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs
@@ -1,10 +1,10 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
- /// Marks the s of s as non-nullable for MySQL/MariaDB
+ /// Marks the s of s as non-nullable for MySQL/MariaDB
///
public partial class MYReattachCompileJobRequired : Migration
{
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs
index e6d62e22c9..b63192e549 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20181124231534_MSToggleTestmergeComments")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.cs b/src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.cs
similarity index 95%
rename from src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.cs
index 8ec93a1f6b..acf6794a78 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20181124231534_MSToggleTestmergeComments.cs
@@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Add the column for MSSQL
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs
index 50d60eb5db..bb82a0eaee 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20181124231549_MYToggleTestmergeComments")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.cs b/src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.cs
similarity index 95%
rename from src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.cs
index dddde6535d..f4b64ac8ba 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20181124231549_MYToggleTestmergeComments.cs
@@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Add the column for MySQL/MariaDB
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs
index 0097146a76..7168c949a0 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs
@@ -5,9 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(SqlServerDatabaseContext))]
[Migration("20190219041825_MSFixRevInfoIndex")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.cs b/src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.cs
similarity index 97%
rename from src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.cs
index 622f0cc147..04ef31f946 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20190219041825_MSFixRevInfoIndex.cs
@@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Make commit shas non-unique per Instance for MSSQL
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs
similarity index 99%
rename from src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs
index e037584904..1977187143 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs
@@ -3,9 +3,8 @@ using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
-using Tgstation.Server.Host.Database;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
[DbContext(typeof(MySqlDatabaseContext))]
[Migration("20190219042440_MYFixRevInfoIndex")]
diff --git a/src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.cs b/src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.cs
similarity index 97%
rename from src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.cs
rename to src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.cs
index a76290268a..7161e0d1ba 100644
--- a/src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.cs
+++ b/src/Tgstation.Server.Host/Database/Migrations/20190219042440_MYFixRevInfoIndex.cs
@@ -1,7 +1,7 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
-namespace Tgstation.Server.Host.Models.Migrations
+namespace Tgstation.Server.Host.Database.Migrations
{
///
/// Make commit shas non-unique per Instance for MSSQL
diff --git a/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.Designer.cs b/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.Designer.cs
new file mode 100644
index 0000000000..e624e85408
--- /dev/null
+++ b/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.Designer.cs
@@ -0,0 +1,653 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Tgstation.Server.Host.Database.Migrations
+{
+ [DbContext(typeof(SqliteDatabaseContext))]
+ [Migration("20200322210825_SLAddSqlite")]
+ partial class SLAddSqlite
+ {
+ ///
+ /// Builds the target model
+ ///
+ /// The to use
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ConnectionString")
+ .IsRequired();
+
+ b.Property("Enabled");
+
+ b.Property("InstanceId");
+
+ b.Property("Name")
+ .IsRequired();
+
+ b.Property("Provider");
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("ChatBots");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ChatSettingsId");
+
+ b.Property("DiscordChannelId");
+
+ b.Property("IrcChannel");
+
+ b.Property("IsAdminChannel")
+ .IsRequired();
+
+ b.Property("IsUpdatesChannel")
+ .IsRequired();
+
+ b.Property("IsWatchdogChannel")
+ .IsRequired();
+
+ b.Property("Tag");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ChatSettingsId", "DiscordChannelId")
+ .IsUnique();
+
+ b.HasIndex("ChatSettingsId", "IrcChannel")
+ .IsUnique();
+
+ b.ToTable("ChatChannels");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ByondVersion")
+ .IsRequired();
+
+ b.Property("DirectoryName")
+ .IsRequired();
+
+ b.Property("DmeName")
+ .IsRequired();
+
+ b.Property("JobId");
+
+ b.Property("MinimumSecurityLevel");
+
+ b.Property("Output")
+ .IsRequired();
+
+ b.Property("RevisionInformationId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DirectoryName");
+
+ b.HasIndex("JobId")
+ .IsUnique();
+
+ b.HasIndex("RevisionInformationId");
+
+ b.ToTable("CompileJobs");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessToken");
+
+ b.Property("AllowWebClient")
+ .IsRequired();
+
+ b.Property("AutoStart")
+ .IsRequired();
+
+ b.Property("InstanceId");
+
+ b.Property("PrimaryPort")
+ .IsRequired();
+
+ b.Property("ProcessId");
+
+ b.Property("SecondaryPort")
+ .IsRequired();
+
+ b.Property("SecurityLevel");
+
+ b.Property("SoftRestart")
+ .IsRequired();
+
+ b.Property("SoftShutdown")
+ .IsRequired();
+
+ b.Property("StartupTimeout")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId")
+ .IsUnique();
+
+ b.ToTable("DreamDaemonSettings");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ApiValidationPort")
+ .IsRequired();
+
+ b.Property("ApiValidationSecurityLevel");
+
+ b.Property("InstanceId");
+
+ b.Property("ProjectName");
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId")
+ .IsUnique();
+
+ b.ToTable("DreamMakerSettings");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AutoUpdateInterval")
+ .IsRequired();
+
+ b.Property("ConfigurationType");
+
+ b.Property("Name")
+ .IsRequired();
+
+ b.Property("Online")
+ .IsRequired();
+
+ b.Property("Path")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("Path")
+ .IsUnique();
+
+ b.ToTable("Instances");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("ByondRights");
+
+ b.Property("ChatBotRights");
+
+ b.Property("ConfigurationRights");
+
+ b.Property("DreamDaemonRights");
+
+ b.Property("DreamMakerRights");
+
+ b.Property("InstanceId");
+
+ b.Property("InstanceUserRights");
+
+ b.Property("RepositoryRights");
+
+ b.Property("UserId")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId");
+
+ b.HasIndex("UserId", "InstanceId")
+ .IsUnique();
+
+ b.ToTable("InstanceUsers");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("CancelRight");
+
+ b.Property("CancelRightsType");
+
+ b.Property("Cancelled")
+ .IsRequired();
+
+ b.Property("CancelledById");
+
+ b.Property("Description")
+ .IsRequired();
+
+ b.Property("ExceptionDetails");
+
+ b.Property("InstanceId");
+
+ b.Property("StartedAt")
+ .IsRequired();
+
+ b.Property("StartedById");
+
+ b.Property("StoppedAt");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CancelledById");
+
+ b.HasIndex("InstanceId");
+
+ b.HasIndex("StartedById");
+
+ b.ToTable("Jobs");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessIdentifier")
+ .IsRequired();
+
+ b.Property("ChatChannelsJson")
+ .IsRequired();
+
+ b.Property("ChatCommandsJson")
+ .IsRequired();
+
+ b.Property("CompileJobId");
+
+ b.Property("IsPrimary");
+
+ b.Property("Port");
+
+ b.Property("ProcessId");
+
+ b.Property("RebootState");
+
+ b.Property("ServerCommandsJson")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("CompileJobId");
+
+ b.ToTable("ReattachInformations");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AccessToken");
+
+ b.Property("AccessUser");
+
+ b.Property("AutoUpdatesKeepTestMerges")
+ .IsRequired();
+
+ b.Property("AutoUpdatesSynchronize")
+ .IsRequired();
+
+ b.Property("CommitterEmail")
+ .IsRequired();
+
+ b.Property("CommitterName")
+ .IsRequired();
+
+ b.Property("InstanceId");
+
+ b.Property("PostTestMergeComment")
+ .IsRequired();
+
+ b.Property("PushTestMergeCommits")
+ .IsRequired();
+
+ b.Property("ShowTestMergeCommitters")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId")
+ .IsUnique();
+
+ b.ToTable("RepositorySettings");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("RevisionInformationId");
+
+ b.Property("TestMergeId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RevisionInformationId");
+
+ b.HasIndex("TestMergeId");
+
+ b.ToTable("RevInfoTestMerges");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("CommitSha")
+ .IsRequired()
+ .HasMaxLength(40);
+
+ b.Property("InstanceId");
+
+ b.Property("OriginCommitSha")
+ .IsRequired()
+ .HasMaxLength(40);
+
+ b.HasKey("Id");
+
+ b.HasIndex("InstanceId", "CommitSha")
+ .IsUnique();
+
+ b.ToTable("RevisionInformations");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("Author")
+ .IsRequired();
+
+ b.Property("BodyAtMerge")
+ .IsRequired();
+
+ b.Property("Comment");
+
+ b.Property("MergedAt");
+
+ b.Property("MergedById");
+
+ b.Property("Number")
+ .IsRequired();
+
+ b.Property("PrimaryRevisionInformationId")
+ .IsRequired();
+
+ b.Property("PullRequestRevision")
+ .IsRequired();
+
+ b.Property("TitleAtMerge")
+ .IsRequired();
+
+ b.Property("Url")
+ .IsRequired();
+
+ b.HasKey("Id");
+
+ b.HasIndex("MergedById");
+
+ b.HasIndex("PrimaryRevisionInformationId")
+ .IsUnique();
+
+ b.ToTable("TestMerges");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AdministrationRights");
+
+ b.Property("CanonicalName")
+ .IsRequired();
+
+ b.Property("CreatedAt")
+ .IsRequired();
+
+ b.Property("CreatedById");
+
+ b.Property("Enabled")
+ .IsRequired();
+
+ b.Property("InstanceManagerRights");
+
+ b.Property("LastPasswordUpdate");
+
+ b.Property("Name")
+ .IsRequired();
+
+ b.Property("PasswordHash");
+
+ b.Property("SystemIdentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("CanonicalName")
+ .IsUnique();
+
+ b.HasIndex("CreatedById");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd();
+
+ b.Property("AlphaId");
+
+ b.Property("AlphaIsActive");
+
+ b.Property("BravoId");
+
+ b.Property("InstanceId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AlphaId");
+
+ b.HasIndex("BravoId");
+
+ b.HasIndex("InstanceId")
+ .IsUnique();
+
+ b.ToTable("WatchdogReattachInformations");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithMany("ChatSettings")
+ .HasForeignKey("InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
+ .WithMany("Channels")
+ .HasForeignKey("ChatSettingsId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
+ .WithOne()
+ .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
+ .WithMany("CompileJobs")
+ .HasForeignKey("RevisionInformationId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithOne("DreamDaemonSettings")
+ .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithOne("DreamMakerSettings")
+ .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithMany("InstanceUsers")
+ .HasForeignKey("InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("Tgstation.Server.Host.Models.User")
+ .WithMany("InstanceUsers")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
+ .WithMany()
+ .HasForeignKey("CancelledById");
+
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithMany("Jobs")
+ .HasForeignKey("InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
+ .WithMany()
+ .HasForeignKey("StartedById")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
+ .WithMany()
+ .HasForeignKey("CompileJobId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithOne("RepositorySettings")
+ .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
+ .WithMany("ActiveTestMerges")
+ .HasForeignKey("RevisionInformationId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
+ .WithMany("RevisonInformations")
+ .HasForeignKey("TestMergeId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
+ .WithMany("RevisionInformations")
+ .HasForeignKey("InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
+ .WithMany("TestMerges")
+ .HasForeignKey("MergedById")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
+ .WithOne("PrimaryTestMerge")
+ .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
+ .OnDelete(DeleteBehavior.Restrict);
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
+ .WithMany("CreatedUsers")
+ .HasForeignKey("CreatedById");
+ });
+
+ modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
+ {
+ b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
+ .WithMany()
+ .HasForeignKey("AlphaId");
+
+ b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
+ .WithMany()
+ .HasForeignKey("BravoId");
+
+ b.HasOne("Tgstation.Server.Host.Models.Instance")
+ .WithOne("WatchdogReattachInformation")
+ .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.cs b/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.cs
new file mode 100644
index 0000000000..99872e864c
--- /dev/null
+++ b/src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.cs
@@ -0,0 +1,639 @@
+// Suppress the too much class coupling warning
+#pragma warning disable CA1506
+
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Tgstation.Server.Host.Database.Migrations
+{
+ ///
+ /// Initial migration for SQLite.
+ ///
+ public partial class SLAddSqlite : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ if (migrationBuilder == null)
+ throw new ArgumentNullException(nameof(migrationBuilder));
+
+ migrationBuilder.CreateTable(
+ name: "Instances",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Name = table.Column(nullable: false),
+ Path = table.Column(nullable: false),
+ Online = table.Column(nullable: false),
+ ConfigurationType = table.Column(nullable: false),
+ AutoUpdateInterval = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Instances", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Enabled = table.Column(nullable: false),
+ CreatedAt = table.Column(nullable: false),
+ SystemIdentifier = table.Column(nullable: true),
+ Name = table.Column(nullable: false),
+ AdministrationRights = table.Column(nullable: false),
+ InstanceManagerRights = table.Column(nullable: false),
+ PasswordHash = table.Column(nullable: true),
+ CreatedById = table.Column(nullable: true),
+ CanonicalName = table.Column(nullable: false),
+ LastPasswordUpdate = table.Column(nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Users_Users_CreatedById",
+ column: x => x.CreatedById,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ChatBots",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Name = table.Column(nullable: false),
+ Enabled = table.Column(nullable: true),
+ Provider = table.Column(nullable: true),
+ ConnectionString = table.Column(nullable: false),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ChatBots", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ChatBots_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "DreamDaemonSettings",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ AllowWebClient = table.Column(nullable: false),
+ SecurityLevel = table.Column(nullable: false),
+ PrimaryPort = table.Column(nullable: false),
+ SecondaryPort = table.Column(nullable: false),
+ StartupTimeout = table.Column(nullable: false),
+ AutoStart = table.Column(nullable: false),
+ SoftRestart = table.Column(nullable: false),
+ SoftShutdown = table.Column(nullable: false),
+ ProcessId = table.Column(nullable: true),
+ AccessToken = table.Column(nullable: true),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id);
+ table.ForeignKey(
+ name: "FK_DreamDaemonSettings_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "DreamMakerSettings",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ ProjectName = table.Column(nullable: true),
+ ApiValidationPort = table.Column(nullable: false),
+ ApiValidationSecurityLevel = table.Column(nullable: false),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_DreamMakerSettings", x => x.Id);
+ table.ForeignKey(
+ name: "FK_DreamMakerSettings_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "RepositorySettings",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ CommitterName = table.Column(nullable: false),
+ CommitterEmail = table.Column(nullable: false),
+ AccessUser = table.Column(nullable: true),
+ AccessToken = table.Column(nullable: true),
+ PushTestMergeCommits = table.Column(nullable: false),
+ ShowTestMergeCommitters = table.Column(nullable: false),
+ AutoUpdatesKeepTestMerges = table.Column(nullable: false),
+ AutoUpdatesSynchronize = table.Column(nullable: false),
+ PostTestMergeComment = table.Column(nullable: false),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_RepositorySettings", x => x.Id);
+ table.ForeignKey(
+ name: "FK_RepositorySettings_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "RevisionInformations",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ CommitSha = table.Column(maxLength: 40, nullable: false),
+ OriginCommitSha = table.Column(maxLength: 40, nullable: false),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_RevisionInformations", x => x.Id);
+ table.ForeignKey(
+ name: "FK_RevisionInformations_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "InstanceUsers",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ UserId = table.Column(nullable: false),
+ InstanceUserRights = table.Column(nullable: false),
+ ByondRights = table.Column(nullable: false),
+ DreamDaemonRights = table.Column(nullable: false),
+ DreamMakerRights = table.Column(nullable: false),
+ RepositoryRights = table.Column(nullable: false),
+ ChatBotRights = table.Column(nullable: false),
+ ConfigurationRights = table.Column(nullable: false),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_InstanceUsers", x => x.Id);
+ table.ForeignKey(
+ name: "FK_InstanceUsers_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_InstanceUsers_Users_UserId",
+ column: x => x.UserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Jobs",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Description = table.Column(nullable: false),
+ ExceptionDetails = table.Column(nullable: true),
+ StartedAt = table.Column(nullable: false),
+ StoppedAt = table.Column(nullable: true),
+ Cancelled = table.Column(nullable: false),
+ CancelRightsType = table.Column(nullable: true),
+ CancelRight = table.Column(nullable: true),
+ StartedById = table.Column(nullable: false),
+ CancelledById = table.Column(nullable: true),
+ InstanceId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Jobs", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Jobs_Users_CancelledById",
+ column: x => x.CancelledById,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Restrict);
+ table.ForeignKey(
+ name: "FK_Jobs_Instances_InstanceId",
+ column: x => x.InstanceId,
+ principalTable: "Instances",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_Jobs_Users_StartedById",
+ column: x => x.StartedById,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ChatChannels",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ IrcChannel = table.Column(nullable: true),
+ DiscordChannelId = table.Column(nullable: true),
+ IsAdminChannel = table.Column(nullable: false),
+ IsWatchdogChannel = table.Column(nullable: false),
+ IsUpdatesChannel = table.Column(nullable: false),
+ Tag = table.Column(nullable: true),
+ ChatSettingsId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ChatChannels", x => x.Id);
+ table.ForeignKey(
+ name: "FK_ChatChannels_ChatBots_ChatSettingsId",
+ column: x => x.ChatSettingsId,
+ principalTable: "ChatBots",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "TestMerges",
+ columns: table => new
+ {
+ Id = table.Column(nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ Number = table.Column(nullable: false),
+ PullRequestRevision = table.Column(nullable: false),
+ Comment = table.Column(nullable: true),
+ TitleAtMerge = table.Column(nullable: false),
+ BodyAtMerge = table.Column