999 lines
33 KiB
C#
999 lines
33 KiB
C#
using System.Diagnostics;
|
|
using System.Net;
|
|
using System.Text.RegularExpressions;
|
|
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;
|
|
|
|
// create JobStatus class to track download battery log job
|
|
public class JobStatus
|
|
{
|
|
public string JobId { get; set; }
|
|
public string Status { get; set; }
|
|
public string FileName { get; set; }
|
|
public DateTime StartTime { get; set; }
|
|
}
|
|
|
|
[Controller]
|
|
[Route("api/")]
|
|
//All the http requests from the frontend that contain "/api" will be forwarded to this controller from the nginx reverse proxy.
|
|
public class Controller : ControllerBase
|
|
{
|
|
[HttpPost(nameof(Login))]
|
|
public ActionResult<Session> Login(String username, String? password)
|
|
{
|
|
//Find the user to the database, verify its password and create a new session.
|
|
//Store the new session to the database and return it to the frontend.
|
|
//If the user log out, the session will be deleted. Each session is valid for 24 hours. The db deletes all invalid/expired sessions every 30 minutes.
|
|
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))
|
|
{
|
|
throw new Exceptions(401, "Wrong Password Exception", "Please try again.", Request.Path.Value!);
|
|
}
|
|
|
|
var session = new Session(user.HidePassword().HideParentIfUserHasNoAccessToParent(user));
|
|
|
|
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)
|
|
{
|
|
//Find the session and delete it from the database.
|
|
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(GetHistoryForInstallation))]
|
|
public ActionResult<IEnumerable<UserAction>> GetHistoryForInstallation(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.UserActions
|
|
.Where(action =>action.InstallationId == id)
|
|
.OrderByDescending(action => action.Timestamp)
|
|
.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(GetCsvTimestampsForInstallation))]
|
|
public ActionResult<IEnumerable<Int64>> GetCsvTimestampsForInstallation(Int64 id, Int32 start, Int32 end, 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();
|
|
|
|
var sampleSize = 100;
|
|
var allTimestamps = new List<Int64>();
|
|
|
|
static string FindCommonPrefix(string str1, string str2)
|
|
{
|
|
int minLength = Math.Min(str1.Length, str2.Length);
|
|
int i = 0;
|
|
while (i < minLength && str1[i] == str2[i])
|
|
{
|
|
i++;
|
|
}
|
|
return str1.Substring(0, i);
|
|
}
|
|
|
|
Int64 startTimestamp = Int64.Parse(start.ToString().Substring(0,5));
|
|
Int64 endTimestamp = Int64.Parse(end.ToString().Substring(0,5));
|
|
|
|
if (installation.Product == 1)
|
|
{
|
|
|
|
start = Int32.Parse(start.ToString().Substring(0, start.ToString().Length - 2));
|
|
end = Int32.Parse(end.ToString().Substring(0, end.ToString().Length - 2));
|
|
}
|
|
|
|
string configPath = "/home/ubuntu/.s3cfg";
|
|
|
|
while (startTimestamp <= endTimestamp)
|
|
{
|
|
string bucketPath = installation.Product==0? "s3://"+installation.S3BucketId + "-3e5b3069-214a-43ee-8d85-57d72000c19d/"+startTimestamp :
|
|
"s3://"+installation.S3BucketId + "-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e/"+startTimestamp;
|
|
Console.WriteLine("Fetching data for "+startTimestamp);
|
|
|
|
try
|
|
{
|
|
// Set up process start info
|
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "s3cmd",
|
|
Arguments = $"--config {configPath} ls {bucketPath}",
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
};
|
|
|
|
// Start the process
|
|
Process process = new Process
|
|
{
|
|
StartInfo = startInfo
|
|
};
|
|
|
|
process.Start();
|
|
|
|
// Read the output
|
|
string output = process.StandardOutput.ReadToEnd();
|
|
string error = process.StandardError.ReadToEnd();
|
|
|
|
process.WaitForExit();
|
|
|
|
// Check for errors
|
|
if (process.ExitCode != 0)
|
|
{
|
|
Console.WriteLine("Error executing command:");
|
|
Console.WriteLine(error);
|
|
}
|
|
else
|
|
{
|
|
// Define a regex pattern to match the filenames without .csv extension
|
|
var pattern = @"/([^/]+)\.csv$";
|
|
var regex = new Regex(pattern);
|
|
|
|
// Process each line of the output
|
|
foreach (var line in output.Split('\n'))
|
|
{
|
|
var match = regex.Match(line);
|
|
|
|
if (match.Success && long.Parse(match.Groups[1].Value) >= start && long.Parse(match.Groups[1].Value) <= end)
|
|
{
|
|
allTimestamps.Add(long.Parse(match.Groups[1].Value));
|
|
//Console.WriteLine(match.Groups[1].Value);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"Exception: {e.Message}");
|
|
}
|
|
|
|
startTimestamp++;
|
|
}
|
|
|
|
int totalRecords = allTimestamps.Count;
|
|
if (totalRecords <= sampleSize)
|
|
{
|
|
// If the total records are less than or equal to the sample size, return all records
|
|
Console.WriteLine("Start timestamp = "+start +" end timestamp = "+end);
|
|
Console.WriteLine("SampledTimestamps = " + allTimestamps.Count);
|
|
return allTimestamps;
|
|
}
|
|
|
|
int interval = totalRecords / sampleSize;
|
|
var sampledTimestamps = new List<Int64>();
|
|
|
|
for (int i = 0; i < totalRecords; i += interval)
|
|
{
|
|
sampledTimestamps.Add(allTimestamps[i]);
|
|
}
|
|
|
|
// If we haven't picked enough records (due to rounding), add the latest record to ensure completeness
|
|
if (sampledTimestamps.Count < sampleSize)
|
|
{
|
|
sampledTimestamps.Add(allTimestamps.Last());
|
|
}
|
|
|
|
Console.WriteLine("Start timestamp = "+start +" end timestamp = "+end);
|
|
Console.WriteLine("TotalRecords = "+totalRecords + " interval = "+ interval);
|
|
Console.WriteLine("SampledTimestamps = " + sampledTimestamps.Count);
|
|
|
|
return sampledTimestamps;
|
|
}
|
|
|
|
[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.UserType);
|
|
}
|
|
|
|
[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(product:0)
|
|
.Select(i => i.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(user).HideWriteKeyIfUserIsNotAdmin(user.UserType))
|
|
.ToList();
|
|
}
|
|
|
|
[HttpGet(nameof(GetAllSalidomoInstallations))]
|
|
public ActionResult<IEnumerable<Installation>> GetAllSalidomoInstallations(Token authToken)
|
|
{
|
|
var user = Db.GetSession(authToken)?.User;
|
|
|
|
if (user is null)
|
|
return Unauthorized();
|
|
|
|
return user
|
|
.AccessibleInstallations(product:1)
|
|
.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(int productId, Token authToken)
|
|
{
|
|
var user = Db.GetSession(authToken)?.User;
|
|
|
|
if (user is null)
|
|
return Unauthorized();
|
|
|
|
|
|
var foldersAndInstallations = user
|
|
.AccessibleFoldersAndInstallations(product:productId)
|
|
.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();
|
|
|
|
if (installation.Product == 0)
|
|
{
|
|
return installation.FillOrderNumbers().HideParentIfUserHasNoAccessToParent(session!.User).HideWriteKeyIfUserIsNotAdmin(session.User.UserType);
|
|
}
|
|
|
|
return installation.HideParentIfUserHasNoAccessToParent(session!.User);
|
|
}
|
|
|
|
[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(UpdateFirmware))]
|
|
public async Task<ActionResult> UpdateFirmware(Int64 batteryNode, Int64 installationId,String version,Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
var installationToUpdate = Db.GetInstallationById(installationId);
|
|
|
|
|
|
if (installationToUpdate != null)
|
|
{
|
|
_ = session.RunScriptInBackground(installationToUpdate.VpnIp, batteryNode,version,installationToUpdate.Product);
|
|
}
|
|
|
|
return Ok();
|
|
}
|
|
|
|
private static Dictionary<string, JobStatus> JobStatuses = new Dictionary<string, JobStatus>();
|
|
|
|
[HttpPost("StartDownloadBatteryLog")]
|
|
public async Task<ActionResult<string>> StartDownloadBatteryLog(long batteryNode, long installationId, Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
var installationToDownload = Db.GetInstallationById(installationId);
|
|
|
|
if (installationToDownload != null)
|
|
{
|
|
string jobId = Guid.NewGuid().ToString();
|
|
_ = Task.Run(async () =>
|
|
{
|
|
await session.RunDownloadLogScript(installationToDownload.VpnIp, batteryNode, installationToDownload.Product);
|
|
string fileName = $"{installationToDownload.VpnIp}-node{batteryNode}-{DateTime.Now:dd-MM-yyyy}.bin";
|
|
string filePath = $"/home/ubuntu/backend/downloadBatteryLog/{fileName}";
|
|
|
|
if (System.IO.File.Exists(filePath))
|
|
{
|
|
SaveJobStatus(jobId, "Completed", fileName:fileName);
|
|
}
|
|
else
|
|
{
|
|
SaveJobStatus(jobId, "Failed");
|
|
}
|
|
});
|
|
|
|
// Store initial job status in in-memory storage
|
|
SaveJobStatus(jobId, "Processing");
|
|
|
|
return Ok(jobId);
|
|
}
|
|
|
|
return NotFound();
|
|
}
|
|
|
|
[HttpGet("DownloadBatteryLog")]
|
|
public async Task<ActionResult> DownloadBatteryLog(string jobId)
|
|
|
|
{
|
|
Console.WriteLine("-----------------------------------Start uploading battery log-----------------------------------");
|
|
var jobStatus = JobStatuses.TryGetValue(jobId, out var status) ? status : null;
|
|
if (jobStatus == null || jobStatus.Status != "Completed" || string.IsNullOrEmpty(jobStatus.FileName))
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
string fileName = jobStatus.FileName;
|
|
string filePath = $"/home/ubuntu/backend/downloadBatteryLog/{fileName}";
|
|
|
|
if (!System.IO.File.Exists(filePath))
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
string contentType = "application/octet-stream";
|
|
var memory = new MemoryStream();
|
|
await using (var stream = new FileStream(filePath, FileMode.Open))
|
|
{
|
|
await stream.CopyToAsync(memory);
|
|
}
|
|
memory.Position = 0;
|
|
|
|
var fileContentResult = new FileContentResult(memory.ToArray(), contentType)
|
|
{
|
|
//FileDownloadName = Path.GetFileName(filePath)
|
|
FileDownloadName = fileName
|
|
};
|
|
|
|
Console.WriteLine("-----------------------------------Stop uploading battery log-----------------------------------");
|
|
|
|
return fileContentResult;
|
|
}
|
|
|
|
[HttpDelete("DeleteBatteryLog")]
|
|
public IActionResult DeleteBatteryLog(string fileName)
|
|
{
|
|
Console.WriteLine("-----------------------------------Start deleting downloaded battery log-----------------------------------");
|
|
string filePath = $"/home/ubuntu/backend/downloadBatteryLog/{fileName}";
|
|
try
|
|
{
|
|
if (System.IO.File.Exists(filePath))
|
|
{
|
|
System.IO.File.Delete(filePath);
|
|
Console.WriteLine("-----------------------------------Stop deleting downloaded battery log-----------------------------------");
|
|
return Ok();
|
|
}
|
|
else
|
|
{
|
|
return NotFound("File not found.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return StatusCode(500, $"Internal server error: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void SaveJobStatus(string jobId, string status, string fileName = null)
|
|
{
|
|
JobStatuses[jobId] = new JobStatus
|
|
{
|
|
JobId = jobId,
|
|
Status = status,
|
|
FileName = fileName,
|
|
StartTime = DateTime.UtcNow // Initialize StartTime when saving
|
|
};
|
|
}
|
|
|
|
[HttpGet("GetJobResult")]
|
|
public ActionResult GetJobResult(string jobId)
|
|
{
|
|
if (string.IsNullOrEmpty(jobId))
|
|
{
|
|
return BadRequest(new { status = "Error", message = "Job ID is required." });
|
|
}
|
|
|
|
if (!JobStatuses.TryGetValue(jobId, out var jobStatus))
|
|
{
|
|
return NotFound();
|
|
}
|
|
|
|
if (jobStatus.Status == "Completed")
|
|
{
|
|
return Ok(new { status = "Completed", fileName = jobStatus.FileName });
|
|
}
|
|
else if (jobStatus.Status == "Failed")
|
|
{
|
|
return StatusCode(500, new { status = "Failed", message = "Job processing failed." });
|
|
}
|
|
else if (jobStatus.Status == "Processing")
|
|
{
|
|
// Check for timeout
|
|
var startTime = jobStatus.StartTime;
|
|
var currentTime = DateTime.UtcNow;
|
|
|
|
if ((currentTime - startTime).TotalMinutes > 60)//60 minutes as timeout => Running multiple tasks in parallel on a crowded backend server will increase the time each task takes to complete
|
|
{
|
|
return StatusCode(500, new { status = "Failed", message = "Job in back end timeout exceeded." });
|
|
}
|
|
|
|
return Ok(new { status = "Processing" });
|
|
}
|
|
else
|
|
{
|
|
return BadRequest(new { status = "Unknown", message = "Unknown job status." });
|
|
}
|
|
}
|
|
|
|
|
|
[HttpPost(nameof(InsertNewAction))]
|
|
public async Task<ActionResult<IEnumerable<Object>>> InsertNewAction([FromBody] UserAction action, Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
var actionSuccess = await session.InsertUserAction(action);
|
|
return actionSuccess ? Ok() : Unauthorized();
|
|
|
|
}
|
|
|
|
[HttpPost(nameof(UpdateAction))]
|
|
public async Task<ActionResult<IEnumerable<Object>>> UpdateAction([FromBody] UserAction action, Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
var actionSuccess = await session.UpdateUserAction(action);
|
|
return actionSuccess ? Ok() : Unauthorized();
|
|
}
|
|
|
|
|
|
[HttpPost(nameof(DeleteAction))]
|
|
public async Task<ActionResult<IEnumerable<Object>>> DeleteAction(Int64 actionId, Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
var actionSuccess = await session.DeleteUserAction(actionId);
|
|
return actionSuccess ? Ok() : Unauthorized();
|
|
}
|
|
|
|
|
|
[HttpPost(nameof(EditInstallationConfig))]
|
|
public async Task<ActionResult<IEnumerable<Object>>> EditInstallationConfig([FromBody] Configuration config, Int64 installationId,Token authToken)
|
|
{
|
|
var session = Db.GetSession(authToken);
|
|
|
|
// Send configuration changes
|
|
var success = await session.SendInstallationConfig(installationId, config);
|
|
|
|
// Record configuration change
|
|
if (success)
|
|
{
|
|
// Create a new UserAction object
|
|
var action = new UserAction
|
|
{
|
|
InstallationId = installationId,
|
|
Timestamp = DateTime.Now,
|
|
Description = config.GetConfigurationString()
|
|
};
|
|
|
|
var actionSuccess = await session.InsertUserAction(action);
|
|
return actionSuccess?Ok():Unauthorized();
|
|
}
|
|
|
|
return 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
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|