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<Session> 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) { Console.WriteLine("------------------------------------Unauthorized user----------------------------------------------"); HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; HttpContext.Abort(); return; } if (!HttpContext.WebSockets.IsWebSocketRequest) { Console.WriteLine("------------------------------------Not a websocket request ----------------------------------------------"); 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(GetAllErrorsForInstallation))] public ActionResult<IEnumerable<Error>> GetAllErrorsForInstallation(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 Db.Errors .Where(error => error.InstallationId == id) .OrderByDescending(error => error.Date) .ThenByDescending(error => error.Time) .ToList(); } [HttpGet(nameof(GetAllWarningsForInstallation))] public ActionResult<IEnumerable<Warning>> GetAllWarningsForInstallation(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 Db.Warnings .Where(error => error.InstallationId == id) .OrderByDescending(error => error.Date) .ThenByDescending(error => error.Time) .ToList(); } [HttpGet(nameof(GetUserById))] public ActionResult<User> 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<Installation> 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<IEnumerable<Object>> 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<IEnumerable<Object>> 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<IEnumerable<Object>> 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<IEnumerable<Object>> 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<Folder> 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<IEnumerable<User>> 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<IEnumerable<User>> 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<IEnumerable<Installation>> 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<IEnumerable<Folder>> 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<IEnumerable<Object>> 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<Object>(); // 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<ActionResult<User>> CreateUser([FromBody] User newUser, Token authToken) { var create = Db.GetSession(authToken).Create(newUser); if (create) { var mail_success= await Db.SendNewUserEmail(newUser); if (!mail_success) { Db.GetSession(authToken).Delete(newUser); } return mail_success ? newUser.HidePassword():Unauthorized(); } return Unauthorized() ; } [HttpPost(nameof(CreateInstallation))] public async Task<ActionResult<Installation>> 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<Folder> 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<User> 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<User> UpdatePassword(String newPassword, Token authToken) { var session = Db.GetSession(authToken); return session.UpdatePassword(newPassword) ? Ok() : Unauthorized(); } [HttpPut(nameof(UpdateInstallation))] public ActionResult<Installation> 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); } [HttpPost(nameof(AcknowledgeError))] public ActionResult AcknowledgeError(Int64 id, Token authToken) { var session = Db.GetSession(authToken); if (session == null) return Unauthorized(); var error=Db.Errors .FirstOrDefault(error => error.Id == id); error.Seen = true; return Db.Update(error) ? Ok() : Unauthorized(); } [HttpPost(nameof(AcknowledgeWarning))] public ActionResult AcknowledgeWarning(Int64 id, Token authToken) { var session = Db.GetSession(authToken); if (session == null) return Unauthorized(); var warning=Db.Warnings .FirstOrDefault(warning => warning.Id == id); warning.Seen = true; return Db.Update(warning) ? Ok() : Unauthorized(); } [HttpPut(nameof(UpdateFolder))] public ActionResult<Folder> 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<ActionResult<IEnumerable<Object>>> EditInstallationConfig([FromBody] Configuration config, Int64 installationId, Token authToken) { var session = Db.GetSession(authToken); //Console.WriteLine(config.GridSetPoint); //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<ActionResult> 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<ActionResult<IEnumerable<Object>>> 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<Object> 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 } }