added Ordernumber to installation relation and automatically filled installation order relations on get calls

This commit is contained in:
Kim 2023-03-23 14:23:03 +01:00
parent 7c385bc51c
commit b07991e75d
18 changed files with 83 additions and 80 deletions

View File

@ -2,6 +2,7 @@ using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes;
using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.DataTypes.Methods;
using InnovEnergy.App.Backend.Relations; using InnovEnergy.App.Backend.Relations;
using InnovEnergy.Lib.Utils;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace InnovEnergy.App.Backend.Controllers; namespace InnovEnergy.App.Backend.Controllers;
@ -113,7 +114,7 @@ public class Controller : ControllerBase
.Ancestors() .Ancestors()
.SelectMany(f => f.UsersWithDirectAccess() .SelectMany(f => f.UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user)) .Where(u => u.IsDescendantOf(user))
.Select(u => new { folderId = f.Id, folderName = f.Name, user = u })) .Select(u => new { folderId = f.Id, folderName = f.Name, user = u.HidePassword() }))
.ToList(); .ToList();
} }
@ -151,7 +152,7 @@ public class Controller : ControllerBase
.Ancestors() .Ancestors()
.SelectMany(f => f.UsersWithDirectAccess() .SelectMany(f => f.UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user)) .Where(u => u.IsDescendantOf(user))
.Select(u => new { folderId = f.Id, folderName = f.Name, user = u })) .Select(u => new { folderId = f.Id, folderName = f.Name, user = u.HidePassword() }))
.ToList(); .ToList();
} }
@ -188,6 +189,8 @@ public class Controller : ControllerBase
if (user is null) if (user is null)
return Unauthorized(); return Unauthorized();
user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
return user.AccessibleInstallations().ToList(); return user.AccessibleInstallations().ToList();
} }
@ -317,9 +320,7 @@ public class Controller : ControllerBase
if (!session.Update(updatedUser)) if (!session.Update(updatedUser))
return Unauthorized(); return Unauthorized();
updatedUser.Password = ""; // TODO: generic sanitize return values
return updatedUser; return updatedUser;
} }

View File

@ -1,6 +1,11 @@
using SQLite;
namespace InnovEnergy.App.Backend.DataTypes; namespace InnovEnergy.App.Backend.DataTypes;
public class DeletedFolder : Folder {} public class DeletedFolder : Folder
{
[PrimaryKey]
public override Int64 Id { get; set; }
}
//Deleted Things need to have AT LEAST every property that normal things have //Deleted Things need to have AT LEAST every property that normal things have
//Todo "Restore" Function? -k

View File

@ -1,7 +1,10 @@
using SQLite;
namespace InnovEnergy.App.Backend.DataTypes; namespace InnovEnergy.App.Backend.DataTypes;
//Deleted Things need to have AT LEAST every property that normal things have //Deleted Things need to have AT LEAST every property that normal things have
public class DeletedInstallation : Installation public class DeletedInstallation : Installation
{ {
[PrimaryKey]
public override Int64 Id { get; set; }
} }

View File

@ -7,4 +7,7 @@ namespace InnovEnergy.App.Backend.DataTypes;
public class DeletedUser : User public class DeletedUser : User
{ {
public override String Name { get; set; } = null!; public override String Name { get; set; } = null!;
[PrimaryKey]
public override Int64 Id { get; set; }
} }

View File

@ -1,3 +1,5 @@
using SQLite;
namespace InnovEnergy.App.Backend.DataTypes; namespace InnovEnergy.App.Backend.DataTypes;
@ -8,12 +10,13 @@ public class Installation : TreeNode
public String Country { get; set; } = ""; public String Country { get; set; } = "";
// TODO: make relation // TODO: make relation
public String OrderNumbers { get; set; } = ""; [Ignore] public IReadOnlyList<String> OrderNumbers { get; set; } = Array.Empty<String>();
public Double Lat { get; set; } public Double Lat { get; set; }
public Double Long { get; set; } public Double Long { get; set; }
public String S3Bucket { get; set; } = ""; public String S3Bucket { get; set; } = "";
public String S3Url { get; set; } = ""; public String S3Url { get; set; } = "";
} }

View File

@ -52,8 +52,8 @@ public static class FolderMethods
public static IEnumerable<Installation> ChildInstallations(this Folder parent) public static IEnumerable<Installation> ChildInstallations(this Folder parent)
{ {
return Db return Db
.Installations .Installations
.Where(f => f.ParentId == parent.Id); .Where(f => f.ParentId == parent.Id);
} }
public static IEnumerable<Folder> DescendantFolders(this Folder parent) public static IEnumerable<Folder> DescendantFolders(this Folder parent)

View File

@ -111,7 +111,20 @@ public static class InstallationMethods
{ {
return Db.Installations.Any(i => i.Id == installation.Id); return Db.Installations.Any(i => i.Id == installation.Id);
} }
public static IReadOnlyList<String> GetOrderNumbers(this Installation installation)
{
return Db.OrderNumber2Installation
.Where(i => i.InstallationId == installation.Id)
.Select(i => i.OrderNumber)
.ToReadOnlyList<String>();
}
public static Installation FillOrderNumbers(this Installation installation)
{
installation.OrderNumbers = installation.GetOrderNumbers();
return installation;
}
} }

View File

@ -118,7 +118,6 @@ public static class SessionMethods
&& user.HasWriteAccess && user.HasWriteAccess
&& user.HasAccessTo(installation) && user.HasAccessTo(installation)
&& Db.Create(installation.ToDeletedInstallation()) && Db.Create(installation.ToDeletedInstallation())
// && installation.DeleteBucket().Result // TODO
&& Db.Delete(installation); && Db.Delete(installation);
} }

View File

@ -29,17 +29,13 @@ public static class UserMethods
.DirectlyAccessibleFolders() .DirectlyAccessibleFolders()
.SelectMany(f => f.DescendantFolders().Prepend(f)) .SelectMany(f => f.DescendantFolders().Prepend(f))
.Distinct(); .Distinct();
// Distinct because the user might have direct access
// to a child folder of a folder he has already access to
// TODO shouldn't we prevent doubling permissions? -K"
// TODO yes we should -ig (still TODO)
// however we should still leave the distinct, defensive programming...
} }
public static IEnumerable<TreeNode> AccessibleFoldersAndInstallations(this User user) public static IEnumerable<TreeNode> AccessibleFoldersAndInstallations(this User user)
{ {
var folders = user.AccessibleFolders() as IEnumerable<TreeNode>; var folders = user.AccessibleFolders() as IEnumerable<TreeNode>;
user.AccessibleInstallations().ForEach(i => i.FillOrderNumbers());
var installations = user.AccessibleInstallations(); var installations = user.AccessibleInstallations();
return folders.Concat(installations); return folders.Concat(installations);
@ -203,20 +199,4 @@ public static class UserMethods
return user; return user;
} }
// TODO?
private static Boolean IsValidEmail(String email)
{
try
{
var emailAddress = new MailAddress(email);
}
catch
{
return false;
}
return true;
}
} }

View File

@ -5,7 +5,7 @@ namespace InnovEnergy.App.Backend.DataTypes;
public abstract partial class TreeNode public abstract partial class TreeNode
{ {
[PrimaryKey, AutoIncrement] [PrimaryKey, AutoIncrement]
public Int64 Id { get; set; } public virtual Int64 Id { get; set; }
public virtual String Name { get; set; } = ""; // overridden by User (unique) public virtual String Name { get; set; } = ""; // overridden by User (unique)
public String Information { get; set; } = ""; // unstructured random info public String Information { get; set; } = ""; // unstructured random info

View File

@ -12,9 +12,5 @@ public class User : TreeNode
[Unique] [Unique]
public override String Name { get; set; } = null!; public override String Name { get; set; } = null!;
// TODO: must reset pwd
} }

View File

@ -16,15 +16,16 @@ public static partial class Db
private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath); private static SQLiteConnection Connection { get; } = new SQLiteConnection(DbPath);
public static TableQuery<Session> Sessions => Connection.Table<Session>(); public static TableQuery<Session> Sessions => Connection.Table<Session>();
public static TableQuery<Folder> Folders => Connection.Table<Folder>(); public static TableQuery<Folder> Folders => Connection.Table<Folder>();
public static TableQuery<DeletedFolder> DeletedFolders => Connection.Table<DeletedFolder>(); public static TableQuery<DeletedFolder> DeletedFolders => Connection.Table<DeletedFolder>();
public static TableQuery<Installation> Installations => Connection.Table<Installation>(); public static TableQuery<Installation> Installations => Connection.Table<Installation>();
public static TableQuery<DeletedInstallation> DeletedInstallations => Connection.Table<DeletedInstallation>(); public static TableQuery<DeletedInstallation> DeletedInstallations => Connection.Table<DeletedInstallation>();
public static TableQuery<User> Users => Connection.Table<User>(); public static TableQuery<User> Users => Connection.Table<User>();
public static TableQuery<DeletedUser> DeletedUsers => Connection.Table<DeletedUser>(); public static TableQuery<DeletedUser> DeletedUsers => Connection.Table<DeletedUser>();
public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>(); public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>();
public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>(); public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>();
public static TableQuery<OrderNumber2Installation> OrderNumber2Installation => Connection.Table<OrderNumber2Installation>();
public static void Init() public static void Init()
@ -47,6 +48,7 @@ public static partial class Db
Connection.CreateTable<FolderAccess>(); Connection.CreateTable<FolderAccess>();
Connection.CreateTable<InstallationAccess>(); Connection.CreateTable<InstallationAccess>();
Connection.CreateTable<Session>(); Connection.CreateTable<Session>();
Connection.CreateTable<OrderNumber2Installation>();
}); });
Observable.Interval(TimeSpan.FromDays(0.5)) Observable.Interval(TimeSpan.FromDays(0.5))

View File

@ -18,12 +18,12 @@ public static partial class Db
public static Installation? GetInstallationById(Int64? id) public static Installation? GetInstallationById(Int64? id)
{ {
return Installations return Installations
.FirstOrDefault(i => i.Id == id); .FirstOrDefault(i => i.Id == id)
.FillOrderNumbers();
} }
public static User? GetUserById(Int64? id) public static User? GetUserById(Int64? id)
{ {
//TODO Sanitize Password here
return Users return Users
.FirstOrDefault(u => u.Id == id) .FirstOrDefault(u => u.Id == id)
.HidePassword(); .HidePassword();
@ -31,7 +31,6 @@ public static partial class Db
public static User? GetUserByName(String userName) public static User? GetUserByName(String userName)
{ {
//TODO Sanitize Password here
return Users return Users
.FirstOrDefault(u => u.Name == userName) .FirstOrDefault(u => u.Name == userName)
.HidePassword(); .HidePassword();
@ -39,7 +38,6 @@ public static partial class Db
public static User? GetUserWithPasswordByName(String userName) public static User? GetUserWithPasswordByName(String userName)
{ {
//TODO Sanitize Password here
return Users return Users
.FirstOrDefault(u => u.Name == userName); .FirstOrDefault(u => u.Name == userName);
} }

View File

@ -14,23 +14,21 @@ public static class Mailer
var email = new MimeMessage(); var email = new MimeMessage();
email.From.Add(new MailboxAddress("InnovEnergy", "noreply@innov.energy")); email.From.Add(new MailboxAddress("InnovEnergy", "noreply@innov.energy"));
email.To.Add(new MailboxAddress(emailRecipientUser.Name, "fern95@ethereal.email")); //TODO CHANGE ME email.To.Add(new MailboxAddress(emailRecipientUser.Name, emailRecipientUser.Email));
email.Subject = "Create a new password for your Innovenergy-Account"; email.Subject = "Create a new password for your Innovenergy-Account";
email.Body = new TextPart(MimeKit.Text.TextFormat.Plain) { email.Body = new TextPart(MimeKit.Text.TextFormat.Plain) {
Text = "Dear " + emailRecipientUser.Name + "\n Please create a new password for your Innovenergy-account." + Text = "Dear " + emailRecipientUser.Name + "\n Please create a new password for your Innovenergy-account." +
"\n To do this just login at https://HEEEEELP" "\n To do this just login at https://HEEEEELP"
}; };
using (var smtp = new SmtpClient())
{ using var smtp = new SmtpClient();
smtp.Connect(config.Url, config.Port, false); smtp.Connect(config.Url, config.Port, false);
// Todo put me into urlAndKey.json smtp.Authenticate(config.Username, config.Password);
smtp.Authenticate(config.Username, config.Password);
smtp.Send(email); smtp.Send(email);
smtp.Disconnect(true); smtp.Disconnect(true);
}
return true; return true;
} }

View File

@ -1,13 +1,13 @@
using System.Diagnostics.CodeAnalysis;
namespace InnovEnergy.App.Backend.Mailer; namespace InnovEnergy.App.Backend.Mailer;
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
public class SmptConfig public class SmptConfig
{ {
public String Url { get; init; } public String Url { get; init; } = null!;
public String Username { get; init; } public String Username { get; init; } = null!;
public String Password { get; init; } public String Password { get; init; } = null!;
public Int32 Port { get; init; } public Int32 Port { get; init; } = 587;
public SmptConfig()
{ }
} }

View File

@ -0,0 +1,9 @@
using SQLite;
namespace InnovEnergy.App.Backend.Relations;
public class OrderNumber2Installation : Relation<String, Int64>
{
[Indexed] public String OrderNumber { get => Left ; init => Left = value;}
[Indexed] public Int64 InstallationId { get => Right; init => Right = value;}
}

View File

@ -1,19 +1,12 @@
using System.Text.Json; using System.Diagnostics.CodeAnalysis;
using static System.IO.File; using static System.IO.File;
using static System.Text.Json.JsonSerializer; using static System.Text.Json.JsonSerializer;
namespace InnovEnergy.App.Backend.S3; namespace InnovEnergy.App.Backend.S3;
[SuppressMessage("Trimming", "IL2026:Members annotated with \'RequiresUnreferencedCodeAttribute\' require dynamic access otherwise can break functionality when trimming application code")]
public static class S3Access public static class S3Access
{ {
// TODO: put these into Json files in /Resources and read them from
// there so they can be changed without recompiling
// they should be read from disk on each use,
// so the backend does not need to be restarted on change
public static S3Cmd ReadOnly => Deserialize<S3Cmd>(OpenRead("./Resources/s3ReadOnlyKey.json"))!; public static S3Cmd ReadOnly => Deserialize<S3Cmd>(OpenRead("./Resources/s3ReadOnlyKey.json"))!;
public static S3Cmd ReadWrite => Deserialize<S3Cmd>(OpenRead("./Resources/s3ReadWriteKey.json"))!; public static S3Cmd ReadWrite => Deserialize<S3Cmd>(OpenRead("./Resources/s3ReadWriteKey.json"))!;
} }

Binary file not shown.