added installation specific s3 keys

This commit is contained in:
Kim 2023-03-09 12:50:21 +01:00
parent 7295e6482b
commit d04ebffc76
6 changed files with 108 additions and 43 deletions

View File

@ -58,18 +58,26 @@ public class Controller
[Returns(HttpStatusCode.OK)] [Returns(HttpStatusCode.OK)]
[Returns(HttpStatusCode.Unauthorized)] [Returns(HttpStatusCode.Unauthorized)]
[HttpPost($"{nameof(UpdateS3Credentials)}")] [HttpGet($"{nameof(GetInstallationS3Key)}")]
public Object UpdateS3Credentials() public Object GetInstallationS3Key(Int64 installationId)
{ {
// TODO: S3Credentials should be per session, not per user
var caller = GetCaller(); var caller = GetCaller();
if (caller is null) if (caller is null)
return new HttpResponseMessage(HttpStatusCode.Unauthorized); return new HttpResponseMessage(HttpStatusCode.Unauthorized);
using var db = Db.Connect(); using var db = Db.Connect();
return db.CreateAndSaveUserS3ApiKey(caller); var installation = db
.GetAllAccessibleInstallations(caller)
.FirstOrDefault(i => i.Id == installationId);
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 // TODO: distinguish between create and update
var caller = GetCaller(); var caller = GetCaller();
if (caller == null)
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
using var db = Db.Connect(); using var db = Db.Connect();
if (caller == null || !db.IsParentOfChild(caller.Id, updatedUser))
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
return db.GetUserById(updatedUser.Id) != null return db.GetUserById(updatedUser.Id) != null
? db.UpdateUser(updatedUser) ? db.UpdateUser(updatedUser)
@ -252,15 +259,21 @@ public class Controller
using var db = Db.Connect(); using var db = Db.Connect();
var hasAccessToInstallation = db var installationFromAccessibleInstallations = db
.GetAllAccessibleInstallations(caller) .GetAllAccessibleInstallations(caller)
.Any(i => i.Id == installation.Id); .FirstOrDefault(i => i.Id == installation.Id);
if (!hasAccessToInstallation) if (installationFromAccessibleInstallations == null)
return new HttpResponseMessage(HttpStatusCode.Unauthorized); return new HttpResponseMessage(HttpStatusCode.Unauthorized);
// TODO: accessibility by other users etc // TODO: accessibility by other users etc
// TODO: sanity check changes // 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); return db.UpdateInstallation(installation);
} }
@ -278,17 +291,24 @@ public class Controller
using var db = Db.Connect(); using var db = Db.Connect();
var hasAccessToFolder = db var installationFromAccessibleFolders = db
.GetAllAccessibleFolders(caller) .GetAllAccessibleFolders(caller)
.Any(f => f.Id == folder.Id); .FirstOrDefault(f => f.Id == folder.Id);
if (!hasAccessToFolder) if (installationFromAccessibleFolders == null)
return new HttpResponseMessage(HttpStatusCode.Unauthorized); return new HttpResponseMessage(HttpStatusCode.Unauthorized);
// TODO: accessibility by other users etc // TODO: accessibility by other users etc
// TODO: sanity check changes // 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)] [Returns(HttpStatusCode.OK)]

View File

@ -210,5 +210,11 @@ public partial class Db : IDisposable
return Result.Ok; return Result.Ok;
} }
public Object? GetInstallationS3Key(Int64 installationId)
{
return Installations
.Where(installation => installation.Id == installationId)
.Select(installation => installation.S3Key);
}
} }

View File

@ -31,5 +31,6 @@ public partial class Db
return Delete(installation); return Delete(installation);
} }
} }

View File

@ -28,12 +28,12 @@ public partial class Db
return Users.FirstOrDefault(u => u.Id == id); return Users.FirstOrDefault(u => u.Id == id);
} }
public Boolean IsParentOfChild(User parent, User child) public Boolean IsParentOfChild(Int64 parentId, User child)
{ {
return child return child
.Unfold(u => GetUserById(u.ParentId)) .Unfold(u => GetUserById(u.ParentId))
.Select(u => u.Id) .Select(u => u.Id)
.Contains(parent.Id); .Contains(parentId);
} }
public User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email); public User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email);
@ -66,7 +66,7 @@ public partial class Db
return bytes; 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 = ""; var messageToSign = "";
messageToSign += method + " /v2/" + path + "\n"; messageToSign += method + " /v2/" + path + "\n";
@ -85,7 +85,59 @@ public partial class Db
var hmac = HmacSha256Digest(messageToSign, secret); var hmac = HmacSha256Digest(messageToSign, secret);
return Convert.ToBase64String(hmac); 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 //EXOSCALE API URL
const String url = "https://api-ch-dk-2.exoscale.com/v2/"; 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 secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0";
const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; 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(); var instList = new JsonArray();
foreach (var installation in installationList)
{
instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"}); 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 jsonPayload = new JsonObject { ["name"] = installation.Id, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList};
var stringPayload = jsonPayload.ToJsonString(); var stringPayload = jsonPayload.ToJsonString();
var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60; var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60;
@ -132,14 +174,10 @@ public partial class Db
var responseString = response.Content.ReadAsStringAsync().Result; var responseString = response.Content.ReadAsStringAsync().Result;
var newKey = Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"')); var newKey = Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"'));
return SetUserS3ApiKey(user, newKey);
} installation.S3Key = newKey;
UpdateInstallation(installation);
public Result SetUserS3ApiKey(User user, String key) return newKey;
{
user.S3Key = key;
return Update(user);
} }
public Result UpdateUser(User user) public Result UpdateUser(User user)

View File

@ -14,6 +14,7 @@ public class Installation : TreeNode
public Double Long { get; set; } public Double Long { get; set; }
public String S3Bucket { get; set; } = ""; public String S3Bucket { get; set; } = "";
public String S3Key { get; set; }
} }

View File

@ -7,7 +7,6 @@ public class User : TreeNode
[Indexed] [Indexed]
public String Email { get; set; } = ""; public String Email { get; set; } = "";
public Boolean HasWriteAccess { get; set; } public Boolean HasWriteAccess { get; set; }
public String S3Key { get; set; }
public String Salt { get; set; } public String Salt { get; set; }
public String Password { get; set; } public String Password { get; set; }