Update to new ticket system; Add migrations

This commit is contained in:
Laura Hausmann 2022-03-20 02:30:56 +01:00
parent 0f8555721b
commit fb6ca021c2
Signed by: zotan
GPG key ID: D044E84C5BE01605
8 changed files with 233 additions and 102 deletions

105
bahnplan.web/Migrations.cs Normal file
View file

@ -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<Migration> _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<DbInfo>();
db.CreateTable<Card>();
db.CreateTable<Leg>();
db.CreateTable<Ticket>();
db.CreateTable<TicketLeg>();
db.CreateTable<Trip>();
db.CreateTable<User>();
db.InsertWithIdentity(new DbInfo { DbVer = DbVer });
}
else if (db.DataProvider.GetSchemaProvider().GetSchema(db).Tables.All(t => t.TableName != "DbInfo")) {
db.CreateTable<DbInfo>();
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);
}
}
}
}

View file

@ -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));
}
}
}
}

View file

@ -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)

View file

@ -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<Startup>(); });
}
}
}

View file

@ -5,77 +5,78 @@
</PropertyGroup>
<ItemGroup>
<Content Update="Pages\Ticket.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Trip.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Logout.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\OEAPI.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Inspection.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Delete.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Card.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Cards.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Plain.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Ticket.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Trip.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Logout.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\OEAPI.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Inspection.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Delete.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Card.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Cards.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Pages\Plain.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Update="Pages\Ticket.cshtml.cs">
<DependentUpon>Ticket.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Logout.cshtml.cs">
<DependentUpon>Logout.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\OEAPI.cshtml.cs">
<DependentUpon>OEAPI.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Inspection.cshtml.cs">
<DependentUpon>Inspection.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Delete.cshtml.cs">
<DependentUpon>Delete.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Cards.cshtml.cs">
<DependentUpon>Cards.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Plain.cshtml.cs">
<DependentUpon>Plain.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Ticket.cshtml.cs">
<DependentUpon>Ticket.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Logout.cshtml.cs">
<DependentUpon>Logout.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\OEAPI.cshtml.cs">
<DependentUpon>OEAPI.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Inspection.cshtml.cs">
<DependentUpon>Inspection.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Delete.cshtml.cs">
<DependentUpon>Delete.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Cards.cshtml.cs">
<DependentUpon>Cards.cshtml</DependentUpon>
</Compile>
<Compile Update="Pages\Plain.cshtml.cs">
<DependentUpon>Plain.cshtml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="CsvHelper" Version="18.0.0" />
<PackageReference Include="Ical.Net" Version="4.2.0" />
<PackageReference Include="linq2db" Version="2.9.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.2" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
<PackageReference Include="CsvHelper" Version="18.0.0"/>
<PackageReference Include="Ical.Net" Version="4.2.0"/>
<PackageReference Include="linq2db" Version="3.2.3"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.2"/>
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.3"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.2"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.115"/>
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0"/>
</ItemGroup>
</Project>

View file

@ -21,12 +21,13 @@ namespace bahnplan.web.database {
public string DefaultDataProvider => "SQLite";
public IEnumerable<IConnectionStringSettings> 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> DbInfo => GetTable<DbInfo>();
public ITable<User> Users => GetTable<User>();
public ITable<Leg> Legs => GetTable<Leg>();
@ -36,4 +37,4 @@ namespace bahnplan.web.database {
public ITable<Card> Cards => GetTable<Card>();
}
}
}
}

View file

@ -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; }
}
}

View file

@ -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; }
}
}
}