diff --git a/csharp/App/Backend/Database/Db.cs b/csharp/App/Backend/Database/Db.cs index 3e673e05c..6da24a5f8 100644 --- a/csharp/App/Backend/Database/Db.cs +++ b/csharp/App/Backend/Database/Db.cs @@ -1,19 +1,18 @@ using System.Diagnostics.CodeAnalysis; using InnovEnergy.App.Backend.Model; using InnovEnergy.App.Backend.Model.Relations; -using InnovEnergy.App.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; namespace InnovEnergy.App.Backend.Database; -public partial class Db : IDisposable +public static partial class Db { internal const String DbPath = "./db.sqlite"; - private readonly SQLiteConnection _Db; // internal handle to the connection, disposable + private static readonly SQLiteConnection _Db = new SQLiteConnection(DbPath); - private TableQuery Sessions => _Db.Table(); + private static TableQuery Sessions => _Db.Table(); [SuppressMessage("ReSharper", "AccessToDisposedClosure")] static Db() @@ -33,16 +32,9 @@ public partial class Db : IDisposable }); } - // private, force access through Connect() - private Db() => _Db = new SQLiteConnection(DbPath); - - public static Db Connect() => new Db(); - - public void Dispose() => _Db.Dispose(); - // the C in CRUD - private Int64 Create(TreeNode treeNode) + private static Int64 Create(TreeNode treeNode) { try { @@ -56,7 +48,7 @@ public partial class Db : IDisposable } - private Boolean Create(Session session) + private static Boolean Create(Session session) { try { @@ -70,7 +62,7 @@ public partial class Db : IDisposable } // the U in CRUD - private Boolean Update(TreeNode treeNode) + private static Boolean Update(TreeNode treeNode) { try { @@ -84,7 +76,7 @@ public partial class Db : IDisposable } // the D in CRUD - private Boolean Delete(TreeNode treeNode) + private static Boolean Delete(TreeNode treeNode) { try { @@ -97,49 +89,49 @@ public partial class Db : IDisposable } } - public IEnumerable GetAllAccessibleInstallations(User user) + public static IEnumerable GetAllAccessibleInstallations(User user) { - var direct = GetDirectlyAccessibleInstallations(user); + var direct = GetDirectlyAccessibleInstallations(user); var fromFolders = GetAllAccessibleFolders(user) - .SelectMany(GetChildInstallations); + .SelectMany(GetChildInstallations); return direct - .Concat(fromFolders) - .Distinct(); + .Concat(fromFolders) + .Distinct(); } - public IEnumerable GetAllAccessibleFolders(User user) + public static IEnumerable GetAllAccessibleFolders(User user) { return GetDirectlyAccessibleFolders(user) - .SelectMany(GetDescendantFolders) - .Distinct(); + .SelectMany(GetDescendantFolders) + .Distinct(); // Distinct because the user might have direct access // to a child folder of a folder he has already access to } - public IEnumerable GetDirectlyAccessibleInstallations(User user) + public static IEnumerable GetDirectlyAccessibleInstallations(User user) { return User2Installation - .Where(r => r.UserId == user.Id) - .Select(r => r.InstallationId) - .Select(GetInstallationById) - .NotNull() - .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user + .Where(r => r.UserId == user.Id) + .Select(r => r.InstallationId) + .Select(GetInstallationById) + .NotNull() + .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user } - public IEnumerable GetDirectlyAccessibleFolders(User user) + public static IEnumerable GetDirectlyAccessibleFolders(User user) { return User2Folder - .Where(r => r.UserId == user.Id) - .Select(r => r.FolderId) - .Select(GetFolderById) - .NotNull() - .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user; + .Where(r => r.UserId == user.Id) + .Select(r => r.FolderId) + .Select(GetFolderById) + .NotNull() + .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user; } - public Boolean AddToAccessibleInstallations(Int64 userId, Int64 updatedInstallationId) + public static Boolean AddToAccessibleInstallations(Int64 userId, Int64 updatedInstallationId) { var con = new User2Installation { @@ -158,7 +150,7 @@ public partial class Db : IDisposable } } - public Boolean AddToAccessibleFolders(Int64 userId, Int64 updatedFolderId) + public static Boolean AddToAccessibleFolders(Int64 userId, Int64 updatedFolderId) { var con = new User2Folder { @@ -178,7 +170,7 @@ public partial class Db : IDisposable } - public User? GetUserByToken(String token) + public static User? GetUserByToken(String token) { return Sessions .Where(s => s.Token == token).ToList() @@ -189,9 +181,9 @@ public partial class Db : IDisposable } - public Boolean NewSession(Session ses) => Create(ses); + public static Boolean NewSession(Session ses) => Create(ses); - public Boolean DeleteSession(Int64 id) + public static Boolean DeleteSession(Int64 id) { try { @@ -204,13 +196,14 @@ public partial class Db : IDisposable } } - public Object? GetInstallationS3Key(Int64 installationId) + public static String? GetInstallationS3Key(Int64 installationId) { return Installations - .FirstOrDefault(installation => installation.Id == installationId).S3Key; + .FirstOrDefault(i => i.Id == installationId)? + .S3Key; } - public void DeleteS3KeysDaily() + public static void DeleteAllS3Keys() { foreach (var installation in Installations.ToList()) { diff --git a/csharp/App/Backend/Database/DbConnection.cs b/csharp/App/Backend/Database/DbConnection.cs deleted file mode 100644 index 4676ca498..000000000 --- a/csharp/App/Backend/Database/DbConnection.cs +++ /dev/null @@ -1,18 +0,0 @@ -using InnovEnergy.App.Backend.Model; -using SQLite; - -namespace InnovEnergy.App.Backend.Database; - - -// TODO ? -public struct DbConnection -{ - public DbConnection(SQLiteConnection connection, User caller) - { - Connection = connection; - Caller = caller; - } - - public SQLiteConnection Connection { get;} - public User Caller { get;} -} \ No newline at end of file diff --git a/csharp/App/Backend/Database/Fake.cs b/csharp/App/Backend/Database/Fake.cs index 63fff39ee..6c88cc3be 100644 --- a/csharp/App/Backend/Database/Fake.cs +++ b/csharp/App/Backend/Database/Fake.cs @@ -2,9 +2,9 @@ using InnovEnergy.App.Backend.Model.Relations; namespace InnovEnergy.App.Backend.Database; -public partial class Db +public static partial class Db { - public void CreateFakeRelations() + public static void CreateFakeRelations() { _Db.RunInTransaction(() => { @@ -16,7 +16,7 @@ public partial class Db }); } - private void CreateFakeUserTree() + private static void CreateFakeUserTree() { foreach (var userId in Enumerable.Range(1, NbUsers)) { @@ -32,7 +32,7 @@ public partial class Db } } - private void CreateFakeFolderTree() + private static void CreateFakeFolderTree() { foreach (var folderId in Enumerable.Range(1, NbFolders)) { @@ -48,7 +48,7 @@ public partial class Db } } - private void LinkFakeInstallationsToFolders() + private static void LinkFakeInstallationsToFolders() { var nFolders = NbFolders; @@ -59,7 +59,7 @@ public partial class Db } } - private void GiveFakeUsersAccessToFolders() + private static void GiveFakeUsersAccessToFolders() { foreach (var uf in User2Folder) // remove existing relations _Db.Delete(uf); @@ -79,7 +79,7 @@ public partial class Db } } - private void GiveFakeUsersAccessToInstallations() + private static void GiveFakeUsersAccessToInstallations() { foreach (var ui in User2Installation) // remove existing relations _Db.Delete(ui); diff --git a/csharp/App/Backend/Database/Folder.cs b/csharp/App/Backend/Database/Folder.cs index 1204ed06c..3b08ad654 100644 --- a/csharp/App/Backend/Database/Folder.cs +++ b/csharp/App/Backend/Database/Folder.cs @@ -1,17 +1,16 @@ using InnovEnergy.App.Backend.Model; -using InnovEnergy.App.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; namespace InnovEnergy.App.Backend.Database; -public partial class Db +public static partial class Db { - private TableQuery Folders => _Db.Table(); + private static TableQuery Folders => _Db.Table(); - public Int32 NbFolders => Folders.Count(); + public static Int32 NbFolders => Folders.Count(); - public Folder? GetFolderById(Int64 id) + public static Folder? GetFolderById(Int64 id) { return Folders.FirstOrDefault(u => u.Id == id); @@ -21,56 +20,76 @@ public partial class Db //return PopulateDescendants(folder); } - public IEnumerable GetChildFolders(Folder parent) + public static IEnumerable GetChildFolders(Folder parent) { return Folders.Where(f => f.ParentId == parent.Id); } - - public IEnumerable GetDescendantFolders(Folder parent) - { - return parent.Traverse(GetChildFolders); - } - - public IEnumerable GetChildInstallations(Folder parent) + + public static IEnumerable GetChildInstallations(Folder parent) { return Installations.Where(f => f.ParentId == parent.Id); } - public IEnumerable GetChildUsers(User parent) + public static IEnumerable GetDescendantFolders(Folder parent) { - return Users.Where(f => f.ParentId == parent.Id); + return parent.Traverse(GetChildFolders); } - public IEnumerable GetDescendantUsers(User parent) + public static Boolean IsDescendantOf(Folder folder, Int64 ancestorFolderId) { - return parent.Traverse(GetChildUsers); + return Ancestors(folder) + .Any(u => u.Id == ancestorFolderId); } - public Int64 CreateFolder(Folder folder) + public static Boolean IsDescendantOf(Folder folder, Folder ancestor) + { + return IsDescendantOf(folder, ancestor.Id); + } + + private static IEnumerable Ancestors(Folder child) + { + return child.Unfold(GetParent); + } + + public static Folder? GetParent(Folder f) + { + return IsRoot(f) + ? null + : GetFolderById(f.ParentId); + } + + public static Boolean IsRoot(Folder f) + { + return f.ParentId == 0; // root has ParentId 0 by definition + } + + public static Int64 CreateFolder(Folder folder) { return Create(folder); } - public Boolean UpdateFolder(Folder folder) + public static Boolean UpdateFolder(Folder folder) { // TODO: no circles in path return Update(folder); } - public Boolean ChangeParent(Installation child, Int64 parentId) - { - child.ParentId = parentId; - return UpdateInstallation(child); - } - - public Boolean ChangeParent(Folder child, Int64 parentId) - { - child.ParentId = parentId; - return UpdateFolder(child); - } + // These should not be necessary, just Update folder/installation with new parentId - public Boolean DeleteFolder(Folder folder) + // public Boolean ChangeParent(Installation child, Int64 parentId) + // { + // child.ParentId = parentId; + // return UpdateInstallation(child); + // } + // + // public Boolean ChangeParent(Folder child, Int64 parentId) + // { + // child.ParentId = parentId; + // return UpdateFolder(child); + // } + + public static Boolean DeleteFolder(Folder folder) { // Delete direct children User2Folder .Delete(f => f.FolderId == folder.Id); diff --git a/csharp/App/Backend/Database/Installation.cs b/csharp/App/Backend/Database/Installation.cs index de8aae85b..777b19cbc 100644 --- a/csharp/App/Backend/Database/Installation.cs +++ b/csharp/App/Backend/Database/Installation.cs @@ -1,37 +1,55 @@ using InnovEnergy.App.Backend.Model; -using InnovEnergy.App.Backend.Utils; using SQLite; namespace InnovEnergy.App.Backend.Database; -public partial class Db +public static partial class Db { - private TableQuery Installations => _Db.Table(); + private static TableQuery Installations => _Db.Table(); - public Int32 NbInstallations => Installations.Count(); + public static Int32 NbInstallations => Installations.Count(); - public Installation? GetInstallationById(Int64 id) => Installations + public static Installation? GetInstallationById(Int64 id) => Installations .FirstOrDefault(u => u.Id == id); - public Int64 CreateInstallation(Installation installation) + private static IEnumerable Ancestors(Installation installation) + { + var parentFolder = GetParent(installation); + + return parentFolder is null + ? Enumerable.Empty() + : Ancestors(parentFolder); + } + + public static Folder? GetParent(Installation installation) + { + return IsRoot(installation) + ? null + : GetFolderById(installation.ParentId); + } + + public static Boolean IsRoot(Installation i) + { + return i.ParentId == 0; // root has ParentId 0 by definition + } + + public static Int64 CreateInstallation(Installation installation) { return Create(installation); } - public Boolean UpdateInstallation(Installation installation) + public static Boolean UpdateInstallation(Installation installation) { return Update(installation); } - - public Boolean DeleteInstallation(Installation installation) + public static Boolean DeleteInstallation(Installation installation) { User2Installation.Delete(i => i.InstallationId == installation.Id); return Delete(installation); } - } diff --git a/csharp/App/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs index 980786076..09c52bd85 100644 --- a/csharp/App/Backend/Database/User.cs +++ b/csharp/App/Backend/Database/User.cs @@ -9,34 +9,43 @@ using InnovEnergy.App.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -#pragma warning disable CS0472 -#pragma warning disable CS8602 namespace InnovEnergy.App.Backend.Database; -public partial class Db + +public static partial class Db { - private TableQuery Users => _Db.Table(); + private static TableQuery Users => _Db.Table(); - public Int32 NbUsers => Users.Count(); + public static Int32 NbUsers => Users.Count(); - public User? GetUserById(Int64 id) + public static IEnumerable GetChildUsers(User parent) + { + return Users.Where(f => f.ParentId == parent.Id); + } + + public static IEnumerable GetDescendantUsers(User parent) + { + return parent.Traverse(GetChildUsers); + } + + public static User? GetUserById(Int64 id) { return Users.FirstOrDefault(u => u.Id == id); } - public Boolean IsParentOfChild(Int64 parentId, User child) + public static Boolean IsDescendantOf(User user, User ancestor) { - return Ancestors(child) - .Any(u => u.Id == parentId); + return Ancestors(user) + .Any(u => u.Id == ancestor.Id); } - - private IEnumerable Ancestors(User child) + + private static IEnumerable Ancestors(User child) { return child.Unfold(GetParent); } - public User? GetParent(User u) + public static User? GetParent(User u) { return IsRoot(u) ? null @@ -48,9 +57,28 @@ public partial class Db return u.ParentId == 0; // root has ParentId 0 by definition } - public User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email); + public static Boolean HasDirectAccessToFolder(User user, Folder folder) + { + return HasDirectAccessToFolder(user, folder.Id); + } + + public static Boolean HasDirectAccessToFolder(User user, Int64 folderId) + { + return User2Folder.Any(r => r.FolderId == folderId && r.UserId == user.Id); + } + + public static Boolean HasAccessToFolder(User user, Int64 folderId) + { + var folder = GetFolderById(folderId); + if (folder is null) + return false; - public Int64 CreateUser(User user) + return Ancestors(folder).Any(f => HasDirectAccessToFolder(user, f)); + } + + public static User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email); + + public static Int64 CreateUser(User user) { if (GetUserByEmail(user.Email) is not null) return -1; // TODO: User with that email already exists @@ -69,13 +97,12 @@ public partial class Db private static Byte[] HmacSha256Digest(String message, String secret) { - var encoding = new UTF8Encoding(); - var keyBytes = encoding.GetBytes(secret); - var messageBytes = encoding.GetBytes(message); + var encoding = new UTF8Encoding(); + var keyBytes = encoding.GetBytes(secret); + var messageBytes = encoding.GetBytes(message); var cryptographer = new HMACSHA256(keyBytes); - var bytes = cryptographer.ComputeHash(messageBytes); - return bytes; + return cryptographer.ComputeHash(messageBytes); } private static String BuildSignature(String method, String path, String data, Int64 time, String secret) @@ -93,7 +120,6 @@ public partial class Db Console.WriteLine("Message to sign:\n" + messageToSign); - var hmac = HmacSha256Digest(messageToSign, secret); return Convert.ToBase64String(hmac); } @@ -149,7 +175,7 @@ public partial class Db // // } - public Object? CreateAndSaveInstallationS3ApiKey(Installation installation) + public static Object CreateAndSaveInstallationS3ApiKey(Installation installation) { //EXOSCALE API URL const String url = "https://api-ch-dk-2.exoscale.com/v2/"; @@ -192,7 +218,7 @@ public partial class Db return newKey; } - public Boolean UpdateUser(User user) + public static Boolean UpdateUser(User user) { var oldUser = GetUserById(user.Id); if (oldUser == null) @@ -208,7 +234,7 @@ public partial class Db return Update(user); } - public Boolean DeleteUser(User user) + public static Boolean DeleteUser(User user) { User2Folder.Delete(u => u.UserId == user.Id); User2Installation.Delete(u => u.UserId == user.Id); diff --git a/csharp/App/Backend/Database/User2Folder.cs b/csharp/App/Backend/Database/User2Folder.cs index 29351f1dd..38316200f 100644 --- a/csharp/App/Backend/Database/User2Folder.cs +++ b/csharp/App/Backend/Database/User2Folder.cs @@ -1,12 +1,12 @@ using InnovEnergy.App.Backend.Model.Relations; using SQLite; -namespace InnovEnergy.App.Backend.Database; +namespace InnovEnergy.App.Backend.Database; -public partial class Db +public static partial class Db { - private TableQuery User2Folder => _Db.Table(); - public Int32 NbUser2Folder => User2Folder.Count(); + private static TableQuery User2Folder => _Db.Table(); + public static Int32 NbUser2Folder => User2Folder.Count(); } diff --git a/csharp/App/Backend/Database/User2Installation.cs b/csharp/App/Backend/Database/User2Installation.cs index 069588d7c..0f8eb36a0 100644 --- a/csharp/App/Backend/Database/User2Installation.cs +++ b/csharp/App/Backend/Database/User2Installation.cs @@ -3,12 +3,9 @@ using SQLite; namespace InnovEnergy.App.Backend.Database; -public partial class Db +public static partial class Db { - private TableQuery User2Installation => _Db.Table(); - public Int32 NbUser2Installation => User2Installation.Count(); - - - + private static TableQuery User2Installation => _Db.Table(); + public static Int32 NbUser2Installation => User2Installation.Count(); }