diff --git a/csharp/App/Backend/DataTypes/Methods/Folder.cs b/csharp/App/Backend/DataTypes/Methods/Folder.cs index 68c12c68b..ee93eeab8 100644 --- a/csharp/App/Backend/DataTypes/Methods/Folder.cs +++ b/csharp/App/Backend/DataTypes/Methods/Folder.cs @@ -68,36 +68,17 @@ public static class FolderMethods public static Folder? Parent(this Folder folder) { - return IsAbsoluteRoot(folder) + return IsRoot(folder) ? null : Db.GetFolderById(folder.ParentId); } - public static Boolean IsAbsoluteRoot(this Folder folder) + public static Boolean IsRoot(this Folder folder) { - return folder.ParentId == 0; // root has ParentId 0 by definition + return folder.ParentId <= 0 + && Db.GetFolderById(folder.Id)?.Id == 0; // might have been 0 because it is a relative root } - public static Boolean IsRelativeRoot(this Folder folder) - { - return folder.ParentId < 0; // TODO - } - - public static Boolean WasMoved(this Folder folder) - { - if (folder.IsRelativeRoot()) - return false; - - var existingFolder = Db.GetFolderById(folder.Id); - - return existingFolder is not null - && existingFolder.ParentId != folder.ParentId; - } - - public static Boolean Exists(this Folder folder) - { - return Db.Folders.Any(f => f.Id == folder.Id); - } } diff --git a/csharp/App/Backend/DataTypes/Methods/Installation.cs b/csharp/App/Backend/DataTypes/Methods/Installation.cs index 134db9c11..d9fc72728 100644 --- a/csharp/App/Backend/DataTypes/Methods/Installation.cs +++ b/csharp/App/Backend/DataTypes/Methods/Installation.cs @@ -76,21 +76,20 @@ public static class InstallationMethods public static Folder? Parent(this Installation installation) { - return installation.IsRelativeRoot() - ? null - : Db.GetFolderById(installation.ParentId); + if (installation.ParentId <= 0) // relative root + { + var i = Db.GetInstallationById(installation.Id); + if (i is null) + return null; + + installation = i; + } + + return Db.GetFolderById(installation.ParentId); } - public static Boolean IsRelativeRoot(this Installation i) - { - return i.ParentId < 0; - } - public static Boolean WasMoved(this Installation installation) { - if (installation.IsRelativeRoot()) - return false; - var existingInstallation = Db.GetInstallationById(installation.Id); return existingInstallation is not null diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index a1ecf900c..5d5d2b4e7 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -1,5 +1,6 @@ using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.Relations; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.App.Backend.DataTypes.Methods; @@ -13,20 +14,23 @@ public static class SessionMethods && folder is not null && user.HasWriteAccess && user.HasAccessTo(folder.Parent()) - && Db.Create(folder) + && Db.Create(folder) // TODO: these two in a transaction && Db.Create(new FolderAccess { UserId = user.Id, FolderId = folder.Id }); } public static Boolean Update(this Session? session, Folder? folder) { - var user = session?.User; + var user = session?.User; + var original = Db.GetFolderById(folder?.Id); return user is not null && folder is not null + && original is not null && user.HasWriteAccess && user.HasAccessTo(folder) - && (folder.IsRelativeRoot() || user.HasAccessTo(folder.Parent())) - && Db.Update(folder); + && folder + .WithParentOf(original) // prevent moving + .Apply(Db.Update); } public static Boolean Delete(this Session? session, Folder? folder) @@ -49,24 +53,27 @@ public static class SessionMethods && installation is not null && user.HasWriteAccess && user.HasAccessTo(installation.Parent()) - && Db.Create(installation) + && Db.Create(installation) // TODO: these two in a transaction && Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id }) && await installation.CreateBucket() && await installation.RenewS3BucketUrl(); // generation of access _after_ generation of - // bucket to prevent "zombie" access-rights. + // bucket to prevent "zombie" access-rights. } public static Boolean Update(this Session? session, Installation? installation) { var user = session?.User; + + var original = Db.GetInstallationById(installation?.Id); return user is not null && installation is not null + && original is not null && user.HasWriteAccess - && installation.Exists() && user.HasAccessTo(installation) - && (installation.IsRelativeRoot() || user.HasAccessTo(installation.Parent())) // TODO: triple check this - && Db.Update(installation); + && installation + .WithParentOf(original) // prevent moving + .Apply(Db.Update); } public static Boolean Delete(this Session? session, Installation? installation) @@ -77,37 +84,37 @@ public static class SessionMethods && installation is not null && user.HasWriteAccess && user.HasAccessTo(installation) - // && installation.DeleteBucket().Result // TODO: await? + // && installation.DeleteBucket().Result // TODO && Db.Delete(installation); } public static Boolean Create(this Session? session, User? newUser) { var sessionUser = session?.User; - - if (sessionUser is null || newUser is null || !sessionUser.HasWriteAccess) - return false; - newUser.ParentId = sessionUser.Id; // Important! - - return Db.Create(newUser); + return sessionUser is not null + && newUser is not null + && sessionUser.HasWriteAccess + && newUser + .WithParent(sessionUser) + .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password)) + .Apply(Db.Create); } public static Boolean Update(this Session? session, User? editedUser) { var sessionUser = session?.User; - if (editedUser == null || sessionUser == null) return false; + var originalUser = Db.GetUserById(editedUser?.Id); - // TODO: make specific method for changing user account settings like pwd - // Password change is only allowed for oneself - editedUser.Password = editedUser.Id != sessionUser.Id - ? sessionUser.Password - : sessionUser.SaltAndHashPassword(editedUser.Password); - - return sessionUser.HasWriteAccess - && sessionUser.HasAccessTo(editedUser) - && (editedUser.IsRelativeRoot() || sessionUser.HasAccessTo(editedUser.Parent()) || editedUser.Id == sessionUser.Id) // TODO: triple check this - && Db.Update(editedUser); + return editedUser is not null + && sessionUser is not null + && originalUser is not null + && sessionUser.HasWriteAccess + && sessionUser.HasAccessTo(editedUser) + && editedUser + .WithParentOf(originalUser) // prevent moving + .WithPasswordOf(originalUser) + .Apply(Db.Update); } public static Boolean Delete(this Session? session, User? userToDelete) @@ -117,7 +124,7 @@ public static class SessionMethods return sessionUser is not null && userToDelete is not null && sessionUser.HasWriteAccess - && sessionUser.HasAccessTo(userToDelete) // TODO: && user.HasAccessTo(installation.Parent()) ??? + && sessionUser.HasAccessTo(userToDelete) && Db.Delete(userToDelete); } @@ -127,8 +134,8 @@ public static class SessionMethods var sessionUser = session?.User; return sessionUser is not null - && user is not null && installation is not null + && user is not null && user.IsDescendantOf(sessionUser) && sessionUser.HasAccessTo(installation) && !user.HasAccessTo(installation) @@ -140,8 +147,8 @@ public static class SessionMethods var sessionUser = session?.User; return sessionUser is not null - && user is not null && folder is not null + && user is not null && user.IsDescendantOf(sessionUser) && sessionUser.HasAccessTo(folder) && !user.HasAccessTo(folder) @@ -153,8 +160,8 @@ public static class SessionMethods var sessionUser = session?.User; return sessionUser is not null - && user is not null && installation is not null + && user is not null && user.IsDescendantOf(sessionUser) && sessionUser.HasAccessTo(installation) && user.HasAccessTo(installation) @@ -166,8 +173,8 @@ public static class SessionMethods var sessionUser = session?.User; return sessionUser is not null - && user is not null && folder is not null + && user is not null && user.IsDescendantOf(sessionUser) && sessionUser.HasAccessTo(folder) && user.HasAccessTo(folder) diff --git a/csharp/App/Backend/DataTypes/Methods/TreeNode.cs b/csharp/App/Backend/DataTypes/Methods/TreeNode.cs new file mode 100644 index 000000000..3c8a530bc --- /dev/null +++ b/csharp/App/Backend/DataTypes/Methods/TreeNode.cs @@ -0,0 +1,24 @@ +namespace InnovEnergy.App.Backend.DataTypes.Methods; + +public static class TreeNodeMethods +{ + + public static T WithParentOf(this T treeNode, T other) where T: TreeNode + { + treeNode.ParentId = other.ParentId; + return treeNode; + } + + public static T WithParent(this T treeNode, T other) where T: TreeNode + { + treeNode.ParentId = other.Id; + return treeNode; + } + + public static T HideParent(this T treeNode) where T: TreeNode + { + treeNode.ParentId = 0; + return treeNode; + } + +} \ No newline at end of file diff --git a/csharp/App/Backend/DataTypes/Methods/User.cs b/csharp/App/Backend/DataTypes/Methods/User.cs index 410b4680b..5907b7c1e 100644 --- a/csharp/App/Backend/DataTypes/Methods/User.cs +++ b/csharp/App/Backend/DataTypes/Methods/User.cs @@ -34,7 +34,7 @@ public static class UserMethods // 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 leave the distinct, defensive programming... + // however we should still leave the distinct, defensive programming... } public static IEnumerable AccessibleFoldersAndInstallations(this User user) @@ -51,9 +51,9 @@ public static class UserMethods .InstallationAccess .Where(r => r.UserId == user.Id) .Select(r => r.InstallationId) - .Select(Db.GetInstallationById) + .Select(i => Db.GetInstallationById(i)) .NotNull() - .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user + .Do(i => i.HideParent()); // hide inaccessible parents from calling user } public static IEnumerable DirectlyAccessibleFolders(this User user) @@ -62,9 +62,9 @@ public static class UserMethods .FolderAccess .Where(r => r.UserId == user.Id) .Select(r => r.FolderId) - .Select(Db.GetFolderById) + .Select(i => Db.GetFolderById(i)) .NotNull() - .Do(i => i.ParentId = 0); // hide inaccessible parents from calling user; + .Do(f => f.HideParent()); // hide inaccessible parents from calling user; } public static IEnumerable ChildUsers(this User parent) @@ -112,21 +112,17 @@ public static class UserMethods public static User? Parent(this User u) { - return u.IsAbsoluteRoot() + return u.IsRoot() ? null : Db.GetUserById(u.ParentId); } - public static Boolean IsAbsoluteRoot(this User u) - { - return u.ParentId == 0; + public static Boolean IsRoot(this User user) + { + return user.ParentId <= 0 + && Db.GetUserById(user.Id)?.Id == 0; // might have been 0 because it is a relative root } - public static Boolean IsRelativeRoot(this User u) - { - return u.ParentId < 0; - } - public static Boolean HasDirectAccessTo(this User user, Folder folder) { return Db @@ -174,12 +170,6 @@ public static class UserMethods .Contains(user); } - public static Boolean IsRelativeRoot(this User user, Installation i) - { - // TODO: determine not by id but by accessibility - return i.ParentId < 0; - } - public static String Salt(this User user) { // + id => salt unique per user @@ -188,6 +178,14 @@ public static class UserMethods return $"{user.Id}InnovEnergy"; } + public static User WithPasswordOf(this User user, User other) + { + user.Password = other.Password; + return user; + } + + + // TODO? private static Boolean IsValidEmail(String email) diff --git a/csharp/App/Backend/Program.cs b/csharp/App/Backend/Program.cs index 39c324dc8..4a24d1aa7 100644 --- a/csharp/App/Backend/Program.cs +++ b/csharp/App/Backend/Program.cs @@ -4,6 +4,9 @@ namespace InnovEnergy.App.Backend; public static class Program { + + // TODO: Trash + public static void Main(String[] args) { //Db.CreateFakeRelations(); diff --git a/csharp/App/Backend/Relations/Session.cs b/csharp/App/Backend/Relations/Session.cs index fa9a993d4..03af863ee 100644 --- a/csharp/App/Backend/Relations/Session.cs +++ b/csharp/App/Backend/Relations/Session.cs @@ -1,6 +1,5 @@ using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.DataTypes; -using InnovEnergy.Lib.Utils; using SQLite; namespace InnovEnergy.App.Backend.Relations; @@ -13,8 +12,8 @@ public class Session : Relation [Indexed] public Int64 UserId { get => Right; init => Right = value;} [Indexed] public DateTime LastSeen { get; set; } - [Ignore] public Boolean Valid => DateTime.Now - LastSeen < MaxAge - && !User.Email.IsNullOrEmpty(); + [Ignore] public Boolean Valid => DateTime.Now - LastSeen < MaxAge + && (User) is not null; [Ignore] public User User => _User ??= Db.GetUserById(UserId)!;