fix handling of relative roots

This commit is contained in:
ig 2023-03-21 11:49:17 +01:00
parent 9098ac81b5
commit 381df5f38d
7 changed files with 100 additions and 89 deletions

View File

@ -68,36 +68,17 @@ public static class FolderMethods
public static Folder? Parent(this Folder folder) public static Folder? Parent(this Folder folder)
{ {
return IsAbsoluteRoot(folder) return IsRoot(folder)
? null ? null
: Db.GetFolderById(folder.ParentId); : 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);
}
} }

View File

@ -76,21 +76,20 @@ public static class InstallationMethods
public static Folder? Parent(this Installation installation) public static Folder? Parent(this Installation installation)
{ {
return installation.IsRelativeRoot() if (installation.ParentId <= 0) // relative root
? null {
: Db.GetFolderById(installation.ParentId); var i = Db.GetInstallationById(installation.Id);
} if (i is null)
return null;
public static Boolean IsRelativeRoot(this Installation i) installation = i;
{ }
return i.ParentId < 0;
return Db.GetFolderById(installation.ParentId);
} }
public static Boolean WasMoved(this Installation installation) public static Boolean WasMoved(this Installation installation)
{ {
if (installation.IsRelativeRoot())
return false;
var existingInstallation = Db.GetInstallationById(installation.Id); var existingInstallation = Db.GetInstallationById(installation.Id);
return existingInstallation is not null return existingInstallation is not null

View File

@ -1,5 +1,6 @@
using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.Relations; using InnovEnergy.App.Backend.Relations;
using InnovEnergy.Lib.Utils;
namespace InnovEnergy.App.Backend.DataTypes.Methods; namespace InnovEnergy.App.Backend.DataTypes.Methods;
@ -13,20 +14,23 @@ public static class SessionMethods
&& folder is not null && folder is not null
&& user.HasWriteAccess && user.HasWriteAccess
&& user.HasAccessTo(folder.Parent()) && 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 }); && Db.Create(new FolderAccess { UserId = user.Id, FolderId = folder.Id });
} }
public static Boolean Update(this Session? session, Folder? folder) 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 return user is not null
&& folder is not null && folder is not null
&& original is not null
&& user.HasWriteAccess && user.HasWriteAccess
&& user.HasAccessTo(folder) && user.HasAccessTo(folder)
&& (folder.IsRelativeRoot() || user.HasAccessTo(folder.Parent())) && folder
&& Db.Update(folder); .WithParentOf(original) // prevent moving
.Apply(Db.Update);
} }
public static Boolean Delete(this Session? session, Folder? folder) public static Boolean Delete(this Session? session, Folder? folder)
@ -49,24 +53,27 @@ public static class SessionMethods
&& installation is not null && installation is not null
&& user.HasWriteAccess && user.HasWriteAccess
&& user.HasAccessTo(installation.Parent()) && 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 }) && Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id })
&& await installation.CreateBucket() && await installation.CreateBucket()
&& await installation.RenewS3BucketUrl(); // generation of access _after_ generation of && 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) public static Boolean Update(this Session? session, Installation? installation)
{ {
var user = session?.User; var user = session?.User;
var original = Db.GetInstallationById(installation?.Id);
return user is not null return user is not null
&& installation is not null && installation is not null
&& original is not null
&& user.HasWriteAccess && user.HasWriteAccess
&& installation.Exists()
&& user.HasAccessTo(installation) && user.HasAccessTo(installation)
&& (installation.IsRelativeRoot() || user.HasAccessTo(installation.Parent())) // TODO: triple check this && installation
&& Db.Update(installation); .WithParentOf(original) // prevent moving
.Apply(Db.Update);
} }
public static Boolean Delete(this Session? session, Installation? installation) public static Boolean Delete(this Session? session, Installation? installation)
@ -77,7 +84,7 @@ public static class SessionMethods
&& installation is not null && installation is not null
&& user.HasWriteAccess && user.HasWriteAccess
&& user.HasAccessTo(installation) && user.HasAccessTo(installation)
// && installation.DeleteBucket().Result // TODO: await? // && installation.DeleteBucket().Result // TODO
&& Db.Delete(installation); && Db.Delete(installation);
} }
@ -85,29 +92,29 @@ public static class SessionMethods
{ {
var sessionUser = session?.User; var sessionUser = session?.User;
if (sessionUser is null || newUser is null || !sessionUser.HasWriteAccess) return sessionUser is not null
return false; && newUser is not null
&& sessionUser.HasWriteAccess
newUser.ParentId = sessionUser.Id; // Important! && newUser
.WithParent(sessionUser)
return Db.Create(newUser); .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password))
.Apply(Db.Create);
} }
public static Boolean Update(this Session? session, User? editedUser) public static Boolean Update(this Session? session, User? editedUser)
{ {
var sessionUser = session?.User; 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 return editedUser is not null
// Password change is only allowed for oneself && sessionUser is not null
editedUser.Password = editedUser.Id != sessionUser.Id && originalUser is not null
? sessionUser.Password && sessionUser.HasWriteAccess
: sessionUser.SaltAndHashPassword(editedUser.Password); && sessionUser.HasAccessTo(editedUser)
&& editedUser
return sessionUser.HasWriteAccess .WithParentOf(originalUser) // prevent moving
&& sessionUser.HasAccessTo(editedUser) .WithPasswordOf(originalUser)
&& (editedUser.IsRelativeRoot() || sessionUser.HasAccessTo(editedUser.Parent()) || editedUser.Id == sessionUser.Id) // TODO: triple check this .Apply(Db.Update);
&& Db.Update(editedUser);
} }
public static Boolean Delete(this Session? session, User? userToDelete) public static Boolean Delete(this Session? session, User? userToDelete)
@ -117,7 +124,7 @@ public static class SessionMethods
return sessionUser is not null return sessionUser is not null
&& userToDelete is not null && userToDelete is not null
&& sessionUser.HasWriteAccess && sessionUser.HasWriteAccess
&& sessionUser.HasAccessTo(userToDelete) // TODO: && user.HasAccessTo(installation.Parent()) ??? && sessionUser.HasAccessTo(userToDelete)
&& Db.Delete(userToDelete); && Db.Delete(userToDelete);
} }
@ -127,8 +134,8 @@ public static class SessionMethods
var sessionUser = session?.User; var sessionUser = session?.User;
return sessionUser is not null return sessionUser is not null
&& user is not null
&& installation is not null && installation is not null
&& user is not null
&& user.IsDescendantOf(sessionUser) && user.IsDescendantOf(sessionUser)
&& sessionUser.HasAccessTo(installation) && sessionUser.HasAccessTo(installation)
&& !user.HasAccessTo(installation) && !user.HasAccessTo(installation)
@ -140,8 +147,8 @@ public static class SessionMethods
var sessionUser = session?.User; var sessionUser = session?.User;
return sessionUser is not null return sessionUser is not null
&& user is not null
&& folder is not null && folder is not null
&& user is not null
&& user.IsDescendantOf(sessionUser) && user.IsDescendantOf(sessionUser)
&& sessionUser.HasAccessTo(folder) && sessionUser.HasAccessTo(folder)
&& !user.HasAccessTo(folder) && !user.HasAccessTo(folder)
@ -153,8 +160,8 @@ public static class SessionMethods
var sessionUser = session?.User; var sessionUser = session?.User;
return sessionUser is not null return sessionUser is not null
&& user is not null
&& installation is not null && installation is not null
&& user is not null
&& user.IsDescendantOf(sessionUser) && user.IsDescendantOf(sessionUser)
&& sessionUser.HasAccessTo(installation) && sessionUser.HasAccessTo(installation)
&& user.HasAccessTo(installation) && user.HasAccessTo(installation)
@ -166,8 +173,8 @@ public static class SessionMethods
var sessionUser = session?.User; var sessionUser = session?.User;
return sessionUser is not null return sessionUser is not null
&& user is not null
&& folder is not null && folder is not null
&& user is not null
&& user.IsDescendantOf(sessionUser) && user.IsDescendantOf(sessionUser)
&& sessionUser.HasAccessTo(folder) && sessionUser.HasAccessTo(folder)
&& user.HasAccessTo(folder) && user.HasAccessTo(folder)

View File

@ -0,0 +1,24 @@
namespace InnovEnergy.App.Backend.DataTypes.Methods;
public static class TreeNodeMethods
{
public static T WithParentOf<T>(this T treeNode, T other) where T: TreeNode
{
treeNode.ParentId = other.ParentId;
return treeNode;
}
public static T WithParent<T>(this T treeNode, T other) where T: TreeNode
{
treeNode.ParentId = other.Id;
return treeNode;
}
public static T HideParent<T>(this T treeNode) where T: TreeNode
{
treeNode.ParentId = 0;
return treeNode;
}
}

View File

@ -34,7 +34,7 @@ public static class UserMethods
// to a child folder of a folder he has already access to // to a child folder of a folder he has already access to
// TODO shouldn't we prevent doubling permissions? -K" // TODO shouldn't we prevent doubling permissions? -K"
// TODO yes we should -ig (still TODO) // 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<TreeNode> AccessibleFoldersAndInstallations(this User user) public static IEnumerable<TreeNode> AccessibleFoldersAndInstallations(this User user)
@ -51,9 +51,9 @@ public static class UserMethods
.InstallationAccess .InstallationAccess
.Where(r => r.UserId == user.Id) .Where(r => r.UserId == user.Id)
.Select(r => r.InstallationId) .Select(r => r.InstallationId)
.Select(Db.GetInstallationById) .Select(i => Db.GetInstallationById(i))
.NotNull() .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<Folder> DirectlyAccessibleFolders(this User user) public static IEnumerable<Folder> DirectlyAccessibleFolders(this User user)
@ -62,9 +62,9 @@ public static class UserMethods
.FolderAccess .FolderAccess
.Where(r => r.UserId == user.Id) .Where(r => r.UserId == user.Id)
.Select(r => r.FolderId) .Select(r => r.FolderId)
.Select(Db.GetFolderById) .Select(i => Db.GetFolderById(i))
.NotNull() .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<User> ChildUsers(this User parent) public static IEnumerable<User> ChildUsers(this User parent)
@ -112,19 +112,15 @@ public static class UserMethods
public static User? Parent(this User u) public static User? Parent(this User u)
{ {
return u.IsAbsoluteRoot() return u.IsRoot()
? null ? null
: Db.GetUserById(u.ParentId); : Db.GetUserById(u.ParentId);
} }
public static Boolean IsAbsoluteRoot(this User u) public static Boolean IsRoot(this User user)
{ {
return u.ParentId == 0; 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) public static Boolean HasDirectAccessTo(this User user, Folder folder)
@ -174,12 +170,6 @@ public static class UserMethods
.Contains(user); .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) public static String Salt(this User user)
{ {
// + id => salt unique per user // + id => salt unique per user
@ -188,6 +178,14 @@ public static class UserMethods
return $"{user.Id}InnovEnergy"; return $"{user.Id}InnovEnergy";
} }
public static User WithPasswordOf(this User user, User other)
{
user.Password = other.Password;
return user;
}
// TODO? // TODO?
private static Boolean IsValidEmail(String email) private static Boolean IsValidEmail(String email)

View File

@ -4,6 +4,9 @@ namespace InnovEnergy.App.Backend;
public static class Program public static class Program
{ {
// TODO: Trash
public static void Main(String[] args) public static void Main(String[] args)
{ {
//Db.CreateFakeRelations(); //Db.CreateFakeRelations();

View File

@ -1,6 +1,5 @@
using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes;
using InnovEnergy.Lib.Utils;
using SQLite; using SQLite;
namespace InnovEnergy.App.Backend.Relations; namespace InnovEnergy.App.Backend.Relations;
@ -13,8 +12,8 @@ public class Session : Relation<String, Int64>
[Indexed] public Int64 UserId { get => Right; init => Right = value;} [Indexed] public Int64 UserId { get => Right; init => Right = value;}
[Indexed] public DateTime LastSeen { get; set; } [Indexed] public DateTime LastSeen { get; set; }
[Ignore] public Boolean Valid => DateTime.Now - LastSeen < MaxAge [Ignore] public Boolean Valid => DateTime.Now - LastSeen < MaxAge
&& !User.Email.IsNullOrEmpty(); && (User) is not null;
[Ignore] public User User => _User ??= Db.GetUserById(UserId)!; [Ignore] public User User => _User ??= Db.GetUserById(UserId)!;