using System.Net; using System.Text; using System.Text.Json; using Backend.Database; using Backend.Model; using Backend.Model.Relations; using Backend.Utils; using Microsoft.AspNetCore.Mvc; using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor; namespace Backend.Controllers; [ApiController] [Route("api/")] public class Controller { [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpPost($"{nameof(Login)}")] public Object Login(Credentials credentials) { if (String.IsNullOrWhiteSpace(credentials.Username) || String.IsNullOrWhiteSpace(credentials.Password)) return new HttpResponseMessage(HttpStatusCode.BadRequest); using var db = Db.Connect(); var user = db.GetUserByEmail(credentials.Username); if (user is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // if (!VerifyPassword(password, user)) // return new HttpResponseMessage(HttpStatusCode.Unauthorized); 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)] [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"]; if (currentUser is null) return new HttpResponseMessage(HttpStatusCode.Conflict); return db.DeleteSession(currentUser.Id); } [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpPost($"{nameof(UpdateS3Creds)}")] public Object UpdateS3Creds() { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; using var db = Db.Connect(); var currentUser = (User)ctx!.Items["User"]!; return db.CreateAndSaveUserS3ApiKey(currentUser); } [ProducesResponseType(typeof(User), 200)] [ProducesResponseType(401)] [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)) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return viewedUser; } [ProducesResponseType(typeof(Installation), 200)] [ProducesResponseType(401)] [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) return new HttpResponseMessage(HttpStatusCode.Unauthorized); var installation = db .GetAllAccessibleInstallations(currentUser) .FirstOrDefault(i => i.Id == id); if (installation is null) return new HttpResponseMessage(HttpStatusCode.NotFound); return installation; } [ProducesResponseType(typeof(Folder), 200)] [ProducesResponseType(401)] [HttpGet($"{nameof(GetFolderById)}")] public Object GetFolderById(Int64 id) { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; using var db = Db.Connect(); var currentUser = (User)ctx.Items["User"]; var folder = db .GetAllAccessibleFolders(currentUser!) .FirstOrDefault(f => f.Id == id); if(folder is null) return new HttpResponseMessage(HttpStatusCode.NotFound); return folder; } [ProducesResponseType(200)] [ProducesResponseType(401)] [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) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.GetAllAccessibleInstallations(user).ToList(); } [ProducesResponseType(200)] [ProducesResponseType(401)] [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) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.GetAllAccessibleFolders(user).ToList(); } [ProducesResponseType(200)] [ProducesResponseType(401)] [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)) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.GetUserById(updatedUser.Id) != null ? db.UpdateUser(updatedUser) : db.CreateUser(updatedUser); } [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpPut($"{nameof(UpdateInstallation)}/")] public Object UpdateInstallation(Installation updatedInstallation) { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; var currentUser = (User)ctx.Items["User"]; if (currentUser == null || !currentUser.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); using var db = Db.Connect(); var hasAccess = db.GetAllAccessibleInstallations(currentUser) .Any(i => i.Id == updatedInstallation.Id); if (!hasAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes return db.UpdateInstallation(updatedInstallation); } [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpPut($"{nameof(UpdateFolder)}/")] public Object UpdateFolder(Folder updatedFolder) { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; using var db = Db.Connect(); var currentUser = (User)ctx.Items["User"]; if (currentUser == null || !currentUser.HasWriteAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); var hasAccess = db.GetAllAccessibleFolders(currentUser) .Any(f => f.Id == updatedFolder.Id); if (!hasAccess) return new HttpResponseMessage(HttpStatusCode.Unauthorized); // TODO: accessibility by other users etc // TODO: sanity check changes return db.UpdateFolder(updatedFolder); } [ProducesResponseType(200)] [ProducesResponseType(401)] [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); if (currentUser == null || userToBeDeleted == null || !currentUser.HasWriteAccess || !db.IsParentOfChild(currentUser,userToBeDeleted)) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteUser(userToBeDeleted); } [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpDelete($"{nameof(DeleteInstallation)}/")] public Object DeleteInstallation(Int64 idOfInstallationToBeDeleted) { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; using var db = Db.Connect(); var currentUser = (User)ctx.Items["User"]; var installationToBeDeleted = db .GetAllAccessibleInstallations(currentUser!) .FirstOrDefault(i => i.Id == idOfInstallationToBeDeleted); if (installationToBeDeleted is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteInstallation(installationToBeDeleted); } [ProducesResponseType(200)] [ProducesResponseType(401)] [HttpDelete($"{nameof(DeleteFolder)}/")] public Object DeleteFolder(Int64 folderId) { var ctxAccessor = new HttpContextAccessor(); var ctx = ctxAccessor.HttpContext; using var db = Db.Connect(); var currentUser = (User)ctx.Items["User"]; var folderToDelete = db .GetAllAccessibleFolders(currentUser!) .FirstOrDefault(f => f.Id == folderId); if (folderToDelete is null) return new HttpResponseMessage(HttpStatusCode.Unauthorized); return db.DeleteFolder(folderToDelete); } }