diff --git a/csharp/App/Backend/Backend.csproj b/csharp/App/Backend/Backend.csproj index 78c8036ca..ef4777f93 100644 --- a/csharp/App/Backend/Backend.csproj +++ b/csharp/App/Backend/Backend.csproj @@ -3,6 +3,7 @@ + diff --git a/csharp/App/Backend/Controller.cs b/csharp/App/Backend/Controller.cs index 269a5e736..f6366cd97 100644 --- a/csharp/App/Backend/Controller.cs +++ b/csharp/App/Backend/Controller.cs @@ -17,14 +17,19 @@ public class Controller : ControllerBase public ActionResult Login(String username, String password) { var user = Db.GetUserByName(username); - + if (user is null) - return Unauthorized(); - + { + throw new Exceptions(400,"Null User Exception", "Must provide a user to log in as.", Request.Path.Value!); + } + if (!(user.Password is null && user.MustResetPassword)) { if (!user.VerifyPassword(password)) - return Unauthorized(); + { + //return Unauthorized("No Password set"); + throw new Exceptions(401,"Wrong Password Exception", "Please try again.", Request.Path.Value!); + } } var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user)); @@ -33,7 +38,7 @@ public class Controller : ControllerBase return Db.Create(session) ? session - : Unauthorized(); + : throw new Exceptions(401,"Session Creation Exception", "Not allowed to log in.", Request.Path.Value!); } @@ -427,8 +432,6 @@ public class Controller : ControllerBase : Unauthorized(); } - - } diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index cf84e848c..0e3eb1685 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -186,7 +186,8 @@ public static class SessionMethods return sessionUser is not null && sessionUser - .Do(() => sessionUser.Password = sessionUser.SaltAndHashPassword(newPassword)) + .Do(() => sessionUser.Password = sessionUser.SaltAndHashPassword(newPassword)) + .Do(() => sessionUser.MustResetPassword = false) .Apply(Db.Update); } diff --git a/csharp/App/Backend/Exceptions.cs b/csharp/App/Backend/Exceptions.cs new file mode 100644 index 000000000..963a488a8 --- /dev/null +++ b/csharp/App/Backend/Exceptions.cs @@ -0,0 +1,16 @@ +namespace InnovEnergy.App.Backend; + +public class Exceptions : Exception +{ + public String Type { get; set; } + public String Detail { get; set; } + public String Instance { get; set; } + public Int32? Status { get; set; } + public Exceptions(Int32? status, String type, String detail, String instance) + { + Type = type; + Detail = detail; + Instance = instance; + Status = status; + } +} \ No newline at end of file diff --git a/csharp/App/Backend/Program.cs b/csharp/App/Backend/Program.cs index ca4cb8655..3b7979293 100644 --- a/csharp/App/Backend/Program.cs +++ b/csharp/App/Backend/Program.cs @@ -1,4 +1,6 @@ +using Hellang.Middleware.ProblemDetails; using InnovEnergy.App.Backend.Database; +using Microsoft.AspNetCore.Mvc; using Microsoft.OpenApi.Models; namespace InnovEnergy.App.Backend; @@ -16,6 +18,21 @@ public static class Program var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); + builder.Services.AddProblemDetails(setup => + { + //This includes the stacktrace in Development Env + setup.IncludeExceptionDetails = (ctx, env) => builder.Environment.IsDevelopment() || builder.Environment.IsStaging(); + + //This handles our Exceptions + setup.Map(exception => new ProblemDetails() + { + Detail = exception.Detail, + Status = exception.Status, + Type = exception.Type, + Instance = exception.Instance + }); + + }); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", OpenApiInfo); @@ -30,10 +47,11 @@ public static class Program app.UseSwagger(); app.UseSwaggerUI(); } - + app.UseCors(p => p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()) ; app.UseHttpsRedirection(); app.MapControllers(); + app.UseProblemDetails(); app.Run(); } diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite index 8cc280df0..c2a26b55c 100644 Binary files a/csharp/App/Backend/db.sqlite and b/csharp/App/Backend/db.sqlite differ diff --git a/csharp/App/BmsTunnel/BatteryConnection.cs b/csharp/App/BmsTunnel/BatteryConnection.cs index 28dd3ee8a..a3cfc5cc2 100644 --- a/csharp/App/BmsTunnel/BatteryConnection.cs +++ b/csharp/App/BmsTunnel/BatteryConnection.cs @@ -38,7 +38,7 @@ public readonly struct BatteryConnection var ttys = await fs.GetFiles("/dev", FileType.CharacterDevice); var candidateTtys = ttys - .Where(f => f.StartsWith("ttyUSB")) + .Where(f => f.Contains("ttyUSB")) .Select(t => t.Split("/").LastOrDefault()) .NotNull() .ToList(); diff --git a/csharp/App/BmsTunnel/BmsTunnel.cs b/csharp/App/BmsTunnel/BmsTunnel.cs index 85cefdf14..bb3999280 100644 --- a/csharp/App/BmsTunnel/BmsTunnel.cs +++ b/csharp/App/BmsTunnel/BmsTunnel.cs @@ -23,15 +23,16 @@ public class BmsTunnel : IDisposable private const Byte TunnelCode = 0x41; private const String CrcError = "?? CRC FAILED"; - public BmsTunnel(String tty, Byte node) + public BmsTunnel(String tty, Byte node, SshHost? host) { Tty = tty; Node = node; - StopSerialStarter(); + StopSerialStarter(host); SerialPort = new SerialPort(Tty, BaudRate, Parity, DataBits, StopBits); SerialPort.ReadTimeout = 100; + SerialPort.Open(); } @@ -164,10 +165,11 @@ public class BmsTunnel : IDisposable .Concat(NewLine); } - private void StopSerialStarter() + private void StopSerialStarter(SshHost? host) { CliPrograms.StopTty .WithArguments(Tty) + .OnHost(host) .ExecuteBufferedAsync() .Task .Wait(3000); diff --git a/csharp/App/BmsTunnel/Program.cs b/csharp/App/BmsTunnel/Program.cs index c3ce8f71e..538ff348b 100644 --- a/csharp/App/BmsTunnel/Program.cs +++ b/csharp/App/BmsTunnel/Program.cs @@ -13,16 +13,19 @@ public static class Program public static async Task Main(String[] args) { - var connection = await ConnectToBms(args.FirstOrDefault()); + var hostName = args.FirstOrDefault(); + + BatteryConnection? connection = hostName is not null ? await ConnectToBms(hostName, new SshHost(hostName)): new BatteryConnection(); if (connection is null) return 2; - + + // connection.Tty; Console.WriteLine("\nstarting BMS tunnel\n"); - // var path = $"/dev/{tty}"; - // if (host != null) - // path = $"root@{host}" + path; + var path = $"/dev/{connection.Value.Tty}"; + // if (hostName != null) + // path = $"root@{hostName}:" + path; // // var node = connection.Nodes.Any() // ? connection.Nodes.First() @@ -30,13 +33,13 @@ public static class Program // // TODO: Fixme - var path = ""; + // var path = ""; Byte node = 2; var nodes = new Byte[] { 1, 2, 3 }; // TODO: Fixme - using var tunnel = new BmsTunnel(path, node); + using var tunnel = new BmsTunnel(path, node, hostName is not null ? new SshHost(hostName): null); ExplainNode(); ExplainNodes(); @@ -117,12 +120,8 @@ public static class Program } } - private static async Task ConnectToBms(String? hostName) + private static async Task ConnectToBms(String? hostName, SshHost host) { - if (hostName is null) - return new BatteryConnection(); - - var host = new SshHost(hostName); if (await host.Ping()) return await BatteryConnection.Connect(host); diff --git a/csharp/Lib/Utils/FileSystem.cs b/csharp/Lib/Utils/FileSystem.cs index 95a77a9b0..f0823676c 100644 --- a/csharp/Lib/Utils/FileSystem.cs +++ b/csharp/Lib/Utils/FileSystem.cs @@ -41,7 +41,7 @@ public class FileSystem public async Task> GetFiles(String path, FileType fileType, Int32 maxDepth = 1) { var result = await Find - .WithArguments($"find {path} -maxdepth {maxDepth} -type {(Char)fileType}") + .WithArguments($"{path} -maxdepth {maxDepth} -type {(Char)fileType}") .OnHost(Host) .ExecuteBufferedAsync(); diff --git a/typescript/DataCache/src/server.ts b/typescript/DataCache/src/server.ts index 69d8b0cfc..840593161 100644 --- a/typescript/DataCache/src/server.ts +++ b/typescript/DataCache/src/server.ts @@ -8,6 +8,7 @@ const resolution = TimeSpan.fromSeconds(2); const cache = new DataCache(x => (Promise.resolve({foo: 0})), resolution) +// @ts-ignore const sampleTimes = [1, 2, 3, 4, 5, 6].select(e => UnixTime.fromTicks(e)).toArray(); const series = cache.getSeries(sampleTimes) diff --git a/typescript/DataCache/src/server/dataCache/dataCache.ts b/typescript/DataCache/src/server/dataCache/dataCache.ts index f26068c54..18b5ca3bf 100644 --- a/typescript/DataCache/src/server/dataCache/dataCache.ts +++ b/typescript/DataCache/src/server/dataCache/dataCache.ts @@ -114,7 +114,8 @@ export default class DataCache> const pn = p + n let interpolated: Partial> = {} - + + //What about string nodes? like Alarms for (const k of Object.keys(dataBefore)) { interpolated[k] = (dataBefore[k] * n + dataAfter[k] * p) / pn diff --git a/typescript/Frontend/src/components/Groups/AccessManagement/AvailableUserDialog.tsx b/typescript/Frontend/src/components/Groups/AccessManagement/AvailableUserDialog.tsx index 7859a03e2..96ed26adf 100644 --- a/typescript/Frontend/src/components/Groups/AccessManagement/AvailableUserDialog.tsx +++ b/typescript/Frontend/src/components/Groups/AccessManagement/AvailableUserDialog.tsx @@ -59,7 +59,7 @@ const AvailableUserDialog = () => { scroll="paper" > - Create new folder + Grant access { sx={{ my: 1 }} onClick={() => setOpen(true)} > - + setOpen(false)} diff --git a/typescript/Frontend/src/tests/test.js b/typescript/Frontend/src/tests/test.js index f2f529b34..72968b030 100644 --- a/typescript/Frontend/src/tests/test.js +++ b/typescript/Frontend/src/tests/test.js @@ -1,4 +1,5 @@ import { Selector } from 'testcafe'; +import { login, logout } from "./helper.js"; fixture('Login testing') .page('http://localhost:3000/'); //Todo write me in a config file @@ -8,33 +9,31 @@ fixture('Login testing') test('Lulu login', async t => { // await t // .debug(); - await t - .login('lulu', '1233') //Todo write me in a config file - .expect(Selector('#demo-simple-select').visible).ok(); + login('lulu', '1233'); //Todo write me in a config file + await t.expect(Selector('#demo-simple-select').visible).ok(); }); test('Wrong PW', async t => { - await t - .login('lulu', '12334') //Todo write me in a config file - .expect(Selector('#demo-simple-select').visible).notOk(); //Todo check for feedback + login('lulu', '12334'); //Todo write me in a config file + await t.expect(Selector('#demo-simple-select').visible).notOk(); //Todo check for feedback }); test('Invalid Username', async t => { + login('Not Agent Smith', '12334') await t - .login('Not Agent Smith', '12334') //Todo write me in a config file .expect(Selector('#demo-simple-select').visible).notOk(); //Todo check for feedback }); test('Logout', async t => { + login('lulu', '1233'); + logout(); await t - .login('lulu', '1233') //Todo write me in a config file - .logout() .expect(Selector('#username-textfield').visible).Ok(); }); test('Installation List Loads', async t => { + login('lulu', '1233'); await t - .login('lulu', '1233') //Todo write me in a config file .expect(Selector('').visible).Ok(); }); \ No newline at end of file