From 01af82092563cbbd1f09fb73fd987eec290e89a0 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 15:24:16 -0400 Subject: [PATCH 01/16] Change UseMySQLMigrations into a property --- .../Database/DatabaseContext.cs | 13 ++++++------- .../Database/MySqlDatabaseContext.cs | 6 +++--- .../Database/SqlServerDatabaseContext.cs | 6 +++--- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index 5be860c5a5..eff5c5df95 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs @@ -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 bool UseMySQLMigrations { get; } + /// /// The for the /// @@ -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) { @@ -201,7 +200,7 @@ namespace Tgstation.Server.Host.Database if (targetMigration == null) return; - if (UseMySQLMigrations()) + if (UseMySQLMigrations) targetMigration = String.Format(CultureInfo.InvariantCulture, "MY{0}", targetMigration.Substring(2)); // even though it clearly implements it in the DatabaseFacade definition this won't work without casting (╯ಠ益ಠ)╯︵ ┻━┻ diff --git a/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs index 593aa93519..b061b0e362 100644 --- a/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs @@ -13,6 +13,9 @@ namespace Tgstation.Server.Host.Database /// sealed class MySqlDatabaseContext : DatabaseContext { + /// + protected override bool UseMySQLMigrations => false; + /// /// Construct a /// @@ -38,8 +41,5 @@ namespace Tgstation.Server.Host.Database else options.UseMySql(DatabaseConfiguration.ConnectionString); } - - /// - protected override bool UseMySQLMigrations() => true; } } diff --git a/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs b/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs index 0acda9944f..caf7d334a5 100644 --- a/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs @@ -10,6 +10,9 @@ namespace Tgstation.Server.Host.Database /// sealed class SqlServerDatabaseContext : DatabaseContext { + /// + protected override bool UseMySQLMigrations => false; + /// /// Construct a /// @@ -26,8 +29,5 @@ namespace Tgstation.Server.Host.Database base.OnConfiguring(options); options.UseSqlServer(DatabaseConfiguration.ConnectionString); } - - /// - protected override bool UseMySQLMigrations() => false; } } From 57302910176fd958fbf079991292be499ad2b804 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 15:47:09 -0400 Subject: [PATCH 02/16] Use DatabaseType instead of UseMySQLMigrations --- .../Database/DatabaseContext.cs | 24 ++++++++++++++++--- .../Database/MySqlDatabaseContext.cs | 2 +- .../Database/SqlServerDatabaseContext.cs | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index eff5c5df95..3ddc95a149 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs @@ -81,7 +81,7 @@ namespace Tgstation.Server.Host.Database /// /// Gets a value indicationg whether the MY_ class of migrations should be used instead of the MS_ class /// - protected abstract bool UseMySQLMigrations { get; } + protected abstract DatabaseType DatabaseType { get; } /// /// The for the @@ -198,10 +198,28 @@ namespace Tgstation.Server.Host.Database targetMigration = nameof(MSReattachCompileJobRequired); 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; + 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/MySqlDatabaseContext.cs b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs index b061b0e362..5d3cd56796 100644 --- a/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs @@ -14,7 +14,7 @@ namespace Tgstation.Server.Host.Database sealed class MySqlDatabaseContext : DatabaseContext { /// - protected override bool UseMySQLMigrations => false; + protected override DatabaseType DatabaseType => DatabaseType.MySql; /// /// Construct a diff --git a/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs b/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs index caf7d334a5..5a01e4a742 100644 --- a/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/SqlServerDatabaseContext.cs @@ -11,7 +11,7 @@ namespace Tgstation.Server.Host.Database sealed class SqlServerDatabaseContext : DatabaseContext { /// - protected override bool UseMySQLMigrations => false; + protected override DatabaseType DatabaseType => DatabaseType.SqlServer; /// /// Construct a From 2c64c01bf811ca42bb68d48ac54f12664ad860f6 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 15:58:20 -0400 Subject: [PATCH 03/16] Minor indentation cleanup --- .../Database/MySqlDatabaseContext.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs index 5d3cd56796..b8f7f227fe 100644 --- a/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs @@ -37,7 +37,13 @@ namespace Tgstation.Server.Host.Database if (stringDeconstructor.Server == "localhost") Logger.LogWarning("MariaDB/MySQL server address is set to 'localhost'! If there are connection issues, try setting it to '127.0.0.1'!"); if (!String.IsNullOrEmpty(DatabaseConfiguration.MySqlServerVersion)) - options.UseMySql(DatabaseConfiguration.ConnectionString, mySqlOptions => mySqlOptions.ServerVersion(Version.Parse(DatabaseConfiguration.MySqlServerVersion), DatabaseConfiguration.DatabaseType == DatabaseType.MariaDB ? ServerType.MariaDb : ServerType.MySql)); + options.UseMySql( + DatabaseConfiguration.ConnectionString, + mySqlOptions => mySqlOptions.ServerVersion( + Version.Parse(DatabaseConfiguration.MySqlServerVersion), + DatabaseConfiguration.DatabaseType == DatabaseType.MariaDB + ? ServerType.MariaDb + : ServerType.MySql)); else options.UseMySql(DatabaseConfiguration.ConnectionString); } From e352741a8b64260dd74e1ab5424f1265c44cc606 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 16:58:38 -0400 Subject: [PATCH 04/16] Add SQLite connection support (no migrations) --- .../Configuration/DatabaseType.cs | 7 +++- src/Tgstation.Server.Host/Core/Application.cs | 3 ++ .../Database/DatabaseConnectionFactory.cs | 10 ++++-- .../Database/SqliteDatabaseContext.cs | 33 +++++++++++++++++++ .../Tgstation.Server.Host.csproj | 1 + 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs 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/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/SqliteDatabaseContext.cs b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs new file mode 100644 index 0000000000..9bb91a9792 --- /dev/null +++ b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tgstation.Server.Host.Configuration; + +namespace Tgstation.Server.Host.Database +{ + /// + /// for MySQL + /// + sealed class SqliteDatabaseContext : DatabaseContext + { + /// + protected override DatabaseType DatabaseType => DatabaseType.Sqlite; + + /// + /// Construct a + /// + /// The for the + /// The of for the + /// The for the + /// The for the + public SqliteDatabaseContext(DbContextOptions dbContextOptions, IOptions databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger) + { } + + /// + protected override void OnConfiguring(DbContextOptionsBuilder options) + { + base.OnConfiguring(options); + options.UseSqlite(DatabaseConfiguration.ConnectionString); + } + } +} diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj index 9e18ee3f8c..f60e60ba95 100644 --- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj +++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj @@ -58,6 +58,7 @@ + all From e13e66b161fe2f39584637951b7eea48c25638ae Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 16:59:01 -0400 Subject: [PATCH 05/16] Make default DB SQLite --- .gitignore | 1 + src/Tgstation.Server.Host/appsettings.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) 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/src/Tgstation.Server.Host/appsettings.json b/src/Tgstation.Server.Host/appsettings.json index 7f9191b101..082bb766fe 100644 --- a/src/Tgstation.Server.Host/appsettings.json +++ b/src/Tgstation.Server.Host/appsettings.json @@ -9,7 +9,7 @@ "UseBasicWatchdogOnWindows": false }, "FileLogging": { - "Directory": null, //use the default path + "Directory": null, "Disable": false, "LogLevel": "Debug", "MicrosoftLogLevel": "Warning" @@ -48,9 +48,9 @@ }, "Database": { "DropDatabase": false, - "DatabaseType": "SqlServer", + "DatabaseType": "Sqlite", "ResetAdminPassword": false, "MySqlServerVersion": null, - "ConnectionString": "Data Source=(local);Initial Catalog=TGS;Integrated Security=True" + "ConnectionString": "Data Source=LocalTestDB.sqlite3;Mode=ReadWriteCreate" } } From 49b740b4b67ffddf71a30d55986dbc396cd50a3f Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 16:59:21 -0400 Subject: [PATCH 06/16] Add SQLite Setup Wizard support --- src/Tgstation.Server.Host/Core/SetupWizard.cs | 315 ++++++++++++------ 1 file changed, 212 insertions(+), 103 deletions(-) diff --git a/src/Tgstation.Server.Host/Core/SetupWizard.cs b/src/Tgstation.Server.Host/Core/SetupWizard.cs index d685044ec7..6fa087c27a 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,129 @@ 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; + } + /// /// Prompts the user to create a /// @@ -163,7 +288,17 @@ namespace Tgstation.Server.Host.Core var databaseConfiguration = new DatabaseConfiguration(); do { - 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); + await console.WriteAsync( + String.Format( + CultureInfo.InvariantCulture, + "Please enter one of {0}, {1}, {2}, or {3}: ", + DatabaseType.Sqlite, + 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)) { @@ -177,52 +312,68 @@ namespace Tgstation.Server.Host.Core string serverAddress; 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) + serverAddress = null; + else + 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)) { - serverAddress = m.Groups["server"].Value; - if (uint.TryParse(m.Groups["port"].Value, out uint port)) + serverAddress = null; + break; + } + else if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer) + { + var m = Regex.Match(serverAddress, @"^(?.+):(?.+)$"); + if (m.Success) { - mySQLServerPort = port; - break; - } - else - { - await console.WriteAsync($@"Failed to parse port ""{m.Groups["port"].Value}"", please try again.", true, cancellationToken).ConfigureAwait(false); + serverAddress = m.Groups["server"].Value; + if (uint.TryParse(m.Groups["port"].Value, out uint port)) + { + mySQLServerPort = port; + break; + } + else + { + await console.WriteAsync($@"Failed to parse port ""{m.Groups["port"].Value}"", please try again.", true, cancellationToken).ConfigureAwait(false); + } } + else break; } else 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)) + { + dbExists = isSqliteDB + ? await ioManager.FileExists(databaseName, cancellationToken).ConfigureAwait(false) + : await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false); + + if (!dbExists && isSqliteDB) + databaseName = await ValidateNonExistantSqliteDBName(databaseName, 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 +384,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 +414,7 @@ namespace Tgstation.Server.Host.Core ApplicationName = application.VersionPrefix, DataSource = serverAddress ?? "(local)" }; + if (useWinAuth) csb.IntegratedSecurity = true; else @@ -274,8 +427,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 +458,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; } From 49bf4463abc55c945536a34ffaad0d01c67cf691 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:03:58 -0400 Subject: [PATCH 07/16] Rename Models.Migrations -> Database.Migrations --- appveyor.yml | 4 ++-- build/test_core.sh | 4 ++-- src/Tgstation.Server.Host/Database/DatabaseContext.cs | 2 +- .../Migrations/20180906135553_MSInitialCreate.Designer.cs | 3 +-- .../Migrations/20180906135553_MSInitialCreate.cs | 2 +- .../Migrations/20180906143029_MYInitialCreate.Designer.cs | 3 +-- .../Migrations/20180906143029_MYInitialCreate.cs | 2 +- .../20180918020726_MYAddMinimumSecurity.Designer.cs | 3 +-- .../Migrations/20180918020726_MYAddMinimumSecurity.cs | 2 +- .../20180918021228_MSAddMinimumSecurity.Designer.cs | 3 +-- .../Migrations/20180918021228_MSAddMinimumSecurity.cs | 2 +- .../20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs | 3 +-- .../20180918204520_MYNullableAndForeignKeyCleanup.cs | 2 +- .../20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs | 3 +-- .../20180918205224_MSNullableAndForeignKeyCleanup.cs | 2 +- .../20180926033145_MSReattachCompileJobRequired.Designer.cs | 3 +-- .../Migrations/20180926033145_MSReattachCompileJobRequired.cs | 2 +- .../20180926034014_MYReattachCompileJobRequired.Designer.cs | 3 +-- .../Migrations/20180926034014_MYReattachCompileJobRequired.cs | 2 +- .../20181124231534_MSToggleTestmergeComments.Designer.cs | 3 +-- .../Migrations/20181124231534_MSToggleTestmergeComments.cs | 2 +- .../20181124231549_MYToggleTestmergeComments.Designer.cs | 3 +-- .../Migrations/20181124231549_MYToggleTestmergeComments.cs | 2 +- .../Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs | 3 +-- .../Migrations/20190219041825_MSFixRevInfoIndex.cs | 2 +- .../Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs | 3 +-- .../Migrations/20190219042440_MYFixRevInfoIndex.cs | 2 +- .../Migrations/MySqlDatabaseContextModelSnapshot.cs | 2 +- .../Migrations/SqlServerDatabaseContextModelSnapshot.cs | 2 +- 29 files changed, 31 insertions(+), 43 deletions(-) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180906135553_MSInitialCreate.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180906135553_MSInitialCreate.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180906143029_MYInitialCreate.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180906143029_MYInitialCreate.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918020726_MYAddMinimumSecurity.cs (96%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918021228_MSAddMinimumSecurity.cs (96%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180926033145_MSReattachCompileJobRequired.cs (97%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20180926034014_MYReattachCompileJobRequired.cs (97%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20181124231534_MSToggleTestmergeComments.cs (95%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20181124231549_MYToggleTestmergeComments.cs (95%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20190219041825_MSFixRevInfoIndex.cs (97%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/20190219042440_MYFixRevInfoIndex.cs (97%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/MySqlDatabaseContextModelSnapshot.cs (99%) rename src/Tgstation.Server.Host/{Models => Database}/Migrations/SqlServerDatabaseContextModelSnapshot.cs (99%) 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..34952fd4c4 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,7 @@ 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/server.xml" --include "[Tgstation.Server*]*" --exclude "[Tgstation.Server.Tests*]*" --exclude "[Tgstation.Server.Host]Tgstation.Server.Host.Database.Migrations.*" cd ../../TestResults diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index 3ddc95a149..b247660562 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 { 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 97% rename from src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs rename to src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs index 8bed2d3671..ecdc8b8ddc 100644 --- a/src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs @@ -1,7 +1,7 @@ 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 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 97% rename from src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs rename to src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs index b51167b1a3..014e3c0449 100644 --- a/src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs @@ -1,7 +1,7 @@ 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 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/Models/Migrations/MySqlDatabaseContextModelSnapshot.cs b/src/Tgstation.Server.Host/Database/Migrations/MySqlDatabaseContextModelSnapshot.cs similarity index 99% rename from src/Tgstation.Server.Host/Models/Migrations/MySqlDatabaseContextModelSnapshot.cs rename to src/Tgstation.Server.Host/Database/Migrations/MySqlDatabaseContextModelSnapshot.cs index 47d90d047d..5eff19e243 100644 --- a/src/Tgstation.Server.Host/Models/Migrations/MySqlDatabaseContextModelSnapshot.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/MySqlDatabaseContextModelSnapshot.cs @@ -4,7 +4,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Tgstation.Server.Host.Database; -namespace Tgstation.Server.Host.Models.Migrations +namespace Tgstation.Server.Host.Database.Migrations { [DbContext(typeof(MySqlDatabaseContext))] partial class MySqlDatabaseContextModelSnapshot : ModelSnapshot diff --git a/src/Tgstation.Server.Host/Models/Migrations/SqlServerDatabaseContextModelSnapshot.cs b/src/Tgstation.Server.Host/Database/Migrations/SqlServerDatabaseContextModelSnapshot.cs similarity index 99% rename from src/Tgstation.Server.Host/Models/Migrations/SqlServerDatabaseContextModelSnapshot.cs rename to src/Tgstation.Server.Host/Database/Migrations/SqlServerDatabaseContextModelSnapshot.cs index 57edfcf3a1..28863df2d5 100644 --- a/src/Tgstation.Server.Host/Models/Migrations/SqlServerDatabaseContextModelSnapshot.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/SqlServerDatabaseContextModelSnapshot.cs @@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Metadata; 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))] partial class SqlServerDatabaseContextModelSnapshot : ModelSnapshot From 90d66396f1e6d96a94f0f6968e29b28ff4600adc Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:14:02 -0400 Subject: [PATCH 08/16] Minor indentation cleanup --- .../Database/Design/MySqlDesignTimeDbContextFactory.cs | 8 +++++++- .../Design/SqlServerDesignTimeDbContextFactory.cs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) 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()); } } } From 80aecc914d4d831092bfb9845042fe93b3d08f72 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:34:44 -0400 Subject: [PATCH 09/16] Reduce setup wizard complexity --- src/Tgstation.Server.Host/Core/SetupWizard.cs | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/src/Tgstation.Server.Host/Core/SetupWizard.cs b/src/Tgstation.Server.Host/Core/SetupWizard.cs index 6fa087c27a..05ff524563 100644 --- a/src/Tgstation.Server.Host/Core/SetupWizard.cs +++ b/src/Tgstation.Server.Host/Core/SetupWizard.cs @@ -273,6 +273,35 @@ namespace Tgstation.Server.Host.Core 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}, {2}, or {3}: ", + DatabaseType.Sqlite, + 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 /// @@ -285,67 +314,39 @@ 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}, {2}, or {3}: ", - DatabaseType.Sqlite, - 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)) - { - 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; bool isSqliteDB = databaseConfiguration.DatabaseType == DatabaseType.Sqlite; - if (isSqliteDB) - serverAddress = null; - else + if (!isSqliteDB) 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)) + if (!String.IsNullOrWhiteSpace(serverAddress) && databaseConfiguration.DatabaseType == DatabaseType.SqlServer) { - serverAddress = null; - break; - } - else if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer) - { - var m = Regex.Match(serverAddress, @"^(?.+):(?.+)$"); - if (m.Success) + var match = Regex.Match(serverAddress, @"^(?.+):(?.+)$"); + if (match.Success) { - serverAddress = m.Groups["server"].Value; - if (uint.TryParse(m.Groups["port"].Value, out uint port)) - { + serverAddress = match.Groups["server"].Value; + var portString = match.Groups["port"].Value; + if (uint.TryParse(portString, out uint port)) mySQLServerPort = port; - break; - } else { - await console.WriteAsync($@"Failed to parse port ""{m.Groups["port"].Value}"", please try again.", true, cancellationToken).ConfigureAwait(false); + await console.WriteAsync($"Failed to parse port \"{portString}\", please try again.", true, cancellationToken).ConfigureAwait(false); + continue; } } - else break; } - else break; + + break; } while (true); @@ -359,12 +360,14 @@ namespace Tgstation.Server.Host.Core databaseName = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false); if (!String.IsNullOrWhiteSpace(databaseName)) { - dbExists = isSqliteDB - ? await ioManager.FileExists(databaseName, cancellationToken).ConfigureAwait(false) - : await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false); - - if (!dbExists && isSqliteDB) - databaseName = await ValidateNonExistantSqliteDBName(databaseName, cancellationToken).ConfigureAwait(false); + 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)) From cd0148cc2d454127dc3ff39f97773f4550e20f79 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:36:53 -0400 Subject: [PATCH 10/16] Minor warning cleanup --- .../Migrations/20180926033145_MSReattachCompileJobRequired.cs | 2 +- .../Migrations/20180926034014_MYReattachCompileJobRequired.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs index ecdc8b8ddc..ca56d5d418 100644 --- a/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20180926033145_MSReattachCompileJobRequired.cs @@ -4,7 +4,7 @@ using System; 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/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs index 014e3c0449..d13c3e7424 100644 --- a/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs +++ b/src/Tgstation.Server.Host/Database/Migrations/20180926034014_MYReattachCompileJobRequired.cs @@ -4,7 +4,7 @@ using System; 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 { From 75e4e49f60b10c40fd4b46b593df9097fa32f681 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:37:03 -0400 Subject: [PATCH 11/16] Add SQLite migration --- .../Database/DatabaseContext.cs | 21 + .../SqliteDesignTimeDbContextFactory.cs | 28 + .../20200322210825_SLAddSqlite.Designer.cs | 653 ++++++++++++++++++ .../Migrations/20200322210825_SLAddSqlite.cs | 639 +++++++++++++++++ .../SqliteDatabaseContextModelSnapshot.cs | 649 +++++++++++++++++ 5 files changed, 1990 insertions(+) create mode 100644 src/Tgstation.Server.Host/Database/Design/SqliteDesignTimeDbContextFactory.cs create mode 100644 src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.Designer.cs create mode 100644 src/Tgstation.Server.Host/Database/Migrations/20200322210825_SLAddSqlite.cs create mode 100644 src/Tgstation.Server.Host/Database/Migrations/SqliteDatabaseContextModelSnapshot.cs diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index b247660562..0bbbbabbea 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs @@ -195,7 +195,25 @@ 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) { @@ -214,6 +232,9 @@ namespace Tgstation.Server.Host.Database case DatabaseType.MariaDB: migrationSubstitution = "MY{0}"; break; + case DatabaseType.Sqlite: + migrationSubstitution = "SL{0}"; + break; default: throw new InvalidOperationException($"Invalid DatabaseType: {DatabaseType}"); } 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/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(nullable: false), + Url = table.Column(nullable: false), + Author = table.Column(nullable: false), + MergedAt = table.Column(nullable: false), + MergedById = table.Column(nullable: false), + PrimaryRevisionInformationId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_TestMerges", x => x.Id); + table.ForeignKey( + name: "FK_TestMerges_Users_MergedById", + column: x => x.MergedById, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId", + column: x => x.PrimaryRevisionInformationId, + principalTable: "RevisionInformations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "CompileJobs", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DmeName = table.Column(nullable: false), + Output = table.Column(nullable: false), + DirectoryName = table.Column(nullable: false), + MinimumSecurityLevel = table.Column(nullable: false), + JobId = table.Column(nullable: false), + RevisionInformationId = table.Column(nullable: false), + ByondVersion = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CompileJobs", x => x.Id); + table.ForeignKey( + name: "FK_CompileJobs_Jobs_JobId", + column: x => x.JobId, + principalTable: "Jobs", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_CompileJobs_RevisionInformations_RevisionInformationId", + column: x => x.RevisionInformationId, + principalTable: "RevisionInformations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "RevInfoTestMerges", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + TestMergeId = table.Column(nullable: false), + RevisionInformationId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_RevInfoTestMerges", x => x.Id); + table.ForeignKey( + name: "FK_RevInfoTestMerges_RevisionInformations_RevisionInformationId", + column: x => x.RevisionInformationId, + principalTable: "RevisionInformations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_RevInfoTestMerges_TestMerges_TestMergeId", + column: x => x.TestMergeId, + principalTable: "TestMerges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ReattachInformations", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ChatCommandsJson = table.Column(nullable: false), + ChatChannelsJson = table.Column(nullable: false), + ServerCommandsJson = table.Column(nullable: false), + AccessIdentifier = table.Column(nullable: false), + ProcessId = table.Column(nullable: false), + IsPrimary = table.Column(nullable: false), + Port = table.Column(nullable: false), + RebootState = table.Column(nullable: false), + CompileJobId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ReattachInformations", x => x.Id); + table.ForeignKey( + name: "FK_ReattachInformations_CompileJobs_CompileJobId", + column: x => x.CompileJobId, + principalTable: "CompileJobs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "WatchdogReattachInformations", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + AlphaIsActive = table.Column(nullable: false), + InstanceId = table.Column(nullable: false), + AlphaId = table.Column(nullable: true), + BravoId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_WatchdogReattachInformations", x => x.Id); + table.ForeignKey( + name: "FK_WatchdogReattachInformations_ReattachInformations_AlphaId", + column: x => x.AlphaId, + principalTable: "ReattachInformations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_WatchdogReattachInformations_ReattachInformations_BravoId", + column: x => x.BravoId, + principalTable: "ReattachInformations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_WatchdogReattachInformations_Instances_InstanceId", + column: x => x.InstanceId, + principalTable: "Instances", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ChatBots_InstanceId", + table: "ChatBots", + column: "InstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_ChatBots_Name", + table: "ChatBots", + column: "Name", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ChatChannels_ChatSettingsId_DiscordChannelId", + table: "ChatChannels", + columns: new[] { "ChatSettingsId", "DiscordChannelId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_ChatChannels_ChatSettingsId_IrcChannel", + table: "ChatChannels", + columns: new[] { "ChatSettingsId", "IrcChannel" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_CompileJobs_DirectoryName", + table: "CompileJobs", + column: "DirectoryName"); + + migrationBuilder.CreateIndex( + name: "IX_CompileJobs_JobId", + table: "CompileJobs", + column: "JobId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_CompileJobs_RevisionInformationId", + table: "CompileJobs", + column: "RevisionInformationId"); + + migrationBuilder.CreateIndex( + name: "IX_DreamDaemonSettings_InstanceId", + table: "DreamDaemonSettings", + column: "InstanceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DreamMakerSettings_InstanceId", + table: "DreamMakerSettings", + column: "InstanceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Instances_Path", + table: "Instances", + column: "Path", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_InstanceUsers_InstanceId", + table: "InstanceUsers", + column: "InstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_InstanceUsers_UserId_InstanceId", + table: "InstanceUsers", + columns: new[] { "UserId", "InstanceId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Jobs_CancelledById", + table: "Jobs", + column: "CancelledById"); + + migrationBuilder.CreateIndex( + name: "IX_Jobs_InstanceId", + table: "Jobs", + column: "InstanceId"); + + migrationBuilder.CreateIndex( + name: "IX_Jobs_StartedById", + table: "Jobs", + column: "StartedById"); + + migrationBuilder.CreateIndex( + name: "IX_ReattachInformations_CompileJobId", + table: "ReattachInformations", + column: "CompileJobId"); + + migrationBuilder.CreateIndex( + name: "IX_RepositorySettings_InstanceId", + table: "RepositorySettings", + column: "InstanceId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_RevInfoTestMerges_RevisionInformationId", + table: "RevInfoTestMerges", + column: "RevisionInformationId"); + + migrationBuilder.CreateIndex( + name: "IX_RevInfoTestMerges_TestMergeId", + table: "RevInfoTestMerges", + column: "TestMergeId"); + + migrationBuilder.CreateIndex( + name: "IX_RevisionInformations_InstanceId_CommitSha", + table: "RevisionInformations", + columns: new[] { "InstanceId", "CommitSha" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_TestMerges_MergedById", + table: "TestMerges", + column: "MergedById"); + + migrationBuilder.CreateIndex( + name: "IX_TestMerges_PrimaryRevisionInformationId", + table: "TestMerges", + column: "PrimaryRevisionInformationId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_CanonicalName", + table: "Users", + column: "CanonicalName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_CreatedById", + table: "Users", + column: "CreatedById"); + + migrationBuilder.CreateIndex( + name: "IX_WatchdogReattachInformations_AlphaId", + table: "WatchdogReattachInformations", + column: "AlphaId"); + + migrationBuilder.CreateIndex( + name: "IX_WatchdogReattachInformations_BravoId", + table: "WatchdogReattachInformations", + column: "BravoId"); + + migrationBuilder.CreateIndex( + name: "IX_WatchdogReattachInformations_InstanceId", + table: "WatchdogReattachInformations", + column: "InstanceId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + if (migrationBuilder == null) + throw new ArgumentNullException(nameof(migrationBuilder)); + + migrationBuilder.DropTable( + name: "ChatChannels"); + + migrationBuilder.DropTable( + name: "DreamDaemonSettings"); + + migrationBuilder.DropTable( + name: "DreamMakerSettings"); + + migrationBuilder.DropTable( + name: "InstanceUsers"); + + migrationBuilder.DropTable( + name: "RepositorySettings"); + + migrationBuilder.DropTable( + name: "RevInfoTestMerges"); + + migrationBuilder.DropTable( + name: "WatchdogReattachInformations"); + + migrationBuilder.DropTable( + name: "ChatBots"); + + migrationBuilder.DropTable( + name: "TestMerges"); + + migrationBuilder.DropTable( + name: "ReattachInformations"); + + migrationBuilder.DropTable( + name: "CompileJobs"); + + migrationBuilder.DropTable( + name: "Jobs"); + + migrationBuilder.DropTable( + name: "RevisionInformations"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.DropTable( + name: "Instances"); + } + } +} diff --git a/src/Tgstation.Server.Host/Database/Migrations/SqliteDatabaseContextModelSnapshot.cs b/src/Tgstation.Server.Host/Database/Migrations/SqliteDatabaseContextModelSnapshot.cs new file mode 100644 index 0000000000..394bbd016d --- /dev/null +++ b/src/Tgstation.Server.Host/Database/Migrations/SqliteDatabaseContextModelSnapshot.cs @@ -0,0 +1,649 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Tgstation.Server.Host.Database; + +namespace Tgstation.Server.Host.Migrations +{ + [DbContext(typeof(SqliteDatabaseContext))] + partial class SqliteDatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(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 + } + } +} From 6a474239ea5a78b33687ec27e766bf51c50478e3 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 17:40:08 -0400 Subject: [PATCH 12/16] Test SQLite in travis --- build/test_core.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build/test_core.sh b/build/test_core.sh index 34952fd4c4..efbde65b7a 100755 --- a/build/test_core.sh +++ b/build/test_core.sh @@ -37,7 +37,13 @@ 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.Database.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" +$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 +52,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 From f5589b02a167837d20f4d8937db98da27779df9f Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Sun, 22 Mar 2020 20:38:35 -0400 Subject: [PATCH 13/16] Adds a user spam integration test. This is mainly to test server load as well as SQLite async support. --- .../Tgstation.Server.Tests/IntegrationTest.cs | 1 + tests/Tgstation.Server.Tests/UsersTest.cs | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/Tgstation.Server.Tests/UsersTest.cs diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index 355d25b031..aa305db13d 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -142,6 +142,7 @@ namespace Tgstation.Server.Tests await Assert.ThrowsExceptionAsync(() => badClient.Version(cancellationToken)).ConfigureAwait(false); await new AdministrationTest(adminClient.Administration).Run(cancellationToken).ConfigureAwait(false); + await new UsersTest(adminClient.Users).Run(cancellationToken).ConfigureAwait(false); await new InstanceManagerTest(adminClient.Instances, server.Directory).Run(cancellationToken).ConfigureAwait(false); } } diff --git a/tests/Tgstation.Server.Tests/UsersTest.cs b/tests/Tgstation.Server.Tests/UsersTest.cs new file mode 100644 index 0000000000..bcce0b08e5 --- /dev/null +++ b/tests/Tgstation.Server.Tests/UsersTest.cs @@ -0,0 +1,60 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Tgstation.Server.Api.Models; +using Tgstation.Server.Client; + +namespace Tgstation.Server.Tests +{ + sealed class UsersTest + { + readonly IUsersClient client; + + public UsersTest(IUsersClient client) + { + this.client = client ?? throw new ArgumentNullException(nameof(client)); + } + + public async Task Run(CancellationToken cancellationToken) + { + await TestSpamCreation(cancellationToken).ConfigureAwait(false); + } + + public async Task TestSpamCreation(CancellationToken cancellationToken) + { + ICollection> tasks = new List>(); + + // Careful with this, very easy to overload the thread pool + const int RepeatCount = 100; + + ThreadPool.GetMaxThreads(out var defaultMaxWorker, out var defaultMaxCompletion); + ThreadPool.GetMinThreads(out var defaultMinWorker, out var defaultMinCompletion); + try + { + ThreadPool.SetMinThreads(Math.Min(RepeatCount * 4, defaultMaxWorker), Math.Min(RepeatCount * 4, defaultMaxCompletion)); + for (int i = 0; i < RepeatCount; ++i) + { + tasks.Add( + client.Create( + new UserUpdate + { + Name = $"SpamTestUser_{i}", + Password = "asdfasdjfhauwiehruiy273894234jhndjkwh" + }, + cancellationToken)); + } + + await Task.WhenAll(tasks).ConfigureAwait(false); + } + finally + { + ThreadPool.SetMinThreads(defaultMinWorker, defaultMinCompletion); + } + + Assert.AreEqual(RepeatCount, tasks.Select(task => task.Result.Id).Distinct().Count(), "Did not receive expected number of unique user IDs!"); + } + } +} \ No newline at end of file From b3292e82caa26627ebf5778572e584fac4ee0582 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 23 Mar 2020 00:10:28 -0400 Subject: [PATCH 14/16] Add missing integration test failure retries --- tests/Tgstation.Server.Tests/IntegrationTest.cs | 16 +++++++++++++++- tests/Tgstation.Server.Tests/TestingServer.cs | 10 +++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/Tgstation.Server.Tests/IntegrationTest.cs b/tests/Tgstation.Server.Tests/IntegrationTest.cs index aa305db13d..688da20e4d 100644 --- a/tests/Tgstation.Server.Tests/IntegrationTest.cs +++ b/tests/Tgstation.Server.Tests/IntegrationTest.cs @@ -2,7 +2,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Diagnostics; using System.IO; -using System.Linq; +using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Threading; @@ -46,6 +46,13 @@ namespace Tgstation.Server.Tests adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false); break; } + catch (HttpRequestException) + { + //migrating, to be expected + if (DateTimeOffset.Now > giveUpAt) + throw; + await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); + } catch (ServiceUnavailableException) { //migrating, to be expected @@ -115,6 +122,13 @@ namespace Tgstation.Server.Tests adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false); break; } + catch (HttpRequestException) + { + //migrating, to be expected + if (DateTimeOffset.Now > giveUpAt) + throw; + await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); + } catch (ServiceUnavailableException) { // migrating, to be expected diff --git a/tests/Tgstation.Server.Tests/TestingServer.cs b/tests/Tgstation.Server.Tests/TestingServer.cs index 29ece7cbca..dae100849a 100644 --- a/tests/Tgstation.Server.Tests/TestingServer.cs +++ b/tests/Tgstation.Server.Tests/TestingServer.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api.Models; @@ -79,7 +80,7 @@ namespace Tgstation.Server.Tests public async Task RunAsync(CancellationToken cancellationToken) { Task runTask = realServer.RunAsync(cancellationToken); - + if (dumpOpenAPISpecpath) { var giveUpAt = DateTimeOffset.Now.AddSeconds(60); @@ -90,6 +91,13 @@ namespace Tgstation.Server.Tests var client = await serverClientFactory.CreateServerClient(Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false); break; } + catch (HttpRequestException) + { + //migrating, to be expected + if (DateTimeOffset.Now > giveUpAt) + throw; + await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); + } catch (ServiceUnavailableException) { //migrating, to be expected From 9c687e3bf0b3b2c289a6e4885148d9a751babecf Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Tue, 24 Mar 2020 23:45:20 -0400 Subject: [PATCH 15/16] Whitespace cleanup --- tests/Tgstation.Server.Tests/TestingServer.cs | 2 +- tests/Tgstation.Server.Tests/UsersTest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Tgstation.Server.Tests/TestingServer.cs b/tests/Tgstation.Server.Tests/TestingServer.cs index dae100849a..527cdb283c 100644 --- a/tests/Tgstation.Server.Tests/TestingServer.cs +++ b/tests/Tgstation.Server.Tests/TestingServer.cs @@ -80,7 +80,7 @@ namespace Tgstation.Server.Tests public async Task RunAsync(CancellationToken cancellationToken) { Task runTask = realServer.RunAsync(cancellationToken); - + if (dumpOpenAPISpecpath) { var giveUpAt = DateTimeOffset.Now.AddSeconds(60); diff --git a/tests/Tgstation.Server.Tests/UsersTest.cs b/tests/Tgstation.Server.Tests/UsersTest.cs index bcce0b08e5..223384846b 100644 --- a/tests/Tgstation.Server.Tests/UsersTest.cs +++ b/tests/Tgstation.Server.Tests/UsersTest.cs @@ -57,4 +57,4 @@ namespace Tgstation.Server.Tests Assert.AreEqual(RepeatCount, tasks.Select(task => task.Result.Id).Distinct().Count(), "Did not receive expected number of unique user IDs!"); } } -} \ No newline at end of file +} From 010cc45289d3c131d3df6c8e0155bd833638b557 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Tue, 24 Mar 2020 23:46:03 -0400 Subject: [PATCH 16/16] Hide and disable Sqlite support --- build/test_core.sh | 5 +++-- src/Tgstation.Server.Host/Core/SetupWizard.cs | 3 +-- src/Tgstation.Server.Host/Database/DatabaseContext.cs | 2 +- src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs | 6 ++++++ src/Tgstation.Server.Host/appsettings.json | 4 ++-- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/build/test_core.sh b/build/test_core.sh index efbde65b7a..a27611b434 100755 --- a/build/test_core.sh +++ b/build/test_core.sh @@ -43,7 +43,8 @@ $HOME/.dotnet/tools/coverlet bin/$CONFIG/netcoreapp2.1/Tgstation.Server.Tests.dl #Run again for Sqlite export TGS4_TEST_DATABASE_TYPE=Sqlite export TGS4_TEST_CONNECTION_STRING="Data Source=TravisTestDB.sqlite3;Mode=ReadWriteCreate" -$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.*" +#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 @@ -53,4 +54,4 @@ 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 servermy.xml -F integration -bash <(curl -s https://codecov.io/bash) -f serversl.xml -F integration +# bash <(curl -s https://codecov.io/bash) -f serversl.xml -F integration diff --git a/src/Tgstation.Server.Host/Core/SetupWizard.cs b/src/Tgstation.Server.Host/Core/SetupWizard.cs index 05ff524563..53a7708d58 100644 --- a/src/Tgstation.Server.Host/Core/SetupWizard.cs +++ b/src/Tgstation.Server.Host/Core/SetupWizard.cs @@ -285,8 +285,7 @@ namespace Tgstation.Server.Host.Core await console.WriteAsync( String.Format( CultureInfo.InvariantCulture, - "Please enter one of {0}, {1}, {2}, or {3}: ", - DatabaseType.Sqlite, + "Please enter one of {0}, {1}, or {2}: ", DatabaseType.MariaDB, DatabaseType.MySql, DatabaseType.SqlServer), diff --git a/src/Tgstation.Server.Host/Database/DatabaseContext.cs b/src/Tgstation.Server.Host/Database/DatabaseContext.cs index 0bbbbabbea..d435a228a8 100644 --- a/src/Tgstation.Server.Host/Database/DatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/DatabaseContext.cs @@ -146,7 +146,7 @@ namespace Tgstation.Server.Host.Database } /// - public async Task Initialize(CancellationToken cancellationToken) + public virtual async Task Initialize(CancellationToken cancellationToken) { if (DatabaseConfiguration.DropDatabase) { diff --git a/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs index 9bb91a9792..02e03d5aa2 100644 --- a/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs @@ -1,6 +1,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System; +using System.Threading; +using System.Threading.Tasks; using Tgstation.Server.Host.Configuration; namespace Tgstation.Server.Host.Database @@ -23,6 +26,9 @@ namespace Tgstation.Server.Host.Database public SqliteDatabaseContext(DbContextOptions dbContextOptions, IOptions databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger) { } + /// + public override Task Initialize(CancellationToken cancellationToken) => throw new NotImplementedException("SQLite support currently is incomplete. See tracking issue at https://github.com/tgstation/tgstation-server/issues/885"); + /// protected override void OnConfiguring(DbContextOptionsBuilder options) { diff --git a/src/Tgstation.Server.Host/appsettings.json b/src/Tgstation.Server.Host/appsettings.json index 082bb766fe..cf71daf70c 100644 --- a/src/Tgstation.Server.Host/appsettings.json +++ b/src/Tgstation.Server.Host/appsettings.json @@ -48,9 +48,9 @@ }, "Database": { "DropDatabase": false, - "DatabaseType": "Sqlite", + "DatabaseType": "SqlServer", "ResetAdminPassword": false, "MySqlServerVersion": null, - "ConnectionString": "Data Source=LocalTestDB.sqlite3;Mode=ReadWriteCreate" + "ConnectionString": "Data Source=(local);Initial Catalog=TGS;Integrated Security=True" } }