Make Controller less magic.

This commit is contained in:
ig 2023-03-20 08:33:44 +01:00
parent 9454fbf878
commit e025b8cd11
6 changed files with 129 additions and 194 deletions

View File

@ -2,95 +2,80 @@ using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes;
using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.DataTypes.Methods;
using InnovEnergy.App.Backend.Relations; using InnovEnergy.App.Backend.Relations;
using InnovEnergy.Lib.Utils;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using static System.Net.HttpStatusCode;
namespace InnovEnergy.App.Backend.Controllers; namespace InnovEnergy.App.Backend.Controllers;
[ApiController] [ApiController]
[Route("api/")] [Route("api/")]
public class Controller public class Controller : ControllerBase
{ {
private static readonly HttpResponseMessage _Unauthorized = new HttpResponseMessage(Unauthorized); [HttpPost(nameof(Login))]
private static readonly HttpResponseMessage _Ok = new HttpResponseMessage(OK); public ActionResult<Session> Login(Credentials credentials)
private static readonly HttpResponseMessage _BadRequest = new HttpResponseMessage(BadRequest);
[Returns<String>]
[Returns(Unauthorized)]
[Returns(BadRequest)]
[HttpPost($"{nameof(Login)}")]
public Object Login(Credentials credentials)
{ {
var session = credentials.Login(); var session = credentials.Login();
return session is null return session is null
? _Unauthorized ? Unauthorized()
: session; : session;
} }
[Returns(OK)] [HttpPost(nameof(Logout))]
[Returns(Unauthorized)] public ActionResult Logout()
[HttpPost($"{nameof(Logout)}")]
public Object Logout()
{ {
var session = GetSession(); var session = GetSession();
return session.Logout() return session.Logout()
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns<User>] [HttpGet(nameof(GetUserById))]
[Returns(Unauthorized)] public ActionResult<User> GetUserById(Int64 id)
[HttpGet($"{nameof(GetUserById)}")]
public Object GetUserById(Int64 id)
{ {
var caller = GetSession()?.User; var caller = GetSession()?.User;
if (caller == null) if (caller == null)
return _Unauthorized; return Unauthorized();
var user = Db.GetUserById(id); var user = Db.GetUserById(id);
if (user is null || !caller.HasAccessTo(user)) if (user is null || !caller.HasAccessTo(user))
return _Unauthorized; return Unauthorized();
user.Password = ""; user.Password = "";
return user; return user;
} }
[Returns<Installation>] [HttpGet(nameof(GetInstallationById))]
[Returns(Unauthorized)] public ActionResult<Installation> GetInstallationById(Int64 id)
[HttpGet($"{nameof(GetInstallationById)}")]
public Object GetInstallationById(Int64 id)
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user == null) if (user == null)
return _Unauthorized; return Unauthorized();
var installation = Db.GetInstallationById(id); var installation = Db.GetInstallationById(id);
if (installation is null || !user.HasAccessTo(installation)) if (installation is null || !user.HasAccessTo(installation))
return _Unauthorized; return Unauthorized();
return installation; return installation;
} }
[Returns<Installation>] [HttpGet(nameof(GetUsersWithAccessToInstallation))]
[Returns(Unauthorized)] public ActionResult<IEnumerable<Object>> GetUsersWithAccessToInstallation(Int64 id)
[HttpGet($"{nameof(GetUsersWithAccessToInstallation)}")]
public Object GetUsersWithAccessToInstallation(Int64 id)
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user == null) if (user == null)
return _Unauthorized; return Unauthorized();
var installation = Db.GetInstallationById(id); var installation = Db.GetInstallationById(id);
if (installation is null || !user.HasAccessTo(installation)) if (installation is null || !user.HasAccessTo(installation))
return _Unauthorized; return Unauthorized();
var directAccess = installation var directAccess = installation
.UsersWithDirectAccess() .UsersWithDirectAccess()
@ -103,128 +88,114 @@ public class Controller
.Select(u => new { folderId = f.Id, user = u })); .Select(u => new { folderId = f.Id, user = u }));
return directAccess return directAccess
.Concat<Object>(inheritedAccess); .Concat<Object>(inheritedAccess)
.Apply(Ok); // TODO: typing
} }
[Returns(Unauthorized)] [HttpGet(nameof(GetUsersWithAccessToFolder))]
[HttpGet($"{nameof(GetUsersWithAccessToFolder)}")] public ActionResult<IEnumerable<Object>> GetUsersWithAccessToFolder(Int64 id)
public Object GetUsersWithAccessToFolder(Int64 id)
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user == null) if (user == null)
return _Unauthorized; return Unauthorized();
var folder = Db.GetFolderById(id); var folder = Db.GetFolderById(id);
if (folder is null || !user.HasAccessTo(folder)) if (folder is null || !user.HasAccessTo(folder))
return _Unauthorized; return Unauthorized();
return folder return folder
.Ancestors() .Ancestors()
.Prepend(folder) .Prepend(folder)
.SelectMany(f => f.UsersWithDirectAccess() .SelectMany(f => f.UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user)) .Where(u => u.IsDescendantOf(user))
.Select(u => new { folderId = f.Id, user = u })); .Select(u => new { folderId = f.Id, user = u }))
.ToList();
} }
[Returns<Folder>] [HttpGet(nameof(GetFolderById))]
[Returns(Unauthorized)] public ActionResult<Folder> GetFolderById(Int64 id)
[HttpGet($"{nameof(GetFolderById)}")]
public Object GetFolderById(Int64 id)
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user == null) if (user == null)
return _Unauthorized; return Unauthorized();
var folder = Db.GetFolderById(id); var folder = Db.GetFolderById(id);
if (folder is null || !user.HasAccessTo(folder)) if (folder is null || !user.HasAccessTo(folder))
return _Unauthorized; return Unauthorized();
return folder; return folder;
} }
[Returns<Installation[]>] // assuming swagger knows about arrays but not lists (JSON) [HttpGet(nameof(GetAllInstallations))]
[Returns(Unauthorized)] public ActionResult<IEnumerable<Installation>> GetAllInstallations()
[HttpGet($"{nameof(GetAllInstallations)}/")]
public Object GetAllInstallations()
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user is null)
return Unauthorized();
return user is null return user.AccessibleInstallations().ToList();
? _Unauthorized
: user.AccessibleInstallations();
} }
[Returns<Folder[]>] // assuming swagger knows about arrays but not lists (JSON)
[Returns(Unauthorized)] [HttpGet(nameof(GetAllFolders))]
[HttpGet($"{nameof(GetAllFolders)}/")] public ActionResult<IEnumerable<Folder>> GetAllFolders()
public Object GetAllFolders()
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
if (user is null)
return Unauthorized();
return user is null return new(user.AccessibleFolders());
? _Unauthorized
: user.AccessibleFolders();
} }
[Returns<TreeNode[]>] // assuming swagger knows about arrays but not lists (JSON)
[Returns(Unauthorized)] [HttpGet(nameof(GetAllFoldersAndInstallations))]
[HttpGet($"{nameof(GetAllFoldersAndInstallations)}/")] public ActionResult<IEnumerable<TreeNode>> GetAllFoldersAndInstallations()
public Object GetAllFoldersAndInstallations()
{ {
var user = GetSession()?.User; var user = GetSession()?.User;
return user is null
? _Unauthorized
: user.AccessibleFoldersAndInstallations();
}
if (user is null)
return Unauthorized();
return new (user.AccessibleFoldersAndInstallations());
}
[Returns(OK)] [HttpPost(nameof(CreateUser))]
[Returns(Unauthorized)] public ActionResult<User> CreateUser(User newUser)
[HttpPost($"{nameof(CreateUser)}/")]
public Object CreateUser(User newUser)
{ {
var session = GetSession(); return GetSession().Create(newUser)
return session.Create(newUser)
? newUser ? newUser
: _Unauthorized ; : Unauthorized() ;
} }
[Returns(OK)] [HttpPost(nameof(CreateInstallation))]
[Returns(Unauthorized)] public async Task<ActionResult<Installation>> CreateInstallation(Installation installation)
[HttpPost($"{nameof(CreateInstallation)}/")] {
public Object CreateInstallation(Installation installation) if (!await GetSession().Create(installation))
return Unauthorized();
return installation;
}
[HttpPost(nameof(CreateFolder))]
public ActionResult<Folder> CreateFolder(Folder folder)
{ {
var session = GetSession(); var session = GetSession();
return session.Create(installation) if (!session.Create(folder))
? installation return Unauthorized();
: _Unauthorized;
return folder;
} }
[Returns(OK)] [HttpPost(nameof(GrantUserAccessToFolder))]
[Returns(Unauthorized)] public ActionResult GrantUserAccessToFolder(FolderAccess folderAccess)
[Returns(InternalServerError)]
[HttpPost($"{nameof(CreateFolder)}/")]
public Object CreateFolder(Folder folder)
{
var session = GetSession();
return session.Create(folder)
? folder
: _Unauthorized;
}
[Returns(OK)]
[Returns(Unauthorized)]
[HttpPost($"{nameof(GrantUserAccessToFolder)}/")]
public Object GrantUserAccessToFolder(FolderAccess folderAccess)
{ {
var session = GetSession(); var session = GetSession();
@ -233,15 +204,13 @@ public class Controller
var user = Db.GetUserById(folderAccess.UserId); var user = Db.GetUserById(folderAccess.UserId);
return session.GrantUserAccessTo(user, folder) return session.GrantUserAccessTo(user, folder)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns(OK)] [HttpPost(nameof(RevokeUserAccessToFolder))]
[Returns(Unauthorized)] public ActionResult RevokeUserAccessToFolder(FolderAccess folderAccess)
[HttpPost($"{nameof(RevokeUserAccessToFolder)}/")]
public Object RevokeUserAccessToFolder(FolderAccess folderAccess)
{ {
var session = GetSession(); var session = GetSession();
@ -250,15 +219,13 @@ public class Controller
var user = Db.GetUserById(folderAccess.UserId); var user = Db.GetUserById(folderAccess.UserId);
return session.RevokeUserAccessTo(user, folder) return session.RevokeUserAccessTo(user, folder)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns(OK)] [HttpPost(nameof(GrantUserAccessToInstallation))]
[Returns(Unauthorized)] public ActionResult GrantUserAccessToInstallation(InstallationAccess installationAccess)
[HttpPost($"{nameof(GrantUserAccessToInstallation)}/")]
public Object GrantUserAccessToInstallation(InstallationAccess installationAccess)
{ {
var session = GetSession(); var session = GetSession();
@ -267,14 +234,12 @@ public class Controller
var user = Db.GetUserById(installationAccess.UserId); var user = Db.GetUserById(installationAccess.UserId);
return session.GrantUserAccessTo(user, installation) return session.GrantUserAccessTo(user, installation)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns(OK)] [HttpPost(nameof(RevokeUserAccessToInstallation))]
[Returns(Unauthorized)] public ActionResult RevokeUserAccessToInstallation(InstallationAccess installationAccess)
[HttpPost($"{nameof(RevokeUserAccessToInstallation)}/")]
public Object RevokeUserAccessToInstallation(InstallationAccess installationAccess)
{ {
var session = GetSession(); var session = GetSession();
@ -283,88 +248,81 @@ public class Controller
var user = Db.GetUserById(installationAccess.UserId); var user = Db.GetUserById(installationAccess.UserId);
return session.RevokeUserAccessTo(user, installation) return session.RevokeUserAccessTo(user, installation)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns(OK)] [HttpPut(nameof(UpdateUser))]
[Returns(Unauthorized)] public ActionResult<User> UpdateUser(User updatedUser)
[HttpPut($"{nameof(UpdateUser)}/")]
public Object UpdateUser(User updatedUser)
{ {
var session = GetSession(); var session = GetSession();
if (!session.Update(updatedUser)) return _Unauthorized; if (!session.Update(updatedUser))
updatedUser.Password = ""; return Unauthorized();
updatedUser.Password = ""; // TODO: generic sanitize return values
return updatedUser; return updatedUser;
} }
[Returns(OK)] [HttpPut(nameof(UpdateInstallation))]
[Returns(Unauthorized)] public ActionResult<Installation> UpdateInstallation(Installation installation)
[HttpPut($"{nameof(UpdateInstallation)}/")]
public Object UpdateInstallation(Installation installation)
{ {
var session = GetSession(); var session = GetSession();
if (!session.Update(installation))
return Unauthorized();
return session.Update(installation) return installation;
? installation
: _Unauthorized;
} }
[Returns(OK)] [HttpPut(nameof(UpdateFolder))]
[Returns(Unauthorized)] public ActionResult<Folder> UpdateFolder(Folder folder)
[HttpPut($"{nameof(UpdateFolder)}/")]
public Object UpdateFolder(Folder folder)
{ {
var session = GetSession(); var session = GetSession();
if (!session.Update(folder))
return Unauthorized();
return session.Update(folder) return folder;
? folder
: _Unauthorized;
} }
[Returns(OK)] [HttpDelete(nameof(DeleteUser))]
[Returns(Unauthorized)] public ActionResult DeleteUser(Int64 userId)
[HttpDelete($"{nameof(DeleteUser)}/")]
public Object DeleteUser(Int64 userId)
{ {
var session = GetSession(); var session = GetSession();
var user = Db.GetUserById(userId); var user = Db.GetUserById(userId);
return session.Delete(user) return session.Delete(user)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[Returns(OK)] [HttpDelete(nameof(DeleteInstallation))]
[Returns(Unauthorized)] public ActionResult DeleteInstallation(Int64 installationId)
[HttpDelete($"{nameof(DeleteInstallation)}/")]
public Object DeleteInstallation(Int64 installationId)
{ {
var session = GetSession(); var session = GetSession();
var installation = Db.GetInstallationById(installationId); var installation = Db.GetInstallationById(installationId);
return session.Delete(installation) return session.Delete(installation)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }
[ProducesResponseType(200)] [HttpDelete(nameof(DeleteFolder))]
[ProducesResponseType(401)] public ActionResult DeleteFolder(Int64 folderId)
[HttpDelete($"{nameof(DeleteFolder)}/")]
public Object DeleteFolder(Int64 folderId)
{ {
var session = GetSession(); var session = GetSession();
var folder = Db.GetFolderById(folderId); var folder = Db.GetFolderById(folderId);
return session.Delete(folder) return session.Delete(folder)
? _Ok ? Ok()
: _Unauthorized; : Unauthorized();
} }

View File

@ -1,22 +0,0 @@
using System.Net;
using Microsoft.AspNetCore.Mvc;
namespace InnovEnergy.App.Backend.Controllers;
public class ReturnsAttribute : ProducesResponseTypeAttribute
{
public ReturnsAttribute(HttpStatusCode statusCode) : base((Int32)statusCode)
{
}
}
public class ReturnsAttribute<T> : ProducesResponseTypeAttribute
{
public ReturnsAttribute(HttpStatusCode statusCode) : base(typeof(T), (Int32)statusCode)
{
}
public ReturnsAttribute() : base(typeof(T), (Int32)HttpStatusCode.OK)
{
}
}

View File

@ -80,7 +80,7 @@ public static class FolderMethods
public static Boolean IsRelativeRoot(this Folder folder) public static Boolean IsRelativeRoot(this Folder folder)
{ {
return folder.ParentId < 0; return folder.ParentId < 0; // TODO
} }
public static Boolean WasMoved(this Folder folder) public static Boolean WasMoved(this Folder folder)

View File

@ -41,7 +41,7 @@ public static class SessionMethods
} }
public static Boolean Create(this Session? session, Installation? installation) public static async Task<Boolean> Create(this Session? session, Installation? installation)
{ {
var user = session?.User; var user = session?.User;
@ -51,8 +51,8 @@ public static class SessionMethods
&& user.HasAccessTo(installation.Parent()) && user.HasAccessTo(installation.Parent())
&& Db.Create(installation) && Db.Create(installation)
&& Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id }) && Db.Create(new InstallationAccess { UserId = user.Id, InstallationId = installation.Id })
&& installation.CreateBucket().Result // TODO: await? && await installation.CreateBucket()
&& installation.RenewS3BucketUrl().Result; // generation of access _after_ generation of && await installation.RenewS3BucketUrl(); // generation of access _after_ generation of
// bucket to prevent "zombie" access-rights. // bucket to prevent "zombie" access-rights.
} }

View File

@ -7,13 +7,11 @@ public static class Program
{ {
public static void Main(String[] args) public static void Main(String[] args)
{ {
Db.CreateFakeRelations(); //Db.CreateFakeRelations();
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // TODO: remove magic, specify controllers explicitly builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod())); builder.Services.AddCors(o => o.AddDefaultPolicy(p => p.WithOrigins("*").AllowAnyHeader().AllowAnyMethod()));
@ -22,6 +20,7 @@ public static class Program
c.SwaggerDoc("v1", new OpenApiInfo { Title = "InnovEnergy Backend API", Version = "v1" }); c.SwaggerDoc("v1", new OpenApiInfo { Title = "InnovEnergy Backend API", Version = "v1" });
c.UseAllOfToExtendReferenceSchemas(); c.UseAllOfToExtendReferenceSchemas();
c.OperationFilter<HeaderFilter>(); //Todo testing throw me out c.OperationFilter<HeaderFilter>(); //Todo testing throw me out
c.SupportNonNullableReferenceTypes();
}); });

Binary file not shown.