diff --git a/bahnplan.web/Migrations.cs b/bahnplan.web/Migrations.cs new file mode 100644 index 0000000..0bc874e --- /dev/null +++ b/bahnplan.web/Migrations.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using bahnplan.web.database; +using bahnplan.web.database.Tables; +using LinqToDB; +using LinqToDB.Data; + +namespace bahnplan.web { + public static class Migrations { + private const int DbVer = 1; + + private static readonly List _migrations = new() { + new Migration(1, + "CREATE TEMPORARY TABLE Tickets_backup(\"TicketID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"UserID\" INTEGER NOT NULL, \"OrderID\" TEXT NOT NULL UNIQUE, \"TicketInfo\" TEXT NOT NULL, \"TicketQR\" BLOB NOT NULL, \"TicketPkPass\" BLOB NOT NULL, \"TicketSecCode\" BLOB NOT NULL, \"Traveller\" TEXT)"), + new Migration(1, "INSERT INTO Tickets_backup SELECT TicketID, UserID, OrderID, TicketInfo, TicketQR, TicketPkPass, TicketSecCode, Traveller FROM Tickets"), + new Migration(1, "DROP Table Tickets"), + new Migration(1, + "CREATE TABLE Tickets(\"TicketID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"UserID\" INTEGER NOT NULL, \"OrderID\" TEXT NOT NULL UNIQUE, \"TicketInfo\" TEXT NOT NULL, \"TicketQR\" BLOB NOT NULL, \"TicketPkPass\" BLOB, \"TicketSecCode\" BLOB NOT NULL, \"Traveller\" TEXT)"), + new Migration(1, "INSERT INTO Tickets SELECT TicketID, UserID, OrderID, TicketInfo, TicketQR, TicketPkPass, TicketSecCode, Traveller FROM Tickets_backup"), + new Migration(1, "DROP TABLE Tickets_backup") + }; + + public static void RunMigrations() { + using var db = new Database.DbConn(); + var ccolor = Console.ForegroundColor; + + if (!db.DataProvider.GetSchemaProvider().GetSchema(db).Tables.Any()) { + Console.ForegroundColor = ConsoleColor.DarkCyan; + Console.Write("Running migration: "); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine("Initialize Database"); + + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + db.CreateTable(); + + db.InsertWithIdentity(new DbInfo { DbVer = DbVer }); + } + else if (db.DataProvider.GetSchemaProvider().GetSchema(db).Tables.All(t => t.TableName != "DbInfo")) { + db.CreateTable(); + db.InsertWithIdentity(new DbInfo { DbVer = 0 }); + } + + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine($"Database version: {db.DbInfo.ToList().First().DbVer}"); + + var migrationsToRun = _migrations.FindAll(p => p.IntroducedWithDbVer > db.DbInfo.First().DbVer); + if (migrationsToRun.Count == 0) { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("No migrations to run."); + } + else { + new Migration(0, "BEGIN TRANSACTION").Run(db); + try { + migrationsToRun.ForEach(p => p.Run(db)); + } + catch { + Console.ForegroundColor = ConsoleColor.DarkRed; + Console.WriteLine($"Migrating to database version {DbVer} failed."); + new Migration(0, "ROLLBACK TRANSACTION").Run(db); + Console.ForegroundColor = ConsoleColor.DarkYellow; + Console.WriteLine("Rolled back migrations."); + Environment.Exit(1); + } + + new Migration(0, "COMMIT TRANSACTION").Run(db); + + var newdb = new Database.DbConn(); + var dbinfo = newdb.DbInfo.First(); + dbinfo.DbVer = DbVer; + newdb.Update(dbinfo); + + Console.ForegroundColor = ConsoleColor.DarkGreen; + Console.WriteLine($"Database version is now: {DbVer}"); + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("Finished running migrations."); + } + + Console.ForegroundColor = ccolor; + } + + private class Migration { + private readonly string _sql; + public readonly int IntroducedWithDbVer; + + public Migration(int introducedWithDbVer, string sql) { + IntroducedWithDbVer = introducedWithDbVer; + _sql = sql; + } + + public void Run(DataConnection db) { + Console.ForegroundColor = ConsoleColor.DarkCyan; + Console.Write("Running migration: "); + Console.ForegroundColor = ConsoleColor.Yellow; + Console.WriteLine(_sql); + db.Execute(_sql); + } + } + } +} diff --git a/bahnplan.web/Pages/Inspection.cshtml.cs b/bahnplan.web/Pages/Inspection.cshtml.cs index a365187..86d04f5 100644 --- a/bahnplan.web/Pages/Inspection.cshtml.cs +++ b/bahnplan.web/Pages/Inspection.cshtml.cs @@ -1,4 +1,6 @@ +using System; using System.Linq; +using System.Text; using bahnplan.web.database; using bahnplan.web.database.Tables; using Microsoft.AspNetCore.Http; @@ -16,6 +18,12 @@ namespace bahnplan.web.Pages { using var db = new Database.DbConn(); Leg = db.Legs.First(p => p.LegId == int.Parse(Request.Query["leg"])); Ticket = db.Tickets.First(p => p.TicketId == Leg.TicketId); + + if (!Ticket.TicketQr.StartsWith("data:image/png")) + Ticket.TicketQr = Encoding.UTF8.GetString(Convert.FromBase64String(Ticket.TicketQr)); + + if (!Ticket.TicketSecCode.StartsWith("data:image/png")) + Ticket.TicketSecCode = Encoding.UTF8.GetString(Convert.FromBase64String(Ticket.TicketSecCode)); } } -} \ No newline at end of file +} diff --git a/bahnplan.web/Pages/Ticket.cshtml.cs b/bahnplan.web/Pages/Ticket.cshtml.cs index 4ccb6b0..58c9690 100644 --- a/bahnplan.web/Pages/Ticket.cshtml.cs +++ b/bahnplan.web/Pages/Ticket.cshtml.cs @@ -28,9 +28,9 @@ namespace bahnplan.web.Pages { if (db.Tickets.Any(p => p.OrderId == Request.Query["order"].ToString())) { var tripId = Request.Query["action"] == "addleg" ? int.Parse(Request.Query["tripid"]) - : db.InsertWithInt32Identity(new Trip {UserId = int.Parse(HttpContext.Session.GetString("uid"))}); - var ticketId = db.Tickets.First(p => p.OrderId == Request.Query["order"].ToString()).TicketId; - var ticketId2 = db.Tickets.FirstOrDefault(p => p.OrderId == Request.Query["order"].ToString() + "_2")?.TicketId; + : db.InsertWithInt32Identity(new Trip { UserId = int.Parse(HttpContext.Session.GetString("uid")) }); + var ticketId = db.Tickets.First(p => p.OrderId == Request.Query["order"].ToString()).TicketId; + var ticketId2 = db.Tickets.FirstOrDefault(p => p.OrderId == Request.Query["order"] + "_2")?.TicketId; foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId).ToList()) db.InsertWithInt32Identity(new Leg { @@ -46,8 +46,8 @@ namespace bahnplan.web.Pages { DepTime = leg.DepTime, TicketId = leg.TicketId }); - - if (ticketId2 != null) { + + if (ticketId2 != null) foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId2).ToList()) db.InsertWithInt32Identity(new Leg { TripId = tripId, @@ -62,7 +62,6 @@ namespace bahnplan.web.Pages { DepTime = leg.DepTime, TicketId = leg.TicketId }); - } TripId = tripId; } @@ -70,9 +69,8 @@ namespace bahnplan.web.Pages { else { var request = new XDocument(new XElement("rqorderdetails", new XAttribute("version", "1.0"), new XElement("rqheader", new XAttribute("ts", "2019-10-31T23:20:48"), new XAttribute("l", "de"), - new XAttribute("v", "19100000"), new XAttribute("d", "iPad7,5"), - new XAttribute("os", "iOS_13.1.3"), new XAttribute("app", "NAVIGATOR")), - new XElement("rqorder", new XAttribute("on", Request.Query["order"])), + new XAttribute("v", "19100000"), new XAttribute("d", "iPad7,5"), new XAttribute("os", "iOS_13.1.3"), + new XAttribute("app", "NAVIGATOR")), new XElement("rqorder", new XAttribute("on", Request.Query["order"])), new XElement("authname", new XAttribute("tln", Request.Query["name"])))).ToString(); var response = new WebClient().UploadString("https://fahrkarten.bahn.de/mobile/dbc/xs.go", "POST", request); var xmlobj = new XmlDocument(); @@ -82,9 +80,9 @@ namespace bahnplan.web.Pages { var tripId = Request.Query["action"] == "addleg" ? int.Parse(Request.Query["tripid"]) - : db.InsertWithInt32Identity(new Trip {UserId = int.Parse(HttpContext.Session.GetString("uid"))}); + : db.InsertWithInt32Identity(new Trip { UserId = int.Parse(HttpContext.Session.GetString("uid")) }); - int ticketId; + int ticketId; int? ticketId2 = null; switch (parsed.Rporderdetails.Order.Tcklist.Tck.Count) { @@ -95,7 +93,10 @@ namespace bahnplan.web.Pages { TicketQr = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "barcode").Text, TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text, UserId = int.Parse(HttpContext.Session.GetString("uid")), - TicketPkPass = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64 + TicketPkPass = + parsed.Rporderdetails.Order.Tcklist.Tck[0] + .Htdata.Ht.FirstOrDefault(p => p.Name == "pass") + ?.Text, // application/vnd.apple.pkpass;base64 Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderVorname + " " + parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderNachname @@ -109,19 +110,25 @@ namespace bahnplan.web.Pages { TicketQr = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "barcode").Text, TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text, UserId = int.Parse(HttpContext.Session.GetString("uid")), - TicketPkPass = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64 + TicketPkPass = + parsed.Rporderdetails.Order.Tcklist.Tck[0] + .Htdata.Ht.First(p => p.Name == "pass") + .Text, // application/vnd.apple.pkpass;base64 Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderVorname + " " + parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderNachname }); - + ticketId2 = db.InsertWithInt32Identity(new Ticket { OrderId = Request.Query["order"] + "_2", TicketInfo = parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.Txt, TicketQr = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "barcode").Text, TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text, UserId = int.Parse(HttpContext.Session.GetString("uid")), - TicketPkPass = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64 + TicketPkPass = + parsed.Rporderdetails.Order.Tcklist.Tck[1] + .Htdata.Ht.First(p => p.Name == "pass") + .Text, // application/vnd.apple.pkpass;base64 Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderVorname + " " + parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderNachname @@ -150,16 +157,16 @@ namespace bahnplan.web.Pages { }); db.InsertWithInt32Identity(new TicketLeg { - TicketId = ticketId, - TrainType = leg.Gattung, - TrainNr = int.Parse(leg.Zugnummer), - ArrStation = leg.Arr.Name, - ArrStationId = int.Parse(leg.Arr.BhfNr), - ArrTime = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time), - DepStation = leg.Dep.Name, - DepStationId = int.Parse(leg.Dep.BhfNr), - DepTime = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time) - }); + TicketId = ticketId, + TrainType = leg.Gattung, + TrainNr = int.Parse(leg.Zugnummer), + ArrStation = leg.Arr.Name, + ArrStationId = int.Parse(leg.Arr.BhfNr), + ArrTime = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time), + DepStation = leg.Dep.Name, + DepStationId = int.Parse(leg.Dep.BhfNr), + DepTime = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time) + }); } if (parsed.Rporderdetails.Order.Schedulelist.Ret != null) diff --git a/bahnplan.web/Program.cs b/bahnplan.web/Program.cs index c1ae6c0..98c57f0 100644 --- a/bahnplan.web/Program.cs +++ b/bahnplan.web/Program.cs @@ -12,11 +12,14 @@ namespace bahnplan.web { DataConnection.DefaultSettings = new Database.Settings(); Configuration.Linq.AllowMultipleQuery = true; Directory.CreateDirectory(Variables.TicketDir); - ThreadPool.SetMinThreads(100,100); + ThreadPool.SetMinThreads(100, 100); + + Migrations.RunMigrations(); + CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } -} \ No newline at end of file +} diff --git a/bahnplan.web/bahnplan.web.csproj b/bahnplan.web/bahnplan.web.csproj index af31509..df93981 100644 --- a/bahnplan.web/bahnplan.web.csproj +++ b/bahnplan.web/bahnplan.web.csproj @@ -5,77 +5,78 @@ - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - - - true - PreserveNewest - + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + + + true + PreserveNewest + - - Ticket.cshtml - - - Logout.cshtml - - - OEAPI.cshtml - - - Inspection.cshtml - - - Delete.cshtml - - - Cards.cshtml - - - Plain.cshtml - + + Ticket.cshtml + + + Logout.cshtml + + + OEAPI.cshtml + + + Inspection.cshtml + + + Delete.cshtml + + + Cards.cshtml + + + Plain.cshtml + - - - - - - - - + + + + + + + + + diff --git a/bahnplan.web/database/Database.cs b/bahnplan.web/database/Database.cs index 9f6fce6..8a9d43e 100644 --- a/bahnplan.web/database/Database.cs +++ b/bahnplan.web/database/Database.cs @@ -21,12 +21,13 @@ namespace bahnplan.web.database { public string DefaultDataProvider => "SQLite"; public IEnumerable ConnectionStrings { - get { yield return new ConnectionStringSettings {Name = "db", ProviderName = "SQLite", ConnectionString = @"Data Source=database.db;"}; } + get { yield return new ConnectionStringSettings { Name = "db", ProviderName = "SQLite", ConnectionString = @"Data Source=database.db;" }; } } } public class DbConn : DataConnection { public DbConn() : base("db") { } + public ITable DbInfo => GetTable(); public ITable Users => GetTable(); public ITable Legs => GetTable(); @@ -36,4 +37,4 @@ namespace bahnplan.web.database { public ITable Cards => GetTable(); } } -} \ No newline at end of file +} diff --git a/bahnplan.web/database/Tables/DbInfo.cs b/bahnplan.web/database/Tables/DbInfo.cs new file mode 100644 index 0000000..46d1c7d --- /dev/null +++ b/bahnplan.web/database/Tables/DbInfo.cs @@ -0,0 +1,9 @@ +using LinqToDB.Mapping; + +namespace bahnplan.web.database.Tables { + [Table(Name = "DbInfo")] + public class DbInfo { + [Column(Name = "ID"), PrimaryKey, Identity, NotNull] public int Id { get; set; } + [Column(Name = "DbVer"), NotNull] public int DbVer { get; set; } + } +} \ No newline at end of file diff --git a/bahnplan.web/database/Tables/Ticket.cs b/bahnplan.web/database/Tables/Ticket.cs index 84b70e5..dffde53 100644 --- a/bahnplan.web/database/Tables/Ticket.cs +++ b/bahnplan.web/database/Tables/Ticket.cs @@ -3,8 +3,7 @@ using LinqToDB.Mapping; namespace bahnplan.web.database.Tables { [Table(Name = "Tickets")] public class Ticket { - [Column(Name = "TicketID"), PrimaryKey, Identity, NotNull] - public int TicketId { get; set; } + [Column(Name = "TicketID"), PrimaryKey, Identity, NotNull] public int TicketId { get; set; } [Column(Name = "OrderID"), NotNull] public string OrderId { get; set; } @@ -14,12 +13,10 @@ namespace bahnplan.web.database.Tables { [Column(Name = "TicketQR"), NotNull] public string TicketQr { get; set; } - [Column(Name = "TicketSecCode"), NotNull] - public string TicketSecCode { get; set; } + [Column(Name = "TicketSecCode"), NotNull] public string TicketSecCode { get; set; } - [Column(Name = "TicketPkPass"), NotNull] - public string TicketPkPass { get; set; } + [Column(Name = "TicketPkPass")] public string TicketPkPass { get; set; } [Column(Name = "Traveller")] public string Traveller { get; set; } } -} \ No newline at end of file +}