diff --git a/csharp/app/Backend/Backend.csproj b/csharp/app/Backend/Backend.csproj index c082226db..e6a136cb1 100644 --- a/csharp/app/Backend/Backend.csproj +++ b/csharp/app/Backend/Backend.csproj @@ -4,6 +4,8 @@ net6.0 enable enable + preview + Innovenergy.Backend diff --git a/csharp/app/Backend/Controllers/Controller.cs b/csharp/app/Backend/Controllers/Controller.cs index 32b53084e..10110397e 100644 --- a/csharp/app/Backend/Controllers/Controller.cs +++ b/csharp/app/Backend/Controllers/Controller.cs @@ -1,21 +1,21 @@ using System.Net; using System.Text; -using System.Text.Json; -using Backend.Database; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Database; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using Microsoft.AspNetCore.Mvc; using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor; -namespace Backend.Controllers; +namespace Innovenergy.Backend.Controllers; [ApiController] [Route("api/")] public class Controller { - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] + [Returns(HttpStatusCode.BadRequest)] [HttpPost($"{nameof(Login)}")] public Object Login(Credentials credentials) { @@ -29,181 +29,175 @@ public class Controller if (user is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - // if (!VerifyPassword(password, user)) - // return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #if !DEBUG + if (!VerifyPassword(credentials.Password, user)) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + #endif var ses = new Session(user); db.NewSession(ses); return ses.Token; } - private static Boolean VerifyPassword(String password, User user) - { - var pwdBytes = Encoding.UTF8.GetBytes(password); - var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); - var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); - return user.Password == pwdHash; - } - - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPost($"{nameof(Logout)}")] public Object Logout() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; + var caller = GetCaller(); - if (currentUser is null) - return new HttpResponseMessage(HttpStatusCode.Conflict); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.DeleteSession(currentUser.Id); + using var db = Db.Connect(); + return db.DeleteSession(caller.Id); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] - [HttpPost($"{nameof(UpdateS3Creds)}")] - public Object UpdateS3Creds() + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] + [HttpPost($"{nameof(UpdateS3Credentials)}")] + public Object UpdateS3Credentials() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx!.Items["User"]!; + // TODO: S3Credentials should be per session, not per user - return db.CreateAndSaveUserS3ApiKey(currentUser); + var caller = GetCaller(); + if (caller is null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + return db.CreateAndSaveUserS3ApiKey(caller); } - [ProducesResponseType(typeof(User), 200)] - [ProducesResponseType(401)] + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetUserById)}")] public Object GetUserById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var viewedUser = db.GetUserById(id); - - //using the same error to prevent fishing for ids - if (currentUser == null || viewedUser == null || !db.IsParentOfChild(currentUser, viewedUser)) + var caller = GetCaller(); + if (caller is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return viewedUser; + var user = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == id); + + return user as Object ?? new HttpResponseMessage(HttpStatusCode.Unauthorized); } - [ProducesResponseType(typeof(Installation), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetInstallationById)}")] public Object GetInstallationById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); + var installation = db - .GetAllAccessibleInstallations(currentUser) + .GetAllAccessibleInstallations(caller) .FirstOrDefault(i => i.Id == id); - if (installation is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return installation; + return installation as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(typeof(Folder), 200)] - [ProducesResponseType(401)] + + [Returns] + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetFolderById)}")] public Object GetFolderById(Int64 id) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - + var folder = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == id); - if(folder is null) - return new HttpResponseMessage(HttpStatusCode.NotFound); - - return folder; + return folder as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllInstallations)}/")] public Object GetAllInstallations() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var user = (User)ctx.Items["User"]; - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); - return db.GetAllAccessibleInstallations(user).ToList(); + return db + .GetAllAccessibleInstallations(caller) + .ToList(); // important! } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns] // assuming swagger knows about arrays but not lists (JSON) + [Returns(HttpStatusCode.Unauthorized)] [HttpGet($"{nameof(GetAllFolders)}/")] public Object GetAllFolders() { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - var user = (User)ctx.Items["User"]; - - using var db = Db.Connect(); - - if (user == null) + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - - return db.GetAllAccessibleFolders(user).ToList(); + + using var db = Db.Connect(); + return db + .GetAllAccessibleFolders(caller) + .ToList(); // important! } + - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateUser)}/")] public Object UpdateUser(User updatedUser) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess || !db.IsParentOfChild(currentUser, updatedUser)) + // TODO: distinguish between create and update + + var caller = GetCaller(); + if (caller == null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - return db.GetUserById(updatedUser.Id) != null ? db.UpdateUser(updatedUser) : db.CreateUser(updatedUser); + using var db = Db.Connect(); + + return db.GetUserById(updatedUser.Id) != null + ? db.UpdateUser(updatedUser) + : db.CreateUser(updatedUser); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateInstallation)}/")] public Object UpdateInstallation(Installation updatedInstallation) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - + using var db = Db.Connect(); - var hasAccess = db.GetAllAccessibleInstallations(currentUser) - .Any(i => i.Id == updatedInstallation.Id); - if (!hasAccess) + var hasAccessToInstallation = db + .GetAllAccessibleInstallations(caller) + .Any(i => i.Id == updatedInstallation.Id); + + if (!hasAccessToInstallation) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc @@ -213,64 +207,68 @@ public class Controller } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpPut($"{nameof(UpdateFolder)}/")] - public Object UpdateFolder(Folder updatedFolder) + public Object UpdateFolder(Folder folder) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - - if (currentUser == null || !currentUser.HasWriteAccess) + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); - var hasAccess = db.GetAllAccessibleFolders(currentUser) - .Any(f => f.Id == updatedFolder.Id); + using var db = Db.Connect(); + + var hasAccessToFolder = db + .GetAllAccessibleFolders(caller) + .Any(f => f.Id == folder.Id); - if (!hasAccess) + if (!hasAccessToFolder) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes - return db.UpdateFolder(updatedFolder); + return db.UpdateFolder(folder); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteUser)}/")] public Object DeleteUser(Int64 userId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; - using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; - var userToBeDeleted = db.GetUserById(userId); + var caller = GetCaller(); - if (currentUser == null - || userToBeDeleted == null - || !currentUser.HasWriteAccess - || !db.IsParentOfChild(currentUser,userToBeDeleted)) + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + + using var db = Db.Connect(); + + var userToBeDeleted = db + .GetDescendantUsers(caller) + .FirstOrDefault(u => u.Id == userId); + + if (userToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteUser(userToBeDeleted); } - [ProducesResponseType(200)] - [ProducesResponseType(401)] + [Returns(HttpStatusCode.OK)] + [Returns(HttpStatusCode.Unauthorized)] [HttpDelete($"{nameof(DeleteInstallation)}/")] - public Object DeleteInstallation(Int64 idOfInstallationToBeDeleted) + public Object DeleteInstallation(Int64 installationId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + + if (caller is null || !caller.HasWriteAccess) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var installationToBeDeleted = db - .GetAllAccessibleInstallations(currentUser!) - .FirstOrDefault(i => i.Id == idOfInstallationToBeDeleted); + .GetAllAccessibleInstallations(caller) + .FirstOrDefault(i => i.Id == installationId); if (installationToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); @@ -278,18 +276,20 @@ public class Controller return db.DeleteInstallation(installationToBeDeleted); } + [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpDelete($"{nameof(DeleteFolder)}/")] public Object DeleteFolder(Int64 folderId) { - var ctxAccessor = new HttpContextAccessor(); - var ctx = ctxAccessor.HttpContext; + var caller = GetCaller(); + if (caller == null) + return new HttpResponseMessage(HttpStatusCode.Unauthorized); + using var db = Db.Connect(); - var currentUser = (User)ctx.Items["User"]; var folderToDelete = db - .GetAllAccessibleFolders(currentUser!) + .GetAllAccessibleFolders(caller) .FirstOrDefault(f => f.Id == folderId); if (folderToDelete is null) @@ -299,5 +299,22 @@ public class Controller } + private static User? GetCaller() + { + var ctxAccessor = new HttpContextAccessor(); + return ctxAccessor.HttpContext?.Items["User"] as User; + } + + private static Boolean VerifyPassword(String password, User user) + { + var pwdBytes = Encoding.UTF8.GetBytes(password); + var saltBytes = Encoding.UTF8.GetBytes(user.Salt + "innovEnergy"); + var pwdHash = Crypto.ComputeHash(pwdBytes, saltBytes); + + return user.Password == pwdHash; + } + } + + diff --git a/csharp/app/Backend/Controllers/Credentials.cs b/csharp/app/Backend/Controllers/Credentials.cs index 43c86a811..2c5c72b45 100644 --- a/csharp/app/Backend/Controllers/Credentials.cs +++ b/csharp/app/Backend/Controllers/Credentials.cs @@ -1,3 +1,6 @@ -namespace Backend.Controllers; +using System.Diagnostics.CodeAnalysis; +namespace Innovenergy.Backend.Controllers; + +[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public record Credentials(String Username, String Password); \ No newline at end of file diff --git a/csharp/app/Backend/Database/Db.cs b/csharp/app/Backend/Database/Db.cs index 92d31ca84..aaabfbfd9 100644 --- a/csharp/app/Backend/Database/Db.cs +++ b/csharp/app/Backend/Database/Db.cs @@ -1,11 +1,11 @@ using System.Diagnostics.CodeAnalysis; -using Backend.Model; -using Backend.Model.Relations; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Model.Relations; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db : IDisposable { @@ -97,6 +97,8 @@ public partial class Db : IDisposable return direct.Concat(fromFolders); } + + public IEnumerable GetAllAccessibleFolders(User user) { diff --git a/csharp/app/Backend/Database/Fake.cs b/csharp/app/Backend/Database/Fake.cs index 94325df6d..427c78434 100644 --- a/csharp/app/Backend/Database/Fake.cs +++ b/csharp/app/Backend/Database/Fake.cs @@ -1,6 +1,6 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/Folder.cs b/csharp/app/Backend/Database/Folder.cs index f7411e017..34e20f529 100644 --- a/csharp/app/Backend/Database/Folder.cs +++ b/csharp/app/Backend/Database/Folder.cs @@ -1,9 +1,9 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -37,6 +37,15 @@ public partial class Db return Installations.Where(f => f.ParentId == parent.Id); } + public IEnumerable GetChildUsers(User parent) + { + return Users.Where(f => f.ParentId == parent.Id); + } + + public IEnumerable GetDescendantUsers(User parent) + { + return parent.Traverse(GetChildUsers); + } public Result CreateFolder(Folder folder) { diff --git a/csharp/app/Backend/Database/Installation.cs b/csharp/app/Backend/Database/Installation.cs index 5473892af..a362a39df 100644 --- a/csharp/app/Backend/Database/Installation.cs +++ b/csharp/app/Backend/Database/Installation.cs @@ -1,8 +1,8 @@ -using Backend.Model; -using Backend.Utils; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User.cs b/csharp/app/Backend/Database/User.cs index cda467968..e002c48be 100644 --- a/csharp/app/Backend/Database/User.cs +++ b/csharp/app/Backend/Database/User.cs @@ -1,18 +1,16 @@ -using System.Net; using System.Net.Mail; using System.Security.Cryptography; using System.Text; -using System.Text.Json; -using Backend.Model; -using Backend.Utils; using Flurl.Http; +using Innovenergy.Backend.Model; +using Innovenergy.Backend.Utils; using InnovEnergy.Lib.Utils; -using Microsoft.AspNetCore.DataProtection; using SQLite; + #pragma warning disable CS0472 #pragma warning disable CS8602 -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { @@ -22,16 +20,16 @@ public partial class Db public User? GetUserById(Int64 id) { - return Users.FirstOrDefault(u => u.Id == id); + return Users.FirstOrDefault(u => u.Id == id); } - + public Boolean IsParentOfChild(User parent, User child) { var parentPointer = child.ParentId; - + if (parent.Id == child.Id) return true; - + while (parentPointer != null && parentPointer != parent.Id) { parentPointer = GetUserById(parentPointer).ParentId; @@ -46,10 +44,10 @@ public partial class Db { if (GetUserByEmail(user.Email) is not null) return Result.Error("User with that email already exists"); - + //Salting and Hashing password var salt = Crypto.GenerateSalt(); - var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), + var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password), Encoding.UTF8.GetBytes(salt + "innovEnergy")); user.Salt = salt; @@ -57,49 +55,51 @@ public partial class Db return Create(user); } - + public Object CreateAndSaveUserS3ApiKey(User user) { //EXOSCALE API URL - const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; + const String url = "https://api-ch-dk-2.exoscale.com/v2/access-key"; const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0"; const String apiKey = "EXOb98ec9008e3ec16e19d7b593"; var payload = new - { name = user.Email, - operations = new List {"getObject", "listBucket"}, - content = new List{}}; - + { + name = user.Email, + operations = new List { "getObject", "listBucket" }, + content = new List { } + }; + var installationIdList = User2Installation .Where(i => i.UserId == user.Id) .SelectMany(i => Installations.Where(f => i.InstallationId == f.Id)) .ToList(); - + foreach (var installation in installationIdList) { - payload.content.Add(new {domain = "sos", resource_type = "bucket", resource_name = installation.Name}); //TODO CHANGE NAME TO S3BUCKET + payload.content.Add(new { domain = "sos", resource_type = "bucket", resource_name = installation.Name }); //TODO CHANGE NAME TO S3BUCKET } - + using var hmacSha1 = new HMACSHA1(Encoding.UTF8.GetBytes(secret)); var signature = Encoding.UTF8 .GetBytes(payload.ToString()) .Apply(hmacSha1.ComputeHash) .Apply(Convert.ToBase64String); - + var keyJson = url .WithHeader("Authorization", $"POST {apiKey};{signature}") .PostJsonAsync(payload) .ReceiveJson() .Result; - + return SetUserS3ApiKey(user, keyJson.GetValue("key")); } - - public Result SetUserS3ApiKey(User user,String key) + + public Result SetUserS3ApiKey(User user, String key) { user.S3Key = key; return Update(user); } - + public Result UpdateUser(User user) { var oldUser = GetUserById(user.Id); @@ -108,42 +108,39 @@ public partial class Db //Checking for unchangeable things // TODO: depends on privileges of caller - - user.Id = oldUser.Id; + + user.Id = oldUser.Id; user.ParentId = oldUser.ParentId; - user.Email = oldUser.Email; - + user.Email = oldUser.Email; + return Update(user); } public Result DeleteUser(User user) { - User2Folder .Delete(u => u.UserId == user.Id); + User2Folder.Delete(u => u.UserId == user.Id); User2Installation.Delete(u => u.UserId == user.Id); - + //Todo check for orphaned Installations/Folders - + // GetChildUsers() - + return Delete(user); } - + // TODO private static Boolean IsValidEmail(String email) { try - { + { var emailAddress = new MailAddress(email); } catch { return false; } + return true; } - - - -} - +} \ No newline at end of file diff --git a/csharp/app/Backend/Database/User2Folder.cs b/csharp/app/Backend/Database/User2Folder.cs index c55458dde..465eea722 100644 --- a/csharp/app/Backend/Database/User2Folder.cs +++ b/csharp/app/Backend/Database/User2Folder.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/Database/User2Installation.cs b/csharp/app/Backend/Database/User2Installation.cs index 79ab547f5..ca329deee 100644 --- a/csharp/app/Backend/Database/User2Installation.cs +++ b/csharp/app/Backend/Database/User2Installation.cs @@ -1,7 +1,7 @@ -using Backend.Model.Relations; +using Innovenergy.Backend.Model.Relations; using SQLite; -namespace Backend.Database; +namespace Innovenergy.Backend.Database; public partial class Db { diff --git a/csharp/app/Backend/HeaderFilter.cs b/csharp/app/Backend/HeaderFilter.cs new file mode 100644 index 000000000..8ca9cdff8 --- /dev/null +++ b/csharp/app/Backend/HeaderFilter.cs @@ -0,0 +1,24 @@ +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Innovenergy.Backend; + +/// +/// This is for convenient testing! Todo throw me out? +/// Operation filter to add the requirement of the custom header +/// +public class HeaderFilter : IOperationFilter +{ + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + operation.Parameters ??= new List(); + + operation.Parameters.Add(new OpenApiParameter + { + Name = "auth", + In = ParameterLocation.Header, + Content = new Dictionary(), + Required = false + }); + } +} \ No newline at end of file diff --git a/csharp/app/Backend/Model/Folder.cs b/csharp/app/Backend/Model/Folder.cs index fbc016201..c9c39c594 100644 --- a/csharp/app/Backend/Model/Folder.cs +++ b/csharp/app/Backend/Model/Folder.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Folder : TreeNode { diff --git a/csharp/app/Backend/Model/Installation.cs b/csharp/app/Backend/Model/Installation.cs index 9c1f23104..4cca94295 100644 --- a/csharp/app/Backend/Model/Installation.cs +++ b/csharp/app/Backend/Model/Installation.cs @@ -1,6 +1,4 @@ -using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class Installation : TreeNode diff --git a/csharp/app/Backend/Model/Relations/Relation.cs b/csharp/app/Backend/Model/Relations/Relation.cs index 388892872..31250df14 100644 --- a/csharp/app/Backend/Model/Relations/Relation.cs +++ b/csharp/app/Backend/Model/Relations/Relation.cs @@ -1,7 +1,7 @@ using System.Diagnostics.CodeAnalysis; using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public abstract class Relation { diff --git a/csharp/app/Backend/Model/Relations/Session.cs b/csharp/app/Backend/Model/Relations/Session.cs index 4db1a9188..ff64b6644 100644 --- a/csharp/app/Backend/Model/Relations/Session.cs +++ b/csharp/app/Backend/Model/Relations/Session.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; public class Session : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Folder.cs b/csharp/app/Backend/Model/Relations/User2Folder.cs index 09d0456bf..6e9f56433 100644 --- a/csharp/app/Backend/Model/Relations/User2Folder.cs +++ b/csharp/app/Backend/Model/Relations/User2Folder.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Folder : Relation { diff --git a/csharp/app/Backend/Model/Relations/User2Installation.cs b/csharp/app/Backend/Model/Relations/User2Installation.cs index 17dd179ab..43fa45d0e 100644 --- a/csharp/app/Backend/Model/Relations/User2Installation.cs +++ b/csharp/app/Backend/Model/Relations/User2Installation.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model.Relations; +namespace Innovenergy.Backend.Model.Relations; internal class User2Installation : Relation { diff --git a/csharp/app/Backend/Model/TreeNode.cs b/csharp/app/Backend/Model/TreeNode.cs index 61eeb2dba..1daf30f74 100644 --- a/csharp/app/Backend/Model/TreeNode.cs +++ b/csharp/app/Backend/Model/TreeNode.cs @@ -1,7 +1,6 @@ using SQLite; - -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public abstract class TreeNode { diff --git a/csharp/app/Backend/Model/User.cs b/csharp/app/Backend/Model/User.cs index b9848cc6c..a1a0be392 100644 --- a/csharp/app/Backend/Model/User.cs +++ b/csharp/app/Backend/Model/User.cs @@ -1,6 +1,6 @@ using SQLite; -namespace Backend.Model; +namespace Innovenergy.Backend.Model; public class User : TreeNode { diff --git a/csharp/app/Backend/Utils/Crypto.cs b/csharp/app/Backend/Utils/Crypto.cs index 57362c5db..199b17fb9 100644 --- a/csharp/app/Backend/Utils/Crypto.cs +++ b/csharp/app/Backend/Utils/Crypto.cs @@ -1,6 +1,6 @@ using System.Security.Cryptography; -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public static class Crypto { diff --git a/csharp/app/Backend/Utils/Result.cs b/csharp/app/Backend/Utils/Result.cs index 1db4a4cf4..21e85876c 100644 --- a/csharp/app/Backend/Utils/Result.cs +++ b/csharp/app/Backend/Utils/Result.cs @@ -1,4 +1,4 @@ -namespace Backend.Utils; +namespace Innovenergy.Backend.Utils; public class Result { diff --git a/csharp/app/Backend/db.sqlite b/csharp/app/Backend/db.sqlite index da6dc625a..fc3ad2ed8 100644 Binary files a/csharp/app/Backend/db.sqlite and b/csharp/app/Backend/db.sqlite differ diff --git a/csharp/app/Backend/program.cs b/csharp/app/Backend/program.cs index e7017ab8f..26c44b71c 100644 --- a/csharp/app/Backend/program.cs +++ b/csharp/app/Backend/program.cs @@ -1,104 +1,59 @@ -using Backend.Controllers; -using Backend.Database; +using Innovenergy.Backend.Database; using Microsoft.OpenApi.Models; -using Swashbuckle.AspNetCore.SwaggerGen; +namespace Innovenergy.Backend; -using (var db = Db.Connect()) +public class Program { - db.CreateFakeRelations(); -} - - - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddControllers(); // TODO: remove magic, specify controllers explicitly -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle - -builder.Services.AddHttpContextAccessor(); -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); -builder.Services.AddSwaggerGen(config => -{ - config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); - config.OperationFilter(); //Todo testing throw me out -}); - - - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(cfg => cfg.EnableFilter()); -} - -app.UseCors(); -app.UseHttpsRedirection(); -app.UseAuthorization(); -app.Use(SetSessionUser); -app.MapControllers(); - -app.Run(); - - - - - - -//================= Functions for above =================== - -//Setting User for current Session -async Task SetSessionUser(HttpContext ctx, RequestDelegate next) -{ - var headers = ctx.Request.Headers; - var hasToken = headers.TryGetValue("auth", out var token); - - if (!ctx.Request.Path.ToString().Contains(nameof(Controller.Login))) + public static void Main(string[] args) { - if (!hasToken) + using (var db = Db.Connect()) + db.CreateFakeRelations(); + + var builder = WebApplication.CreateBuilder(args); + + builder.Services.AddControllers(); // TODO: remove magic, specify controllers explicitly + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + + builder.Services.AddHttpContextAccessor(); + builder.Services.AddEndpointsApiExplorer(); + builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); + builder.Services.AddSwaggerGen(config => { - ctx.Response.StatusCode = 403; - return; - } - - using var db = Db.Connect(); - var user = db.GetUserByToken(token.ToString()); - - if (user is null) - { - ctx.Response.StatusCode = 403; - return; - } - - ctx.Items["User"] = user; - } - - await next(ctx); -} - - - - -/// -/// This is for convenient testing! Todo throw me out? -/// Operation filter to add the requirement of the custom header -/// -public class MyHeaderFilter : IOperationFilter -{ - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - operation.Parameters ??= new List(); - - operation.Parameters.Add(new OpenApiParameter - { - Name = "auth", - In = ParameterLocation.Header, - Content = new Dictionary(), - Required = false + config.SwaggerDoc("v1", new OpenApiInfo{ Title = "My API", Version = "V1" }); + config.OperationFilter(); //Todo testing throw me out }); + + + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseSwagger(); + app.UseSwaggerUI(cfg => cfg.EnableFilter()); + } + + app.UseCors(); + app.UseHttpsRedirection(); + app.UseAuthorization(); + app.Use(SetSessionUser); + app.MapControllers(); + + app.Run(); + } + + private static async Task SetSessionUser(HttpContext ctx, RequestDelegate next) + { + var headers = ctx.Request.Headers; + var hasToken = headers.TryGetValue("auth", out var token); + + if (hasToken) + { + using var db = Db.Connect(); + ctx.Items["User"] = db.GetUserByToken(token.ToString()); + } + + await next(ctx); } } \ No newline at end of file