From 8a0308e4414c5f34ef3230c1ac938310c39f011b Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 23 Feb 2023 17:58:33 +0100 Subject: [PATCH 1/5] extract topology related stuff into Topology.cs --- csharp/app/SaliMax/src/Program.cs | 177 +-------------------------- csharp/app/SaliMax/src/Topology.cs | 184 +++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+), 176 deletions(-) create mode 100644 csharp/app/SaliMax/src/Topology.cs diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/app/SaliMax/src/Program.cs index 1bbbc8883..e188de1a3 100644 --- a/csharp/app/SaliMax/src/Program.cs +++ b/csharp/app/SaliMax/src/Program.cs @@ -11,13 +11,11 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc; using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc; using InnovEnergy.Lib.Devices.Ampt; using InnovEnergy.Lib.Devices.Battery48TL; -using InnovEnergy.Lib.Utils; using InnovEnergy.SaliMax.Controller; using InnovEnergy.SaliMax.Log; using InnovEnergy.SaliMax.SaliMaxRelays; using InnovEnergy.SaliMax.SystemConfig; using InnovEnergy.Time.Unix; -using Utils = InnovEnergy.Lib.StatusApi.Utils; #pragma warning disable IL2026 @@ -148,7 +146,7 @@ internal static class Program //JsonSerializer.Serialize(jsonLog, JsonOptions).WriteLine(ConsoleColor.DarkBlue); #endif - PrintTopology(status); + Topology.Print(status); while (UnixTime.Now == t) await Task.Delay(delayTime); @@ -157,181 +155,8 @@ internal static class Program } - private static void PrintTopology(StatusRecord s) - { - const String chargingSeparator = ">>>>>>>>>>"; - const String dischargingSeparator = "<<<<<<<<<"; - const Int32 height = 25; - var pwr = s.InverterStatus!.Ac.ActivePower; - var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt - var loadPower = Utils.Round3((s.GridMeterStatus!.ActivePowerL123 + pwr)); // it's a + because the pwr is inverted - - var gridSeparator = s.GridMeterStatus!.ActivePowerL123 > 0 ? chargingSeparator : dischargingSeparator; - var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator; - var dcSeparator = -s.DcDcStatus!.Dc.Power > 0 ? chargingSeparator : dischargingSeparator; -#if BatteriesAllowed - var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator; - var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator; -#endif - - ////////////////// Grid ////////////////////// - var boxGrid = AsciiArt.CreateBox - ( - "Grid", - s.GridMeterStatus.Ac.L1.Voltage.V(), - s.GridMeterStatus.Ac.L2.Voltage.V(), - s.GridMeterStatus.Ac.L3.Voltage.V() - ).AlignCenterVertical(height); - - var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator) - .AlignCenterVertical(height); - - - ////////////////// Ac Bus ////////////////////// - var boxAcBus = AsciiArt.CreateBox - ( - "AC Bus", - s.InverterStatus.Ac.L1.Voltage.V(), - s.InverterStatus.Ac.L2.Voltage.V(), - s.InverterStatus.Ac.L3.Voltage.V() - ); - - var boxLoad = AsciiArt.CreateBox - ( - "", - "LOAD", - "" - ); - - var loadRect = CreateRect(boxAcBus, boxLoad, loadPower).AlignBottom(height); - - var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) - .AlignCenterVertical(height); - - //////////////////// Inverter ///////////////////////// - var inverterBox = AsciiArt.CreateBox - ( - "", - "Inverter", - "" - ).AlignCenterVertical(height); - - var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) - .AlignCenterVertical(height); - - - //////////////////// DC Bus ///////////////////////// - var dcBusBox = AsciiArt.CreateBox - ( - "DC Bus", - (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(), - "" - ); - - var pvBox = AsciiArt.CreateBox - ( - "MPPT", - ((s.AmptStatus!.Devices[0].Dc.Voltage + s.AmptStatus!.Devices[1].Dc.Voltage) / 2).Round0().V(), - "" - ); - - var pvRect = CreateRect(pvBox, dcBusBox, pvPower).AlignTop(height); - - var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator) - .AlignCenterVertical(height); - - //////////////////// Dc/Dc ///////////////////////// - var dcBox = AsciiArt.CreateBox - ( - "Dc/Dc", - s.DcDcStatus.BatteryVoltage.V(), - "" - ).AlignCenterVertical(height); -#if BatteriesAllowed - var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power.Round0(), battery1Separator); - var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power.Round0(), battery2Separator); -#else - var dcArrow1 =""; - var dcArrow2 = ""; - var dcArrowRect = CreateRect(dcArrow1, dcArrow2).AlignCenterVertical(height); -#endif - - -#if BatteriesAllowed - - //////////////////// Batteries ///////////////////////// - var battery1Box = AsciiArt.CreateBox - ( - "Battery 1", - s.BatteriesStatus[0].Voltage.V(), - s.BatteriesStatus[0].Soc.Percent(), - s.BatteriesStatus[0].Temperature.Celsius() - ); - - var battery2Box = AsciiArt.CreateBox - ( - "Battery 2", - s.BatteriesStatus[1].Voltage.V(), - s.BatteriesStatus[1].Soc.Percent(), - s.BatteriesStatus[1].Temperature.Celsius() - ); - - var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height); - - var avgBatteryBox = AsciiArt.CreateBox - ( - "Batteries", - s.AvgBatteriesStatus!.Voltage.V(), - s.AvgBatteriesStatus.Soc.Percent(), - s.AvgBatteriesStatus.Temperature.Celsius() - ).AlignCenterVertical(height); - - - var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") - .SideBySideWith(loadRect, "") - .SideBySideWith(acBusInvertArrow, "") - .SideBySideWith(inverterBox, "") - .SideBySideWith(inverterArrow, "") - .SideBySideWith(pvRect, "") - .SideBySideWith(dcBusArrow, "") - .SideBySideWith(dcBox, "") - .SideBySideWith(dcArrowRect, "") - .SideBySideWith(batteryRect, "") - .SideBySideWith(avgBatteryBox, "")+ "\n"; -#else - var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") - .SideBySideWith(loadRect, "") - .SideBySideWith(acBusInvertArrow, "") - .SideBySideWith(inverterBox, "") - .SideBySideWith(inverterArrow, "") - .SideBySideWith(pvRect, "") - .SideBySideWith(dcBusArrow, "") - .SideBySideWith(dcBox, "")+ "\n"; -#endif - Console.WriteLine(topology); - } - - private static String CreateRect(String boxTop, String boxBottom, Decimal power) - { - var powerArrow = AsciiArt.CreateVerticalArrow(power); - var boxes = new[] { boxTop, powerArrow, boxBottom }; - var maxWidth = boxes.Max(l => l.Width()); - - var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); - return rect; - } - - private static String CreateRect(String boxTop, String boxBottom) - { - var boxes = new[] { boxTop, boxBottom }; - var maxWidth = boxes.Max(l => l.Width()); - - var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); - return rect; - } - // to delete not used anymore [Conditional("RELEASE")] private static void ReleaseWriteLog(JsonObject jsonLog, UnixTime timestamp) diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/app/SaliMax/src/Topology.cs new file mode 100644 index 000000000..e111f8ec4 --- /dev/null +++ b/csharp/app/SaliMax/src/Topology.cs @@ -0,0 +1,184 @@ +using InnovEnergy.Lib.Utils; +using InnovEnergy.SaliMax.Controller; +using InnovEnergy.SaliMax.Log; + +namespace InnovEnergy.SaliMax; + +public static class Topology +{ + public static void Print(StatusRecord s) + { + const String chargingSeparator = ">>>>>>>>>>"; + const String dischargingSeparator = "<<<<<<<<<"; + const Int32 height = 25; + + + var pwr = s.InverterStatus!.Ac.ActivePower; + var pvPower = (s.AmptStatus!.Devices[0].Dc.Voltage * s.AmptStatus.Devices[0].Dc.Current + s.AmptStatus!.Devices[1].Dc.Voltage * s.AmptStatus.Devices[1].Dc.Current).Round0(); // TODO using one Ampt + var loadPower = Utils.Round3((s.GridMeterStatus!.ActivePowerL123 + pwr)); // it's a + because the pwr is inverted + + var gridSeparator = s.GridMeterStatus!.ActivePowerL123 > 0 ? chargingSeparator : dischargingSeparator; + var inverterSeparator = -pwr > 0 ? chargingSeparator : dischargingSeparator; + var dcSeparator = -s.DcDcStatus!.Dc.Power > 0 ? chargingSeparator : dischargingSeparator; +#if BatteriesAllowed + var battery1Separator = s.BatteriesStatus[0]!.Power > 0 ? chargingSeparator : dischargingSeparator; + var battery2Separator = s.BatteriesStatus[1]!.Power > 0 ? chargingSeparator : dischargingSeparator; +#endif + + ////////////////// Grid ////////////////////// + var boxGrid = AsciiArt.CreateBox + ( + "Grid", + s.GridMeterStatus.Ac.L1.Voltage.V(), + s.GridMeterStatus.Ac.L2.Voltage.V(), + s.GridMeterStatus.Ac.L3.Voltage.V() + ).AlignCenterVertical(height); + + var gridAcBusArrow = AsciiArt.CreateHorizontalArrow(s.GridMeterStatus!.ActivePowerL123.Round0(), gridSeparator) + .AlignCenterVertical(height); + + + ////////////////// Ac Bus ////////////////////// + var boxAcBus = AsciiArt.CreateBox + ( + "AC Bus", + s.InverterStatus.Ac.L1.Voltage.V(), + s.InverterStatus.Ac.L2.Voltage.V(), + s.InverterStatus.Ac.L3.Voltage.V() + ); + + var boxLoad = AsciiArt.CreateBox + ( + "", + "LOAD", + "" + ); + + var loadRect = StringUtils.AlignBottom(CreateRect(boxAcBus, boxLoad, loadPower), height); + + var acBusInvertArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) + .AlignCenterVertical(height); + + //////////////////// Inverter ///////////////////////// + var inverterBox = AsciiArt.CreateBox + ( + "", + "Inverter", + "" + ).AlignCenterVertical(height); + + var inverterArrow = AsciiArt.CreateHorizontalArrow(-pwr.Round0(), inverterSeparator) + .AlignCenterVertical(height); + + + //////////////////// DC Bus ///////////////////////// + var dcBusBox = AsciiArt.CreateBox + ( + "DC Bus", + (s.InverterStatus.ActualDcLinkVoltageLowerHalfExt + s.InverterStatus.ActualDcLinkVoltageUpperHalfExt).V(), + "" + ); + + var pvBox = AsciiArt.CreateBox + ( + "MPPT", + ((s.AmptStatus!.Devices[0].Dc.Voltage + s.AmptStatus!.Devices[1].Dc.Voltage) / 2).Round0().V(), + "" + ); + + var pvRect = StringUtils.AlignTop(CreateRect(pvBox, dcBusBox, pvPower), height); + + var dcBusArrow = AsciiArt.CreateHorizontalArrow(-s.DcDcStatus!.Dc.Power, dcSeparator) + .AlignCenterVertical(height); + + //////////////////// Dc/Dc ///////////////////////// + var dcBox = AsciiArt.CreateBox + ( + "Dc/Dc", + s.DcDcStatus.BatteryVoltage.V(), + "" + ).AlignCenterVertical(height); +#if BatteriesAllowed + var dcArrow1 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[0]!.Power.Round0(), battery1Separator); + var dcArrow2 = AsciiArt.CreateHorizontalArrow(s.BatteriesStatus[1]!.Power.Round0(), battery2Separator); +#else + var dcArrow1 =""; + var dcArrow2 = ""; + var dcArrowRect = StringUtils.AlignCenterVertical(CreateRect(dcArrow1, dcArrow2), height); +#endif + + +#if BatteriesAllowed + + //////////////////// Batteries ///////////////////////// + var battery1Box = AsciiArt.CreateBox + ( + "Battery 1", + s.BatteriesStatus[0].Voltage.V(), + s.BatteriesStatus[0].Soc.Percent(), + s.BatteriesStatus[0].Temperature.Celsius() + ); + + var battery2Box = AsciiArt.CreateBox + ( + "Battery 2", + s.BatteriesStatus[1].Voltage.V(), + s.BatteriesStatus[1].Soc.Percent(), + s.BatteriesStatus[1].Temperature.Celsius() + ); + + var batteryRect = CreateRect(battery1Box, battery2Box).AlignCenterVertical(height); + + var avgBatteryBox = AsciiArt.CreateBox + ( + "Batteries", + s.AvgBatteriesStatus!.Voltage.V(), + s.AvgBatteriesStatus.Soc.Percent(), + s.AvgBatteriesStatus.Temperature.Celsius() + ).AlignCenterVertical(height); + + + var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") + .SideBySideWith(loadRect, "") + .SideBySideWith(acBusInvertArrow, "") + .SideBySideWith(inverterBox, "") + .SideBySideWith(inverterArrow, "") + .SideBySideWith(pvRect, "") + .SideBySideWith(dcBusArrow, "") + .SideBySideWith(dcBox, "") + .SideBySideWith(dcArrowRect, "") + .SideBySideWith(batteryRect, "") + .SideBySideWith(avgBatteryBox, "")+ "\n"; +#else + var topology = boxGrid.SideBySideWith(gridAcBusArrow, "") + .SideBySideWith(loadRect, "") + .SideBySideWith(acBusInvertArrow, "") + .SideBySideWith(inverterBox, "") + .SideBySideWith(inverterArrow, "") + .SideBySideWith(pvRect, "") + .SideBySideWith(dcBusArrow, "") + .SideBySideWith(dcBox, "")+ "\n"; +#endif + Console.WriteLine(topology); + } + + private static String CreateRect(String boxTop, String boxBottom, Decimal power) + { + var powerArrow = AsciiArt.CreateVerticalArrow(power); + var boxes = new[] { boxTop, powerArrow, boxBottom }; + var maxWidth = boxes.Max(l => l.Width()); + + var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); + return rect; + } + + private static String CreateRect(String boxTop, String boxBottom) + { + var boxes = new[] { boxTop, boxBottom }; + var maxWidth = boxes.Max(l => l.Width()); + + var rect = boxes.Select(l => l.AlignCenterHorizontal(maxWidth)).JoinLines(); + return rect; + } + +} \ No newline at end of file From a7af1c434c43c116145807e939cedf9170c0d60b Mon Sep 17 00:00:00 2001 From: ig Date: Thu, 23 Feb 2023 17:59:55 +0100 Subject: [PATCH 2/5] move undef to Topology.cs --- csharp/app/SaliMax/src/Program.cs | 2 +- csharp/app/SaliMax/src/Topology.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/csharp/app/SaliMax/src/Program.cs b/csharp/app/SaliMax/src/Program.cs index e188de1a3..0734b5b6f 100644 --- a/csharp/app/SaliMax/src/Program.cs +++ b/csharp/app/SaliMax/src/Program.cs @@ -1,4 +1,4 @@ -#undef BatteriesAllowed + using System.Diagnostics; diff --git a/csharp/app/SaliMax/src/Topology.cs b/csharp/app/SaliMax/src/Topology.cs index e111f8ec4..ab8a26ee9 100644 --- a/csharp/app/SaliMax/src/Topology.cs +++ b/csharp/app/SaliMax/src/Topology.cs @@ -1,3 +1,5 @@ +#undef BatteriesAllowed + using InnovEnergy.Lib.Utils; using InnovEnergy.SaliMax.Controller; using InnovEnergy.SaliMax.Log; From 08bd5c31e0f8c5f8718fe9c14a7e8309f9c5b01e Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 09:26:55 +0100 Subject: [PATCH 3/5] remove CsController.csproj --- csharp/InnovEnergy.sln | 7 --- csharp/app/CsController/CsController.csproj | 15 ----- csharp/app/CsController/Program.cs | 62 --------------------- csharp/app/CsController/debug.sh | 21 ------- csharp/app/CsController/service/log/run | 3 - csharp/app/CsController/service/run | 3 - 6 files changed, 111 deletions(-) delete mode 100644 csharp/app/CsController/CsController.csproj delete mode 100644 csharp/app/CsController/Program.cs delete mode 100644 csharp/app/CsController/debug.sh delete mode 100755 csharp/app/CsController/service/log/run delete mode 100755 csharp/app/CsController/service/run diff --git a/csharp/InnovEnergy.sln b/csharp/InnovEnergy.sln index 9247b7144..69f33a105 100644 --- a/csharp/InnovEnergy.sln +++ b/csharp/InnovEnergy.sln @@ -24,8 +24,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S3", "lib/S3/S3.csproj", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deprecated", "deprecated", "{46DE03C4-52D1-47AA-8E60-8BB15361D723}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsController", "app/CsController/CsController.csproj", "{72DBBE42-A09F-43C0-9613-331039857056}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SaliMax", "app/SaliMax/SaliMax.csproj", "{25073794-D859-4824-9984-194C7E928496}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatusApi", "lib/StatusApi/StatusApi.csproj", "{9D17E78C-8A70-43DB-A619-DC12D20D023D}" @@ -112,10 +110,6 @@ Global {C3639841-13F4-4F24-99C6-7D965593BF89}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3639841-13F4-4F24-99C6-7D965593BF89}.Release|Any CPU.Build.0 = Release|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72DBBE42-A09F-43C0-9613-331039857056}.Release|Any CPU.Build.0 = Release|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Debug|Any CPU.Build.0 = Debug|Any CPU {25073794-D859-4824-9984-194C7E928496}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -195,7 +189,6 @@ Global {E3A5F3A3-72A5-47CC-85C6-2D8E962A0EC1} = {145597B4-3E30-45E6-9F72-4DD43194539A} {46DE03C4-52D1-47AA-8E60-8BB15361D723} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {4A67D79F-F0C9-4BBC-9601-D5948E6C05D3} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} - {72DBBE42-A09F-43C0-9613-331039857056} = {145597B4-3E30-45E6-9F72-4DD43194539A} {25073794-D859-4824-9984-194C7E928496} = {145597B4-3E30-45E6-9F72-4DD43194539A} {9D17E78C-8A70-43DB-A619-DC12D20D023D} = {AD5B98A8-AB7F-4DA2-B66D-5B4E63E7D854} {C3639841-13F4-4F24-99C6-7D965593BF89} = {46DE03C4-52D1-47AA-8E60-8BB15361D723} diff --git a/csharp/app/CsController/CsController.csproj b/csharp/app/CsController/CsController.csproj deleted file mode 100644 index aab629be3..000000000 --- a/csharp/app/CsController/CsController.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - - enable - InnovEnergy.CsController - true - - - - - - - - diff --git a/csharp/app/CsController/Program.cs b/csharp/app/CsController/Program.cs deleted file mode 100644 index 4d625c96c..000000000 --- a/csharp/app/CsController/Program.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Reactive.Linq; -using InnovEnergy.Lib.Protocols.DBus; -using InnovEnergy.Lib.Protocols.DBus.Protocol.DataTypes; -using InnovEnergy.Lib.Victron.VeDBus; - - -// dotnet publish EmuMeter.csproj -c Release -r linux-arm -p:PublishSingleFile=true --self-contained true && \ -// rsync -av bin/Release/net6.0/linux-arm/publish/ root@10.2.1.6:/home/root/emu && clear && \ -// ssh root@10.2.1.6 /home/root/emu/EmuMeter - - -Console.WriteLine("Starting CsController "); - -//Enable out InnovEnergy GUI Page through DBusService.DBUS_SERVICE_UNSUPPORTED -// var service = new DBusService("com.victronenergy.unsupported"); -var veProperties = new VeProperties(); -veProperties.Set("/CustomName", "InnovEnergy"); -veProperties.Set("/ProductName", "InnovEnergySW"); - - -var dbus = new DBusConnection(Bus.System); -// var ep = new UnixDomainSocketEndPoint("/home/kim/graber_dbus.sock"); -// var auth = AuthenticationMethod.ExternalAsRoot(); -// var dbusAddress = new Bus(ep, auth); -// var dbus = new DBusConnection(dbusAddress); - - -await veProperties.PublishOnDBus(Bus.System, "com.victronenergy.unsupported"); - -var battery = "com.victronenergy.battery.ttyUSB0"; -var soc = 21.0; - -//TODO change ttyUSB0 for generic Battery on dbus -var names = await dbus.ListNames(); -foreach (var name in names) -{ - if(name.Contains("com.victronenergy.battery.")) - { - battery = name; - break; - } -} - -var mustCharge = dbus - .ObserveSignalMessages(sender: battery, objectPath: "/Soc") - .Select(m => m.Payload)! - .OfType>() - .Where(d => d.ContainsKey("Value")) - .Select(d => d["Value"].Value) - .OfType() - .Do(s => Console.WriteLine($"soc = {s}")) - .Select(d => d < 67) - .DistinctUntilChanged(); - - -mustCharge.Subscribe(b => -{ - dbus.SetValue("com.victronenergy.settings", "/Settings/CGwacs/BatteryLife/State", b ? 9 : 10); // 9 = charge battery, 10 = optimized (no batterylife) -}); - - -// Console.ReadLine(); \ No newline at end of file diff --git a/csharp/app/CsController/debug.sh b/csharp/app/CsController/debug.sh deleted file mode 100644 index 3f25d1795..000000000 --- a/csharp/app/CsController/debug.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -csproj="CsController.csproj" -exe="CsController" -remote="10.2.1.6" -#remote="10.2.2.152" - -netVersion="net6.0" -platform="linux-arm" -config="Release" -host="root@$remote" -dir="/data/innovenergy/$exe" - -set -e - -dotnet publish "$csproj" -c $config -r $platform -p:SuppressTrimmAnalysisWarnings=true -p:PublishSingleFile=true -p:PublishTrimmed=true -p:DebugType=None -p:DebugSymbols=false --self-contained true -rsync -av "bin/$config/$netVersion/$platform/publish/" "$host:$dir" - -clear -ssh "$host" "$dir/$exe" - \ No newline at end of file diff --git a/csharp/app/CsController/service/log/run b/csharp/app/CsController/service/log/run deleted file mode 100755 index d42c9d38b..000000000 --- a/csharp/app/CsController/service/log/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -exec 2>&1 -exec multilog t s25000 n4 /var/log/CsController diff --git a/csharp/app/CsController/service/run b/csharp/app/CsController/service/run deleted file mode 100755 index a509d6c68..000000000 --- a/csharp/app/CsController/service/run +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -exec 2>&1 -exec softlimit -d 100000000 -s 1000000 -a 100000000 /opt/innovenergy/CsController/CsController From d2006b52e16b63c35f3193369dd0d8c34c625ecb Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 12:57:51 +0100 Subject: [PATCH 4/5] add ReturnsAttribute to make annotating API more convenient --- .../Backend/Controllers/ReturnsAttribute.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 csharp/app/Backend/Controllers/ReturnsAttribute.cs diff --git a/csharp/app/Backend/Controllers/ReturnsAttribute.cs b/csharp/app/Backend/Controllers/ReturnsAttribute.cs new file mode 100644 index 000000000..6d94088f5 --- /dev/null +++ b/csharp/app/Backend/Controllers/ReturnsAttribute.cs @@ -0,0 +1,22 @@ +using System.Net; +using Microsoft.AspNetCore.Mvc; + +namespace Innovenergy.Backend.Controllers; + +public class ReturnsAttribute : ProducesResponseTypeAttribute +{ + public ReturnsAttribute(HttpStatusCode statusCode) : base((Int32)statusCode) + { + } +} + +public class ReturnsAttribute : ProducesResponseTypeAttribute +{ + public ReturnsAttribute(HttpStatusCode statusCode) : base(typeof(T), (Int32)statusCode) + { + } + + public ReturnsAttribute() : base(typeof(T), (Int32)HttpStatusCode.OK) + { + } +} \ No newline at end of file From c7649dced20f52ab957ce5d5a934f4919921dfeb Mon Sep 17 00:00:00 2001 From: ig Date: Fri, 24 Feb 2023 12:58:47 +0100 Subject: [PATCH 5/5] cleanup Rest API --- csharp/app/Backend/Backend.csproj | 2 + csharp/app/Backend/Controllers/Controller.cs | 311 +++++++++--------- csharp/app/Backend/Controllers/Credentials.cs | 5 +- csharp/app/Backend/Database/Db.cs | 10 +- csharp/app/Backend/Database/Fake.cs | 4 +- csharp/app/Backend/Database/Folder.cs | 15 +- csharp/app/Backend/Database/Installation.cs | 6 +- csharp/app/Backend/Database/User.cs | 79 +++-- csharp/app/Backend/Database/User2Folder.cs | 4 +- .../app/Backend/Database/User2Installation.cs | 4 +- csharp/app/Backend/HeaderFilter.cs | 24 ++ csharp/app/Backend/Model/Folder.cs | 4 +- csharp/app/Backend/Model/Installation.cs | 4 +- .../app/Backend/Model/Relations/Relation.cs | 2 +- csharp/app/Backend/Model/Relations/Session.cs | 2 +- .../Backend/Model/Relations/User2Folder.cs | 2 +- .../Model/Relations/User2Installation.cs | 2 +- csharp/app/Backend/Model/TreeNode.cs | 3 +- csharp/app/Backend/Model/User.cs | 2 +- csharp/app/Backend/Utils/Crypto.cs | 2 +- csharp/app/Backend/Utils/Result.cs | 2 +- csharp/app/Backend/db.sqlite | Bin 290816 -> 290816 bytes csharp/app/Backend/program.cs | 145 +++----- 23 files changed, 319 insertions(+), 315 deletions(-) create mode 100644 csharp/app/Backend/HeaderFilter.cs diff --git a/csharp/app/Backend/Backend.csproj b/csharp/app/Backend/Backend.csproj index c082226db..e6a136cb1 100644 --- a/csharp/app/Backend/Backend.csproj +++ b/csharp/app/Backend/Backend.csproj @@ -4,6 +4,8 @@ net6.0 enable enable + preview + Innovenergy.Backend diff --git a/csharp/app/Backend/Controllers/Controller.cs b/csharp/app/Backend/Controllers/Controller.cs index 32b53084e..10110397e 100644 --- a/csharp/app/Backend/Controllers/Controller.cs +++ b/csharp/app/Backend/Controllers/Controller.cs @@ -1,21 +1,21 @@ using System.Net; using System.Text; -using System.Text.Json; -using Backend.Database; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Database; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using Microsoft.AspNetCore.Mvc; using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor; -namespace Backend.Controllers; +namespace Innovenergy.Backend.Controllers; [ApiController] [Route("api/")] public class Controller { - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] + [Returns(HttpStatusCode.BadRequest)] [HttpPost($"{nameof(Login)}")] public Object Login(Credentials credentials) { @@ -29,181 +29,175 @@ public class Controller if (user is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - // if (!VerifyPassword(password, user)) - // return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #if !DEBUG + if (!VerifyPassword(credentials.Password, user)) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #endif var ses = new Session(user); db.NewSession(ses); return ses.Token; } - private static Boolean VerifyPassword(String password, User user) - { - var pwdBytes = Encoding.UTF8.GetBytes(password); - var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); - var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); - return user.Password == pwdHash; - } - - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPost($"{nameof(Logout)}")] public Object Logout() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; + var caller = GetCaller(); - if (currentUser is null) - return new HttpResponseMessage(HttpStatusCode.Conflict); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.DeleteSession(currentUser.Id); + using var db = Db.Connect(); + return db.DeleteSession(caller.Id); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] - [HttpPost($"{nameof(UpdateS3Creds)}")] - public Object UpdateS3Creds() + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] + [HttpPost($"{nameof(UpdateS3Credentials)}")] + public Object UpdateS3Credentials() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx!.Items["User"]!; + // TODO: S3Credentials should be per session, not per user - return db.CreateAndSaveUserS3ApiKey(currentUser); + var caller = GetCaller(); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + return db.CreateAndSaveUserS3ApiKey(caller); } - [ProducesResponseType(typeof(User), 200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetUserById)}")] public Object GetUserById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var viewedUser = db.GetUserById(id); - - //using the same error to prevent fishing for ids - if (currentUser == null || viewedUser == null || !db.IsParentOfChild(currentUser, viewedUser)) + var caller = GetCaller(); + if (caller is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return viewedUser; + var user = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == id); + + return user as Object ?? new HttpResponseMessage(HttpStatusCode.Unauthorized); } - [ProducesResponseType(typeof(Installation), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetInstallationById)}")] public Object GetInstallationById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); + var installation = db - .GetAllAccessibleInstallations(currentUser) + .GetAllAccessibleInstallations(caller) .FirstOrDefault(i => i.Id == id); - if (installation is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return installation; + return installation as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(typeof(Folder), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetFolderById)}")] public Object GetFolderById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - + var folder = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == id); - if(folder is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return folder; + return folder as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllInstallations)}/")] public Object GetAllInstallations() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var user = (User)ctx.Items["User"]; - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return db.GetAllAccessibleInstallations(user).ToList(); + return db + .GetAllAccessibleInstallations(caller) + .ToList(); // important! } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllFolders)}/")] public Object GetAllFolders() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - var user = (User)ctx.Items["User"]; - - using var db = Db.Connect(); - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - - return db.GetAllAccessibleFolders(user).ToList(); + + using var db = Db.Connect(); + return db + .GetAllAccessibleFolders(caller) + .ToList(); // important! } + - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateUser)}/")] public Object UpdateUser(User updatedUser) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess || !db.IsParentOfChild(currentUser, updatedUser)) + // TODO: distinguish between create and update + + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.GetUserById(updatedUser.Id) != null ? db.UpdateUser(updatedUser) : db.CreateUser(updatedUser); + using var db = Db.Connect(); + + return db.GetUserById(updatedUser.Id) != null + ? db.UpdateUser(updatedUser) + : db.CreateUser(updatedUser); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateInstallation)}/")] public Object UpdateInstallation(Installation updatedInstallation) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - + using var db = Db.Connect(); - var hasAccess = db.GetAllAccessibleInstallations(currentUser) - .Any(i => i.Id == updatedInstallation.Id); - if (!hasAccess) + var hasAccessToInstallation = db + .GetAllAccessibleInstallations(caller) + .Any(i => i.Id == updatedInstallation.Id); + + if (!hasAccessToInstallation) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc @@ -213,64 +207,68 @@ public class Controller } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateFolder)}/")] - public Object UpdateFolder(Folder updatedFolder) + public Object UpdateFolder(Folder folder) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - var hasAccess = db.GetAllAccessibleFolders(currentUser) - .Any(f => f.Id == updatedFolder.Id); + using var db = Db.Connect(); + + var hasAccessToFolder = db + .GetAllAccessibleFolders(caller) + .Any(f => f.Id == folder.Id); - if (!hasAccess) + if (!hasAccessToFolder) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes - return db.UpdateFolder(updatedFolder); + return db.UpdateFolder(folder); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteUser)}/")] public Object DeleteUser(Int64 userId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var userToBeDeleted = db.GetUserById(userId); + var caller = GetCaller(); - if (currentUser == null - || userToBeDeleted == null - || !currentUser.HasWriteAccess - || !db.IsParentOfChild(currentUser,userToBeDeleted)) + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + var userToBeDeleted = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == userId); + + if (userToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteUser(userToBeDeleted); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteInstallation)}/")] - public Object DeleteInstallation(Int64 idOfInstallationToBeDeleted) + public Object DeleteInstallation(Int64 installationId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var installationToBeDeleted = db - .GetAllAccessibleInstallations(currentUser!) - .FirstOrDefault(i => i.Id == idOfInstallationToBeDeleted); + .GetAllAccessibleInstallations(caller) + .FirstOrDefault(i => i.Id == installationId); if (installationToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); @@ -278,18 +276,20 @@ public class Controller return db.DeleteInstallation(installationToBeDeleted); } + [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpDelete($"{nameof(DeleteFolder)}/")] public Object DeleteFolder(Int64 folderId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var folderToDelete = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == folderId); if (folderToDelete is null) @@ -299,5 +299,22 @@ public class Controller } + private static User? GetCaller() + { + var ctxAccessor = new HttpContextAccessor(); + return ctxAccessor.HttpContext?.Items["User"] as User; + } + + private static Boolean VerifyPassword(String password, User user) + { + var pwdBytes = Encoding.UTF8.GetBytes(password); + var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); + var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); + + return user.Password == pwdHash; + } + } + + diff --git a/csharp/app/Backend/Controllers/Credentials.cs b/csharp/app/Backend/Controllers/Credentials.cs index 43c86a811..2c5c72b45 100644 --- a/csharp/app/Backend/Controllers/Credentials.cs +++ b/csharp/app/Backend/Controllers/Credentials.cs @@ -1,3 +1,6 @@ -namespace Backend.Controllers; +using System.Diagnostics.CodeAnalysis; +namespace Innovenergy.Backend.Controllers; + +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public record Credentials(String Username, String Password); \ No newline at end of file diff --git a/csharp/app/Backend/Database/Db.cs b/csharp/app/Backend/Database/Db.cs index 92d31ca84..aaabfbfd9 100644 --- a/csharp/app/Backend/Database/Db.cs +++ b/csharp/app/Backend/Database/Db.cs @@ -1,11 +1,11 @@ using System.Diagnostics.CodeAnalysis; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db : IDisposable { @@ -97,6 +97,8 @@ public partial class Db : IDisposable return direct.Concat(fromFolders); } + + public IEnumerable GetAllAccessibleFolders(User user) { diff --git a/csharp/app/Backend/Database/Fake.cs b/csharp/app/Backend/Database/Fake.cs index 94325df6d..427c78434 100644 --- a/csharp/app/Backend/Database/Fake.cs +++ b/csharp/app/Backend/Database/Fake.cs @@ -1,6 +1,6 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/Folder.cs b/csharp/app/Backend/Database/Folder.cs index f7411e017..34e20f529 100644 --- a/csharp/app/Backend/Database/Folder.cs +++ b/csharp/app/Backend/Database/Folder.cs @@ -1,9 +1,9 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -37,6 +37,15 @@ public partial class Db return Installations.Where(f => f.ParentId == parent.Id); } + public IEnumerable GetChildUsers(User parent) + { + return Users.Where(f => f.ParentId == parent.Id); + } + + public IEnumerable GetDescendantUsers(User parent) + { + return parent.Traverse(GetChildUsers); + } public Result CreateFolder(Folder folder) { diff --git a/csharp/app/Backend/Database/Installation.cs b/csharp/app/Backend/Database/Installation.cs index 5473892af..a362a39df 100644 --- a/csharp/app/Backend/Database/Installation.cs +++ b/csharp/app/Backend/Database/Installation.cs @@ -1,8 +1,8 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User.cs b/csharp/app/Backend/Database/User.cs index cda467968..e002c48be 100644 --- a/csharp/app/Backend/Database/User.cs +++ b/csharp/app/Backend/Database/User.cs @@ -1,18 +1,16 @@ -using System.Net; using System.Net.Mail; using System.Security.Cryptography; using System.Text; -using System.Text.Json; -using Backend.Model; -using Backend.Utils; using Flurl.Http; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; -using Microsoft.AspNetCore.DataProtection; using SQLite; + #pragma warning disable CS0472 #pragma warning disable CS8602 -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -22,16 +20,16 @@ public partial class Db public User? GetUserById(Int64 id) { - return Users.FirstOrDefault(u => u.Id == id); + return Users.FirstOrDefault(u => u.Id == id); } - + public Boolean IsParentOfChild(User parent, User child) { var parentPointer = child.ParentId; - + if (parent.Id == child.Id) return true; - + while (parentPointer != null && parentPointer != parent.Id) { parentPointer = GetUserById(parentPointer).ParentId; @@ -46,10 +44,10 @@ public partial class Db { if (GetUserByEmail(user.Email) is not null) return Result.Error("User with that email already exists"); - + //Salting and Hashing password var salt = Crypto.GenerateSalt(); - var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), + var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), Encoding.UTF8.GetBytes(salt + "innovEnergy")); user.Salt = salt; @@ -57,49 +55,51 @@ public partial class Db return Create(user); } - + public Object CreateAndSaveUserS3ApiKey(User user) { //EXOSCALE API URL - const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; + const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; var payload = new - { name = user.Email, - operations = new List {"getObject", "listBucket"}, - content = new List{}}; - + { + name = user.Email, + operations = new List { "getObject", "listBucket" }, + content = new List { } + }; + var installationIdList = User2Installation .Where(i => i.UserId == user.Id) .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) .ToList(); - + foreach (var installation in installationIdList) { - payload.content.Add(new {domain = "sos", resource_type = "bucket", resource_name = installation.Name}); //TODO CHANGE NAME TO S3BUCKET + payload.content.Add(new { domain = "sos", resource_type = "bucket", resource_name = installation.Name }); //TODO CHANGE NAME TO S3BUCKET } - + using var hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); var signature = Encoding.UTF8 .GetBytes(payload.ToString()) .Apply(hmacSha1.ComputeHash) .Apply(Convert.ToBase64String); - + var keyJson = url .WithHeader("Authorization", $"POST {apiKey};{signature}") .PostJsonAsync(payload) .ReceiveJson() .Result; - + return SetUserS3ApiKey(user, keyJson.GetValue("key")); } - - public Result SetUserS3ApiKey(User user,String key) + + public Result SetUserS3ApiKey(User user, String key) { user.S3Key = key; return Update(user); } - + public Result UpdateUser(User user) { var oldUser = GetUserById(user.Id); @@ -108,42 +108,39 @@ public partial class Db //Checking for unchangeable things // TODO: depends on privileges of caller - - user.Id = oldUser.Id; + + user.Id = oldUser.Id; user.ParentId = oldUser.ParentId; - user.Email = oldUser.Email; - + user.Email = oldUser.Email; + return Update(user); } public Result DeleteUser(User user) { - User2Folder .Delete(u => u.UserId == user.Id); + User2Folder.Delete(u => u.UserId == user.Id); User2Installation.Delete(u => u.UserId == user.Id); - + //Todo check for orphaned Installations/Folders - + // GetChildUsers() - + return Delete(user); } - + // TODO private static Boolean IsValidEmail(String email) { try - { + { var emailAddress = new MailAddress(email); } catch { return false; } + return true; } - - - -} - +} \ No newline at end of file diff --git a/csharp/app/Backend/Database/User2Folder.cs b/csharp/app/Backend/Database/User2Folder.cs index c55458dde..465eea722 100644 --- a/csharp/app/Backend/Database/User2Folder.cs +++ b/csharp/app/Backend/Database/User2Folder.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User2Installation.cs b/csharp/app/Backend/Database/User2Installation.cs index 79ab547f5..ca329deee 100644 --- a/csharp/app/Backend/Database/User2Installation.cs +++ b/csharp/app/Backend/Database/User2Installation.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/HeaderFilter.cs b/csharp/app/Backend/HeaderFilter.cs new file mode 100644 index 000000000..8ca9cdff8 --- /dev/null +++ b/csharp/app/Backend/HeaderFilter.cs @@ -0,0 +1,24 @@ +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Innovenergy.Backend; + +/// +/// This is for convenient testing! Todo throw me out? +/// Operation filter to add the requirement of the custom header +/// +public class HeaderFilter : IOperationFilter +{ + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + operation.Parameters ??= new List(); + + operation.Parameters.Add(new OpenApiParameter + { + Name = "auth", + In = ParameterLocation.Header, + Content = new Dictionary(), + Required = false + }); + } +} \ No newline at end of file diff --git a/csharp/app/Backend/Model/Folder.cs b/csharp/app/Backend/Model/Folder.cs index fbc016201..c9c39c594 100644 --- a/csharp/app/Backend/Model/Folder.cs +++ b/csharp/app/Backend/Model/Folder.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Folder : TreeNode { diff --git a/csharp/app/Backend/Model/Installation.cs b/csharp/app/Backend/Model/Installation.cs index 9c1f23104..4cca94295 100644 --- a/csharp/app/Backend/Model/Installation.cs +++ b/csharp/app/Backend/Model/Installation.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Installation : TreeNode diff --git a/csharp/app/Backend/Model/Relations/Relation.cs b/csharp/app/Backend/Model/Relations/Relation.cs index 388892872..31250df14 100644 --- a/csharp/app/Backend/Model/Relations/Relation.cs +++ b/csharp/app/Backend/Model/Relations/Relation.cs @@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public abstract class Relation { diff --git a/csharp/app/Backend/Model/Relations/Session.cs b/csharp/app/Backend/Model/Relations/Session.cs index 4db1a9188..ff64b6644 100644 --- a/csharp/app/Backend/Model/Relations/Session.cs +++ b/csharp/app/Backend/Model/Relations/Session.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public class Session : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Folder.cs b/csharp/app/Backend/Model/Relations/User2Folder.cs index 09d0456bf..6e9f56433 100644 --- a/csharp/app/Backend/Model/Relations/User2Folder.cs +++ b/csharp/app/Backend/Model/Relations/User2Folder.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Folder : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Installation.cs b/csharp/app/Backend/Model/Relations/User2Installation.cs index 17dd179ab..43fa45d0e 100644 --- a/csharp/app/Backend/Model/Relations/User2Installation.cs +++ b/csharp/app/Backend/Model/Relations/User2Installation.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Installation : Relation { diff --git a/csharp/app/Backend/Model/TreeNode.cs b/csharp/app/Backend/Model/TreeNode.cs index 61eeb2dba..1daf30f74 100644 --- a/csharp/app/Backend/Model/TreeNode.cs +++ b/csharp/app/Backend/Model/TreeNode.cs @@ -1,7 +1,6 @@ using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public abstract class TreeNode { diff --git a/csharp/app/Backend/Model/User.cs b/csharp/app/Backend/Model/User.cs index b9848cc6c..a1a0be392 100644 --- a/csharp/app/Backend/Model/User.cs +++ b/csharp/app/Backend/Model/User.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class User : TreeNode { diff --git a/csharp/app/Backend/Utils/Crypto.cs b/csharp/app/Backend/Utils/Crypto.cs index 57362c5db..199b17fb9 100644 --- a/csharp/app/Backend/Utils/Crypto.cs +++ b/csharp/app/Backend/Utils/Crypto.cs @@ -1,6 +1,6 @@ using System.Security.Cryptography; -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public static class Crypto { diff --git a/csharp/app/Backend/Utils/Result.cs b/csharp/app/Backend/Utils/Result.cs index 1db4a4cf4..21e85876c 100644 --- a/csharp/app/Backend/Utils/Result.cs +++ b/csharp/app/Backend/Utils/Result.cs @@ -1,4 +1,4 @@ -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public class Result { diff --git a/csharp/app/Backend/db.sqlite b/csharp/app/Backend/db.sqlite index da6dc625ad4a4b6ece95382bb2505180a0801411..fc3ad2ed8207696af0e245f9f64a04984997fcba 100644 GIT binary patch delta 97995 zcma&Pb$k}b7dJXH&+fCnnl6_D)8mQq}t+ zq7jYu5=u3dV>3)W)vFd!n@w!sZ7tPMYgI!}ZKaVE&HJoWW9oSEkxi)N4T)?Gb?=9? zoOeI684dSpm2OOJZ*uA8G|@X*x;G7adQ>(o;}u3Vr?U4-)Kn;GQl>pk@e0edg-*X! zrU9f*bOtrNHqi~Czj@IOpq{JIbEx8FmYoUZ&0^blzm=^|t9Yp~&BKGn1)`>Eq;exk z�`D>YBGcwytD0CiT55F?FDZM=>p`C?lth4rA645|g2l6hW^E6NXM2J9_A(kxi#h zoH=@8Ge^%5mo%?Ux%%GLa?NSH_i4Gd&}gOdt!bP$xxDDik@BtNNP7k8>it%}qcykDQj)dh&!3Bd7KM{h1eP zHVPYaHQavRe%l%AjBwi9UpOnALG~^CXXjO?p3}!!YrpK+PMQ<%oVKqzWt~z^W2cML z()rp^ok{k`&LO9olkEK9Jhp##?m8EpU!0B3ZRff(!+G2O$Jy@8b3SnPILDpEPQfz? z@l9;+=}uO*{UZr#h8&<&QANrWk;=h9Jt?4376_=CD6qmr)^P%li3U`X@K(GM5hs3^ zi&XG#Dw;@KPcTi@=g_IU6#8kjSXENHt5eW19HeAVi>~is+&8sfK9U8JR}iL_i*k;YdMsa;v5iIwC)Yv@;s z$dpPJX_+LEMpYCkOB88L1(C)jh%_Qzq*{5AhL;m*WDJ&}6Irel@NdYmM&qX?&&uoML2@10k?u)nrS;M{sXbVRZv!s`js%tmMh4OXCVP`@Wiwe1 zR*n8e-=YU;4((X9YoND@*P*7jv#2(0?!8l#Om*+?qROn@YZiPU?2YBbz+du=l9=lGuoP zH`gVql@nS)d(e2?j2PO|GuGFn&AbNdlWC^6ent|g;?nh%pdTmJ*P)fXZ`Q|wqADAb zK?!SYNTT(<9vdn_x^P1cFk?qHl!v~&xFL>O-gi(E@}hYwTHYJXGrvNTWKT+^$!xekr>CT*?@ z1K$g2Iq##*71V^Z1h@qV*?V3!H8Le0XkVFnE9ND@^#NOw)Y27Vp)b(<$Mee3Qr^BT zm7tw@MM+?BU)z!l*7vt9)xi>1+?oa!wD;Cb=u6SoN-(zbTPvxd#7LP`h59BeC=Ui% z-Bt^XYUZ{os$D5uCaKk__h3N!|Ydz8rF68U#|tn`M|EO07Nj;&#oP9|TIUPaAH2VJY2 z8Etv}yDSZnoo+D3jIlypD=SJ@m@mB{JLdx3#_cMi( ziQB4DuX^`ow3m0{spVlaTq_bUr9P>l!=A-q9o)!LX8Gd#fruaPSxTFFqxY_))x1Z0 zS1U_hBV4!M!}<1u|DP<+doH?>Na#b)U~E4g$kSX zSx8%Xrw^mZog}ZT7HK{lLP+nL?*U)gN4MY_QbnW3q zbd|O)vEjX6b1k4*DG2}wPnQXr=H?%ugSERjGMRSX(8ng8u^iEPK z?b$#cd&q`smDJ7jjv7u|k_$>s@L_PI{7TWTg<-DjHa4T2P*?0nBJ*B)b~Yo=dmo-C z3O(y;ZUdxL9nr}o=6!T(emJ@9T5i3PZdPSp&YA3Rvc)ys3><#CxVtj*!p|-WCtIPo zZV6#)GH;hCJ_D81#!9g66y~L#gGvs%5pH#}d??fvi{b9tm-532hr6qkRFcZPK9{o@ zIqI!{W&@jD=v8}mRVdTd-KHho0u^}q_(HnS%Q~@|uJ>A;S`r!schol{q4HuLk2$?C zG}%?%OfvyUkRR#vbg>-=T!TB{I z$93FVW+I3JG7UI6|3Xfv2hg=9h~JY^@avq5b3%=w&KhP)CDJmVXqyM9Yg z({^YfHBWi03=6&$tPQi1F69J%4-8`;vMhRztf7fTySjNRudWU4gCC~%rEt?MV;+`uAb$3H<1v4EUOhFb?@62;~p@pvECZL#L zDfIZ-wRyC$*XY&~7;(^zLn@+t#Zj;0^|?^nbGLQ?;bYwLW(u$ay8%k{-t|?X5w78u z!}gKxK)E?L7KO$^mt&B*C|v2xoArENI4J<$mBpKVjbWZ~dmbbEyn@>+LeqiWWl(5} zIg|LpLhvVdzp$2e^Xk0lg|>l!N0x{zNdNmU&S&I`*YhP0WaitKw$hzm!OP1-$ANJn zvnC82^&Oh8@XFF~au&og%uFff6^PD-S3rojxn*6)Yybl*wlG<*t`K*Za&0rCxER#? z-m6RKByZ|#s|F%x%aINNXNvu)-OGB-s$)KDrWjido!-|cXzyxm)yryaWv3Df&X>QH z`$*5zVdRd~Ag~V}ie!0U2>#E1Ky$rBSzuIq-<-q9O0VhL%R_}gv0#Z#!^Mx@o);oH zZp1vaXQ&yV(q%pbwYv)AGfT)@oq2h0fZ84Oq&L@uYJxCmDEP=I5ayb1<-t6E>aD`? z{?EgcGV;r}h0GiM4p3%46ia3_kO0*io*Df5V$jiV-YKHpy}5VR!xGAQcV+n8C2p8Y zutO*}K-r`3<}h->OM7n_?d@HJbdcBP{Z(|Zcjx_eU`@-;M@hnJL09K}urg#Ga-F%@ zd#ob^Cfe6?pn>fl7ScSg@<%J2f!VW=6sY(K%)9x~)DXGpM$I%ci+KuWtkuWM7}?~# z_HjWNi1YN48bLNkelnNN_U?YNCM?0VrlL-vfI^2Cf12H&oUoJ-Sm<_Apu97Yt+YR~ zJJP?bt5%A+m5w#Tj2!Z|{wryxkJR4K8cVg+vub5!i{NnJnA}Zz?*Fiq5Ld}*j7%*i z$nJ0E3M&=LX^72cqDF!Q-pdUqMXsHbX~qGakvA~3vEMBYC&!_aR?2HlArhel5mpisyTIWh`zE?uiOvwS?Mia zl^<8pB=6jhYeH$zi&P|Xv7~=@KSvv2(Icb>d6s(WgC^N)^d5Rm?H}!J?WDF)>#sG? zsQR9|L!G9!QxlXwl$Vrs${?j;@Q2`~;KtzCV5?w^{HJ_DcID1;CFuw0w#21@Qic>3 z_=c7t9|mRyIt9wIU)UA4lnoBtUr>t8;Lw6|U;gK+pk?iUt}KsW4N0;$=jQ~id74{A zxPQ#s{c}}eIbZ#`wpKQ9m?XjyK=X`WV$@_eMJ7q0R5gEz2cNd4eEs2rE-iF^Qib5Nx019zK6fX6?{VhYQk>P@`otj0x%D<=5 zG2VdR>p;5p_qw3*FZ^B|{OaF-Pod4dxW_4UsMqFkCGZQTJg!FPd)pq@gUy{gP*TJD z?{OxqH8TH*16Q!`9|`J|^lWhP8);t7A2qxaeg#&;MwZSq{PRA@PN`1rA6p)k^$@^?kr*IWO03N(8O ze#d*CL)y_({;35u*ZZd$EbK=9lMLl6{%HVXxcyH}7~$i8s?wfb#eY+PB^~~)3+?9q zTLIQJ`~FRbr#|?%68J@d|0=;#)&3KLGW@@4;5Ds*k`CUv|Kg$Kga4A6DZ-N}N4f;0 z7J(Da_&}_E*KTWFv0#c}in-ei8H@G%`Vj3+t(kg;E>LSJ8_1XPD0r+(aIyTe^zQoR z^eK94{nwO-U3AsaXw=Z&Br<+nq2L5?zMIkIVXmtVEOx{?ld6obHYiMZhup9}Xmrqm zB{6=}qB$Y5(sg>FrlT#Y$@up+bwlKq8|sN(DK=4^@dXaeWh9qh3(%FJw$R3Sv~B2U zq%bZ8MH^>ab28eYCx(y@l4v%y_@@$GLHqCtGF?LJoXHN-1WL1bRh2FSIHl4xVPjom z1lm_Ld(|oLsnJDrGJi*-D=FiPC@l)hckQ8AJ2sk1c^so|Sek1OL678#G3C>A>e5X9 zNT-EigIs4o$s7gMHVV+3u!U~0KURbW5J(YiQt%g6@wF!9)Z|qxcr?ik^)B&pYf|3J zrg?)yhkQPEk^;w_Y4#^}XX~0(H;`f;F-x;8#xfSr|Io+N3ED?mYuH*zP}VC_aE|;r z`G9nidrPlK4TU)?`Onq5ik@^XrlS^4=ZhKH>4Mb9F#+}0g;SUX3i-|`x*=?<8`;uK zi3oK?DpzKFcr=Ao-Y!>bj#7c6f`X%3k=-6+ubYWBC z`U{fnk~0AoB#o`3R)XoVUromP8T0f9dS7~jrfIKewbiFogKSr31V0P*mT$|M(jh4n zaEo>g2?Iy3X9*R6eO?O92`5XzQ|w|U!EB982dVt9G6moB7=JT?ZV2VLk#3e*9WEo8 zK;;%yr7)Y{2A{tjjtU6_<@>7%!tCIQ73nHA^*BFSk@E09t6-JU9~~s*JXF6YkuD4; zr=h$bs&cVi=$Awng7eJZOQI{o=iC6_x({A2?$)eip)A|@PswyGmHF;?x`FQGr7O`5 zEafDBx)R97d7ha-H_|h_ab>z3ba8A27y;};xE*oeSQCiK_$qWRt--&p0%jqT2dlx8 zQ+dVepz-baGu6Rl)aOlW(A6Q+jdEL=sl}uLUA$X^7KRj9h=L+OF)Bh5SjI#!X_JA# zEl_idDYc*`&1p_<`~_{EE7n|N5@WjlwcZn0)=)hP`npVu35dLi&ZIKSr?uh#O(}F!C|gb z6-5vG55m4DLrem&L*(y4U?)Jd>eLg%+QLuP10EgVO*4UGwfP&FbO|Vzos2{;?(mrU zba4n4RC*Hfyx71!t}m)M%x5+L{?6vCA?UW^8WnJt0-uGx?P>_dzYI@k1lF#F8;VEU zgnfev>iI@OKf&jX!|@c0WxvLt@#Go)c4N9LY__YG$7X#q$9R4dITtV-wa%GnzH3K2^{uOh=@7G%-d}&q7-}DNp0gU;v#e42R(Qej zoW=v~X)R?d8AY13V7x(ln!wZB(}uJY-`Jj3j0;UtXHIFm)o4P(NcFmP+-BhWG@rg@O_VdODkPaJ9cYE53NGv> zr&MMc@mZ5*&X_)VlBloyjG@!US8q9a(xj0SCd?&!`PB9_St>g_Y#*P~f!2n}_~{N% z&|_blY5YJZT9x(8=2AzR6zFYT;MF?POj)bwwvqXVooEGV%cSWo`I?S2Ss8g_*tDV6 zul!O+T1Sqsr$Qfo??@}CDQ0J*Nv{DTX@HQG!HgXw49n|T*-bT-_u=8%PV<&4=|ibyme1nL>KbI zUFd516o0QLJUX0D>;+SHG;h!qtmu0FdoSwovVG|C@ES{DtyvN0C0v<-Dg3f4%@3b{ z09I^?SdNMY<@3AI9M-#t?}z6?gIy^n0iD9)dA~(pI-AwM#V_`ScH8qe`+*BF7S`6~ za3>Cx3KVf%f0{?*_=En?)l|M@0GM$GOX_IU^x~Pg#y|>7?K5sLrwrXYGhRS)%+nhu-rVZj3V0ovw9fupbqzl<^1g#UtcDeVdUO5JdB z05*f>l<*A1B{)pD&R4lRjIM?4zJNOm$@FCJp7$LB))jJqB)*B) z7z2}ZG`}_my!LeH(by6hfsPIyOS3~|VK;M3@q$6Tu;35Ig7?>gPZ&p6(d+!LaUdEA zFnNze?iN$V8xP!#<@N-+neOHXCjcd8!tUa*60-~PlQoeppk?_B6Y0{>Zn!!GX^+w+ zyv#{(bqv2d38sImmq25di zdpl3LdX9L{@nq*3WTNaGF-NW7HRb~G*70=|v z;0#do+1EkQZEO!U1uWyRSu~$c;or`JiE})kH5>ZYm~Wgz*M-MzbgdkJXVRa*DQ_?p zX5V>WxfC3+KY>&J#$2#awGQ%2Q|XG(MIeZbB8OcAhpgW;x*$ArFKD=ga)RZsk{CLV z!me2k|6(5XLd{@A422C%O#{mBO#?yc#b?h4OEV81CMDh%_!1Ed1f6by4lOcciai<_ zPsT!U)@FcEEHERAi4ScJSR~Bj20ksDu56n1L>~4Bz#6Vp zAPoHNT568+Kp7f*Em%)JAV*1sfyaR{>^+u6_809M3om?fMwWP3(4lcTbaps#!D9Bo zQ5G{!TPjRM0hr3(SdL3k(4{R)=`8VDN6Q&e;z5DxU0h5TgkoS87>?sA=I^gLViq{Z zr{#iWt;<;+Xhs0`+=i5R(V!XaT^Q!rC47Az2>)cBoDVm5<)`z(!uAIe4nTLzx3HAI z>%x+DFz;9Zk~8ikT<(W#!;XV|e_tTjvyo3&0t=?l4IaJ>_%Vy`S_U)A44z&H#(O+} zu@H1{KG@%G=rW`IfPM^L4vX+9{Qhz<5V0UeUC_NmI|ntdSV3VE+l3Z8m&g(DuG~uK z&``c@CCI~Sw?a-wvr#D28S4ZIZ?=lAgPk>gXB7-;DIc|(Zt7dgxA1Mne*ay&t990@ zVy-m<#vJgz2f%vyMXkAdPOYKrQ0!o~{EIvkUbHqLACb0!6X1d8(TBwr-VMuHSn{?A z^f1GNiH_{%7d%)hEC=pQK`tTffZJbg65Pvk&0Ja{>!9R6tr6B3Uccp%|4}noRuu_j zaRAgW8wrI%4$YKWOX2;?IxrR>#vrf0rZIkKE$9qvOWQf~OX>#_4Ojytl6lrTScR26 z#XndFd`{%!*Ms6s2ECk(H={9y%GC|RqgV&BGz-gpZ<+E98(d zQ+CkRP3HRc`%T%IWq)J$v7Wc;ng`4nW10T9K1O?kj)m>5v*b-RS=kW$J2*!EK<+9% zC)I(;Jc{Mh$3?r=f%(o2!xyx;AWeq_?S8?LeAmdePzZ}D-|L_tT8^vbmP4Wy5A@re zFs;nwqj%9Ytl|~^co$tCo^{F%dLDhfHnU3?QoaOZG z!aHC_8q4*+^zqt9^lvRoy{M)rn?a@L%0JKv@<8cD^0`!#^bG6>lxC}onni{|Kj8%p zxW`CHV9S|jL_ZJn`^UlG*#;x8Rl;qbl5sNC9SRoFrExde0Tao8qWz|)_FnZ7iP+JE_h zN&%8^=UMRQ`a(}@7H`URhQLL>^aRS;*Qe+@@W7N@e|_z%uEv+22Jwl3hpGvw>RjAX z6m0H-Q@s8RIK^#vm9t>c%N>PLRz^19!%+3@v%rRd=lO@{fDJw1vcJ&qZ4u@3&I9`g z^S{o6;!WVoFMtUj#Un35=Q~1!6;LqoULe5Pi!e*2gHk2nob7u8jJLi-^Tj6H%a>q> zrUCDB83-_$e{mT^s41Uvg|5!NtV_e`5{Z?U-_#SOU1pa2L$I%r<($%{sSl)6_DAwB zdJ}z^mhL=M-*zTTQEE-OnaZW3`ghu=!E(xvda83#y=v8Vx~pZix1=OX(SA@{YGw4t znyJ>+ubExtkTo^<(3oJHGDlg-O0xcu)y|paRF>-p|H{_Fl^Vtp`wR7V^;Nw{dBZ+u zA2w>pi-O-Mi=8pjH`*UcZ%NaZ$d{a<@=L*qa)0}zHrK4H$-&CT@1|*9v$B=-au4H% zaZ!oVV&xUed&<}5?ci#unqJSGq|7xQ=tLfCKI3Fq1=jH373I_5NiE6QZ*G?s1+$k1 zU8RmP%@}NaYfLltJ67-|<+S;SH6XanoT0adh{S5f3)=hI74u`Oy8f@4ppDQwIvq@| zG?Zf1nZ_#RrumEXNKOxSmwM{CQd{Xo_Pp_gqCrvT7DqB_C zjL=R<`Sw+9t6aud?DSJB$+IOUe;wRl<^&xr`zdL^5@x(@+4eiZ_k(XbZ&*ZKV~o;X zcHT3O1gW|}Jt^M|){;8~OUt{09n3G~Kh@ECIcud=Mj2t4<{f9Du9)ZLeEnyIspquC zW+ij5`fqTQa?JS=!cT5!_05*@Y4bH{g?d|CFHcdPQZ5A#oAd3T6-_>tt&erq8ojMJ zdyiUZ9F;e#S-}eW7wWfCy1q}};gkwy$e#uqtGU`C=WA`e(@JY=$i{m0L+QTqtA1PQ zs(r1jGRsQu>ycV7XOmgem@73?Ck3agL^&vp)jB(QR!=3?_|RPARFLi}f7sicT274C z%;>6BQ(8#bVL>&xN9trX&<0BNr5nn4YmV$0t(={~!RGh>?|*ug|F3_+!@81jMnH z0vfZX0(!8<0vfUg0@7JMIiN9yQM0Y=MWRe*eFX$q9|3h)ZvmrOF9B6p7XcZp^JRg9 z*Z=_|SU&-gY`cK$f%LJ!6gE^qRW`_nfdVpFX#pmEO?18~1_D>ZvDRYK4RI-vO%ss9 zCI|>)BLv8FJ`Q$)NV7(XqO$B&0cF@K0aa;^fLJ;S!-;!E#fxk+Hd8oU)Q7z^8cRA6fbjAF|L^rFa+II>YRP^+Uz<5JW}5{yGJOJFaG+gihJ3_vTkUO*cAT|g5cyRU$FYq9lIf=c zMp1k+le{6C7&KUvm8K^}CJkk+1N$Qg<7Z>YUH|E80%FNt0j1bc0h#1w0fWd60cF`1 z0gcH{QA@9}A{~b6*^O-#S1Qml0(w#GUJ7|A?x@;Ol!dbc0%F)+Q5M$-30sb4FB4g% zok#~&7k7+c$bq30d)0vM6ork+F1-hl)5LEj5H28z))3H)1_a3DT>&P+Zr3H)n9k0K z!anSjfHayepgv6ykWLN?$j)Ln1rA|11SGTT0@|_j0{XMFqF;R`iA)>zmjKxp*mSyE zi!T;zA4^As~+G0!ERG0s?_(0o~ah0VCNv0tT?R1q@@a zi>C)K#9Kzw&qQHTHm!~K&{P2df|QCTM?|g*Ll%@~C{OhnieOKQ(%(3MdfPI9obJ!C zw#L*H&()%MB%)$Bk!eIv3usHxdZ~3qA1c-nMM1g&^>5H3QKq96uFJj@mrB#R0%B=b z0i9`S0h#2QfI)$vfGqYET9#`#@P+|J6evIClEy*KJ%^(?)R*zE%r+@Vwp;9x4#8~R3~wDg58oPMDnAxhmqDe-ha`lWcd zUkCkFV)qY3i^qoe>`SBAwn=V@I|g+YZDs_@i#xgm%8G|=`W-+vaKDAPCD%VC}1$%C!i_CX(~kfid+hLTiiHsHlF2Z zJi~a6$T-I(&^&)Q8zv(GKxei`m?w^f{wAeWD`YaUyE!4 zL5L+^iCkIoxq!N4rGT0QZEabCL~TrtiNZl-kAUvvDFIz6&YXkk0FjF(NSAaXXv}($ zpQ|Gyx;%Q~}8psTD^j zid=1m2C^N+e#X*5QP`Ol2q;VE2`EPo3Ftxh3+PC(*A=rVn$#@1S(J{YD+Hv_a{?;R zBLdpc!vZvhmar8A?*^5w1EZq6H~m|HMgI^`kvE3V!2q=@0J{jS-h=f6Nbb%00>rgqUE%N#EmMubI}REez#twD z>Si4P0=-yrTHH4~(SWiCiYV2k>Y#eS<*zk0koK$fnYl#XY0xivnWl3j!FuEuLsWpBJ|T z=yibmedu`s{d{Xag1slG)tkL3Ae_A+pbUG-&%Gd^F+=@qz;M#2!`6wyR;&o;-vC=J zvLUumKvgzhKrc30Kz)`WAeEs#tjCad2`p6<_G6U~;i6Q=dF9N(YdW0=ko2 zA!`yIjH_2hw=U6*fiW@8ANGIR0%@>T*QoFO3J3STaz4>hoY$?Jc2nhqbKPj~9Ch|P zJDp9=T4%YFXFgW@S}UD?PIsq+(+Up%W#~7hADzmMA-EHn^M7S7+4&*YE-qF7={smjjmsv3HtZ? z7y5^RDf&x#oYY(2s;_ev=y?*6$HQ^EN&0Agu-;p*DOHl*2^_ay(aY#zx~h}F8rVB{ zLwiBH7Q750w1>4l+E#6ywnEDb{up==oUIXUf;K{G8aR+GZ*tCS9ktdFFx}Qjlhd`D zT8b7YCo0X=W?C8bfqGB9tG*X}RefE(tzLy~^b>)N+GFjW>Z)_qsp?p%p59qnqIOl= zN%3ZFwZ59JR#g+#7}HZrsg@d4{)0ml50rb#UFE%CZ~ZCdoEGNHP!1`(mCb?2QuZt6 zcx9fx!uUiPrwmj2NwtixooKng(oJbE|7RyE^_4WGiV~xgQcQWiay9smwJ`WeFe-RQ znHJco9#n1zkDAlX_k%m&K;i1(lE54|V>~)IIQUhtO|VHYBUm$-Vzmjz1+#;lgNl<7 z+^08@e^NKe_vFvy_w~agjCt}KfqU{fDa>dtpODwe%jI1CqFhza&;}S0>N2^7+(0P| zyccwowSlurjyzp`ESs_{{iCV&6zMDJVVqLLd8|#F4m~}+l$l4;_Vr>vFv(|`( ztOnwK`V-=2dJpj^{Sa{Dy(7%WZ2AsnH?UnIJC1opBA-oelTY!&ZSv9+ zyzvAtAns$c5uc|QeI$Q9!OMuZXx_5cA>}ABw%qQb>)F)&1 zb2L))XDT~>T;M`hyEfiM&VsMSvcZVR)DyJ4MV(6 z5BNyFK`dm85Odj|h)3BYzdW1$ia$28&k=91R}fFI3W!(9V{HE__$$zjtI1fpoxO#) zgdIc7XAKdrkoAa{={C{LnE_eGd@g+-@e;j>c##INx{Kqoee{WPfh_iE@ZEQK+cD;o z_&o8OyUt$2@@JUOnsd}A?m6m@?i?MC*U!<$K9X}!aKDcM9q}Mj5YN(e+5QiL!a&ZF z)tKMLot#0(7f@twG$)auA;- zm+z#N`Z@dqC}zO)#57A0nQhZ)5R^sXo-h(jvA2@i@(Vg0Vi5 zwTL^JU&}G_I_8g&!-z+zAUeGKI7&Y83&Jd9oStTEIZeVSf1qmMJQlLqGov%TLjd5%G*-cg*^M{y>_3vtl*`4Ih6ZEinC%RkX*e}0e z@eTt18W3eiZ6DIH^mf2P%)Z8!;E(Op@sXf=IGuffW^){iE`{aW=rcYN-@I-kzSwOe zYp~vJEqnmq6dK!R2+GV3L`2|2TWRknSjR_l25;Ni#@D~)?0YQV%RWN9P4D}8`UBz? z>dX2T>a%hSIg8J4se+d`Ff=#g*|>3--%Oh#US(e+o@YK|Rx#g%?_=>;zKQ1g?QbGK zV11ir`q12m26)$P`W50v+7Iz*)(Vl6r|~vE8nXx4e#DCm$3CC_`KwRSs}z0Qsq{Cz zzJdIWxQaCg1pQl2D`CNUa^(rGLtIDw&aI>V1hkI&V!Dp1c>NmtMi6->TjpDp=jdP9 zAJ4zMgMqHVL>DMm4sXBAaFbvXtL&>q5p4+N(EieZZ>0*^LA)_H5G5X*$1a`0{6*FQ zaW(DaBk=`m1?z$NRpdWxcU6BM(tIc{Dw)s9KE|6?(waV!51wEl-j=b>=qGugE(q8PpM%Tk1uR}p7a$grC3v~83ugDTdx%90>@~yPmy^Uc>{n(X%qSCb1_H<4RJagTKoZSCipAdnx$ifvJ<^^hnF1EodT1lC=^LRt-h zWMB1hw-0&ZfrYqTvw%KpmnX{nK)krLfSnL9pW>2mKE+z*Q~bur{7!aH5}e0y5Xaa< zapOFS`xNtF6Af~+0_bE-U_C`{E**tHTzeesHO=u?;B)ADQ96gbZ*L^Q+5Q}N)87)D zO~b{t+2p$D-|Xp_V%xK0?b}3|#rBKqvuH1IWmXT7nMuLM2{`7%Rs`~e{g}wUtZ!!j z`21hWV9KLx2F32ppfG(wj{GYsn^D>+MU?3b=6q0Q`n7=R^d$tc$*D!;X*lkqYzpFe zHe6hrM&ELtCCXHWtxu)bMd4KPu@AVApF)9ku-89@+M;v{@nwExz_~#DiDzAaV4a6p z3L>XyaVFCp;(^K37f(7EbL6HExUDpqY!{uMJi>W_1Sk2l+#Y~AoU%z|mGdr9CiriU z#!aAmVc$d<&z6ac z)V?Bj@Y@wt;I(Q9!e)Pvhr^MEbof|HG+RP{rX#&(cQ-jkZcB_7C=Qby@vR8(xWq?& z21k9SZQ`%rh2Yb}{O8XgrX&f1F1nP2GDGC5_c?^YDm>~7S^&qUwtqo4hBw{phH^V% z{G1;SMtPerX&#HZ!C(0jBG4is5+=*6?8i%XCJ-n!>MIEJnC>dM?J=MO;}&2)ntlx@ z$|Tp$ZTEkL!ma!of@K{yklPjyvp{r9X97nZ;=h47-C7VR(WaylsQbV-5a2o=id*9- zu}2VIk$De_J3|ymtCBO+5PJCHJrTK?%Rm1XB3>)QQ_cUc%I19sPfdj$HN(I#jFC&w zxb{8G;VZs}K&j_kJ+}!C-4Casyvh%BA;e@@xs5T1r8s=}+z)gy(5=Cb5FkDp#?r7P zG#et;UjI=9COywv-v^>E2crMaK_nQ{z55V1Sr>{kaZC^;)tNw$%7UM0PO}t0B&VGu z4{_#5FT?J^QTR~M@IX21HU#HvG-YFk{-ZuXdsS<~R;j1y->|d0SgojRmVZ$k@*Zi& z+dP0UZ8)`_I|)x)`8|f{pY=>Z~UPx*T zo&m}X|5t?i?ckICgX-YWP3{Ci?I#hmjJJCzLh<%O`B)?kJ_aFM<}V=BX*kwgp{ivxx~2HuU{!*@M~aKE8E?GGSVvKyT{2!p@;BUY5Z^9O|4 zwBp16gsZ1O3etU59U;Y*a194gMM&B)=}VkPb?*fuev!Zh+mrNBb7-$`5nH^Asd1 z5*v6F9$@e-jDx&4g@aD!TK*MfD?(#jBTq${#a@Bfe9zAD38RsFhnfFM#n(IADmr?;taXcDn(OF{H6SRLZ}S*#a8IhX>h8+F|{5wk~uX zxR;Gw#YiP!I#Xb_19D_5Y&jjt4V4u_l-mZCt){(svc@*i=lE5PZ2&#jbLW;A3*hW% zoh^jOdLwrZ79+zUBhysHx5k~=RlWl~9X!}jJDpV1yz>JcS zLWE>%i$MTd4wO$XIZg+azGJa$IIz~sW-CJjK+^qhBNT^yJ+zq%9G~s5rA-oiCT=Cp z4Eswsd34mOV6KLJ$m#lLdVB4Hma1}9R;C2s4Yr5#@~P5Rh-aS4z93uSvnCg4Ro-k0 z#C~-Rhjvc5W}bh%3YiI3pm7L#F_K>ivDF}VrSkkUA=ryLlKsBm?vU<~YWWRb&uK zdH{ItpLNCFf#lsu0G>DIy(=&t+6h-1qw1kWg22?H@hm&MM*-+_BOG~g0N{TW7(~x* zgRwS5t|PsG*eesoSo67Bk!_$2d3q9P-35Ln3A8Sqw@+s4L-oOg)WtSXb3h`RB(VHY zD$u14av4u7fP3(BGSH@>2|mbpQHLx>TD0QUJhIjWUwPvbMuUu!s6*F@|&^62$A7>zV=9- zsEt+MS34>fmD<7e(tE+8T^0H147QeD;zKfld)t5>9Z|M%h6J0W))%6GnCGOj<#1p_ z$!m+3ky$X7#tnt|Zsc|vnB7}oURxtIQ8U1FzR-}t0hi0JoYw+v7|H}l{e;F0PC(?q zX#1mt74yDPx)|+hpg$ZEhZuLP2j=NAbr~E#U%@w}!Pg1~74d87Y+Lw<^I$RhmUu2; zZ|Brvv%=+lu9epZpZ85T-H^%_(*Pe_n-#LUm-zR!!8i#egD(seAN&A^Z+RV9&P?E& z>w*?d;8ij}?iTWP^}w1`;cwN0Tn1lOAD$crRA`SP3j%;1WaS31zG=kwHh@W{+G>!_ zR_I`&d_eDeHWCxu)BJ-*%!QD5CC@)5?;8llA2w$2v6NNN>1JpZeFdR>Q4_YfSp}cN zgCvM&|I+RyFSK5;8cO%!xPN(LjUh|D12^>9+BaJNKs~mfh0|>EBYaaaE2t?Klq$iE zWKhwrSU5nKHwS}~i|IL{C2VZNasGX6SP{S9lzCt&bDFVrbS;l+&ep(@3MCJYc@;-R z1Ebrv6`foLHeqaud;%wbYA0;Mb+CG4P{>g}VV25i&md-g1++Z8WcGrI_;LrK_2+^3 zLvZ%ODFEvEu%poW%X~;vFrrU`7|zD((87V~`K2X8N6pNeh1H>Af^o@f1;%9zhh}D? z;1zQuvNfn=vxCsgbTa|stWo#CRPSvKJg&tnv|+hm3a+;WuBPx#?SQMzL3qcN7$T_q zY;&0R$8Y9Z7U*d&zAlR`51(}dni^RmIpF#dcCn1FUb zN{KNT|omde}tg||^Wlb=uJ%$`noay#w@IAm2R%JE`j;b)2 zpFhz%YNxac>PGsmYQovG2f-1v895?_rB*c(bk`)Vq1Lfnf8q_?@nx+UNL%fiSbQbWWxjDSYFt(nS;@=Nrt5}yS{L~OIQ>Xa+;cP3AE_wtIWx^p> z&aZ^p;+td2KNt$M3t!4#8Ob)o(EvNYB3emcQ)dDOaLy86p04#;i&A|fP9~0&Fc<`UP@nz%T*|H#`WlNkdXg6g7OuFDR=0}&P7ZBp|1O{uZ z8_*Pdan4`Oi;qaciBD)Mj=we$>_}@@$}f!qj7@>EPMQQ01bnPZ&5y(mqWOVk)1ygj zJ}euw{8A;t22zwWnJwsF$2Y<4)qvxSw%=t-!DT*eC7B%DsoAjZ8B8D3iQ4O08mwR2 ztGm?*B|rEmI7+%Me<;-o?3Fvie#(>oU=;ob6R|&_X!mD|QS1S7`s;QypD<<2pCuIb zSy#!2Z;ip|u%9sMhI9P6!pv`gtScVZtvL+N{5``jEMx_t?LfntI6S-zdOJT`==l<$ zd^=Q3Jd*>o9Xti5@9<6hx2f|4z%n7dg^c0 zpjLw>G?@WS4UIhd9-4vK&l9%vKGePI#_W7lMr+!J97vleEAsm0t^8W`EM9{PRU@NzmB@2}?E#C;F50yu4D@6e zDp|3ytCA-?rj2}h4k-3{;Oqbtc5E0X#y9c>XZJ$+NMsR~gNnSn7@UNxP5j>+@KWpY z)wygLoZ4jhL$Pw4zd%JNy0DP$&kyIpT-4<%DEMHMR}>FmNt=8&2hI=a`Ge4w;ZvX! z4_(;ct_OZ#tj51ia!tJYp$W$PxU&QsDSDUV9n%0^RxTWzdO{yl){e zet;X9-yJDi?9V(d6zkOOeDQLyLA`nD6~NPQzIO$T7ks1q&e)}5$!xk(NbGgcxK8NZ z_;wu5tE~i$D+@DENBqho&PXuP_g*Dt9++kGJD?1p^#Misah32`4)gJ=*}7(Be2p9; z!IxC-*?r;Ljp?upQ3irjmgtWHR|3`avD!y$i`Egp?zc^eg1D{PCiBBQ zdMhaJY<_Sn*ofu4_BOT!+~wD|q1YPvW015+Lg3!G?V`o~{N8qG@fx4GgB3Qp>g(P$ z23twuq~;q|WAkY<)>y0mrjM7Nmda_L1Xi(s*krAndV_wfrqd3}Hu#v;1aeJ&Uv6Er zE0;$<1tJIEwJj)()bLk>jCb54dRW88BSsxXD~B!5Ig{{?AI@^dKQ#jh==Li9v3lKo;|;ztag-GL zS7!1)N5Mecbj^YQ_7{~HDEa$Qu^>L{$^{G=gR%`z6&wTe)Y39_BI(~p>)#uTtW)NC z_^Qo^y5u?q<@wADP~Uo2Er`YX@Hv>ZA6#bhf)E&674~54i);zkFS0fIvga>3aFn|x z_@gy1u>zscab{xiWC@QoxCG&vWT$#8WZpE7g8%)ddB?bAjB@rlt?l#1 z2BWU?k&|O?GyXP?Iy>z)=2J$V6=midpE&pI0oLcn1LHlXgK-`lg(ByOIo;`FKp>;J z+{}(QK=}19?A7*SbFOpJS>V(+qRjqIH*=`j&Mf8Jac)}Qnmyqo`nH*DG&kB>Z(B2A zN#EIQWc=nB#>-}^bJ|<4(5RU0+_#5YvCcRr1RU6D9Dqo}T250d$>?YOYs@hkI-lFu;K*UD z^`TSVo@*_4UWc=Nvy3Wss?`8opFC%?HOg8Gf6n2owaLD1wX-f+)to^FfoRPL`-r{Q zso_*|Wb1d^wEwWH*!3WA^N!ugdSLajm)PU%=nD1*yNR{HE^BqM6zit7ACB%$v>YoP zM1jg@Hr-;GQnvXqQOQ&A)vT_7oSerOSmC9%h(F#in>_!#_=5@Lzy-9%cyt4NhDB5mGDq-F4EP;>|QolPrd ziJ~g)McM=pza+L5zk_W=3g7RCv}G%iHft%;Ogtl?H5b2YHWO(jJXWGK5x)bCMOwcR zrVT}^HV|oYeUVz3A`QXWHK;#Bq}k>17zX^k1IU=QMXKW;hX_j(ziXsoc`cEat0__y z|2TwPUHpb`^+Otke;gtb|2RY?Jfae+B+ARA2$Cg>pRq|IO~hBHP0i6iG3ZG84;6;yY7NyxL*(7iw*(l)u;q5)Zq^91! z|CvcoCdmQ|3oNipS^6#=HuT zd;Q;K{FV3ryzle;ym-*-%I7}!NiwrTa_8in`+QHe$SnvxvIWsNl~-60*^I@U2xL0J z{GrH31T@v@L`yIe35)BfxH57R7V~(v$hZg%v5(_PBXc8=eF8Tz&q-+?fqX3(2p@^b zBRJh}1!4iGiKRuZ=hG}hRE;b}jENK=rbU+EwM3Wh#Km}lR9J-DW(#p!hvsK>y$*Mo zkB$lRXge3T)#u>0)NI@~p9R}6DpOiPdz-#gJ_zMItp!>Ci_^|pj~PtZikG(ZT4{7hNXuggrT_YIRv+* z1KcV!?Wnznw(jD#UIMpuDA%FaAPMdT!G@_6uojd3Gpv{Mh5fYsxP91uz}^K(_v`Ex z@VuD`!GDCEuzT4Z?B;d@2-jJ589Q#rAYgwB&9S$w@S=6jdIFN}4_JGx+pW#k8f&RF zAJ%&rV-2+iTHUR-R#Pk2s%n*k6nn+|-Tcn{!hFws6&mAb&Et?(zX!B(HkdcSsxULn zapq818>Xw-%4}rTGPBImreQ|oKgPd`e-M8y{yaQiAC4En_{4S)L|h(U5T70&8^(vm z2Y@hV>v-dM?RZu^J+6ZQ)At~~^PX|ZIA@$P9y0bDyNzw|q+4z*Fs2)0j3Gupql?kf zXkgSZDjFpX6%rAW`lrxsc0qqeKcOGd@7M3tZ_#hmm+ABMsrqQ$*Zb<7^_F@Ay@p;% zFQseRpW64@7utJT_=Ns_nIza8Jwo)6aHPuRx@2*3(`*+Ic$~($M z(5OD498n&CJoj6nmuQ(XUzw_mR(z$e(kXiQe$BakbtXZxm0kVn;3<89#GqrYMX)8g)BdW+RlH~b|PON zsO?DB0ys+tKFi(UY){S>;B3dvW8iE{&e7m(!_GBewr2BjsBcB}_}MMV5}~>US04p4 zY|i!p*ukM4t_3Tftdd|gBg=t3oAQp!!ED0jaj0)h_32URs*tnfmNR@ z{D-PXR#iAn9-JnGpM3*(bICgith!`1h59=DF^_<=HaUBOvlcr+wc|idayAF623ZZk zs!rAfuyV-4>#Z7D!@;Ub)-I3l3B!6JGcZWb?V7g!(LU&I4y9cH;G45uIvZ za8^L43N4O;1DWK+bCxFy@0oI3eKR=AlCuR^8Dvcds|;DA!73e+IR=hN|K}-7krVH( zlI+|9W(hW*05grvJ#Ye>cGbbM$f^$2CRd*XGtTBsP;XE@WQ`oq*|`f$4L%?L5d7;@ z+Cc$JA*(c4GFkZTC9-CNC6a|#sX$h5uwa%P{4x$$QL@H@6(MVeQc#rokfU-z(PDCr z0&5XjVII^k+f%fV?a6-_GMue7N zQOp$TgGDh@fUCF&VkY$92zVJ6QPdRhOF`5`=Z)Z`uqi-rDT1(xPPk@@Aa0_$8R{W! z!s#JQ6+zfU=U#9^+yv)buqbQ_?ZASt2|frTMHDrK$Zjw(YKEyZQP>n}fS1Ci0IvZB zMG!XOsBYkdxQVC7D}Vy0Fdr<4oA^Oc4S^G@@v5Q7DddBbBBu~J4JJfRtltMFg-!w5 z*9AowI^pwOFx$|n@LHqL2|o##5IXTF{Btda_fAaH6C0ct613bq2*AH+@klojBmz$w5ZxrhR%Pzo#xoI-y% z4+Ku!@env6a>7Svf<<>_qC~nd}B*jeup65jrH-&*n9NEK1o6e4$mnZ@4`T1-U{H{lai za6;I`FOEMs#7%HE1dGC^Acs&7aTDtc!KA<`z}rSa5d}`64>%!kV*LqlQsfkBgR?X{ zw}BHPC!BO4SQIz~yay<7@KH*aW2*`28tv#;So6;$}1gdBg=p z5H`V@2Np%m*lai>Ma>wzmlhOhR1HzFh+-yW!xt1m%#1}~#1xzqG-Iv6qM#Y`pc;ZE zR__24q9&SqpgsooKYY*_Fez?=mQO(u#Z8z#SWrlD6O@MKfBKK3&JKG z4F9Hu5H-OX2NnfQn1@wRNI??@tH6YyN#6}jh?;1wf?X+WhOru8LfnMop?OqDVKWBJ zmqG}e^o_wuaT8|17Zg(5jOBqvVKW8~-$DqRaPR`KC~D$QSx8Y6W`q6)Xyx zF&Qifn&8U-YdrjkU_yu}q?ifQ?+OYbX5uFofeAqq&5ck`Q4^B!3kpZE6C!0H1=5*#zn-X2v4WBr1fMiJy75 zR8Z)PS~OAv3=fUAV7O>>fMY?E4CLa^f@?6jz!-#v2z3Lg?jX1ZpsOMn{n3CcudpB0 z;UCl&tuV3+YWrX?Aqblswm3G<* zt}f^r1V(2x5@2*f122w_v=iL!g&oM+EER->?Xk8!?A8tq{H|@$SPVuRGz2hOqtO$L zR%j?-v_vBpj237ZU^GXg3>Xd?T+61o3=o$bR>U+ijuapfUCIRWm>ZNr}>k4+5Fu6z!6Eak~!KO26OlOLU(j~=%#LL=9<-^tD&q}!qiP6{#*Qe=-mG#{w{PlycB;Hx*Q&j zAAw|zz41Ha+v1zzYoX&|aeQukT6}!`ns^Wo2gZBFJIC9^^I^q<+VQIK3h~m=9j`zq z#Lq?&x*#q#ZsT_27U+&xWh{jbiCM;E=#m(2xX>xl-RJ<_ z5>1Re=$Obh%0btJVTjN<@q_*ibWgmezYg>K&*^9M$MmCm5v-ECOWz*qo1vd#g&ykj z^y&Hp{aSs9K1lDachTGGj^0qOqgT@_>Sc5r=JH3iU$kQFOYI}=ZCJPN1(?%+3etEV zgszJ{AW?j)wn1C1Ez=fiv$ZMOSZ##nY5igG-Huu-ttm|9uc=km%4?;xICN$F0b+;W zs-LOvtKl2!1@%10o<9zQs0Y;hU_Fr?>dop+(66xsX7$fdC#s{=q3U3@5A<%dqdEO` z)g0*I$WYT%4dm>9g{sqlb}CzyjmjG3dSwx;_B&M> zr;LO?j{!PBs~km`Hw>KYaxg>-zjZ_-jTJ^a%r(NSDGe`m%?kLKpH6Zk~&Lmq>DmAF(~AkGpei(|y$ zqAT`;#fm$KEur@$Pplzki{-?Uq5NngA@5}L{ml+68$p0#$0T~ zXvk>5sL!a!$YbO(>N4suYBOpvYBFjtsxxvJ)fiQ&|J(GcaIrFjCf=D|7MCh9Dl#fC zG8yF=~2|x%x2F(vMJ)6B2!(_x62193P43(iUWQN2L83H55 zh%zDs_fJGNJ`NHQ)nzC{@BH;k_tUlBt0 zOD=xF_?+<>LU%u9e8Tvc@e$)g#s`e|8SgRPWxT_9oADOoO~xAt%?)2?zQ%Z!@e1P- z<09h%<7LK6j29U%FrH^T$2iY8$9R_U4C86WQz7$7##zQ0#%abAj8lx0j1!E<8ILg@ zWjw+-&Ulz{jPVfTDB}p-f0}!kiw`mmF%B{gFp3z3jQxy#j0YI^Gwx&D%h=1fhp~ro zH)A*5f0}z27k4r4Wb9)9RV=7|`A#^8maS~%9V*+D5V;o~FV+><7V-(|B#x;zQ zj1i3CjA4wS2+19S5Zo|e`V5cZG7^lzj6sZni~)@PjDC#1j6RIsj9!eMj2?{cjBfPf z3vO2~c42g8bYgU5bYQe+v}3eov|+Snv|_Ymv|u!6IE;KoGrIo-w<#B!Fd8!&F&Z)& zFzPevG4dF>jJk|EjM|J^jGBxZjOvUWy8i^X8W*cFsxT@uvKd*7N{ot(3XDufc}6)# zSw;q<45Kt7oly!9!ZlEmizOIoh?r|LEQZO5GYp2#&=@L1VaN=LAu=zGD;jL#UK zGCpB^%=n1$A>#wa`;7M(?=s$Dyv=xv5x&WM0~JIQuhaH5+P+HLS7>{Qwiju8fwnKx z_9fcBNZS`^`#f!*qwRUxo}=xvw0(xQPt*1(+J;XO&eHY_ZBNto3EG120DP^Jv^_!F z$7%Z*Z6BrWBeXqE+lOg;jJ6Na_9$(S(DpEGAEfOe+8%@?2Kayjv@N1-A#L~5b{}mY zpzZy%y^pr{(snOx@1gA;+TKmu-L$=nw!0+EouN>W;bV$Ag@d^J3-=Fv2BM3RNE_%N z_{?0Y__hLXCmXF%T2eVH7imwLr{bgZmY`;SRQyUDYnRqK*-7(wytlbQd0bkkrHS9! zRm}&D_q7w!YH694C;y_TY%f+b9pepsg4q_b5@woJ^$ht-;W6_S?JeoGOQ+!sGBe6D4Hh#q z%=f9i+Da-dKvHk0)mzoHOYo}MSkjHsN*TLPyilzq7mFjzF2*0yFJc+nG8d@b6!d5ID0{S0W2*xQdwpf>bI$T^*lArDl*QAjqDHOQW$R*udiN~H%Xp#Ug}|8 zkUkRE8lEXBbL6S!pm;5%qI|DDU%FGBEnNb=P*18M+QK=hT>M$(En}0mR?5?lt8XZK z%?j%K+8lAQ^@iEoZeVRt$HMz=fBTF0qiSQRr4=_uX!n`5jm6qA^{Bc~{8*T!UWlh_ z;UeLv*vGN`Lcv zy}x}#ZZE}*Zu$-KSn-&!)p|c3m(GgKp|dMLK2aKLhHt|h*`4zB+H=Z9=`CxbG1VBW z?}o0CLdbY{9oA$VV!UjX7pGYDwd`HVR# z{zH7JR!R5ei^88q1?_+qG1^JbDUIZQVjXLc(NNo^Zjd&JFJQ!*<_(~9sqi*_p>F8) zqw-p>FIEd)A1dzis1Xr*y{LGvN3DqV9~+IKntIfT80m2%!s|>&9Q0U1 z=b%T;h-&;&UD~5&#A2@<=bxSO+S1;~J!(me^r$7#!=skOB9FpHIgcfQ&Un<6=`}X-jc3x|uX)t4hNJ?gRA%YKjbcusrNycq69Xzv63ww>UY?fEV>FG{+< zQTwk4zirocf1!OJc7G<`;Zh4@p-U}{`YyFFI=a-tSmaU*qmxT5j501uQ$65P6JwV9 zEuG*Dzj2Rnsfp3X{ffN%_>J3lsf`ilxzxy5qjG#zla`vewSxSYaz%sq+4(e4SVUE@AZ zeB6Bu-J1I-LUbP??@^aUx(>Jxqx)L-7^0;65W;a;Wh`9oa!%`UehE)^AH?bo?jb}! z_aLH|djQehEkaav3+enD-2GUbbvdW?5%+#9_H^%~omRT{VzIfq7tzqY2Qk6j zgOJ_3>G~V)?#ALYeh+Wt?!r?{gAd(~SmbUa z@6GO3EVgiOMND^ZL5y~{AjY^ir;gl=#c-g@B4JzHjpTpA<+Rp4?s}}(-F1lS?oCvC z(!G&*le-q(rn`oUyWG{pB6k(K6?Y|~w0i@hg}VYV+g*<6<6e*G?Jh$&p}Q10)-6EH zaF@_|j`Bmls)RQPU#N9I85iG=YlRF&C!`xwrh3-(=YahR( zw{!#a)^~kGU)Q6`gRYCkvMwte-sld-;%Ije)$VdxBX6@i0No4R{^Z{4_QT>_m!7fh z+&*;wIc{&N-R<@wZgzX(UNzhvR6Op|Q?{Gijfzk3yZU^$3!jP~vuE8-Sj=}j(oUz{ z4#a(Kd*T+i9ag(;Tf}6y4S5f`t@-ai=(a-tVwWDYQ`{Ce9Q(5+0Lb*Gz6T;swM7Q4;( z0lUSmh{c9(1%&Ko!cH*$S?HFhy_dS>(BH=`OT`mz1{Q0(WvIB#Ese#6ZaSkBc{lUR zdv~`4dds?Lh)MkNUd^S4?6t0m&UtPeG21ohz=vHOi!DM|LpFES)Q2iqY~{)b&y~o# z!{vwU9#=s37&nHf9{D}2667-DinV@HEEb$$GdZHLBwL}t;m$-~*p7<8AAn^^N8o$LGiLbDvCcZ?- z33|e2Bk+lVHKx5#@m!H?Lx6K|lqMuHx(Z4<9ysYBvb+UacK6)w^vR!oE!$$cGVRiq+vxqS945Dh{X*$Qw z1UzMBlBR+xB*xHoYWYts@(5Zx1p5w#KzBHASmA;N`;gS79Ri37yd zi6Zp(N$^9qFhLL5_6d5(wn*?pc6)*zvUL;uklmfQ7mw+i*h{B)AaM^Cox~n09!lIz zT$!N9Y}3SDRNR!<1$%`c@E?gZCl55%!KQEnHzCg3d`r0@V*g}+Yky+DZC|v{*{AGd zb`hiv>;P5&mG)wL7ELf144DG$ZO5)>=h(0)qODlJgB;vv);lmC>>T6;9J30oyRGfk z2ACJN$eIar!$w$xAs3*7<%Cu}D+dw*O3>tjV)HZe9moK97DNV*f?(BdQ0)I}a=`?1 zggMykX?8FjQ0=d7RxnGNYW$D*ck$0*wEt549EkKk1QYmn!}Nj;@f+fcKns3+e0Y3t zyl1>U4DZ*AgM?MQL|id`H@-7IH{PZB1tCr_D1s^CuW1jKM}vn2?tb zBl*>g@Q(h} zAighaziCPBGwmJiBFr&3r9GtW2l4%F+InpT4ARfg#%aT}fuYu2YYXG^b+sxm%^*#a z)!)_c)Xza^|B`x6Jq3gE`_JLYE!kYT173Z+92ZfE4+Ar zs=TdSfC2cwrW$Nj)+;y2PyaXnOSHo+??#0NN6W>8A`v=-v}TZi)F_e!D;KN=kwair z1*?9nELi2xigpFdhCHYGi@=b<$g32IsJ}y9Ui1U7iqVR|iXZA{_9frnJjk5D71atV^t|rW8ZgB_u@Vf-HG4q+Q~U z{gq-$yUYcZ?qbNg#2w+QK-MK%FDk{5b%|Cxr5LgOpYenIYfK*HPXNDCJiZdu7xfV#D7elHgI6<$!m{Kikfm(PmWLm<%eXN^O44IZ- zfh2M^9iI%PuL!KqpKCKi(o@FdjJvK)vhCIty zq#D*jo+Vh33rbi_iI&wOr{rSFv#eTODORzz3J8i9Q<`NJNPR7)EX&HHlwwG-j72I( z)+)u6WLY`(yi!a#mf5fbLU9a#o$Sg=aTIsU7BZD$NU#Je_MDQWA3HnRSV=;DCHiJ6 zVGLT)8kFu^cMxs};flq98AX2mTgVmHW1O0BFESCWuf2`<^g|^%o@-Ys$#G=C8URU3 ztgHk-a+2~YD@A`%l8{yzi&TV#4U&{rSuup)AW3PJ6(Jiu30aj;9o?cNN0KF^DM`qx zj72KIRgfG`R`hcv2}zaUi>^?TkW`7*IVDLsl@%a=IteM2(MW}XO48@b(@N4~E0mKi zRT@e%fv&IuWNaq~Q*GofB{_(#eM)j5A2C)*4nQkYD5WI(lLh*`$$og2%xjfoUvkAR zDak%;l~j_w$%?F2lD*jXo09BFmSD@t9&{-DVco$MMlz!}E6HxWUyhRON>=ouoa{pT zRZ^0j(N#VQr|U#kY_O7qs0Y5tD@qc=UMx}$mV8J;+yg7}rIKuiR@vwxISGLe5<&Yb z$u{hoq$DZsm4%s4NeFw;ATJ9cAxUwsY;2d3q_~$68?GcN?v;sbR+13+Vv*8tGbJhT zm5we^k`(yT;igMM;EP4lVL_23MZR>nb(0kN(qZ+1Bt^bbuy$V(B40F8sNllo+BUDe9Go?vRt!$kkLyR;Bn;A|@$G3VLa= z4N9^ye!H~TZAy}YUK(DPS>%h3P?8Y!pf$B&?}r$^!Erm&~SMk+}NdoY_0 zFB*z_dJL{)ihFwWd*w3yBWsb9%4LdsTI62kGKD=Y60VRhQ{2-QD3>YjsnH|KWr}+$ zr1M{BBfqT(@&VJH9VIMo1{ch~;XwEe4 zfAIe;@0P&kSxF(GK(j|)-zdKgU{!VsesjQ>ynF{R zJTD&_ShAa!581(Tzr6gWfbMzuu$-IRAuk_V{c_8^{6>H#x%mwNdA0IkjW@YQt^E3c z?3($o)SFzcW_}*zi_0Zz=mn~tLoZPE9D0GO z=gN)fRRnMUpsCo{)K;=2d@ML+;LkxO-%5~`VDc8Z*r!bc5(EC%aL+?+y z4)svxItTEGT!&tsa-Bjh(YsTwL+?(x&I9bESEpR(J}%LlQ?5hZlerGPIORHfxbAKS zy*AZ#?!r=7*TL7OSY78%L~Vz9Cu=)*aOrl&ZHQXV4#sxIHpW)Qt&Ce3TNpPZYC4-4 zn;07rHJlBE&{@yLb&Q)3)tws=)tt4AHH_7Ws?I7z6^FVct2j4csj{vMRF{UCaIa3&u z8I$O1RB|SAaROsJgL)z>Ib*pr22s%&%^1bFmT?VZB%%VZ;#t8N&ZS|Dp^PDnfZ
*NsLaS_WHBl+Dl#fC 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 I!_=n#1Ih?U!~g&Q delta 95238 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 o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); -builder.Services.AddSwaggerGen(config => -{ - config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); - config.OperationFilter(); //Todo testing throw me out -}); - - - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(cfg => cfg.EnableFilter()); -} - -app.UseCors(); -app.UseHttpsRedirection(); -app.UseAuthorization(); -app.Use(SetSessionUser); -app.MapControllers(); - -app.Run(); - - - - - - -//================= Functions for above =================== - -//Setting User for current Session -async Task SetSessionUser(HttpContext ctx, RequestDelegate next) -{ - var headers = ctx.Request.Headers; - var hasToken = headers.TryGetValue("auth", out var token); - - if (!ctx.Request.Path.ToString().Contains(nameof(Controller.Login))) + public static void Main(string[] args) { - if (!hasToken) + using (var db = Db.Connect()) + db.CreateFakeRelations(); + + var builder = WebApplication.CreateBuilder(args); + + builder.Services.AddControllers(); // TODO: remove magic, specify controllers explicitly + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + + builder.Services.AddHttpContextAccessor(); + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); + builder.Services.AddSwaggerGen(config => { - ctx.Response.StatusCode = 403; - return; - } - - using var db = Db.Connect(); - var user = db.GetUserByToken(token.ToString()); - - if (user is null) - { - ctx.Response.StatusCode = 403; - return; - } - - ctx.Items["User"] = user; - } - - await next(ctx); -} - - - - -/// -/// This is for convenient testing! Todo throw me out? -/// Operation filter to add the requirement of the custom header -/// -public class MyHeaderFilter : IOperationFilter -{ - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - operation.Parameters ??= new List(); - - operation.Parameters.Add(new OpenApiParameter - { - Name = "auth", - In = ParameterLocation.Header, - Content = new Dictionary(), - Required = false + config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); + config.OperationFilter(); //Todo testing throw me out }); + + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(cfg => cfg.EnableFilter()); + } + + app.UseCors(); + app.UseHttpsRedirection(); + app.UseAuthorization(); + app.Use(SetSessionUser); + app.MapControllers(); + + app.Run(); + } + + private static async Task SetSessionUser(HttpContext ctx, RequestDelegate next) + { + var headers = ctx.Request.Headers; + var hasToken = headers.TryGetValue("auth", out var token); + + if (hasToken) + { + using var db = Db.Connect(); + ctx.Items["User"] = db.GetUserByToken(token.ToString()); + } + + await next(ctx); } } \ No newline at end of file