From d04ebffc76a229ede43c4e3549a4abd907a7b43a Mon Sep 17 00:00:00 2001 From: Kim Date: Thu, 9 Mar 2023 12:50:21 +0100 Subject: [PATCH] added installation specific s3 keys --- csharp/App/Backend/Controllers/Controller.cs | 52 ++++++++---- csharp/App/Backend/Database/Db.cs | 8 +- csharp/App/Backend/Database/Installation.cs | 1 + csharp/App/Backend/Database/User.cs | 88 ++++++++++++++------ csharp/App/Backend/Model/Installation.cs | 1 + csharp/App/Backend/Model/User.cs | 1 - 6 files changed, 108 insertions(+), 43 deletions(-) diff --git a/csharp/App/Backend/Controllers/Controller.cs b/csharp/App/Backend/Controllers/Controller.cs index 9136ac151..484039384 100644 --- a/csharp/App/Backend/Controllers/Controller.cs +++ b/csharp/App/Backend/Controllers/Controller.cs @@ -58,18 +58,26 @@ public class Controller [Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.Unauthorized)] - [HttpPost($"{nameof(UpdateS3Credentials)}")] - public Object UpdateS3Credentials() + [HttpGet($"{nameof(GetInstallationS3Key)}")] + public Object GetInstallationS3Key(Int64 installationId) { - // TODO: S3Credentials should be per session, not per user - var caller = GetCaller(); if (caller is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); using var db = Db.Connect(); + + var installation = db + .GetAllAccessibleInstallations(caller) + .FirstOrDefault(i => i.Id == installationId); - return db.CreateAndSaveUserS3ApiKey(caller); + if(installation == null) + { + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + } + + var key = db.GetInstallationS3Key(installationId); + return key ?? db.CreateAndSaveInstallationS3ApiKey(installation); } @@ -229,10 +237,9 @@ public class Controller // TODO: distinguish between create and update var caller = GetCaller(); - if (caller == null) - return new HttpResponseMessage(HttpStatusCode.Unauthorized); - using var db = Db.Connect(); + if (caller == null || !db.IsParentOfChild(caller.Id, updatedUser)) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.GetUserById(updatedUser.Id) != null ? db.UpdateUser(updatedUser) @@ -252,15 +259,21 @@ public class Controller using var db = Db.Connect(); - var hasAccessToInstallation = db + var installationFromAccessibleInstallations = db .GetAllAccessibleInstallations(caller) - .Any(i => i.Id == installation.Id); + .FirstOrDefault(i => i.Id == installation.Id); - if (!hasAccessToInstallation) + if (installationFromAccessibleInstallations == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes + // foreach(var property in installationFromAccessibleInstallations.GetType().GetProperties()){ + // if(installation.GetType().GetProperties().Contains(property)) + // { + // property.SetValue(installationFromAccessibleInstallations, property.GetValue(installation)); + // } + // } return db.UpdateInstallation(installation); } @@ -278,17 +291,24 @@ public class Controller using var db = Db.Connect(); - var hasAccessToFolder = db + var installationFromAccessibleFolders = db .GetAllAccessibleFolders(caller) - .Any(f => f.Id == folder.Id); + .FirstOrDefault(f => f.Id == folder.Id); - if (!hasAccessToFolder) + if (installationFromAccessibleFolders == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes - - return db.UpdateFolder(folder); + + // foreach(var property in installationFromAccessibleFolders.GetType().GetProperties()){ + // if(folder.GetType().GetProperties().Contains(property)) + // { + // property.SetValue(installationFromAccessibleFolders, property.GetValue(folder)); + // } + // } + + return db.UpdateFolder(installationFromAccessibleFolders); } [Returns(HttpStatusCode.OK)] diff --git a/csharp/App/Backend/Database/Db.cs b/csharp/App/Backend/Database/Db.cs index 5c87cc9c8..95afb8bc2 100644 --- a/csharp/App/Backend/Database/Db.cs +++ b/csharp/App/Backend/Database/Db.cs @@ -209,6 +209,12 @@ public partial class Db : IDisposable return Result.Ok; } - + + public Object? GetInstallationS3Key(Int64 installationId) + { + return Installations + .Where(installation => installation.Id == installationId) + .Select(installation => installation.S3Key); + } } diff --git a/csharp/App/Backend/Database/Installation.cs b/csharp/App/Backend/Database/Installation.cs index 6e554f483..e02ad9277 100644 --- a/csharp/App/Backend/Database/Installation.cs +++ b/csharp/App/Backend/Database/Installation.cs @@ -31,5 +31,6 @@ public partial class Db return Delete(installation); } + } diff --git a/csharp/App/Backend/Database/User.cs b/csharp/App/Backend/Database/User.cs index 7f9e33fbc..0e11edde9 100644 --- a/csharp/App/Backend/Database/User.cs +++ b/csharp/App/Backend/Database/User.cs @@ -28,12 +28,12 @@ public partial class Db return Users.FirstOrDefault(u => u.Id == id); } - public Boolean IsParentOfChild(User parent, User child) + public Boolean IsParentOfChild(Int64 parentId, User child) { return child .Unfold(u => GetUserById(u.ParentId)) .Select(u => u.Id) - .Contains(parent.Id); + .Contains(parentId); } public User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email); @@ -66,7 +66,7 @@ public partial class Db return bytes; } - public String BuildSignature(String method, String path, String data, Int64 time, String secret) + private static String BuildSignature(String method, String path, String data, Int64 time, String secret) { var messageToSign = ""; messageToSign += method + " /v2/" + path + "\n"; @@ -85,7 +85,59 @@ public partial class Db var hmac = HmacSha256Digest(messageToSign, secret); return Convert.ToBase64String(hmac); } - public Object CreateAndSaveUserS3ApiKey(User user) + + // public Object CreateAndSaveUserS3ApiKey(User user) + // { + // //EXOSCALE API URL + // const String url = "https://api-ch-dk-2.exoscale.com/v2/"; + // const String path = "access-key"; + // + // //TODO HIDE ME + // const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; + // const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; + // + // var installationList = User2Installation + // .Where(i => i.UserId == user.Id) + // .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) + // .ToList(); + // + // + // var instList = new JsonArray(); + // + // foreach (var installation in installationList) + // { + // instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); + // } + // + // var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList}; + // var stringPayload = jsonPayload.ToJsonString(); + // + // var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60; + // var signature = BuildSignature("POST", path, stringPayload, unixExpiration , secret); + // + // var authHeader = "credential="+apiKey+",expires="+unixExpiration+",signature="+signature; + // + // var client = new HttpClient(); + // client.DefaultRequestHeaders.Authorization = + // new AuthenticationHeaderValue("EXO2-HMAC-SHA256", authHeader); + // + // var content = new StringContent(stringPayload, Encoding.UTF8, "application/json"); + // + // + // var response = client.PostAsync(url+path, content).Result; + // + // if (response.StatusCode.ToString() != "OK") + // { + // return response; + // } + // + // var responseString = response.Content.ReadAsStringAsync().Result; + // return Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"')); + // // return SetUserS3ApiKey(user, newKey); + // + // } + + public Object CreateAndSaveInstallationS3ApiKey(Installation installation) { //EXOSCALE API URL const String url = "https://api-ch-dk-2.exoscale.com/v2/"; @@ -95,20 +147,10 @@ public partial class Db const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; - var installationList = User2Installation - .Where(i => i.UserId == user.Id) - .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) - .ToList(); - - var instList = new JsonArray(); - - foreach (var installation in installationList) - { - instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); - } - - var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList}; + instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); + + var jsonPayload = new JsonObject { ["name"] = installation.Id, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList}; var stringPayload = jsonPayload.ToJsonString(); var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60; @@ -132,16 +174,12 @@ public partial class Db var responseString = response.Content.ReadAsStringAsync().Result; var newKey = Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"')); - return SetUserS3ApiKey(user, newKey); - - } - public Result SetUserS3ApiKey(User user, String key) - { - user.S3Key = key; - return Update(user); + installation.S3Key = newKey; + UpdateInstallation(installation); + return newKey; } - + public Result UpdateUser(User user) { var oldUser = GetUserById(user.Id); diff --git a/csharp/App/Backend/Model/Installation.cs b/csharp/App/Backend/Model/Installation.cs index b9858e9c8..b04885b40 100644 --- a/csharp/App/Backend/Model/Installation.cs +++ b/csharp/App/Backend/Model/Installation.cs @@ -14,6 +14,7 @@ public class Installation : TreeNode public Double Long { get; set; } public String S3Bucket { get; set; } = ""; + public String S3Key { get; set; } } diff --git a/csharp/App/Backend/Model/User.cs b/csharp/App/Backend/Model/User.cs index 762c819a4..2a4346dd4 100644 --- a/csharp/App/Backend/Model/User.cs +++ b/csharp/App/Backend/Model/User.cs @@ -7,7 +7,6 @@ public class User : TreeNode [Indexed] public String Email { get; set; } = ""; public Boolean HasWriteAccess { get; set; } - public String S3Key { get; set; } public String Salt { get; set; } public String Password { get; set; }