add GetTree endpoint

This commit is contained in:
ig 2023-02-24 13:59:56 +01:00
parent 313e5f4a81
commit 599b23da2c
4 changed files with 78 additions and 27 deletions

View File

@ -160,8 +160,47 @@ public class Controller
.GetAllAccessibleFolders(caller) .GetAllAccessibleFolders(caller)
.ToList(); // important! .ToList(); // important!
} }
[Returns<TreeNode[]>] // assuming swagger knows about arrays but not lists (JSON)
[Returns(HttpStatusCode.Unauthorized)]
[HttpGet($"{nameof(GetTree)}/")]
public Object GetTree()
{
var caller = GetCaller();
if (caller == null)
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
using var db = Db.Connect();
var folders = db
.GetDirectlyAccessibleFolders(caller) // ReSharper disable once AccessToDisposedClosure
.Select(f => PopulateChildren(db, f));
var installations = db.GetDirectlyAccessibleInstallations(caller);
return folders
.Concat<TreeNode>(installations)
.ToList(); // important!
}
private static Folder PopulateChildren(Db db, Folder folder, HashSet<Int64>? hs = null)
{
// TODO: remove cycle detector
hs ??= new HashSet<Int64>();
if (!hs.Add(folder.Id))
throw new Exception("Cycle detected: folder " + folder.Id);
var installations = db.GetChildInstallations(folder);
var folders = db
.GetChildFolders(folder)
.Select(c => PopulateChildren(db, c, hs));
folder.Children = folders.Concat<TreeNode>(installations).ToList();
return folder;
}
[Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.OK)]
[Returns(HttpStatusCode.Unauthorized)] [Returns(HttpStatusCode.Unauthorized)]
[HttpPut($"{nameof(UpdateUser)}/")] [HttpPut($"{nameof(UpdateUser)}/")]
@ -184,7 +223,7 @@ public class Controller
[Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.OK)]
[Returns(HttpStatusCode.Unauthorized)] [Returns(HttpStatusCode.Unauthorized)]
[HttpPut($"{nameof(UpdateInstallation)}/")] [HttpPut($"{nameof(UpdateInstallation)}/")]
public Object UpdateInstallation(Installation updatedInstallation) public Object UpdateInstallation(Installation installation)
{ {
var caller = GetCaller(); var caller = GetCaller();
@ -195,7 +234,7 @@ public class Controller
var hasAccessToInstallation = db var hasAccessToInstallation = db
.GetAllAccessibleInstallations(caller) .GetAllAccessibleInstallations(caller)
.Any(i => i.Id == updatedInstallation.Id); .Any(i => i.Id == installation.Id);
if (!hasAccessToInstallation) if (!hasAccessToInstallation)
return new HttpResponseMessage(HttpStatusCode.Unauthorized); return new HttpResponseMessage(HttpStatusCode.Unauthorized);
@ -203,7 +242,7 @@ public class Controller
// TODO: accessibility by other users etc // TODO: accessibility by other users etc
// TODO: sanity check changes // TODO: sanity check changes
return db.UpdateInstallation(updatedInstallation); return db.UpdateInstallation(installation);
} }

View File

@ -0,0 +1,24 @@
using System.Diagnostics.CodeAnalysis;
namespace Innovenergy.Backend.Model;
public abstract partial class TreeNode
{
protected Boolean Equals(TreeNode other)
{
return Id == other.Id && ParentId == other.ParentId;
}
public override Boolean Equals(Object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((TreeNode)obj);
}
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
public override Int32 GetHashCode()
{
return HashCode.Combine(Id, ParentId);
}
}

View File

@ -2,33 +2,20 @@ using SQLite;
namespace Innovenergy.Backend.Model; namespace Innovenergy.Backend.Model;
public abstract class TreeNode public abstract partial class TreeNode
{ {
[PrimaryKey, AutoIncrement] [PrimaryKey, AutoIncrement]
public Int64 Id { get; set; } public Int64 Id { get; set; }
public String Name { get; set; } = ""; public String Name { get; set; } = "";
public String Information { get; set; } = ""; // unstructured random info public String Information { get; set; } = ""; // unstructured random info
protected Boolean Equals(TreeNode other)
{
return Id == other.Id && ParentId == other.ParentId;
}
public override Boolean Equals(Object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == this.GetType() && Equals((TreeNode)obj);
}
public override Int32 GetHashCode()
{
return HashCode.Combine(Id, ParentId);
}
[Indexed] // parent/child relation [Indexed] // parent/child relation
public Int64 ParentId { get; set; } public Int64 ParentId { get; set; }
[Ignore] // not in DB, can be used in typescript as type discriminator [Ignore] // not in DB, can be used in typescript as type discriminator
public String Type => GetType().Name; public String Type => GetType().Name;
[Ignore]
public IReadOnlyList<TreeNode>? Children { get; set; }
} }

View File

@ -3,9 +3,9 @@ using Microsoft.OpenApi.Models;
namespace Innovenergy.Backend; namespace Innovenergy.Backend;
public class Program public static class Program
{ {
public static void Main(string[] args) public static void Main(String[] args)
{ {
using (var db = Db.Connect()) using (var db = Db.Connect())
db.CreateFakeRelations(); db.CreateFakeRelations();
@ -18,10 +18,11 @@ public class Program
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod()));
builder.Services.AddSwaggerGen(config => builder.Services.AddSwaggerGen(c =>
{ {
config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); c.SwaggerDoc("v1", new OpenApiInfo { Title = "InnovEnergy Backend API", Version = "v1" });
config.OperationFilter<HeaderFilter>(); //Todo testing throw me out c.UseAllOfToExtendReferenceSchemas();
c.OperationFilter<HeaderFilter>(); //Todo testing throw me out
}); });