diff --git a/csharp/App/Backend/Controllers/Controller.cs b/csharp/App/Backend/Controllers/Controller.cs index e3c285dcb..46d6d67ad 100644 --- a/csharp/App/Backend/Controllers/Controller.cs +++ b/csharp/App/Backend/Controllers/Controller.cs @@ -81,7 +81,57 @@ public class Controller return installation; } + + [Returns] + [Returns(Unauthorized)] + [HttpGet($"{nameof(GetUsersWithAccessToInstallation)}")] + public Object GetUsersWithAccessToInstallation(Int64 id) + { + var user = GetSession()?.User; + if (user == null) + return _Unauthorized; + + var installation = Db.GetInstallationById(id); + + if (installation is null || !user.HasAccessTo(installation)) + return _Unauthorized; + var usersWithInheritedAccess = installation + .Ancestors() + .SelectMany(f => f.UsersWithDirectAccess() + .Where(u => u.IsDescendantOf(user)) + .Select(u => new { folderId = f.Id, user = u })) + .OfType(); + + var usersWithDirectAccess = installation.UsersWithDirectAccess() + .Where(u => u.IsDescendantOf(user)) + .Select(u => new { installationId = installation.Id, user = u }) + .OfType(); + + return usersWithInheritedAccess.Concat(usersWithDirectAccess); + } + + [Returns] + [Returns(Unauthorized)] + [HttpGet($"{nameof(GetUsersWithAccessToFolder)}")] + public Object GetUsersWithAccessToFolder(Int64 id) + { + var user = GetSession()?.User; + if (user == null) + return _Unauthorized; + + var folder = Db.GetFolderById(id); + + if (folder is null || !user.HasAccessTo(folder)) + return _Unauthorized; + + return folder + .Ancestors() + .Append(folder) + .SelectMany(f => f.UsersWithDirectAccess() + .Where(u => u.IsDescendantOf(user)) + .Select(u => new { folderId = f.Id, user = u })); + } [Returns] [Returns(Unauthorized)] diff --git a/csharp/App/Backend/DataTypes/Installation.cs b/csharp/App/Backend/DataTypes/Installation.cs index ebc9244c7..f149135a3 100644 --- a/csharp/App/Backend/DataTypes/Installation.cs +++ b/csharp/App/Backend/DataTypes/Installation.cs @@ -15,5 +15,5 @@ public class Installation : TreeNode public String S3Bucket { get; set; } = ""; public String S3Url { get; set; } = ""; - + } \ No newline at end of file diff --git a/csharp/App/Backend/DataTypes/Methods/Folder.cs b/csharp/App/Backend/DataTypes/Methods/Folder.cs index 321aca9eb..664ae48bf 100644 --- a/csharp/App/Backend/DataTypes/Methods/Folder.cs +++ b/csharp/App/Backend/DataTypes/Methods/Folder.cs @@ -1,3 +1,4 @@ +using System.Collections; using InnovEnergy.App.Backend.Database; using InnovEnergy.Lib.Utils; @@ -5,6 +6,25 @@ namespace InnovEnergy.App.Backend.DataTypes.Methods; public static class FolderMethods { + + public static IEnumerable UsersWithAccess(this Folder folder) + { + return UsersWithDirectAccess(folder).Concat(UsersWithInheritedAccess(folder)); + } + + public static IEnumerable UsersWithDirectAccess(this Folder folder) + { + return Db.FolderAccess + .Where(access => access.FolderId == folder.Id) + .Select(access => Db.GetUserById(access.UserId)) + .NotNull(); + } + + public static IEnumerable UsersWithInheritedAccess(this Folder folder) + { + return folder.Ancestors().SelectMany(f => f.UsersWithDirectAccess()).NotNull(); + } + public static IEnumerable ChildFolders(this Folder parent) { return Db diff --git a/csharp/App/Backend/DataTypes/Methods/Installation.cs b/csharp/App/Backend/DataTypes/Methods/Installation.cs index 3ac08bdb2..e27b3be67 100644 --- a/csharp/App/Backend/DataTypes/Methods/Installation.cs +++ b/csharp/App/Backend/DataTypes/Methods/Installation.cs @@ -1,6 +1,7 @@ using CliWrap; using CliWrap.Buffered; using InnovEnergy.App.Backend.Database; +using InnovEnergy.Lib.Utils; namespace InnovEnergy.App.Backend.DataTypes.Methods; @@ -11,10 +12,10 @@ public static class InstallationMethods { await RenewS3BucketUrl(installation, TimeSpan.FromDays(1)); } - + public static async Task RenewS3BucketUrl(this Installation installation, TimeSpan validity) { - //secret 55MAqyO_FqUmh7O64VIO0egq50ERn_WIAWuc2QC44QU + const String secret = "55MAqyO_FqUmh7O64VIO0egq50ERn_WIAWuc2QC44QU"; const String apiKey = "EXO44d2979c8e570eae81ead564"; const String salt = "3e5b3069-214a-43ee-8d85-57d72000c19d"; var cmd = Cli @@ -22,16 +23,70 @@ public static class InstallationMethods .WithArguments(new[] { "Resources/s3cmd.py", "signurl", $"s3://{installation.Id}-{salt}", validity.TotalSeconds.ToString(), "--access_key", - apiKey + apiKey, "--secret_key", secret }); var x = await cmd.ExecuteBufferedAsync(); installation.S3Url = x.StandardOutput.Replace("\n", "").Replace(" ", ""); - Console.WriteLine(installation.S3Url); - - Db.Update(installation); + Db.Update(installation); } + + public static async Task CreateBucket(this Installation installation) + { + //NOTE this key has all the rights, please be sure you know what you're doing + + const String secret = "z8brNDUAbpktvyWZN1jMIrsQhavDgK2t4cb8GLvsxYg"; + + const String apiKey = "EXO277645911ee6bde3875e99ae"; + const String salt = "3e5b3069-214a-43ee-8d85-57d72000c19d"; + var cmd = Cli + .Wrap("python3") + .WithArguments(new[] + { + "Resources/s3cmd.py", "mb", $"s3://{installation.Id}-{salt}", "--access_key", + apiKey, "--secret_key", secret + }); + var x = await cmd.ExecuteBufferedAsync(); + return x.ExitCode == 0; + } + + public static async Task DeleteBucket(this Installation installation) + { + //NOTE this key has all the rights, please be sure you know what you're doing + const String secret = "z8brNDUAbpktvyWZN1jMIrsQhavDgK2t4cb8GLvsxYg"; + const String apiKey = "EXO277645911ee6bde3875e99ae"; + const String salt = "3e5b3069-214a-43ee-8d85-57d72000c19d"; + var cmd = Cli + .Wrap("python3") + .WithArguments(new[] + { + "Resources/s3cmd.py", "rb", $"s3://{installation.Id}-{salt}", "--access_key", + apiKey + }); + var x = await cmd.ExecuteBufferedAsync(); + return x.ExitCode == 0; + } + + + public static IEnumerable UsersWithAccess(this Installation installation) + { + return UsersWithDirectAccess(installation).Concat(UsersWithInheritedAccess(installation)); + } + + public static IEnumerable UsersWithDirectAccess(this Installation installation) + { + return Db.InstallationAccess + .Where(access => access.InstallationId == installation.Id) + .Select(access => Db.GetUserById(access.UserId)) + .NotNull(); + } + + public static IEnumerable UsersWithInheritedAccess(this Installation installation) + { + return installation.Ancestors().SelectMany(f => f.UsersWithDirectAccess()).NotNull(); + } + public static IEnumerable Ancestors(this Installation installation) { var parentFolder = Parent(installation); diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs index 844b1cca2..6cc3616c6 100644 --- a/csharp/App/Backend/DataTypes/Methods/Session.cs +++ b/csharp/App/Backend/DataTypes/Methods/Session.cs @@ -1,3 +1,4 @@ +using System.Security.Cryptography; using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.Relations; @@ -48,7 +49,8 @@ public static class SessionMethods && installation is not null && user.HasWriteAccess && user.HasAccessTo(installation.Parent()) - && Db.Create(installation); + && Db.Create(installation) + && InstallationMethods.CreateBucket(installation).Result; } public static Boolean Update(this Session? session, Installation? installation) @@ -90,13 +92,20 @@ public static class SessionMethods public static Boolean Update(this Session? session, User? editedUser) { var sessionUser = session?.User; + if (editedUser == null || sessionUser == null) return false; - return sessionUser is not null - && editedUser is not null - && sessionUser.HasWriteAccess - && sessionUser.HasAccessTo(editedUser) - //&& (editedUser.IsRelativeRoot() || sessionUser.HasAccessTo(editedUser.Parent())) // TODO: triple check this - && Db.Update(editedUser); + + //Password change is only allowed for oneself + if ( editedUser.Id != sessionUser.Id) editedUser.Password = sessionUser.Password; + else + { + editedUser.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); } public static Boolean Delete(this Session? session, User? userToDelete) diff --git a/csharp/App/Backend/DataTypes/Methods/User.cs b/csharp/App/Backend/DataTypes/Methods/User.cs index b7498ccfe..b31c0485e 100644 --- a/csharp/App/Backend/DataTypes/Methods/User.cs +++ b/csharp/App/Backend/DataTypes/Methods/User.cs @@ -78,7 +78,7 @@ public static class UserMethods public static Boolean IsDescendantOf(this User user, User ancestor) { - if (user.Id == ancestor.Id) return true; + // if (user.Id == ancestor.Id) return true; return user .Ancestors() .Any(u => u.Id == ancestor.Id); diff --git a/csharp/App/Backend/Database/Update.cs b/csharp/App/Backend/Database/Update.cs index 98c5a64fe..72aef3015 100644 --- a/csharp/App/Backend/Database/Update.cs +++ b/csharp/App/Backend/Database/Update.cs @@ -40,16 +40,12 @@ public static partial class Db public static Boolean Update(User user) { var originalUser = GetUserById(user.Id); - - //Todo change password backend - user.Password = originalUser.Password; - + return originalUser is not null - && user.Id == originalUser.Id // these columns must not be modified! - && user.ParentId == originalUser.ParentId - && user.Email == originalUser.Email - && user.Password == originalUser.Password - && Connection.InsertOrReplace(user) > 0; + && user.Id == originalUser.Id // these columns must not be modified! + && user.ParentId == originalUser.ParentId + && user.Email == originalUser.Email + && Connection.InsertOrReplace(user) > 0; } public static Boolean Update(this Session session) diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite index ef955850d..ea45e7dbd 100644 Binary files a/csharp/App/Backend/db.sqlite and b/csharp/App/Backend/db.sqlite differ