Use SSO auth, remove legacy deutschebahn endpoints

This commit is contained in:
Laura Hausmann 2022-05-03 00:59:32 +02:00
parent 6ab3774228
commit c8f95c7e18
Signed by: zotan
GPG Key ID: D044E84C5BE01605
39 changed files with 439 additions and 2281 deletions

View File

@ -1,214 +0,0 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using trainav.web.JSON.CardResponse;
//
// var cardResponse = CardResponse.FromJson(jsonString);
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace trainav.web.JSON.CardResponse {
public partial class CardResponse {
[JsonProperty("?xml", NullValueHandling = NullValueHandling.Ignore)]
public Xml Xml { get; set; }
[JsonProperty("rporderdetails", NullValueHandling = NullValueHandling.Ignore)]
public Rporderdetails Rporderdetails { get; set; }
}
public class Rporderdetails {
[JsonProperty("@version", NullValueHandling = NullValueHandling.Ignore)]
public string Version { get; set; }
[JsonProperty("rpheader", NullValueHandling = NullValueHandling.Ignore)]
public Rpheader Rpheader { get; set; }
[JsonProperty("order", NullValueHandling = NullValueHandling.Ignore)]
public Order Order { get; set; }
}
public class Order {
[JsonProperty("@cdt", NullValueHandling = NullValueHandling.Ignore)]
public string Cdt { get; set; }
[JsonProperty("@cid", NullValueHandling = NullValueHandling.Ignore)]
public string Cid { get; set; }
[JsonProperty("@ddt", NullValueHandling = NullValueHandling.Ignore)]
public string Ddt { get; set; }
[JsonProperty("@fkat", NullValueHandling = NullValueHandling.Ignore)]
public string Fkat { get; set; }
[JsonProperty("@ldt", NullValueHandling = NullValueHandling.Ignore)]
public string Ldt { get; set; }
[JsonProperty("@on", NullValueHandling = NullValueHandling.Ignore)]
public string On { get; set; }
[JsonProperty("@pg", NullValueHandling = NullValueHandling.Ignore)]
public string Pg { get; set; }
[JsonProperty("@sdt", NullValueHandling = NullValueHandling.Ignore)]
public string Sdt { get; set; }
[JsonProperty("@version", NullValueHandling = NullValueHandling.Ignore)]
public string Version { get; set; }
[JsonProperty("@vfrom", NullValueHandling = NullValueHandling.Ignore)]
public string Vfrom { get; set; }
[JsonProperty("@vto", NullValueHandling = NullValueHandling.Ignore)]
public string Vto { get; set; }
[JsonProperty("@zweg", NullValueHandling = NullValueHandling.Ignore)]
public string Zweg { get; set; }
[JsonProperty("tcklist", NullValueHandling = NullValueHandling.Ignore)]
public Tcklist Tcklist { get; set; }
[JsonProperty("posinfolist", NullValueHandling = NullValueHandling.Ignore)]
public Posinfolist Posinfolist { get; set; }
}
public class Posinfolist {
[JsonProperty("posinfo", NullValueHandling = NullValueHandling.Ignore)]
public Posinfo Posinfo { get; set; }
}
public class Posinfo {
[JsonProperty("@dir", NullValueHandling = NullValueHandling.Ignore)]
public string Dir { get; set; }
[JsonProperty("@dirlabel", NullValueHandling = NullValueHandling.Ignore)]
public string Dirlabel { get; set; }
[JsonProperty("@posnr", NullValueHandling = NullValueHandling.Ignore)]
public string Posnr { get; set; }
[JsonProperty("@shownr", NullValueHandling = NullValueHandling.Ignore)]
public string Shownr { get; set; }
[JsonProperty("@state", NullValueHandling = NullValueHandling.Ignore)]
public string State { get; set; }
[JsonProperty("@type", NullValueHandling = NullValueHandling.Ignore)]
public string Type { get; set; }
[JsonProperty("@typeinfo", NullValueHandling = NullValueHandling.Ignore)]
public string Typeinfo { get; set; }
[JsonProperty("@vfo", NullValueHandling = NullValueHandling.Ignore)]
public string Vfo { get; set; }
[JsonProperty("@vto", NullValueHandling = NullValueHandling.Ignore)]
public string Vto { get; set; }
[JsonProperty("childlist")] public object Childlist { get; set; }
}
public class Tcklist {
[JsonProperty("tck", NullValueHandling = NullValueHandling.Ignore)]
public Tck Tck { get; set; }
}
public class Tck {
[JsonProperty("@posnr", NullValueHandling = NullValueHandling.Ignore)]
public string Posnr { get; set; }
[JsonProperty("htdata", NullValueHandling = NullValueHandling.Ignore)]
public Htdata Htdata { get; set; }
[JsonProperty("mtk", NullValueHandling = NullValueHandling.Ignore)]
public Mtk Mtk { get; set; }
[JsonProperty("bahncardimage", NullValueHandling = NullValueHandling.Ignore)]
public Bahncardimage Bahncardimage { get; set; }
}
public class Bahncardimage {
[JsonProperty("#cdata-section", NullValueHandling = NullValueHandling.Ignore)]
public string CdataSection { get; set; }
}
public class Htdata {
[JsonProperty("ht", NullValueHandling = NullValueHandling.Ignore)]
public List<Ht> Ht { get; set; }
}
public class Ht {
[JsonProperty("@name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("@pos", NullValueHandling = NullValueHandling.Ignore)]
public string Pos { get; set; }
[JsonProperty("@type", NullValueHandling = NullValueHandling.Ignore)]
public string Type { get; set; }
[JsonProperty("#text", NullValueHandling = NullValueHandling.Ignore)]
public string Text { get; set; }
}
public class Mtk {
[JsonProperty("@dir", NullValueHandling = NullValueHandling.Ignore)]
public string Dir { get; set; }
[JsonProperty("@status", NullValueHandling = NullValueHandling.Ignore)]
public string Status { get; set; }
[JsonProperty("txt", NullValueHandling = NullValueHandling.Ignore)]
public string Txt { get; set; }
[JsonProperty("zb", NullValueHandling = NullValueHandling.Ignore)]
public string Zb { get; set; }
[JsonProperty("nvplist", NullValueHandling = NullValueHandling.Ignore)]
public Nvplist Nvplist { get; set; }
}
public class Nvplist {
[JsonProperty("nvp", NullValueHandling = NullValueHandling.Ignore)]
public List<Nvp> Nvp { get; set; }
}
public class Nvp {
[JsonProperty("@name", NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty("#text", NullValueHandling = NullValueHandling.Ignore)]
public string Text { get; set; }
}
public class Rpheader {
[JsonProperty("@tnr", NullValueHandling = NullValueHandling.Ignore)]
public string Tnr { get; set; }
[JsonProperty("@ts", NullValueHandling = NullValueHandling.Ignore)]
public string Ts { get; set; }
}
public class Xml {
[JsonProperty("@version", NullValueHandling = NullValueHandling.Ignore)]
public string Version { get; set; }
[JsonProperty("@encoding", NullValueHandling = NullValueHandling.Ignore)]
public string Encoding { get; set; }
}
public partial class CardResponse {
public static CardResponse FromJson(string json) => JsonConvert.DeserializeObject<CardResponse>(json, Converter.Settings);
}
internal static class Converter {
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings {
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {new IsoDateTimeConverter {DateTimeStyles = DateTimeStyles.AssumeUniversal}}
};
}
}

View File

@ -1,75 +0,0 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using trainav.web.JSON;
//
// var listOrdersResponse = ListOrdersResponse.FromJson(jsonString);
using System.Collections.Generic;
using Newtonsoft.Json;
namespace trainav.web.JSON.ListOrdersResponse {
public partial class ListOrdersResponse {
[JsonProperty("?xml", NullValueHandling = NullValueHandling.Ignore)]
public Xml Xml { get; set; }
[JsonProperty("rporderheadlist", NullValueHandling = NullValueHandling.Ignore)]
public Rporderheadlist Rporderheadlist { get; set; }
}
public class Rporderheadlist {
[JsonProperty("@version", NullValueHandling = NullValueHandling.Ignore)]
public string Version { get; set; }
[JsonProperty("rpheader", NullValueHandling = NullValueHandling.Ignore)]
public Rpheader Rpheader { get; set; }
[JsonProperty("orderheadlist", NullValueHandling = NullValueHandling.Ignore)]
public Orderheadlist Orderheadlist { get; set; }
}
public class Orderheadlist {
[JsonProperty("orderhead", NullValueHandling = NullValueHandling.Ignore)]
public List<Orderhead> Orderhead { get; set; }
}
public class Orderhead {
[JsonProperty("@ldt", NullValueHandling = NullValueHandling.Ignore)]
public string Ldt { get; set; }
[JsonProperty("@on", NullValueHandling = NullValueHandling.Ignore)]
public string On { get; set; }
[JsonProperty("authtmp", NullValueHandling = NullValueHandling.Ignore)]
public Authtmp Authtmp { get; set; }
}
public class Authtmp {
[JsonProperty("@htmp", NullValueHandling = NullValueHandling.Ignore)]
public string Htmp { get; set; }
[JsonProperty("@ts", NullValueHandling = NullValueHandling.Ignore)]
public string Ts { get; set; }
}
public class Rpheader {
[JsonProperty("@tnr", NullValueHandling = NullValueHandling.Ignore)]
public string Tnr { get; set; }
[JsonProperty("@ts", NullValueHandling = NullValueHandling.Ignore)]
public string Ts { get; set; }
}
public class Xml {
[JsonProperty("@version", NullValueHandling = NullValueHandling.Ignore)]
public string Version { get; set; }
[JsonProperty("@encoding", NullValueHandling = NullValueHandling.Ignore)]
public string Encoding { get; set; }
}
public partial class ListOrdersResponse {
public static ListOrdersResponse FromJson(string json) => JsonConvert.DeserializeObject<ListOrdersResponse>(json, Converter.Settings);
}
}

View File

@ -13,6 +13,12 @@ namespace trainav.web.JSON {
using J = JsonPropertyAttribute;
using R = Required;
using N = NullValueHandling;
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
public partial class OeapiResponse {
[J("status", NullValueHandling = N.Ignore)]
@ -259,4 +265,24 @@ namespace trainav.web.JSON {
public partial class OeapiResponse {
public static OeapiResponse FromJson(string json) => JsonConvert.DeserializeObject<OeapiResponse>(json, Converter.Settings);
}
}
internal static class Converter {
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings {
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {new IsoDateTimeConverter {DateTimeStyles = DateTimeStyles.AssumeUniversal}}
};
}
internal class SingleOrArrayConverter<T> : JsonConverter {
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(List<T>);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var token = JToken.Load(reader);
return token.Type == JTokenType.Array ? token.ToObject<List<T>>() : new List<T> {token.ToObject<T>()};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
}

View File

@ -1,434 +0,0 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using trainav.web.JSON;
//
// var ticketResponse = TicketResponse.FromJson(jsonString);
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace trainav.web.JSON {
using J = JsonPropertyAttribute;
using R = Required;
using NV = NullValueHandling;
public partial class TicketResponse {
[J("?xml", NullValueHandling = NV.Ignore)]
public Xml Xml { get; set; }
[J("rporderdetails", NullValueHandling = NV.Ignore)]
public Rporderdetails Rporderdetails { get; set; }
}
public class Rporderdetails {
[J("rpheader", NullValueHandling = NV.Ignore)]
public Rpheader Rpheader { get; set; }
[J("@version", NullValueHandling = NV.Ignore)]
public string Version { get; set; }
[J("order", NullValueHandling = NV.Ignore)]
public Order Order { get; set; }
}
public class Order {
[J("@cid", NullValueHandling = NV.Ignore)]
public string Cid { get; set; }
[J("@cdt", NullValueHandling = NV.Ignore)]
public string Cdt { get; set; }
[J("schedulelist", NullValueHandling = NV.Ignore)]
public Schedulelist Schedulelist { get; set; }
[J("tcklist", NullValueHandling = NV.Ignore)]
public Tcklist Tcklist { get; set; }
[J("@sdt", NullValueHandling = NV.Ignore)]
public string Sdt { get; set; }
[J("@zweg", NullValueHandling = NV.Ignore)]
public string Zweg { get; set; }
[J("@vto", NullValueHandling = NV.Ignore)]
public string Vto { get; set; }
[J("@vfrom", NullValueHandling = NV.Ignore)]
public string Vfrom { get; set; }
[J("@ldt", NullValueHandling = NV.Ignore)]
public string Ldt { get; set; }
[J("@pg", NullValueHandling = NV.Ignore)]
public string Pg { get; set; }
[J("posinfolist", NullValueHandling = NV.Ignore)]
public Posinfolist Posinfolist { get; set; }
[J("@on", NullValueHandling = NV.Ignore)]
public string On { get; set; }
[J("txt", NullValueHandling = NV.Ignore)]
public string Txt { get; set; }
[J("@hkey", NullValueHandling = NV.Ignore)]
public string Hkey { get; set; }
[J("reslist", NullValueHandling = NV.Ignore)]
public Reslist Reslist { get; set; }
[J("@ddt", NullValueHandling = NV.Ignore)]
public string Ddt { get; set; }
[J("@version", NullValueHandling = NV.Ignore)]
public string Version { get; set; }
[J("@fkat", NullValueHandling = NV.Ignore)]
public string Fkat { get; set; }
}
public class Posinfolist {
[J("posinfo", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<PosinfoElement>))]
public List<PosinfoElement> Posinfo { get; set; }
}
public class FluffyChildlist {
[J("posinfo", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<PosinfoElement>))]
public List<PosinfoElement> Posinfo { get; set; }
}
public class PurplePosinfo {
[J("@state", NullValueHandling = NV.Ignore)]
public string State { get; set; }
[J("@dir", NullValueHandling = NV.Ignore)]
public string Dir { get; set; }
[J("@posnr", NullValueHandling = NV.Ignore)]
public string Posnr { get; set; }
[J("@type", NullValueHandling = NV.Ignore)]
public string Type { get; set; }
[J("@shownr", NullValueHandling = NV.Ignore)]
public string Shownr { get; set; }
[J("@dirlabel", NullValueHandling = NV.Ignore)]
public string Dirlabel { get; set; }
[J("@vfo", NullValueHandling = NV.Ignore)]
public string Vfo { get; set; }
[J("@typeinfo", NullValueHandling = NV.Ignore)]
public string Typeinfo { get; set; }
[J("@vto", NullValueHandling = NV.Ignore)]
public string Vto { get; set; }
[J("childlist", NullValueHandling = NV.Ignore)]
public FluffyChildlist Childlist { get; set; }
}
public class PurpleChildlist {
[J("posinfo", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<PurplePosinfo>))]
public List<PurplePosinfo> Posinfo { get; set; }
}
public class PosinfoElement {
[J("@state", NullValueHandling = NV.Ignore)]
public string State { get; set; }
[J("@dir", NullValueHandling = NV.Ignore)]
public string Dir { get; set; }
[J("@posnr", NullValueHandling = NV.Ignore)]
public string Posnr { get; set; }
[J("@type", NullValueHandling = NV.Ignore)]
public string Type { get; set; }
[J("@shownr", NullValueHandling = NV.Ignore)]
public string Shownr { get; set; }
[J("@dirlabel", NullValueHandling = NV.Ignore)]
public string Dirlabel { get; set; }
[J("@vfo", NullValueHandling = NV.Ignore)]
public string Vfo { get; set; }
[J("@typeinfo", NullValueHandling = NV.Ignore)]
public string Typeinfo { get; set; }
[J("@vto", NullValueHandling = NV.Ignore)]
public string Vto { get; set; }
[J("childlist", NullValueHandling = NV.Ignore)]
public PurpleChildlist Childlist { get; set; }
}
public class Reslist {
[J("res", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<Re>))]
public List<Re> Res { get; set; }
}
public class Re {
[J("@tid", NullValueHandling = NV.Ignore)]
public string Tid { get; set; }
[J("@posnr", NullValueHandling = NV.Ignore)]
public string Posnr { get; set; }
[J("@dt", NullValueHandling = NV.Ignore)]
public string Dt { get; set; }
[J("nvplist", NullValueHandling = NV.Ignore)]
public Nvplist Nvplist { get; set; }
[J("@cdt", NullValueHandling = NV.Ignore)]
public string Cdt { get; set; }
[J("plaetze", NullValueHandling = NV.Ignore)]
public Plaetze Plaetze { get; set; }
[J("txt", NullValueHandling = NV.Ignore)]
public string Txt { get; set; }
[J("@tn", NullValueHandling = NV.Ignore)]
public string Tn { get; set; }
}
public class Nvplist {
[J("nvp", NullValueHandling = NV.Ignore)]
public List<Nvp> Nvp { get; set; }
}
public class Nvp {
[J("@name", NullValueHandling = NV.Ignore)]
public string Name { get; set; }
[J("#text", NullValueHandling = NV.Ignore)]
public string Text { get; set; }
}
public class Plaetze {
[J("platz", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<Platz>))]
public List<Platz> Platz { get; set; }
}
public class Platz {
[J("platznr", NullValueHandling = NV.Ignore)]
public string Platznr { get; set; }
[J("wagennr", NullValueHandling = NV.Ignore)]
public string Wagennr { get; set; }
}
public class Schedulelist {
[J("out", NullValueHandling = NV.Ignore)]
public Journey Out { get; set; }
[J("ret", NullValueHandling = NV.Ignore)]
public Journey Ret { get; set; }
}
public class Journey {
[J("txt", NullValueHandling = NV.Ignore)]
public string Txt { get; set; }
[J("@posnr", NullValueHandling = NV.Ignore)]
public string Posnr { get; set; }
[J("trainlist", NullValueHandling = NV.Ignore)]
public Trainlist Trainlist { get; set; }
}
public class Trainlist {
[J("train", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<Train>))]
public List<Train> Train { get; set; }
}
public class Train {
[J("@tid", NullValueHandling = NV.Ignore)]
public string Tid { get; set; }
[J("@type", NullValueHandling = NV.Ignore)]
public string Type { get; set; }
[J("zugnr", NullValueHandling = NV.Ignore)]
public string Zugnummer { get; set; }
[J("arr", NullValueHandling = NV.Ignore)]
public Station Arr { get; set; }
[J("gat", NullValueHandling = NV.Ignore)]
public string Gattung { get; set; }
[J("sci", NullValueHandling = NV.Ignore)]
public string Zugklasse { get; set; }
[J("dep", NullValueHandling = NV.Ignore)]
public Station Dep { get; set; }
[J("@tn", NullValueHandling = NV.Ignore)]
public string Line { get; set; }
}
public class Station {
[J("x", NullValueHandling = NV.Ignore)]
public string X { get; set; }
[J("y", NullValueHandling = NV.Ignore)]
public string Y { get; set; }
[J("@dt", NullValueHandling = NV.Ignore)]
public string Date { get; set; }
[J("ebhf_name", NullValueHandling = NV.Ignore)]
public string EbhfName { get; set; }
[J("ebhf_nr", NullValueHandling = NV.Ignore)]
public string EbhfNr { get; set; }
[J("@t", NullValueHandling = NV.Ignore)]
public string Time { get; set; }
[J("n", NullValueHandling = NV.Ignore)]
public string Name { get; set; }
[J("nr", NullValueHandling = NV.Ignore)]
public string BhfNr { get; set; }
[J("plz", NullValueHandling = NV.Ignore)]
public string Plz { get; set; }
[J("ptf", NullValueHandling = NV.Ignore)]
public string Ptf { get; set; }
}
public class Tcklist {
[J("tck", NullValueHandling = NV.Ignore), JsonConverter(typeof(SingleOrArrayConverter<Tck>))]
public List<Tck> Tck { get; set; }
}
public class Tck {
[J("mtk", NullValueHandling = NV.Ignore)]
public Mtk Mtk { get; set; }
[J("@posnr", NullValueHandling = NV.Ignore)]
public string Posnr { get; set; }
[J("htdata", NullValueHandling = NV.Ignore)]
public Htdata Htdata { get; set; }
}
public class Htdata {
[J("ht", NullValueHandling = NV.Ignore)]
public List<Ht> Ht { get; set; }
}
public class Ht {
[J("@pos", NullValueHandling = NV.Ignore)]
public string Pos { get; set; }
[J("#text", NullValueHandling = NV.Ignore)]
public string Text { get; set; }
[J("@name", NullValueHandling = NV.Ignore)]
public string Name { get; set; }
[J("@type", NullValueHandling = NV.Ignore)]
public string Type { get; set; }
}
public class Mtk {
[J("@status", NullValueHandling = NV.Ignore)]
public string Status { get; set; }
[J("@dir", NullValueHandling = NV.Ignore)]
public string Dir { get; set; }
[J("iss", NullValueHandling = NV.Ignore)]
public string Iss { get; set; }
[J("tkey", NullValueHandling = NV.Ignore)]
public string Tkey { get; set; }
[J("bc", NullValueHandling = NV.Ignore)]
public Bc Bc { get; set; }
[J("nvplist", NullValueHandling = NV.Ignore)]
public Nvplist Nvplist { get; set; }
[J("reisender_vorname", NullValueHandling = NV.Ignore)]
public string ReisenderVorname { get; set; }
[J("reisender_nachname", NullValueHandling = NV.Ignore)]
public string ReisenderNachname { get; set; }
[J("txt", NullValueHandling = NV.Ignore)]
public string Txt { get; set; }
[J("zb", NullValueHandling = NV.Ignore)]
public string Zb { get; set; }
[J("ot_nr_hin", NullValueHandling = NV.Ignore)]
public string OtNrHin { get; set; }
}
public class Bc {
[J("rbs", NullValueHandling = NV.Ignore)]
public string Rbs { get; set; }
[J("anz", NullValueHandling = NV.Ignore)]
public string Anz { get; set; }
}
public class Rpheader {
[J("@ts", NullValueHandling = NV.Ignore)]
public string Ts { get; set; }
[J("@tnr", NullValueHandling = NV.Ignore)]
public string Tnr { get; set; }
}
public class Xml {
[J("@version", NullValueHandling = NV.Ignore)]
public string Version { get; set; }
[J("@encoding", NullValueHandling = NV.Ignore)]
public string Encoding { get; set; }
}
public partial class TicketResponse {
public static TicketResponse FromJson(string json) => JsonConvert.DeserializeObject<TicketResponse>(json, Converter.Settings);
}
internal static class Converter {
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings {
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters = {new IsoDateTimeConverter {DateTimeStyles = DateTimeStyles.AssumeUniversal}}
};
}
internal class SingleOrArrayConverter<T> : JsonConverter {
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(List<T>);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var token = JToken.Load(reader);
return token.Type == JTokenType.Array ? token.ToObject<List<T>>() : new List<T> {token.ToObject<T>()};
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
}
}

View File

@ -9,7 +9,7 @@ using trainav.web.database.Tables;
namespace trainav.web;
public static class Migrations {
private const int DbVer = 1;
private const int DbVer = 2;
private static readonly List<Migration> _migrations = new() {
new Migration(1,
@ -19,7 +19,28 @@ public static class Migrations {
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")
new Migration(1, "DROP TABLE Tickets_backup"),
new Migration(2,
"CREATE TEMPORARY TABLE Legs_backup(\"LegID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"TripID\" INTEGER NOT NULL, \"UserID\" INTEGER NOT NULL, \"TrainType\" TEXT NOT NULL, \"TrainNr\" INTEGER NOT NULL, \"DepStationID\" INTEGER NOT NULL, \"DepStation\" TEXT NOT NULL, \"DepTime\" TEXT NOT NULL, \"ArrStationID\" INTEGER NOT NULL, \"ArrStation\" TEXT NOT NULL, \"ArrTime\" TEXT NOT NULL, \"TicketID\" INTEGER, Comment TEXT)"),
new Migration(2,
"INSERT INTO Legs_backup SELECT LegID, TripID, UserID, TrainType, TrainNr, DepStationID, DepStation, DepTime, ArrStationID, ArrStation, ArrTime, TicketID, Comment FROM Legs"),
new Migration(2, "DROP Table Legs"),
new Migration(2,
"CREATE TABLE Legs(\"LegID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"TripID\" INTEGER NOT NULL, \"UserID\" INTEGER NOT NULL, \"TrainType\" TEXT NOT NULL, \"TrainNr\" INTEGER NOT NULL, \"DepStationID\" INTEGER NOT NULL, \"DepStation\" TEXT NOT NULL, \"DepTime\" TEXT NOT NULL, \"ArrStationID\" INTEGER NOT NULL, \"ArrStation\" TEXT NOT NULL, \"ArrTime\" TEXT NOT NULL, Comment TEXT)"),
new Migration(2, "INSERT INTO Legs SELECT LegID, TripID, UserID, TrainType, TrainNr, DepStationID, DepStation, DepTime, ArrStationID, ArrStation, ArrTime, Comment FROM Legs_backup"),
new Migration(2,
"CREATE TEMPORARY TABLE Users_backup(\"UserID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"Username\" TEXT NOT NULL UNIQUE, \"Password\" TEXT NOT NULL)"),
new Migration(2,
"INSERT INTO Users_backup SELECT UserID, Username, Password FROM Users"),
new Migration(2, "DROP Table Users"),
new Migration(2,
"CREATE TABLE Users(\"UserID\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, \"Username\" TEXT NOT NULL UNIQUE)"),
new Migration(2, "INSERT INTO Users SELECT UserID, Username FROM Users_backup"),
new Migration(2, "DROP TABLE Users_backup"),
new Migration(2, "DROP TABLE Legs_backup"),
new Migration(2, "DROP TABLE Tickets"),
new Migration(2, "DROP TABLE TicketLegs"),
new Migration(2, "DROP TABLE Cards")
};
public static void RunMigrations() {
@ -33,10 +54,7 @@ public static class Migrations {
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>();
@ -102,4 +120,4 @@ public static class Migrations {
db.Execute(_sql);
}
}
}
}

View File

@ -1,16 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@model CardModel
@{
ViewData["Title"] = "Card";
Response.Redirect("/Cards");
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
}
Card saved. Redirecting...

View File

@ -1,65 +0,0 @@
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.JSON.CardResponse;
using trainav.web.JSON.ListOrdersResponse;
namespace trainav.web.Pages;
public class CardModel : PageModel {
public void OnPost() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
using var db = new Database.DbConn();
var request = new XDocument(new XElement("rqorderheadlist",
new XElement("rqheader", new XAttribute("ts", "2020-02-19T15:59:00"), new XAttribute("l", "de"), new XAttribute("v", "19120000"),
new XAttribute("d", "iPad7,5"), new XAttribute("os", "iOS_13.3.1"), new XAttribute("app", "NAVIGATOR")),
new XElement("authlogin", new XAttribute("user", Request.Form["user"]), new XAttribute("pw", Request.Form["pass"]),
new XElement("sso", new XAttribute("genToken", "FALSE"))),
new XElement("criteria", new XAttribute("validonly", "0")))).ToString();
var response = new WebClient().UploadString("https://fahrkarten.bahn.de/mobile/dbc/xs.go", "POST", request);
var xmlobj = new XmlDocument();
xmlobj.LoadXml(response);
var json = JsonConvert.SerializeXmlNode(xmlobj);
var parsed = ListOrdersResponse.FromJson(json);
foreach (var order in parsed.Rporderheadlist.Orderheadlist.Orderhead.Where(order => order.On.StartsWith("EBC_"))) {
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", order.On)), new XElement("authname", new XAttribute("tln", Request.Form["name"]))))
.ToString();
response = new WebClient().UploadString("https://fahrkarten.bahn.de/mobile/dbc/xs.go", "POST", request);
xmlobj = new XmlDocument();
xmlobj.LoadXml(response);
json = JsonConvert.SerializeXmlNode(xmlobj);
var parsedCard = CardResponse.FromJson(json);
db.InsertWithInt32Identity(new Card {
OrderId = order.On,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
Class = int.Parse(parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "klasse").Text),
Value = int.Parse(parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "rbs").Text),
CardNumber = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "bcnummer").Text,
CardInfo = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Txt,
CardQr = parsedCard.Rporderdetails.Order.Tcklist.Tck.Htdata.Ht.First(p => p.Name == "barcode").Text,
CardSecCode = parsedCard.Rporderdetails.Order.Tcklist.Tck.Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text,
CardImage = parsedCard.Rporderdetails.Order.Tcklist.Tck.Bahncardimage.CdataSection,
Traveller = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "inhaber").Text,
ValidFrom = parsedCard.Rporderdetails.Order.Vfrom,
ValidTo = parsedCard.Rporderdetails.Order.Vto,
QrValidFrom = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "ebcbarcodegueltigab").Text,
QrValidTo = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "ebcbarcodegueltigbis").Text
});
}
}
}

View File

@ -1,169 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using System.Text
@model CardsModel
@{
ViewData["Title"] = "Cards";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
if (Request.Query.ContainsKey("refresh")) {
Response.Redirect("?edit=true");
return;
}
}
@if (Request.Query["edit"] == "true") {
<table class="table table-striped">
<thead>
<tr>
<th>Card</th>
<th>Number</th>
<th>Traveller</th>
<th>Card Validity</th>
<th>QR Validity</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var card in Model.Cards) {
<tr>
<td>@card.CardInfo.TrimEnd('#')</td>
<td>@card.CardNumber</td>
<td>@card.Traveller</td>
<td>
@{
var from = DateTime.Parse(card.ValidFrom);
var to = DateTime.Parse(card.ValidTo);
if (from > DateTime.Now) {
<span style="color: red">
@card.ValidFrom.Split("T")[0]
</span>
}
else {
@card.ValidFrom.Split("T")[0]
}
<br/>
if (to < DateTime.Now) {
<span style="color: red">
@card.ValidTo.Split("T")[0]
</span>
}
else {
@card.ValidTo.Split("T")[0]
}
}
</td>
<td>
@{
var qrfrom = DateTime.Parse(card.QrValidFrom);
var qrto = DateTime.Parse(card.QrValidTo);
if (qrfrom > DateTime.Now) {
<span style="color: red">
@card.QrValidFrom.Split("T")[0]
</span>
}
else {
@card.QrValidFrom.Split("T")[0]
}
<br/>
if (qrto < DateTime.Now) {
<span style="color: red">
@card.QrValidTo.Split("T")[0]
</span>
}
else {
@card.QrValidTo.Split("T")[0]
}
}
</td>
<td>
<a class="btn btn-sm btn-primary" href="?refresh=@card.CardId">Refresh QR</a>
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=card&id=@card.CardId&redir=@Request.GetDisplayUrl().UrlEncode()">Delete</a>
</td>
</tr>
}
</tbody>
</table>
<p>
Please refresh your BahnCard list in the mobile DB Navigator before clicking "Refresh QR". This will be fixed in a later release.
</p>
<a class="btn btn-sm btn-secondary" href="@Request.Path">Back</a>
<br/>
<br/>
<br/>
}
else if (Model.Cards.Any()) {
foreach (var card in Model.Cards) {
if (!card.CardQr.StartsWith("data:image/png"))
card.CardQr = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardQr));
if (!card.CardSecCode.StartsWith("data:image/png"))
card.CardSecCode = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardSecCode));
if (!card.CardImage.StartsWith("<?xml"))
card.CardImage = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardImage));
<div class="flex-grid">
<div class="flex-col">
<img src="@card.CardQr" alt="Ticketcode"/>
</div>
<div class="flex-col">
<img src="@card.CardSecCode" alt="Sichtmerkmal"/>
</div>
<div class="flex-col">
<div class="bahncard-outer">
<img class="bahncard" src='data:image/svg+xml;base64,@card.CardImage.Base64Encode()' alt="Bahncardimage"/>
</div>
</div>
</div>
var from = DateTime.Parse(card.ValidFrom);
var to = DateTime.Parse(card.ValidTo);
var qrfrom = DateTime.Parse(card.QrValidFrom);
var qrto = DateTime.Parse(card.QrValidTo);
if (from > DateTime.Now) {
<div class="alert alert-info" role="alert">
The above card is not valid yet.
</div>
}
if (to < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above card is expired.
</div>
}
if (qrfrom > DateTime.Now && !(from > DateTime.Now)) {
<div class="alert alert-info" role="alert">
The above QR code is somehow not valid yet. Congrats, please open a bug report.
</div>
}
if (qrto < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above QR code is expired. Please refresh the card. <a href="/Cards?edit=true">You can do that now</a>.
</div>
}
<br/>
}
<br/>
<a class="btn btn-sm btn-secondary" href="?edit=true">Edit cards</a>
}
@if (!Model.Cards.Any() || Request.Query["edit"] == "true") {
<h3>Get Cards from bahn.de account</h3>
<br/>
<form method="POST" action="/Card">
<div class="form-group">
<input type="text" class="form-control" id="InputUser" name="user" placeholder="bahn.de username">
</div>
<div class="form-group">
<input type="password" class="form-control" id="InputPassword" name="pass" placeholder="bahn.de password">
</div>
<div class="form-group">
<input type="text" class="form-control" id="inputName" name="name" placeholder="Last name of traveller">
</div>
@Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary">Submit</button>
</form>
}

View File

@ -1,54 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.JSON.CardResponse;
namespace trainav.web.Pages;
public class CardsModel : PageModel {
public List<Card> Cards;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
using var db = new Database.DbConn();
if (Request.Query.ContainsKey("refresh")) {
var card = db.Cards.First(p => p.CardId == int.Parse(Request.Query["refresh"]));
if (card.UserId != int.Parse(HttpContext.Session.GetString("uid")))
return;
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", card.OrderId)),
new XElement("authname", new XAttribute("tln", card.Traveller.Split(" ").Last())))).ToString();
var response = new WebClient().UploadString("https://fahrkarten.bahn.de/mobile/dbc/xs.go", "POST", request);
var xmlobj = new XmlDocument();
xmlobj.LoadXml(response);
var json = JsonConvert.SerializeXmlNode(xmlobj);
var parsedCard = CardResponse.FromJson(json);
card.CardQr = parsedCard.Rporderdetails.Order.Tcklist.Tck.Htdata.Ht.First(p => p.Name == "barcode").Text;
card.CardSecCode = parsedCard.Rporderdetails.Order.Tcklist.Tck.Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text;
card.CardImage = parsedCard.Rporderdetails.Order.Tcklist.Tck.Bahncardimage.CdataSection;
card.QrValidFrom = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "ebcbarcodegueltigab").Text;
card.QrValidTo = parsedCard.Rporderdetails.Order.Tcklist.Tck.Mtk.Nvplist.Nvp.First(p => p.Name == "ebcbarcodegueltigbis").Text;
db.Update(card);
return;
}
Cards = db.Cards.Where(p => p.UserId == int.Parse(HttpContext.Session.GetString("uid"))).ToList();
}
}

View File

@ -2,68 +2,50 @@
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using trainav.web.database
@using trainav.web.Utils
@model DeleteModel
@{
ViewData["Title"] = "Home";
ViewData["Title"] = "Home";
if (Request.Query.ContainsKey("confirm") && Request.Query["confirm"] == "true") {
Layout = null;
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
if (Request.Query.ContainsKey("redir")) {
Response.Redirect(Request.Query["redir"]);
}
else {
Response.Redirect("/");
}
if (Request.Query.ContainsKey("confirm") && Request.Query["confirm"] == "true") {
Layout = null;
return;
}
if (Request.Query.ContainsKey("redir")) {
Response.Redirect(Request.Query["redir"]);
}
else {
Response.Redirect("/");
}
<h3>Are you sure?</h3>
<p>
You are attempting to delete
@{
await using var db = new Database.DbConn();
return;
}
switch (Request.Query["item"]) {
case "trip": {
var trip = db.Trips.First(p => p.TripId == int.Parse(Request.Query["id"]));
if (trip.UserId != Model.AuthorizedUser.UserId) {
return;
}
var legs = db.Legs.Where(p => p.TripId == int.Parse(Request.Query["id"])).OrderBy(p => p.DepTime).ToList();
<h3>Are you sure?</h3>
<p>
You are attempting to delete
@{
await using var db = new Database.DbConn();
switch (Request.Query["item"]) {
case "trip": {
var trip = db.Trips.First(p => p.TripId == int.Parse(Request.Query["id"]));
if (trip.UserId != int.Parse(HttpContext.Session.GetString("uid"))) {
return;
}
var legs = db.Legs.Where(p => p.TripId == int.Parse(Request.Query["id"])).OrderBy(p => p.DepTime).ToList();
<span>
the trip from <b>@legs.First().DepStation</b> to <b>@legs.Last().ArrStation</b>, starting <i>@legs.First().DepTime</i>
</span>
break;
}
case "leg": {
Response.Redirect($"/Delete?item={Request.Query["item"]}&id={Request.Query["id"]}&confirm=true&redir={Request.Query["redir"].ToString().UrlEncode()}");
break;
}
case "ticket": {
Response.Redirect($"/Delete?item={Request.Query["item"]}&id={Request.Query["id"]}&confirm=true&redir={Request.Query["redir"].ToString().UrlEncode()}");
break;
}
case "card": {
var card = db.Cards.First(p => p.CardId == int.Parse(Request.Query["id"]));
if (card.UserId != int.Parse(HttpContext.Session.GetString("uid"))) {
return;
}
<span>
the card <b>@card.CardInfo.TrimEnd('#')</b> with the number <i>@card.CardNumber</i>, owned by <b>@card.Traveller</b>
</span>
break;
}
}
}
</p>
<a href="@Request.Query["redir"]" class="btn btn-sm btn-secondary">Cancel</a>
<a href="/Delete?item=@Request.Query["item"]&id=@Request.Query["id"]&confirm=true&redir=@Request.Query["redir"].ToString().UrlEncode()" class="btn btn-sm btn-danger">Confirm</a>
}
<span>
the trip from <b>@legs.First().DepStation</b> to <b>@legs.Last().ArrStation</b>, starting <i>@legs.First().DepTime</i>
</span>
break;
}
case "leg": {
Response.Redirect($"/Delete?item={Request.Query["item"]}&id={Request.Query["id"]}&confirm=true&redir={Request.Query["redir"].ToString().UrlEncode()}");
break;
}
}
}
</p>
<a href="@Request.Query["redir"]" class="btn btn-sm btn-secondary">Cancel</a>
<a href="/Delete?item=@Request.Query["item"]&id=@Request.Query["id"]&confirm=true&redir=@Request.Query["redir"].ToString().UrlEncode()" class="btn btn-sm btn-danger">Confirm</a>
}

View File

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.Utils;
namespace trainav.web.Pages;
@ -11,21 +12,17 @@ public class DeleteModel : PageModel {
public User AuthorizedUser;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
if (!Request.Query.ContainsKey("confirm") || Request.Query["confirm"] != "true")
return;
var uid = int.Parse(HttpContext.Session.GetString("uid"));
using var db = new Database.DbConn();
AuthorizedUser = db.Users.FirstOrDefault(p => p.UserId == uid);
AuthorizedUser = db.Users.FirstOrDefault(p => p.Username == AuthUtil.GetRemoteUser(HttpContext, db));
var id = int.Parse(Request.Query["id"]);
switch (Request.Query["item"]) {
case "trip": {
var trip = db.Trips.First(p => p.TripId == id);
if (trip.UserId != int.Parse(HttpContext.Session.GetString("uid")))
if (trip.UserId != AuthorizedUser!.UserId)
return;
db.Trips.Delete(p => p.TripId == id);
@ -34,7 +31,7 @@ public class DeleteModel : PageModel {
}
case "leg": {
var leg = db.Legs.First(p => p.LegId == id);
if (leg.UserId != int.Parse(HttpContext.Session.GetString("uid")))
if (leg.UserId != AuthorizedUser!.UserId)
return;
var tripid = db.Legs.First(p => p.LegId == id).TripId;
@ -62,22 +59,6 @@ public class DeleteModel : PageModel {
break;
}
case "ticket": {
var leg = db.Legs.First(p => p.LegId == id);
if (leg.UserId != int.Parse(HttpContext.Session.GetString("uid")))
return;
db.Legs.Where(p => p.LegId == id).Set(p => p.TicketId, 0).Update();
break;
}
case "card": {
var card = db.Cards.First(p => p.CardId == id);
if (card.UserId != int.Parse(HttpContext.Session.GetString("uid")))
return;
db.Cards.Delete(p => p.CardId == id);
break;
}
}
}
}
}

View File

@ -1,101 +1,97 @@
@page
@using LinqToDB
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using LinqToDB
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using trainav.web.Utils
@using trainav.web.database
@model IndexModel
@{
ViewData["Title"] = "Home";
ViewData["Title"] = "Home";
}
<div class="text-center">
@if (HttpContext.Session.GetString("authorized") != "true") {
<h1 class="display-4">Welcome</h1>
<p>Please <a href="/Login">log in</a> to see your personal plan.</p>
}
else {
<h1 class="display-4">
Welcome, @Model.AuthorizedUser.Username
</h1>
<p>
Here are your planned trips.
</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Origin</th>
<th scope="col">Via</th>
<th scope="col">Destination</th>
<th scope="col">Comments</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
@{
await using var db = new Database.DbConn();
var trips = db.Trips.Where(p => p.UserId == Model.AuthorizedUser.UserId).ToList();
<h1 class="display-4">
Welcome, @Model.AuthorizedUser.Username
</h1>
<p>
Here are your planned trips.
</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Origin</th>
<th scope="col">Via</th>
<th scope="col">Destination</th>
<th scope="col">Comments</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
@{
await using var db = new Database.DbConn();
var trips = db.Trips.Where(p => p.UserId == Model.AuthorizedUser.UserId).ToList();
foreach (var trip in trips.Where(trip => !db.Legs.Any(p => p.TripId == trip.TripId))) {
await db.DeleteAsync(trip);
trips = db.Trips.Where(p => p.UserId == Model.AuthorizedUser.UserId).ToList();
}
foreach (var trip in trips.Where(trip => !db.Legs.Any(p => p.TripId == trip.TripId))) {
await db.DeleteAsync(trip);
trips = db.Trips.Where(p => p.UserId == Model.AuthorizedUser.UserId).ToList();
}
foreach (var trip in trips.OrderBy(p => db.Legs.Where(a => a.TripId == p.TripId).OrderBy(leg => leg.DepTime).First().DepTime)) {
var legs = db.Legs.Where(p => p.TripId == trip.TripId).OrderBy(p => p.DepTime).ToList();
<tr>
<td>
<b>@legs.First().DepStation.Delimit(30)</b>
<br/>
<small>@DateTime.Parse(legs.First().DepTime).ToString("ddd dd.MM.yyyy, HH:mm")</small>
</td>
<td>
@((from index in from leg in legs where leg.TrainType == "placeholder" select legs.IndexOf(leg) select legs[index - 1].ArrStation.Delimit(30)).ToList().DefaultIfEmpty("-").Aggregate((s1, s2) => $"{s1}, {s2}"))
</td>
<td>
<b>@legs.Last().ArrStation.Delimit(30)</b>
<br/>
<small>@DateTime.Parse(legs.Last().ArrTime).ToString("ddd dd.MM.yyyy, HH:mm")</small>
</td>
<td>
@Html.Raw(legs.Where(leg => !string.IsNullOrWhiteSpace(leg.Comment)).Select(p => p.Comment.Replace(", ", "<br/>")).DefaultIfEmpty("").Aggregate((s1, s2) => $"{s1}<br/>{s2}"))
</td>
<td>
<a class="btn btn-sm btn-primary" href="/Trip?id=@trip.TripId">View</a>
&nbsp;
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=trip&id=@trip.TripId&redir=@Request.GetDisplayUrl().UrlEncode()">Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
<br/>
<div class="d-flex flex-row" style="justify-content: space-between">
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/Ticket">
<h3>Add trip from ticket</h3>
<br/>
<div class="form-group">
<input type="text" class="form-control" name="order" placeholder="bahn.de order #">
</div>
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Last name of traveller">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/OEAPI">
<h3>Add trip from <a href="https://oeffisear.ch" target="_blank">oeffisear.ch</a> or <a href="https://transit.ztn.sh" target="_blank">transit.ztn.sh</a></h3>
<br/>
<div class="form-group">
<input type="text" class="form-control" name="link" placeholder="paste link / shortcode here">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
}
foreach (var trip in trips.OrderBy(p => db.Legs.Where(a => a.TripId == p.TripId).OrderBy(leg => leg.DepTime).First().DepTime)) {
var legs = db.Legs.Where(p => p.TripId == trip.TripId).OrderBy(p => p.DepTime).ToList();
<tr>
<td>
<b>@legs.First().DepStation.Delimit(30)</b>
<br/>
<small>@DateTime.Parse(legs.First().DepTime).ToString("ddd dd.MM.yyyy, HH:mm")</small>
</td>
<td>
@((from index in from leg in legs where leg.TrainType == "placeholder" select legs.IndexOf(leg) select legs[index - 1].ArrStation.Delimit(30)).ToList().DefaultIfEmpty("-").Aggregate((s1, s2) => $"{s1}, {s2}"))
</td>
<td>
<b>@legs.Last().ArrStation.Delimit(30)</b>
<br/>
<small>@DateTime.Parse(legs.Last().ArrTime).ToString("ddd dd.MM.yyyy, HH:mm")</small>
</td>
<td>
@Html.Raw(legs.Where(leg => !string.IsNullOrWhiteSpace(leg.Comment)).Select(p => p.Comment.Replace(", ", "<br/>")).DefaultIfEmpty("").Aggregate((s1, s2) => $"{s1}<br/>{s2}"))
</td>
<td>
<a class="btn btn-sm btn-primary" href="/Trip?id=@trip.TripId">View</a>
&nbsp;
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=trip&id=@trip.TripId&redir=@Request.GetDisplayUrl().UrlEncode()">Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
<br/>
<div class="d-flex flex-row" style="justify-content: space-between">
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/Ticket">
<h3>Add trip from ticket</h3>
<br/>
<div class="form-group">
<input type="text" class="form-control" name="order" placeholder="bahn.de order #">
</div>
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Last name of traveller">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/OEAPI">
<h3>Add trip from <a href="https://oeffisear.ch" target="_blank">oeffisear.ch</a> or <a href="https://transit.ztn.sh" target="_blank">transit.ztn.sh</a></h3>
<br/>
<div class="form-group">
<input type="text" class="form-control" name="link" placeholder="paste link / shortcode here">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.Utils;
namespace trainav.web.Pages;
@ -10,11 +11,7 @@ public class IndexModel : PageModel {
public User AuthorizedUser;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
var uid = int.Parse(HttpContext.Session.GetString("uid"));
using var db = new Database.DbConn();
AuthorizedUser = db.Users.FirstOrDefault(p => p.UserId == uid);
AuthorizedUser = db.Users.FirstOrDefault(p => p.Username == AuthUtil.GetRemoteUser(HttpContext, db));
}
}
}

View File

@ -1,151 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using trainav.web.database
@using System.Text
@model InspectionModel
@{
ViewData["Title"] = "Inspection";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
if (Model.Leg.UserId != int.Parse(HttpContext.Session.GetString("uid"))) {
return;
}
}
<p>
Ticket for <b>@Model.Leg.TrainType @Model.Leg.TrainNr</b> from <b>@Model.Leg.DepStation</b> to <b>@Model.Leg.ArrStation</b>, starting @DateTime.Parse(Model.Leg.DepTime).ToString("yyyy-MM-dd HH:mm")
</p>
<div class="flex-grid">
<div class="flex-col">
<img src="@Model.Ticket.TicketQr" alt="Ticketcode"/>
</div>
<div class="flex-col">
<img src="@Model.Ticket.TicketSecCode" alt="Sichtmerkmal"/>
</div>
</div>
<br/>
<br/>
@Model.Ticket.TicketInfo
<br/>
<br/>
@if (Model.Ticket.TicketInfo.Contains("BC 50")) {
await using var db = new Database.DbConn();
if (db.Cards.Any(p => p.Value == 50 && p.Traveller == Model.Ticket.Traveller && p.UserId == Model.Leg.UserId)) {
var card = db.Cards.First(p => p.Value == 50 && p.Traveller == Model.Ticket.Traveller && p.UserId == Model.Leg.UserId);
if (!card.CardQr.StartsWith("data:image/png"))
card.CardQr = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardQr));
if (!card.CardSecCode.StartsWith("data:image/png"))
card.CardSecCode = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardSecCode));
if (!card.CardImage.StartsWith("<?xml"))
card.CardImage = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardImage));
<div class="flex-grid">
<div class="flex-col">
<img src="@card.CardQr" alt="Ticketcode"/>
</div>
<div class="flex-col">
<img src="@card.CardSecCode" alt="Sichtmerkmal"/>
</div>
<div class="flex-col">
<div class="bahncard-outer">
<img class="bahncard" src='data:image/svg+xml;base64,@card.CardImage.Base64Encode()' alt="Bahncardimage"/>
</div>
</div>
</div>
var from = DateTime.Parse(card.ValidFrom);
var to = DateTime.Parse(card.ValidTo);
var qrfrom = DateTime.Parse(card.QrValidFrom);
var qrto = DateTime.Parse(card.QrValidTo);
if (from > DateTime.Now) {
<div class="alert alert-info" role="alert">
The above card is not valid yet.
</div>
}
if (to < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above card is expired.
</div>
}
if (qrfrom > DateTime.Now && !(from > DateTime.Now)) {
<div class="alert alert-info" role="alert">
The above QR code is somehow not valid yet. Congrats, please open a bug report.
</div>
}
if (qrto < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above QR code is expired. Please refresh the card. <a href="/Cards?edit=true">You can do that now</a>.
</div>
}
}
else {
<div class="alert alert-warning" role="alert">
I would show your BahnCard but you haven't added a card matching the value and name of the ticket yet. <a href="/Cards">You can do that now</a>.
</div>
}
}
else if (Model.Ticket.TicketInfo.Contains("BC 25")) {
await using var db = new Database.DbConn();
if (db.Cards.Any(p => p.Value == 25 && p.Traveller == Model.Ticket.Traveller && p.UserId == Model.Leg.UserId)) {
var card = db.Cards.First(p => p.Value == 25 && p.Traveller == Model.Ticket.Traveller && p.UserId == Model.Leg.UserId);
if (!card.CardQr.StartsWith("data:image/png"))
card.CardQr = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardQr));
if (!card.CardSecCode.StartsWith("data:image/png"))
card.CardSecCode = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardSecCode));
if (!card.CardImage.StartsWith("<?xml"))
card.CardImage = Encoding.UTF8.GetString(Convert.FromBase64String(card.CardImage));
<div class="flex-grid">
<div class="flex-col">
<img src="@card.CardQr" alt="Ticketcode"/>
</div>
<div class="flex-col">
<img src="@card.CardSecCode" alt="Sichtmerkmal"/>
</div>
<div class="flex-col">
<div class="bahncard-outer">
<img class="bahncard" src='data:image/svg+xml;base64,@card.CardImage.Base64Encode()' alt="Bahncardimage"/>
</div>
</div>
</div>
var from = DateTime.Parse(card.ValidFrom);
var to = DateTime.Parse(card.ValidTo);
var qrfrom = DateTime.Parse(card.QrValidFrom);
var qrto = DateTime.Parse(card.QrValidTo);
if (from > DateTime.Now) {
<div class="alert alert-info" role="alert">
The above card is not valid yet.
</div>
}
if (to < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above card is expired.
</div>
}
if (qrfrom > DateTime.Now && !(from > DateTime.Now)) {
<div class="alert alert-info" role="alert">
The above QR code is somehow not valid yet. Congrats, please open a bug report.
</div>
}
if (qrto < DateTime.Now) {
<div class="alert alert-warning" role="alert">
The above QR code is expired. Please refresh the card. <a href="/Cards?edit=true">You can do that now</a>.
</div>
}
}
else {
<div class="alert alert-warning" role="alert">
I would show your BahnCard but you haven't added a card matching the value and name of the ticket yet. <a href="/Cards">You can do that now</a>.
</div>
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
namespace trainav.web.Pages;
public class InspectionModel : PageModel {
public Leg Leg;
public Ticket Ticket;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
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

@ -1,30 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@model LoginModel
@{
ViewData["Title"] = "Login";
if (HttpContext.Session.GetString("authorized") == "true") {
if (Request.Query.ContainsKey("redir")) {
Response.Redirect(Request.Query["redir"]);
}
else {
Response.Redirect("/");
}
return;
}
}
<h3>@ViewData["Title"]</h3>
<form method="POST">
<div class="form-group">
<label for="InputUser">Username</label>
<input type="text" class="form-control" id="InputUser" name="user">
</div>
<div class="form-group">
<label for="InputPassword">Password</label>
<input type="password" class="form-control" id="InputPassword" name="pass">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

View File

@ -1,7 +0,0 @@
@page
@model LogoutModel
@{
Layout = null;
Response.Redirect("/");
}

View File

@ -1,9 +0,0 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace trainav.web.Pages;
public class LogoutModel : PageModel {
public void OnGet() {
HttpContext.Session.Clear();
}
}

View File

@ -1,16 +1,12 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using trainav.web.Utils
@model OEAPIModel
@{
ViewData["Title"] = "OEAPI";
ViewData["Title"] = "OEAPI";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
Response.Redirect("/Trip?id=" + Model.TripId + "&edit=true");
Response.Redirect("/Trip?id=" + Model.TripId + "&edit=true");
}
Trip saved. Redirecting...
Trip saved. Redirecting...

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.JSON;
using trainav.web.Utils;
using Leg = trainav.web.database.Tables.Leg;
// ReSharper disable PossibleInvalidOperationException
@ -18,9 +19,6 @@ public class OEAPIModel : PageModel {
public int TripId;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
var link = Request.Query["link"].ToString();
var shortcode = link;
var oepage = "oeffisear.ch";
@ -40,13 +38,15 @@ public class OEAPIModel : PageModel {
var parsed = OeapiResponse.FromJson(response);
var authorizedUser = db.Users.FirstOrDefault(p => p.Username == AuthUtil.GetRemoteUser(HttpContext, db));
if (!string.IsNullOrWhiteSpace(Request.Query["tripid"].ToString()))
if (db.Trips.First(p => p.TripId == int.Parse(Request.Query["tripid"].ToString())).UserId != int.Parse(HttpContext.Session.GetString("uid")))
if (db.Trips.First(p => p.TripId == int.Parse(Request.Query["tripid"].ToString())).UserId != authorizedUser!.UserId)
return;
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 = authorizedUser!.UserId });
foreach (var journey in parsed.Data.Journeys[jid].Legs.Where(p => p.IsTransfer != true && p.IsWalking != true)) {
var arrtime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
@ -62,7 +62,7 @@ public class OEAPIModel : PageModel {
db.InsertWithInt32Identity(new Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
UserId = authorizedUser!.UserId,
TrainType = journey.Line.ProductName,
TrainNr = trainNo,
ArrStation = journey.Arrival.Point.Stop.Name,
@ -76,4 +76,4 @@ public class OEAPIModel : PageModel {
TripId = tripId;
}
}
}

View File

@ -1,44 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using trainav.web.database
@model PlainModel
@{
ViewData["Title"] = "Plain";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
await using var db = new Database.DbConn();
}
<div>
<code>
@foreach (var trip in db.Trips.Where(p => p.UserId == Model.AuthorizedUser.UserId).ToList().OrderBy(p => db.Legs.Where(l => l.TripId == p.TripId).OrderBy(l => l.DepTime).First().DepTime)) {
<div>
&nbsp;
</div>
foreach (var leg in db.Legs.Where(p => p.TripId == trip.TripId).OrderBy(p => p.DepTime)) {
if (leg.TrainType == "placeholder") {
<div>
... ... &nbsp;&nbsp; ..:.. ... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - &nbsp; ... ... &nbsp;&nbsp; - &nbsp; ..:.. ... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...
</div>
continue;
}
var deptime = DateTime.Parse(leg.DepTime);
var arrtime = DateTime.Parse(leg.ArrTime);
var date = DateTime.Parse(leg.DepTime).ToString("ddd dd.MM.");
var dept = date + " " + deptime.ToString("HH:mm");
var depst = leg.DepStation.PadRight(20, ' ').Substring(0, 20).Replace(" ", "&nbsp;");
var arrt = arrtime.ToString("HH:mm");
var arrst = leg.ArrStation.PadRight(20, ' ').Substring(0, 20).Replace(" ", "&nbsp;");
var line = leg.TrainType.PadRight(3).Replace(" ", "&nbsp;") + "&nbsp;" + leg.TrainNr.ToString().PadRight(6).Replace(" ", "&nbsp;");
var comment = leg.Comment;
<div>
@dept @Html.Raw(depst) - &nbsp; @Html.Raw(line) - &nbsp; @arrt @Html.Raw(arrst) @(string.IsNullOrWhiteSpace(comment) ? "..." : comment)
</div>
}
}
</code>
</div>

View File

@ -1,20 +0,0 @@
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
namespace trainav.web.Pages;
public class PlainModel : PageModel {
public User AuthorizedUser;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
var uid = int.Parse(HttpContext.Session.GetString("uid"));
using var db = new Database.DbConn();
AuthorizedUser = db.Users.FirstOrDefault(p => p.UserId == uid);
}
}

View File

@ -1,29 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@model RegisterModel
@{
ViewData["Title"] = "Register";
if (HttpContext.Session.GetString("authorized") == "true") {
Response.Redirect("/");
return;
}
}
<h3>@ViewData["Title"]</h3>
<form method="POST">
<div class="form-group">
<label for="InputUser">Username</label>
<input type="text" class="form-control" id="InputUser" name="user">
</div>
<div class="form-group">
<label for="InputPassword">Password</label>
<input type="password" class="form-control" id="InputPassword" name="pass">
</div>
<div class="form-group">
<label for="InputCode">Register Code</label>
<input type="password" class="form-control" id="InputCode" name="code">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>

View File

@ -1,31 +0,0 @@
using System.Linq;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
namespace trainav.web.Pages;
public class RegisterModel : PageModel {
public void OnPost() {
if (!Request.HasFormContentType
|| string.IsNullOrWhiteSpace(Request.Form["user"])
|| string.IsNullOrWhiteSpace(Request.Form["pass"])
|| string.IsNullOrWhiteSpace(Request.Form["code"]))
return;
if (Request.Form["code"] != System.IO.File.ReadAllLines("regkey.txt")[0])
return;
using var db = new Database.DbConn();
var user = db.Users.FirstOrDefault(p => p.Username == Request.Form["user"].ToString());
if (user != null)
return; //user already exists
var uid = db.InsertWithInt32Identity(new User { Username = Request.Form["user"].ToString(), Password = Request.Form["pass"].ToString().Sha256() });
HttpContext.Session.SetString("uid", uid.ToString());
HttpContext.Session.SetString("authorized", "true");
}
}

View File

@ -1,67 +1,41 @@
@using Microsoft.AspNetCore.Http
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@ViewData["Title"] - Trainav</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="~/css/site.css"/>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@ViewData["Title"] - Trainav</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="~/css/site.css"/>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">Trainav <sup>v2</sup></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
@if (Context.Session.GetString("authorized") == "true") {
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Plain">Plain</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Cards">Cards</a>
</li>
}
</ul>
<ul class="navbar-nav ml-auto">
@if (Context.Session.GetString("authorized") != "true") {
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Register">Register</a>
</li>
}
else {
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Logout">Logout</a>
</li>
}
</ul>
</div>
</div>
</nav>
<nav class="navbar navbar-expand-md navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">Trainav <sup>v2</sup></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
&copy; 2020-@DateTime.Now.Year - Laura Hausmann - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
<div class="container">
&copy; 2020-@DateTime.Now.Year - Laura Hausmann - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
@ -70,4 +44,4 @@
@RenderSection("Scripts", false)
</body>
</html>
</html>

View File

@ -1,16 +0,0 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@model TicketModel
@{
ViewData["Title"] = "Ticket";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
Response.Redirect("/Trip?id=" + Model.TripId + "&edit=true");
}
Ticket saved. Redirecting...

View File

@ -1,255 +0,0 @@
using System;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.JSON;
using Leg = trainav.web.database.Tables.Leg;
namespace trainav.web.Pages;
public class TicketModel : PageModel {
public int TripId;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
using var db = new Database.DbConn();
if (!string.IsNullOrWhiteSpace(Request.Query["tripid"].ToString()))
if (db.Trips.First(p => p.TripId == int.Parse(Request.Query["tripid"].ToString())).UserId != int.Parse(HttpContext.Session.GetString("uid")))
return;
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"] + "_2")?.TicketId;
var lastleg_ticket = 0;
foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId).ToList()) {
if (leg.TrainType == "placeholder") {
db.Insert(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
TrainType = "placeholder",
TrainNr = lastleg_ticket,
ArrStation = "_",
ArrStationId = 0,
ArrTime = "_",
DepStation = "_",
DepStationId = 0,
DepTime = db.Legs.First(p => p.LegId == lastleg_ticket).DepTime + "_placeholder"
});
continue;
}
lastleg_ticket = db.InsertWithInt32Identity(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
TrainType = leg.TrainType,
TrainNr = leg.TrainNr,
ArrStation = leg.ArrStation,
ArrStationId = leg.ArrStationId,
ArrTime = leg.ArrTime,
DepStation = leg.DepStation,
DepStationId = leg.DepStationId,
DepTime = leg.DepTime,
TicketId = leg.TicketId
});
}
if (ticketId2 != null) {
var lastleg = 0;
foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId2).ToList())
db.InsertWithInt32Identity(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
TrainType = leg.TrainType,
TrainNr = leg.TrainNr,
ArrStation = leg.ArrStation,
ArrStationId = leg.ArrStationId,
ArrTime = leg.ArrTime,
DepStation = leg.DepStation,
DepStationId = leg.DepStationId,
DepTime = leg.DepTime,
TicketId = leg.TicketId
});
}
TripId = tripId;
}
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 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();
xmlobj.LoadXml(response);
var json = JsonConvert.SerializeXmlNode(xmlobj);
var parsed = TicketResponse.FromJson(json);
var tripId = Request.Query["action"] == "addleg"
? int.Parse(Request.Query["tripid"])
: db.InsertWithInt32Identity(new Trip { UserId = int.Parse(HttpContext.Session.GetString("uid")) });
int ticketId;
int? ticketId2 = null;
switch (parsed.Rporderdetails.Order.Tcklist.Tck.Count) {
case 1: {
ticketId = db.InsertWithInt32Identity(new Ticket {
OrderId = Request.Query["order"],
TicketInfo = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.Txt,
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.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
});
break;
}
case 2: {
ticketId = db.InsertWithInt32Identity(new Ticket {
OrderId = Request.Query["order"],
TicketInfo = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.Txt,
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
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
Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderVorname
+ " "
+ parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderNachname
});
break;
}
default: {
throw new Exception("Order contains zero or more than two tickets");
}
}
var lastleg = 0;
var lastticketleg = 0;
foreach (var leg in parsed.Rporderdetails.Order.Schedulelist.Out.Trainlist.Train) {
lastleg = db.InsertWithInt32Identity(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
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
});
lastticketleg = 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)
});
}
if (parsed.Rporderdetails.Order.Schedulelist.Ret != null) {
db.Insert(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
TrainType = "placeholder",
TrainNr = lastleg,
ArrStation = "_",
ArrStationId = 0,
ArrTime = "_",
DepStation = "_",
DepStationId = 0,
DepTime = db.Legs.First(p => p.LegId == lastleg).DepTime + "_placeholder"
});
db.Insert(new TicketLeg {
TicketId = ticketId2 ?? ticketId,
TrainType = "placeholder",
TrainNr = lastticketleg,
ArrStation = "_",
ArrStationId = 0,
ArrTime = "_",
DepStation = "_",
DepStationId = 0,
DepTime = db.TicketLegs.First(p => p.TicketLegId == lastticketleg).DepTime + "_placeholder"
});
foreach (var leg in parsed.Rporderdetails.Order.Schedulelist.Ret.Trainlist.Train) {
db.InsertWithInt32Identity(new database.Tables.Leg {
TripId = tripId,
UserId = int.Parse(HttpContext.Session.GetString("uid")),
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 = ticketId2 ?? ticketId
});
db.InsertWithInt32Identity(new TicketLeg {
TicketId = ticketId2 ?? 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)
});
}
}
TripId = tripId;
}
}
}

View File

@ -1,185 +1,170 @@
@page
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Extensions
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using trainav.web.Utils
@model TripModel
@{
ViewData["Title"] = "Trip";
ViewData["Title"] = "Trip";
if (HttpContext.Session.GetString("authorized") != "true") {
Response.Redirect($"/Login?&redir={Request.GetDisplayUrl().UrlEncode()}");
return;
}
if (Request.Query.ContainsKey("separator")) {
Response.Redirect(Request.Query["redir"]);
return;
}
if (Request.Query.ContainsKey("separator")) {
Response.Redirect(Request.Query["redir"]);
return;
}
if (Model.RedirToIndex) {
Response.Redirect("/");
}
if (Model.RedirToIndex) {
Response.Redirect("/");
}
if (Request.HasFormContentType) {
Response.Redirect(Request.GetEncodedUrl());
return;
}
if (Request.HasFormContentType) {
Response.Redirect(Request.GetEncodedUrl());
return;
}
if (!Model.Legs.Any()) {
Response.Redirect("/");
return;
}
if (!Model.Legs.Any()) {
Response.Redirect("/");
return;
}
if (Model.Legs.First().UserId != Model.AuthorizedUser.UserId) {
return;
}
if (Model.Legs.First().UserId != int.Parse(HttpContext.Session.GetString("uid"))) {
return;
}
var dep = Model.Legs.First().DepStation;
var arr = Model.Legs.Last().ArrStation;
var dep = Model.Legs.First().DepStation;
var arr = Model.Legs.Last().ArrStation;
}
<div>
<p>
Your Trip from <b>@dep</b> to <b>@arr</b>, starting @DateTime.Parse(Model.Legs.First().DepTime).ToString("yyyy-MM-dd HH:mm")
</p>
<p>
Your Trip from <b>@dep</b> to <b>@arr</b>, starting @DateTime.Parse(Model.Legs.First().DepTime).ToString("yyyy-MM-dd HH:mm")
</p>
</div>
<div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col">Departure</th>
<th scope="col">Arrival</th>
<th scope="col">Train</th>
<th scope="col">Comment</th>
@if (!Request.Query.ContainsKey("edit")) {
<th scope="col">Actions</th>
}
else {
<th scope="col">Danger zone</th>
}
</tr>
</thead>
<tbody>
@foreach (var leg in Model.Legs) {
if (leg.TrainType == "placeholder") {
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
@if (!Request.Query.ContainsKey("edit")) {
<td></td>
}
else {
<td>
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=leg&id=@leg.LegId&redir=@Request.GetDisplayUrl().UrlEncode()">- Separator</a>
</td>
}
continue;
}
var deptime = DateTime.Parse(leg.DepTime);
var arrtime = DateTime.Parse(leg.ArrTime);
var date = DateTime.Parse(leg.DepTime).ToString("ddd, dd.MM.");
var dept = deptime.ToString("HH:mm");
var arrt = arrtime.ToString("HH:mm");
<tr>
<td>
@date
</td>
<td>
<b>@dept</b> @Html.Raw(leg.DepStation.PadRight(30, ' ').Substring(0, 30).TrimEnd())
</td>
<td>
<b>@arrt</b> @Html.Raw(leg.ArrStation.PadRight(30, ' ').Substring(0, 30).TrimEnd())
</td>
<td>@leg.TrainType @leg.TrainNr</td>
@if (!Request.Query.ContainsKey("edit")) {
<td>
@if (!string.IsNullOrWhiteSpace(leg.Comment)) {
@Html.Raw(leg.Comment)
}
</td>
<td>
@if (leg.TicketId != 0) {
<a class="btn btn-sm btn-danger" href="/Inspection?leg=@leg.LegId" target="_blank">Ticket</a>
}
else {
<a class="btn btn-sm btn-danger disabled">Ticket</a>
}
<a class="btn btn-sm btn-primary" href="https://marudor.de/details/@leg.TrainType @leg.TrainNr/@(deptime.ToUniversalTime().ToString("O"))/?station=@leg.DepStationId" target="_blank">Marudor</a>
<a class="btn btn-sm btn-warning" href="https://travelynx.de/s/@leg.DepStationId?train=@leg.TrainType @leg.TrainNr" target="_blank">Travelynx</a>
</td>
}
else {
<td>
<form method="POST">
<input type="hidden" name="id" value="@leg.LegId">
<input type="text" class="form-control" name="comment" value="@leg.Comment"/>
</form>
</td>
<td>
@{
if (Model.Legs.All(p => p.DepTime != leg.DepTime + "_placeholder") && Model.Legs.IndexOf(leg) != Model.Legs.Count - 1) {
<a class="btn btn-sm btn-outline-secondary" href="?separator=true&legid=@leg.LegId&id=@leg.TripId&redir=@Request.GetDisplayUrl().UrlEncode()">+ Separator</a>
}
else {
<a class="btn btn-sm btn-outline-secondary disabled">+ Separator</a>
}
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col">Departure</th>
<th scope="col">Arrival</th>
<th scope="col">Train</th>
<th scope="col">Comment</th>
@if (!Request.Query.ContainsKey("edit")) {
<th scope="col">Actions</th>
}
else {
<th scope="col">Danger zone</th>
}
</tr>
</thead>
<tbody>
@foreach (var leg in Model.Legs) {
if (leg.TrainType == "placeholder") {
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
@if (!Request.Query.ContainsKey("edit")) {
<td></td>
}
else {
<td>
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=leg&id=@leg.LegId&redir=@Request.GetDisplayUrl().UrlEncode()">- Separator</a>
</td>
}
continue;
}
var deptime = DateTime.Parse(leg.DepTime);
var arrtime = DateTime.Parse(leg.ArrTime);
var date = DateTime.Parse(leg.DepTime).ToString("ddd, dd.MM.");
var dept = deptime.ToString("HH:mm");
var arrt = arrtime.ToString("HH:mm");
<tr>
<td>
@date
</td>
<td>
<b>@dept</b> @Html.Raw(leg.DepStation.PadRight(30, ' ').Substring(0, 30).TrimEnd())
</td>
<td>
<b>@arrt</b> @Html.Raw(leg.ArrStation.PadRight(30, ' ').Substring(0, 30).TrimEnd())
</td>
<td>@leg.TrainType @leg.TrainNr</td>
@if (!Request.Query.ContainsKey("edit")) {
<td>
@if (!string.IsNullOrWhiteSpace(leg.Comment)) {
@Html.Raw(leg.Comment)
}
</td>
<td>
<a class="btn btn-sm btn-primary" href="https://marudor.de/details/@leg.TrainType @leg.TrainNr/@(deptime.ToUniversalTime().ToString("O"))/?station=@leg.DepStationId" target="_blank">Marudor</a>
<a class="btn btn-sm btn-warning" href="https://travelynx.de/s/@leg.DepStationId?train=@leg.TrainType @leg.TrainNr" target="_blank">Travelynx</a>
</td>
}
else {
<td>
<form method="POST">
<input type="hidden" name="id" value="@leg.LegId">
<input type="text" class="form-control" name="comment" value="@leg.Comment"/>
</form>
</td>
<td>
@{
if (Model.Legs.All(p => p.DepTime != leg.DepTime + "_placeholder") && Model.Legs.IndexOf(leg) != Model.Legs.Count - 1) {
<a class="btn btn-sm btn-outline-secondary" href="?separator=true&legid=@leg.LegId&id=@leg.TripId&redir=@Request.GetDisplayUrl().UrlEncode()">+ Separator</a>
}
else {
<a class="btn btn-sm btn-outline-secondary disabled">+ Separator</a>
}
}
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=leg&id=@leg.LegId&redir=@Request.GetDisplayUrl().UrlEncode()">- Leg</a>
@if (leg.TicketId != 0) {
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=ticket&id=@leg.LegId&redir=@Request.GetDisplayUrl().UrlEncode()">- Ticket</a>
}
else {
<a class="btn btn-sm btn-outline-danger disabled">- Ticket</a>
}
</td>
}
</tr>
}
</tbody>
</table>
}
<a class="btn btn-sm btn-outline-danger" href="/Delete?item=leg&id=@leg.LegId&redir=@Request.GetDisplayUrl().UrlEncode()">- Leg</a>
</td>
}
</tr>
}
</tbody>
</table>
</div>
@if (!Request.Query.ContainsKey("edit")) {
<a class="btn btn-sm btn-success" href="/SharedTrip?id=@Request.Query["id"]&user=@Model.User">Share Trip</a>
<a class="btn btn-sm btn-primary" href="/GenIcs?id=@Request.Query["id"]&user=@Model.User">Download ICS</a>
<a class="btn btn-sm btn-secondary" href="/Trip?id=@Request.Query["id"]&edit=true">Edit Trip</a>
<a class="btn btn-sm btn-success" href="/SharedTrip?id=@Request.Query["id"]&user=@Model.User">Share Trip</a>
<a class="btn btn-sm btn-primary" href="/GenIcs?id=@Request.Query["id"]&user=@Model.User">Download ICS</a>
<a class="btn btn-sm btn-secondary" href="/Trip?id=@Request.Query["id"]&edit=true">Edit Trip</a>
}
else {
<a class="btn btn-sm btn-secondary" href="/Trip?id=@Request.Query["id"]">Back</a>
<br/>
<br/>
<div class="d-flex flex-row" style="justify-content: space-between">
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/Ticket">
<h3>Add leg(s) from ticket</h3>
<br/>
<input type="hidden" name="action" value="addleg">
<input type="hidden" name="tripid" value="@Request.Query["id"]">
<div class="form-group">
<input type="text" class="form-control" name="order" placeholder="bahn.de order #">
</div>
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Last name of traveller">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/OEAPI">
<h3>Add leg(s) from <a href="https://oeffisear.ch" target="_blank">oeffisear.ch</a> or <a href="https://transit.ztn.sh" target="_blank">transitztn.sh</a></h3>
<br/>
<input type="hidden" name="action" value="addleg">
<input type="hidden" name="tripid" value="@Request.Query["id"]">
<div class="form-group">
<input type="text" class="form-control" name="link" placeholder="oeffisear.ch link / shortcode">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<a class="btn btn-sm btn-secondary" href="/Trip?id=@Request.Query["id"]">Back</a>
<br/>
<br/>
<div class="d-flex flex-row" style="justify-content: space-between">
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/Ticket">
<h3>Add leg(s) from ticket</h3>
<br/>
<input type="hidden" name="action" value="addleg">
<input type="hidden" name="tripid" value="@Request.Query["id"]">
<div class="form-group">
<input type="text" class="form-control" name="order" placeholder="bahn.de order #">
</div>
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Last name of traveller">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<div class="d-flex p-2" style="width: 40%">
<form style="width: 100%" method="GET" action="/OEAPI">
<h3>Add leg(s) from <a href="https://oeffisear.ch" target="_blank">oeffisear.ch</a> or <a href="https://transit.ztn.sh" target="_blank">transitztn.sh</a></h3>
<br/>
<input type="hidden" name="action" value="addleg">
<input type="hidden" name="tripid" value="@Request.Query["id"]">
<div class="form-group">
<input type="text" class="form-control" name="link" placeholder="oeffisear.ch link / shortcode">
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
}

View File

@ -5,27 +5,28 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
using trainav.web.database.Tables;
using trainav.web.Utils;
namespace trainav.web.Pages;
public class TripModel : PageModel {
public List<Leg> Legs;
public bool RedirToIndex;
public User AuthorizedUser;
public new string User;
public void OnGet() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
using var db = new Database.DbConn();
AuthorizedUser = db.Users.FirstOrDefault(p => p.Username == AuthUtil.GetRemoteUser(HttpContext, db));
if (Request.Query.ContainsKey("separator")) {
var leg = db.Legs.First(p => p.LegId == int.Parse(Request.Query["legid"]));
if (leg.UserId != int.Parse(HttpContext.Session.GetString("uid")))
if (leg.UserId != AuthorizedUser!.UserId)
return;
db.Insert(new Leg {
TripId = int.Parse(Request.Query["id"]),
UserId = int.Parse(HttpContext.Session.GetString("uid")),
UserId = AuthorizedUser.UserId,
TrainType = "placeholder",
TrainNr = int.Parse(Request.Query["legid"]),
ArrStation = "_",
@ -49,19 +50,16 @@ public class TripModel : PageModel {
}
public void OnPost() {
if (HttpContext.Session.GetString("authorized") != "true")
return;
using var db = new Database.DbConn();
if (!Request.Form.ContainsKey("comment"))
return;
var leg = db.Legs.First(p => p.LegId == int.Parse(Request.Form["id"]));
if (leg.UserId != int.Parse(HttpContext.Session.GetString("uid")))
if (leg.UserId != AuthorizedUser.UserId)
return;
leg.Comment = Request.Form["comment"];
db.Update(leg);
}
}
}

View File

@ -0,0 +1,17 @@
using System.Linq;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using trainav.web.database;
using trainav.web.database.Tables;
namespace trainav.web.Utils;
public static class AuthUtil {
public static string GetRemoteUser(HttpContext ctx, Database.DbConn db) {
var remoteUser = ctx.Request.Headers["Remote-User"];
if (!db.Users.Any(p => p.Username == remoteUser)) {
db.InsertWithInt32Identity(new User {Username = remoteUser});
}
return ctx.Request.Headers["Remote-User"];
}
}

View File

@ -1,45 +1,20 @@
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using trainav.web.database;
namespace trainav.web.Pages;
public class LoginModel : PageModel {
public void OnPost() {
if (!Request.HasFormContentType || string.IsNullOrWhiteSpace(Request.Form["user"]) || string.IsNullOrWhiteSpace(Request.Form["pass"]))
return;
using var db = new Database.DbConn();
var user = db.Users.FirstOrDefault(p => p.Username == Request.Form["user"].ToString() && p.Password == Request.Form["pass"].ToString().Sha256());
if (user == null)
return;
var uid = user.UserId;
HttpContext.Session.SetString("uid", uid.ToString());
HttpContext.Session.SetString("authorized", "true");
//TODO
}
}
namespace trainav.web.Utils;
public static class StringExtensions {
public static string Sha256(this string rawData) {
// Create a SHA256
using var sha256Hash = SHA256.Create();
// ComputeHash - returns byte array
var bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
// Convert byte array to a string
var builder = new StringBuilder();
for (var i = 0; i < bytes.Length; i++)
builder.Append(bytes[i].ToString("x2"));
return builder.ToString();
}

View File

@ -32,9 +32,6 @@ public class Database {
public ITable<User> Users => GetTable<User>();
public ITable<Leg> Legs => GetTable<Leg>();
public ITable<Ticket> Tickets => GetTable<Ticket>();
public ITable<TicketLeg> TicketLegs => GetTable<TicketLeg>();
public ITable<Trip> Trips => GetTable<Trip>();
public ITable<Card> Cards => GetTable<Card>();
}
}
}

View File

@ -1,36 +0,0 @@
using LinqToDB.Mapping;
namespace trainav.web.database.Tables;
[Table(Name = "Cards")]
public class Card {
[Column(Name = "CardID"), PrimaryKey, Identity, NotNull] public int CardId { get; set; }
[Column(Name = "OrderID"), NotNull] public string OrderId { get; set; }
[Column(Name = "UserID"), NotNull] public int UserId { get; set; }
[Column(Name = "CardNumber"), NotNull] public string CardNumber { get; set; }
[Column(Name = "Class"), NotNull] public int Class { get; set; }
[Column(Name = "Value"), NotNull] public int Value { get; set; }
[Column(Name = "Traveller")] public string Traveller { get; set; }
[Column(Name = "CardQR")] public string CardQr { get; set; }
[Column(Name = "CardSecCode")] public string CardSecCode { get; set; }
[Column(Name = "CardImage")] public string CardImage { get; set; }
[Column(Name = "CardInfo")] public string CardInfo { get; set; }
[Column(Name = "ValidFrom")] public string ValidFrom { get; set; }
[Column(Name = "ValidTo")] public string ValidTo { get; set; }
[Column(Name = "QRValidFrom")] public string QrValidFrom { get; set; }
[Column(Name = "QRValidTo")] public string QrValidTo { get; set; }
}

View File

@ -26,7 +26,5 @@ public class Leg {
[Column(Name = "ArrTime"), NotNull] public string ArrTime { get; set; }
[Column(Name = "TicketID")] public int TicketId { get; set; }
[Column(Name = "Comment")] public string Comment { get; set; }
}
}

View File

@ -1,22 +0,0 @@
using LinqToDB.Mapping;
namespace trainav.web.database.Tables;
[Table(Name = "Tickets")]
public class Ticket {
[Column(Name = "TicketID"), PrimaryKey, Identity, NotNull] public int TicketId { get; set; }
[Column(Name = "OrderID"), NotNull] public string OrderId { get; set; }
[Column(Name = "UserID"), NotNull] public int UserId { get; set; }
[Column(Name = "TicketInfo"), NotNull] public string TicketInfo { get; set; }
[Column(Name = "TicketQR"), NotNull] public string TicketQr { get; set; }
[Column(Name = "TicketSecCode"), NotNull] public string TicketSecCode { get; set; }
[Column(Name = "TicketPkPass")] public string TicketPkPass { get; set; }
[Column(Name = "Traveller")] public string Traveller { get; set; }
}

View File

@ -1,27 +0,0 @@
using LinqToDB.Mapping;
namespace trainav.web.database.Tables;
[Table(Name = "TicketLegs")]
public class TicketLeg {
[Column(Name = "TicketLegID"), PrimaryKey, Identity, NotNull]
public int TicketLegId { get; set; }
[Column(Name = "TicketID"), NotNull] public int TicketId { get; set; }
[Column(Name = "TrainType"), NotNull] public string TrainType { get; set; }
[Column(Name = "TrainNr"), NotNull] public int TrainNr { get; set; }
[Column(Name = "DepStationID"), NotNull] public int DepStationId { get; set; }
[Column(Name = "DepStation"), NotNull] public string DepStation { get; set; }
[Column(Name = "DepTime"), NotNull] public string DepTime { get; set; }
[Column(Name = "ArrStationID"), NotNull] public int ArrStationId { get; set; }
[Column(Name = "ArrStation"), NotNull] public string ArrStation { get; set; }
[Column(Name = "ArrTime"), NotNull] public string ArrTime { get; set; }
}

View File

@ -7,6 +7,4 @@ public class User {
[Column(Name = "UserID"), PrimaryKey, Identity, NotNull] public int UserId { get; set; }
[Column(Name = "Username"), NotNull] public string Username { get; set; }
[Column(Name = "Password"), NotNull] public string Password { get; set; }
}
}

View File

@ -6,66 +6,27 @@
</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>
</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>
</ItemGroup>
<ItemGroup>

View File

@ -2,105 +2,97 @@
for details on configuring this project to bundle and minify static web assets. */
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
white-space: normal;
text-align: center;
word-break: break-all;
}
/* Provide sufficient contrast against white background */
a {
color: #0366d6;
color: #0366d6;
}
/* oeffisear.ch link */
h3 a, h3 a:hover {
color: #212529;
color: #212529;
}
h3 a {
text-decoration: underline;
text-decoration-style: dotted;
text-decoration-thickness: 1.5pt;
text-decoration: underline;
text-decoration-style: dotted;
text-decoration-thickness: 1.5pt;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
font-size: 14px;
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
html {
font-size: 16px;
}
}
.border-top {
border-top: 1px solid #e5e5e5;
border-top: 1px solid #e5e5e5;
}
.border-bottom {
border-bottom: 1px solid #e5e5e5;
border-bottom: 1px solid #e5e5e5;
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}
button.accept-policy {
font-size: 1rem;
line-height: inherit;
font-size: 1rem;
line-height: inherit;
}
/* Sticky footer styles
-------------------------------------------------- */
html {
position: relative;
min-height: 100%;
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
/* Margin bottom by footer height */
margin-bottom: 60px;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px; /* Vertically center the text there */
position: absolute;
bottom: 0;
width: 100%;
white-space: nowrap;
line-height: 60px; /* Vertically center the text there */
}
td {
vertical-align: middle !important;
vertical-align: middle !important;
}
.flex-grid {
display: flex;
flex-wrap: wrap;
display: flex;
flex-wrap: wrap;
}
.flex-col {
margin: 3px 3px 10px;
margin: 3px 3px 10px;
}
.bahncard-outer {
width: 400px;
height: 260px;
}
.bahncard {
height: 400px;
transform-origin: top left;
transform: rotate(-90deg) translate(-100%);
}