440 lines
15 KiB
C#
440 lines
15 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using System.Web.Http;
|
|
using InnovEnergy.App.Backend.Database;
|
|
using InnovEnergy.App.Backend.Model;
|
|
using InnovEnergy.App.Backend.Model.Relations;
|
|
using InnovEnergy.App.Backend.Utils;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using HttpContextAccessor = Microsoft.AspNetCore.Http.HttpContextAccessor;
|
|
|
|
namespace InnovEnergy.App.Backend.Controllers;
|
|
|
|
[ApiController]
|
|
[Microsoft.AspNetCore.Mvc.Route("api/")]
|
|
public class Controller
|
|
{
|
|
[Returns<String>]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Returns(HttpStatusCode.BadRequest)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPost($"{nameof(Login)}")]
|
|
public Object Login(Credentials credentials)
|
|
{
|
|
if (String.IsNullOrWhiteSpace(credentials.Username) ||
|
|
String.IsNullOrWhiteSpace(credentials.Password))
|
|
return new HttpResponseException(HttpStatusCode.BadRequest);
|
|
|
|
using var db = Db.Connect();
|
|
var user = db.GetUserByEmail(credentials.Username);
|
|
|
|
|
|
if (user is null)
|
|
return new HttpResponseException(HttpStatusCode.BadRequest);
|
|
|
|
if (!VerifyPassword(credentials.Password, user))
|
|
return new HttpResponseException(HttpStatusCode.Unauthorized);
|
|
|
|
var ses = new Session(user);
|
|
db.NewSession(ses);
|
|
return new {ses.Token, user.Language};
|
|
}
|
|
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPost($"{nameof(Logout)}")]
|
|
public Object Logout()
|
|
{
|
|
var caller = GetCaller();
|
|
|
|
if (caller is null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
return db.DeleteSession(caller.Id);
|
|
}
|
|
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetInstallationS3Key)}")]
|
|
public Object GetInstallationS3Key(Int64 installationId)
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller is null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var installation = db
|
|
.GetAllAccessibleInstallations(caller)
|
|
.FirstOrDefault(i => i.Id == installationId);
|
|
|
|
if(installation == null)
|
|
{
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
var key = db.GetInstallationS3Key(installationId);
|
|
return key ?? db.CreateAndSaveInstallationS3ApiKey(installation);
|
|
}
|
|
|
|
|
|
[Returns<User>]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetUserById)}")]
|
|
public Object GetUserById(Int64 id)
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller is null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var user = db
|
|
.GetDescendantUsers(caller)
|
|
.FirstOrDefault(u => u.Id == id);
|
|
|
|
return user as Object ?? new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
|
|
[Returns<Installation>]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetInstallationById)}")]
|
|
public Object GetInstallationById(Int64 id)
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var installation = db
|
|
.GetAllAccessibleInstallations(caller)
|
|
.FirstOrDefault(i => i.Id == id);
|
|
|
|
return installation as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound);
|
|
}
|
|
|
|
|
|
[Returns<Folder>]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetFolderById)}")]
|
|
public Object GetFolderById(Int64 id)
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var folder = db
|
|
.GetAllAccessibleFolders(caller)
|
|
.FirstOrDefault(f => f.Id == id);
|
|
|
|
return folder as Object ?? new HttpResponseMessage(HttpStatusCode.NotFound);
|
|
}
|
|
|
|
|
|
[Returns<Installation[]>] // assuming swagger knows about arrays but not lists (JSON)
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetAllInstallations)}/")]
|
|
public Object GetAllInstallations()
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
return db
|
|
.GetAllAccessibleInstallations(caller)
|
|
.ToList(); // important!
|
|
}
|
|
|
|
|
|
[Returns<Folder[]>] // assuming swagger knows about arrays but not lists (JSON)
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetAllFolders)}/")]
|
|
public Object GetAllFolders()
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
return db
|
|
.GetAllAccessibleFolders(caller)
|
|
.ToList(); // important!
|
|
}
|
|
|
|
[Returns<TreeNode[]>] // assuming swagger knows about arrays but not lists (JSON)
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetTree)}/")]
|
|
public Object GetTree()
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var folders = db
|
|
.GetDirectlyAccessibleFolders(caller) // ReSharper disable once AccessToDisposedClosure
|
|
.Select(f => PopulateChildren(db, f));
|
|
|
|
var installations = db.GetDirectlyAccessibleInstallations(caller);
|
|
|
|
return folders
|
|
.Concat<TreeNode>(installations)
|
|
.ToList(); // important!
|
|
}
|
|
|
|
[Returns<TreeNode[]>] // assuming swagger knows about arrays but not lists (JSON)
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpGet($"{nameof(GetAllFoldersAndInstallations)}/")]
|
|
public Object GetAllFoldersAndInstallations()
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var folders = db.GetAllAccessibleFolders(caller) as IEnumerable<TreeNode>;
|
|
var installations = db.GetAllAccessibleInstallations(caller);
|
|
|
|
return folders
|
|
.Concat(installations)
|
|
.ToList(); // important!
|
|
}
|
|
|
|
private static Folder PopulateChildren(Db db, Folder folder, HashSet<Int64>? hs = null)
|
|
{
|
|
// TODO: remove cycle detector
|
|
hs ??= new HashSet<Int64>();
|
|
if (!hs.Add(folder.Id))
|
|
throw new Exception("Cycle detected: folder " + folder.Id);
|
|
|
|
var installations = db.GetChildInstallations(folder);
|
|
var folders = db
|
|
.GetChildFolders(folder)
|
|
.Select(c => PopulateChildren(db, c, hs));
|
|
|
|
folder.Children = folders.Concat<TreeNode>(installations).ToList();
|
|
|
|
return folder;
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPost($"{nameof(CreateUser)}/")]
|
|
public Object CreateUser(User newUser)
|
|
{
|
|
var caller = GetCaller();
|
|
using var db = Db.Connect();
|
|
if (caller == null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
newUser.ParentId = caller.Id;
|
|
|
|
return db.CreateUser(newUser);
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPost($"{nameof(CreateInstallation)}/")]
|
|
public Object CreateInstallation(Installation installation)
|
|
{
|
|
var caller = GetCaller();
|
|
using var db = Db.Connect();
|
|
if (caller == null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
var id = db.CreateInstallation(installation);
|
|
|
|
return db.AddToAccessibleInstallations(caller.Id, id);
|
|
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPost($"{nameof(CreateFolder)}/")]
|
|
public Object CreateFolder(Folder folder)
|
|
{
|
|
var caller = GetCaller();
|
|
using var db = Db.Connect();
|
|
if (caller == null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
var id = db.CreateFolder(folder);
|
|
return db.AddToAccessibleFolders(caller.Id, id);
|
|
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPut($"{nameof(UpdateUser)}/")]
|
|
public Object UpdateUser(User updatedUser)
|
|
{
|
|
var caller = GetCaller();
|
|
using var db = Db.Connect();
|
|
if (caller == null || !db.IsParentOfChild(caller.Id, updatedUser) || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
return db.UpdateUser(updatedUser);
|
|
}
|
|
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPut($"{nameof(UpdateInstallation)}/")]
|
|
public Object UpdateInstallation(Installation installation)
|
|
{
|
|
var caller = GetCaller();
|
|
|
|
if (caller is null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var installationFromAccessibleInstallations = db
|
|
.GetAllAccessibleInstallations(caller)
|
|
.FirstOrDefault(i => i.Id == installation.Id);
|
|
|
|
if (installationFromAccessibleInstallations == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
// TODO: accessibility by other users etc
|
|
// TODO: sanity check changes
|
|
// foreach(var property in installationFromAccessibleInstallations.GetType().GetProperties()){
|
|
// if(installation.GetType().GetProperties().Contains(property))
|
|
// {
|
|
// property.SetValue(installationFromAccessibleInstallations, property.GetValue(installation));
|
|
// }
|
|
// }
|
|
|
|
return db.UpdateInstallation(installation);
|
|
}
|
|
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpPut($"{nameof(UpdateFolder)}/")]
|
|
public Object UpdateFolder(Folder folder)
|
|
{
|
|
var caller = GetCaller();
|
|
|
|
if (caller is null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var installationFromAccessibleFolders = db
|
|
.GetAllAccessibleFolders(caller)
|
|
.FirstOrDefault(f => f.Id == folder.Id);
|
|
|
|
if (installationFromAccessibleFolders == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
// TODO: accessibility by other users etc
|
|
// TODO: sanity check changes
|
|
|
|
// foreach(var property in installationFromAccessibleFolders.GetType().GetProperties()){
|
|
// if(folder.GetType().GetProperties().Contains(property))
|
|
// {
|
|
// property.SetValue(installationFromAccessibleFolders, property.GetValue(folder));
|
|
// }
|
|
// }
|
|
|
|
return db.UpdateFolder(installationFromAccessibleFolders);
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpDelete($"{nameof(DeleteUser)}/")]
|
|
public Object DeleteUser(Int64 userId)
|
|
{
|
|
var caller = GetCaller();
|
|
|
|
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);
|
|
}
|
|
|
|
[Returns(HttpStatusCode.OK)]
|
|
[Returns(HttpStatusCode.Unauthorized)]
|
|
[Microsoft.AspNetCore.Mvc.HttpDelete($"{nameof(DeleteInstallation)}/")]
|
|
public Object DeleteInstallation(Int64 installationId)
|
|
{
|
|
var caller = GetCaller();
|
|
|
|
if (caller is null || !caller.HasWriteAccess)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var installationToBeDeleted = db
|
|
.GetAllAccessibleInstallations(caller)
|
|
.FirstOrDefault(i => i.Id == installationId);
|
|
|
|
if (installationToBeDeleted is null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
return db.DeleteInstallation(installationToBeDeleted);
|
|
}
|
|
|
|
|
|
[ProducesResponseType(200)]
|
|
[ProducesResponseType(401)]
|
|
[Microsoft.AspNetCore.Mvc.HttpDelete($"{nameof(DeleteFolder)}/")]
|
|
public Object DeleteFolder(Int64 folderId)
|
|
{
|
|
var caller = GetCaller();
|
|
if (caller == null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
using var db = Db.Connect();
|
|
|
|
var folderToDelete = db
|
|
.GetAllAccessibleFolders(caller)
|
|
.FirstOrDefault(f => f.Id == folderId);
|
|
|
|
if (folderToDelete is null)
|
|
return new HttpResponseMessage(HttpStatusCode.Unauthorized);
|
|
|
|
return db.DeleteFolder(folderToDelete);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|