Implemented api permission system (backend)

This commit is contained in:
Baumgartner Marcel
2024-06-06 08:59:52 +02:00
parent 1cc32fa5c4
commit 1254925c4a
3 changed files with 58 additions and 14 deletions

View File

@@ -1,17 +1,20 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Controllers; using MoonCore.Abstractions;
using MoonCore.Helpers;
using Moonlight.Core.Attributes; using Moonlight.Core.Attributes;
using Moonlight.Core.Database.Entities;
using Newtonsoft.Json;
namespace Moonlight.Core.Http.Middleware; namespace Moonlight.Core.Http.Middleware;
public class ApiPermissionMiddleware public class ApiPermissionMiddleware
{ {
private RequestDelegate Next; private RequestDelegate Next;
private readonly IServiceProvider Provider;
public ApiPermissionMiddleware(RequestDelegate next) public ApiPermissionMiddleware(RequestDelegate next, IServiceProvider provider)
{ {
Next = next; Next = next;
Provider = provider;
} }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
@@ -39,17 +42,56 @@ public class ApiPermissionMiddleware
if (metadata == null) if (metadata == null)
return true; return true;
if (metadata.ControllerTypeInfo.CustomAttributes var controllerAttrInfo = metadata.ControllerTypeInfo.CustomAttributes
.All(x => x.AttributeType != typeof(ApiControllerAttribute))) .FirstOrDefault(x => x.AttributeType == typeof(ApiPermissionAttribute));
var methodAttrInfo = metadata.MethodInfo.CustomAttributes
.FirstOrDefault(x => x.AttributeType == typeof(ApiPermissionAttribute));
if (methodAttrInfo == null && controllerAttrInfo == null)
return true; return true;
var permissionAttr = if (!context.Request.Headers.TryGetValue("Authorization", out var apiKeySv))
metadata.ControllerTypeInfo.CustomAttributes.FirstOrDefault(x => return false;
x.AttributeType == typeof(ApiPermissionAttribute));
// Entity framework won't work with the StringValues type returned by the Headers.TryGetValue method
// that's why we convert that to a regular string here
var apiKey = apiKeySv.ToString();
if (string.IsNullOrEmpty(apiKey))
return false;
using var scope = Provider.CreateScope();
var apiKeyRepo = scope.ServiceProvider.GetRequiredService<Repository<ApiKey>>();
var apiKeyModel = apiKeyRepo
.Get()
.FirstOrDefault(x => x.Key == apiKey);
if (apiKeyModel == null)
return false;
if (apiKeyModel.ExpiresAt < DateTime.UtcNow)
return false;
var permissions = JsonConvert.DeserializeObject<string[]>(apiKeyModel.PermissionJson) ?? Array.Empty<string>();
if (controllerAttrInfo != null)
{
var permissionToLookFor = controllerAttrInfo.ConstructorArguments.First().Value as string;
if (permissionToLookFor != null && !permissions.Contains(permissionToLookFor))
return false;
}
if (methodAttrInfo != null)
{
var permissionToLookFor = methodAttrInfo.ConstructorArguments.First().Value as string;
if (permissionToLookFor != null && !permissions.Contains(permissionToLookFor))
return false;
}
if (permissionAttr == null)
return true; return true;
if(metadata.)
} }
} }

View File

@@ -14,5 +14,6 @@ public class CreateApiKeyForm
public DateTime ExpiresAt { get; set; } = DateTime.UtcNow; public DateTime ExpiresAt { get; set; } = DateTime.UtcNow;
[Required(ErrorMessage = "You need to specify what permissions the api key should have")] [Required(ErrorMessage = "You need to specify what permissions the api key should have")]
public string Permissions { get; set; } = "[]"; [DisplayName("Permissions")]
public string PermissionJson { get; set; } = "[]";
} }

View File

@@ -14,5 +14,6 @@ public class UpdateApiKeyForm
public DateTime ExpiresAt { get; set; } public DateTime ExpiresAt { get; set; }
[Required(ErrorMessage = "You need to specify what permissions the api key should have")] [Required(ErrorMessage = "You need to specify what permissions the api key should have")]
public string Permissions { get; set; } = "[]"; [DisplayName("Permissions")]
public string PermissionJson { get; set; } = "[]";
} }