Testing new error messages in Backend, fixing small bugs, possibly breaking BMSTunnel, fixed tests
This commit is contained in:
parent
e45be0e144
commit
b8fc04a90c
|
@ -3,6 +3,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Flurl.Http" Version="3.2.4" />
|
||||
<PackageReference Include="Hellang.Middleware.ProblemDetails" Version="6.5.1" />
|
||||
<PackageReference Include="MailKit" Version="3.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.3" />
|
||||
<PackageReference Include="Microsoft.AspNet.Identity.Owin" Version="2.2.3" />
|
||||
|
|
|
@ -17,14 +17,18 @@ public class Controller : ControllerBase
|
|||
public ActionResult<Session> 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();
|
||||
{
|
||||
throw new Exceptions(401,"Wrong Password Exception", "Please try again.", Request.Path.Value!);
|
||||
}
|
||||
}
|
||||
|
||||
var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user));
|
||||
|
@ -33,7 +37,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!);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<Exceptions>(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();
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -13,16 +13,19 @@ public static class Program
|
|||
|
||||
public static async Task<Int32> 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<BatteryConnection?> ConnectToBms(String? hostName)
|
||||
private static async Task<BatteryConnection?> 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);
|
||||
|
|
|
@ -41,7 +41,7 @@ public class FileSystem
|
|||
public async Task<IReadOnlyList<String>> 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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -114,7 +114,8 @@ export default class DataCache<T extends Record<string, number>>
|
|||
const pn = p + n
|
||||
|
||||
let interpolated: Partial<Record<string, number>> = {}
|
||||
|
||||
|
||||
//What about string nodes? like Alarms
|
||||
for (const k of Object.keys(dataBefore))
|
||||
{
|
||||
interpolated[k] = (dataBefore[k] * n + dataAfter[k] * p) / pn
|
||||
|
|
|
@ -59,7 +59,7 @@ const AvailableUserDialog = () => {
|
|||
scroll="paper"
|
||||
>
|
||||
<DialogTitle id="available-user-dialog-title">
|
||||
Create new folder
|
||||
Grant access
|
||||
</DialogTitle>
|
||||
<DialogContent id="available-user-dialog-content">
|
||||
<Autocomplete
|
||||
|
|
|
@ -27,7 +27,7 @@ const AddUser = () => {
|
|||
sx={{ my: 1 }}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<FormattedMessage id="addUser" defaultMessage="Add user" />
|
||||
<FormattedMessage id="addUser" defaultMessage="Create user" />
|
||||
</InnovenergyButton>
|
||||
<Dialog
|
||||
onClose={() => setOpen(false)}
|
||||
|
|
|
@ -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();
|
||||
});
|
Loading…
Reference in New Issue