using System.Net; using System.Net.WebSockets; using System.Text; using System.Text.Json; using InnovEnergy.App.Backend.Database; using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.Relations; using InnovEnergy.App.Backend.Websockets; using InnovEnergy.Lib.Utils; using Microsoft.AspNetCore.Mvc; namespace InnovEnergy.App.Backend; using Token = String; [Controller] [Route("api/")] public class Controller : ControllerBase { [HttpPost(nameof(Login))] public ActionResult Login(String username, String? password) { var user = Db.GetUserByEmail(username); if (user is null) throw new Exceptions(400, "Null User Exception", "Must provide a user to log in as.", Request.Path.Value!); if (!(user.Password.IsNullOrEmpty() && user.MustResetPassword) && !user.VerifyPassword(password)) { //return Unauthorized("No Password set"); throw new Exceptions(401, "Wrong Password Exception", "Please try again.", Request.Path.Value!); } var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user)); //TODO The Frontend should check for the MustResetPassword Flag return Db.Create(session) ? session : throw new Exceptions(401,"Session Creation Exception", "Not allowed to log in.", Request.Path.Value!); } [HttpPost(nameof(Logout))] public ActionResult Logout(Token authToken) { var session = Db.GetSession(authToken); return session.Logout() ? Ok() : Unauthorized(); } [HttpGet(nameof(CreateWebSocket))] public async Task CreateWebSocket(Token authToken) { var session = Db.GetSession(authToken)?.User; if (session is null) { HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; HttpContext.Abort(); return; } if (!HttpContext.WebSockets.IsWebSocketRequest) { HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; HttpContext.Abort(); return; } var webSocketContext = await HttpContext.WebSockets.AcceptWebSocketAsync(); var webSocket = webSocketContext; //Handle the WebSocket connection await WebsocketManager.HandleWebSocketConnection(webSocket); } [HttpGet(nameof(GetUserById))] public ActionResult GetUserById(Int64 id, Token authToken) { var session = Db.GetSession(authToken)?.User; if (session == null) return Unauthorized(); var user = Db.GetUserById(id); if (user is null || !session.HasAccessTo(user)) return Unauthorized(); return user .HidePassword() .HideParentIfUserHasNoAccessToParent(session); } [HttpGet(nameof(GetInstallationById))] public ActionResult GetInstallationById(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var installation = Db.GetInstallationById(id); if (installation is null || !user.HasAccessTo(installation)) return Unauthorized(); return installation .FillOrderNumbers() .HideParentIfUserHasNoAccessToParent(user) .HideWriteKeyIfUserIsNotAdmin(user.HasWriteAccess); } [HttpGet(nameof(GetUsersWithDirectAccessToInstallation))] public ActionResult> GetUsersWithDirectAccessToInstallation(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var installation = Db.GetInstallationById(id); if (installation is null || !user.HasAccessTo(installation)) return Unauthorized(); return installation .UsersWithDirectAccess() .Where(u => u.IsDescendantOf(user)) .Select(u => u.HidePassword()) .ToList(); } [HttpGet(nameof(GetUsersWithInheritedAccessToInstallation))] public ActionResult> GetUsersWithInheritedAccessToInstallation(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var installation = Db.GetInstallationById(id); if (installation is null || !user.HasAccessTo(installation)) return Unauthorized(); return installation .Ancestors() .SelectMany(f => f.UsersWithDirectAccess() .Where(u => u.IsDescendantOf(user)) .Select(u => new { folderId = f.Id, folderName = f.Name, user = u.HidePassword() })) .ToList(); } [HttpGet(nameof(GetUsersWithDirectAccessToFolder))] public ActionResult> GetUsersWithDirectAccessToFolder(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var folder = Db.GetFolderById(id); if (folder is null || !user.HasAccessTo(folder)) return Unauthorized(); return folder .UsersWithDirectAccess() .Where(u => u.IsDescendantOf(user)) .Select(u => u.HidePassword()) .ToList(); } [HttpGet(nameof(GetUsersWithInheritedAccessToFolder))] public ActionResult> GetUsersWithInheritedAccessToFolder(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var folder = Db.GetFolderById(id); if (folder is null || !user.HasAccessTo(folder)) return Unauthorized(); return folder .Ancestors() .SelectMany(f => f.UsersWithDirectAccess() .Where(u => u.IsDescendantOf(user)) .Select(u => new { folderId = f.Id, folderName = f.Name, user = u.HidePassword() })) .ToList(); } [HttpGet(nameof(GetFolderById))] public ActionResult GetFolderById(Int64 id, Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); var folder = Db.GetFolderById(id); if (folder is null || !user.HasAccessTo(folder)) return Unauthorized(); return folder.HideParentIfUserHasNoAccessToParent(user); } [HttpGet(nameof(GetAllDirectChildUsers))] public ActionResult> GetAllDirectChildUsers(Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); return user.ChildUsers().Select(u => u.HidePassword()).ToList(); } [HttpGet(nameof(GetAllChildUsers))] public ActionResult> GetAllChildUsers(Token authToken) { var user = Db.GetSession(authToken)?.User; if (user == null) return Unauthorized(); return user .DescendantUsers() .Select(u => u.HidePassword()) .ToList(); } [HttpGet(nameof(GetAllInstallations))] public ActionResult> GetAllInstallations(Token authToken) { var user = Db.GetSession(authToken)?.User; if (user is null) return Unauthorized(); return user .AccessibleInstallations() .Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user).HideWriteKeyIfUserIsNotAdmin(user.HasWriteAccess)) .ToList(); } [HttpGet(nameof(GetAllFolders))] public ActionResult> GetAllFolders(Token authToken) { var user = Db.GetSession(authToken)?.User; if (user is null) return Unauthorized(); return new(user.AccessibleFolders().HideParentIfUserHasNoAccessToParent(user)); } [HttpGet(nameof(GetAllFoldersAndInstallations))] public ActionResult> GetAllFoldersAndInstallations(Token authToken) { var user = Db.GetSession(authToken)?.User; if (user is null) return Unauthorized(); var foldersAndInstallations = user .AccessibleFoldersAndInstallations() .Do(o => o.FillOrderNumbers()) .Select(o => o.HideParentIfUserHasNoAccessToParent(user)) .OfType(); // Important! JSON serializer must see Objects otherwise // it will just serialize the members of TreeNode %&@#!!! // TODO Filter out write keys return new (foldersAndInstallations); } [HttpPost(nameof(CreateUser))] public async Task> CreateUser([FromBody] User newUser, Token authToken) { var create = Db.GetSession(authToken).Create(newUser); return create && await Db.SendNewUserEmail(newUser) ? newUser.HidePassword() : Unauthorized() ; } [HttpPost(nameof(CreateInstallation))] public async Task> CreateInstallation([FromBody] Installation installation, Token authToken) { var session = Db.GetSession(authToken); if (! await session.Create(installation)) return Unauthorized(); return installation; } [HttpPost(nameof(CreateFolder))] public ActionResult CreateFolder([FromBody] Folder folder, Token authToken) { var session = Db.GetSession(authToken); if (!session.Create(folder)) return Unauthorized(); return folder.HideParentIfUserHasNoAccessToParent(session!.User); } [HttpPost(nameof(GrantUserAccessToFolder))] public ActionResult GrantUserAccessToFolder(FolderAccess folderAccess, Token authToken) { var session = Db.GetSession(authToken); // TODO: automatic BadRequest when properties are null during deserialization var folder = Db.GetFolderById(folderAccess.FolderId); var user = Db.GetUserById(folderAccess.UserId); return session.GrantUserAccessTo(user, folder) ? Ok() : Unauthorized(); } [HttpPost(nameof(RevokeUserAccessToFolder))] public ActionResult RevokeUserAccessToFolder(FolderAccess folderAccess, Token authToken) { var session = Db.GetSession(authToken); // TODO: automatic BadRequest when properties are null during deserialization var folder = Db.GetFolderById(folderAccess.FolderId); var user = Db.GetUserById(folderAccess.UserId); return session.RevokeUserAccessTo(user, folder) ? Ok() : Unauthorized(); } [HttpPost(nameof(GrantUserAccessToInstallation))] public ActionResult GrantUserAccessToInstallation(InstallationAccess installationAccess, Token authToken) { var session = Db.GetSession(authToken); // TODO: automatic BadRequest when properties are null during deserialization var installation = Db.GetInstallationById(installationAccess.InstallationId); var user = Db.GetUserById(installationAccess.UserId); return session.GrantUserAccessTo(user, installation) ? Ok() : Unauthorized(); } [HttpPost(nameof(RevokeUserAccessToInstallation))] public ActionResult RevokeUserAccessToInstallation(InstallationAccess installationAccess, Token authToken) { var session = Db.GetSession(authToken); // TODO: automatic BadRequest when properties are null during deserialization var installation = Db.GetInstallationById(installationAccess.InstallationId); var user = Db.GetUserById(installationAccess.UserId); return session.RevokeUserAccessTo(user, installation) ? Ok() : Unauthorized(); } [HttpPut(nameof(UpdateUser))] public ActionResult UpdateUser([FromBody] User updatedUser, Token authToken) { var session = Db.GetSession(authToken); if (!session.Update(updatedUser)) return Unauthorized(); return updatedUser.HidePassword(); } [HttpPut(nameof(UpdatePassword))] public ActionResult UpdatePassword(String newPassword, Token authToken) { var session = Db.GetSession(authToken); return session.UpdatePassword(newPassword) ? Ok() : Unauthorized(); } [HttpPut(nameof(UpdateInstallation))] public ActionResult UpdateInstallation([FromBody] Installation installation, Token authToken) { var session = Db.GetSession(authToken); if (!session.Update(installation)) return Unauthorized(); return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(session!.User).HideWriteKeyIfUserIsNotAdmin(session.User.HasWriteAccess); } [HttpPut(nameof(UpdateFolder))] public ActionResult UpdateFolder([FromBody] Folder folder, Token authToken) { var session = Db.GetSession(authToken); if (!session.Update(folder)) return Unauthorized(); return folder.HideParentIfUserHasNoAccessToParent(session!.User); } [HttpPut(nameof(MoveInstallation))] public ActionResult MoveInstallation(Int64 installationId,Int64 parentId, Token authToken) { var session = Db.GetSession(authToken); return session.MoveInstallation(installationId, parentId) ? Ok() : Unauthorized(); } [HttpPost(nameof(EditInstallationConfig))] public async Task>> EditInstallationConfig([FromBody] String config, Int64 installationId, Token authToken) { var session = Db.GetSession(authToken); //var installationToUpdate = Db.GetInstallationById(installationId); return await session.SendInstallationConfig(installationId, config) ? Ok() : Unauthorized(); } [HttpPut(nameof(MoveFolder))] public ActionResult MoveFolder(Int64 folderId,Int64 parentId, Token authToken) { var session = Db.GetSession(authToken); return session.MoveFolder(folderId, parentId) ? Ok() : Unauthorized(); } [HttpDelete(nameof(DeleteUser))] public ActionResult DeleteUser(Int64 userId, Token authToken) { var session = Db.GetSession(authToken); var user = Db.GetUserById(userId); return session.Delete(user) ? Ok() : Unauthorized(); } [HttpDelete(nameof(DeleteInstallation))] public async Task DeleteInstallation(Int64 installationId, Token authToken) { var session = Db.GetSession(authToken); var installation = Db.GetInstallationById(installationId); return await session.Delete(installation) ? Ok() : Unauthorized(); } [HttpDelete(nameof(DeleteFolder))] public ActionResult DeleteFolder(Int64 folderId, Token authToken) { var session = Db.GetSession(authToken); var folder = Db.GetFolderById(folderId); return session.Delete(folder) ? Ok() : Unauthorized(); } [HttpPost(nameof(ResetPasswordRequest))] public async Task>> ResetPasswordRequest(String username) { var user = Db.GetUserByEmail(username); if (user is null) return Unauthorized(); var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user)); var success = Db.Create(session); return success && await Db.SendPasswordResetEmail(user, session.Token) ? Ok() : Unauthorized(); } [HttpGet(nameof(ResetPassword))] public ActionResult ResetPassword(Token token) { var user = Db.GetSession(token)?.User; if (user is null) return Unauthorized(); Db.DeleteUserPassword(user); return Redirect($"https://monitor.innov.energy/?username={user.Email}&reset=true"); // TODO: move to settings file } }