diff --git a/.gitignore b/.gitignore index add57be..9a682c8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,3 @@ bin/ obj/ /packages/ riderModule.iml -/_ReSharper.Caches/ \ No newline at end of file diff --git a/DatabaseTest/.gitignore b/DatabaseTest/.gitignore index 15d40be..ab7b4dc 100644 --- a/DatabaseTest/.gitignore +++ b/DatabaseTest/.gitignore @@ -2,4 +2,3 @@ bin Migrations appsettings.Development.json -test.db diff --git a/DatabaseTest/Controllers/TestController.cs b/DatabaseTest/Controllers/TestController.cs index 148829b..1b78deb 100644 --- a/DatabaseTest/Controllers/TestController.cs +++ b/DatabaseTest/Controllers/TestController.cs @@ -1,4 +1,3 @@ -using HopFrame.Api.Controller; using HopFrame.Security.Authorization; using HopFrame.Security.Claims; using Microsoft.AspNetCore.Mvc; @@ -6,7 +5,8 @@ using Microsoft.AspNetCore.Mvc; namespace DatabaseTest.Controllers; [ApiController] -public class TestController(DatabaseContext context, ITokenContext userContext) : SecurityController(context) { +[Route("test")] +public class TestController(ITokenContext userContext) : ControllerBase { [HttpGet("permissions"), Authorized] public ActionResult> Permissions() { diff --git a/DatabaseTest/DatabaseContext.cs b/DatabaseTest/DatabaseContext.cs index e386a1b..c43f7e8 100644 --- a/DatabaseTest/DatabaseContext.cs +++ b/DatabaseTest/DatabaseContext.cs @@ -7,6 +7,6 @@ public class DatabaseContext : HopDbContextBase { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); - optionsBuilder.UseSqlite("Data Source=C:\\Users\\Remote\\Documents\\Projekte\\HopFrame\\DatabaseTest\\test.db;Mode=ReadWrite;"); + optionsBuilder.UseSqlite("Data Source=C:\\Users\\Remote\\Documents\\Projekte\\HopFrame\\DatabaseTest\\bin\\Debug\\net8.0\\test.db;Mode=ReadWrite;"); } } \ No newline at end of file diff --git a/DatabaseTest/Program.cs b/DatabaseTest/Program.cs index 8cc3933..845e92a 100644 --- a/DatabaseTest/Program.cs +++ b/DatabaseTest/Program.cs @@ -1,22 +1,18 @@ using DatabaseTest; -using HopFrame.Api; -using HopFrame.Api.Controller; -using HopFrame.Security.Authentication; +using HopFrame.Api.Extensions; using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. -builder.Services.AddControllers() - .AddController>(); +builder.Services.AddControllers(); +builder.Services.AddHopFrame(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddDbContext(); -builder.Services.AddHopFrameAuthentication(); -//builder.Logging.AddFilter>(options => options == LogLevel.None); builder.Services.AddSwaggerGen(c => { c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { @@ -51,7 +47,7 @@ if (app.Environment.IsDevelopment()) { app.UseSwaggerUI(); } -//app.UseHttpsRedirection(); +app.UseHttpsRedirection(); app.UseAuthorization(); diff --git a/DatabaseTest/test.db b/DatabaseTest/test.db deleted file mode 100644 index 37ca2d0..0000000 Binary files a/DatabaseTest/test.db and /dev/null differ diff --git a/HopFrame.Api/ControllerExtensions.cs b/HopFrame.Api/ControllerExtensions.cs deleted file mode 100644 index dedead8..0000000 --- a/HopFrame.Api/ControllerExtensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; - -namespace HopFrame.Api; - -public static class ControllerExtensions { - - public static IMvcBuilder AddController(this IMvcBuilder builder) where TController : ControllerBase { - //TODO: Change implementation method - return builder.AddApplicationPart(typeof(TController).Assembly); - } - -} \ No newline at end of file diff --git a/HopFrame.Api/Extensions/MvcExtensions.cs b/HopFrame.Api/Extensions/MvcExtensions.cs new file mode 100644 index 0000000..d176de7 --- /dev/null +++ b/HopFrame.Api/Extensions/MvcExtensions.cs @@ -0,0 +1,86 @@ +//Source: https://gist.github.com/damianh/5d69be0e3004024f03b6cc876d7b0bd3 + +using System.Reflection; +using Microsoft.AspNetCore.Mvc.ApplicationParts; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.Extensions.DependencyInjection; +using IMvcCoreBuilder = Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder; + +namespace HopFrame.Api.Extensions; + +public static class MvcExtensions { + /// + /// Finds the appropriate controllers + /// + /// The manager for the parts + /// The controller types that are allowed. + public static void UseSpecificControllers(this ApplicationPartManager partManager, params Type[] controllerTypes) { + partManager.FeatureProviders.Add(new InternalControllerFeatureProvider()); + //partManager.ApplicationParts.Clear(); + partManager.ApplicationParts.Add(new SelectedControllersApplicationParts(controllerTypes)); + } + + /// + /// Only allow selected controllers + /// + /// The builder that configures mvc core + /// The controller types that are allowed. + public static IMvcCoreBuilder + UseSpecificControllers(this IMvcCoreBuilder mvcCoreBuilder, params Type[] controllerTypes) => + mvcCoreBuilder.ConfigureApplicationPartManager(partManager => + partManager.UseSpecificControllers(controllerTypes)); + + /// + /// Only instantiates selected controllers, not all of them. Prevents application scanning for controllers. + /// + private class SelectedControllersApplicationParts : ApplicationPart, IApplicationPartTypeProvider { + public SelectedControllersApplicationParts() { + Name = "Only allow selected controllers"; + } + + public SelectedControllersApplicationParts(Type[] types) { + Types = types.Select(x => x.GetTypeInfo()).ToArray(); + } + + public override string Name { get; } + + public IEnumerable Types { get; } + } + + /// + /// Ensure that internal controllers are also allowed. The default ControllerFeatureProvider hides internal controllers, but this one allows it. + /// + private class InternalControllerFeatureProvider : ControllerFeatureProvider { + private const string ControllerTypeNameSuffix = "Controller"; + + /// + /// Determines if a given is a controller. The default ControllerFeatureProvider hides internal controllers, but this one allows it. + /// + /// The candidate. + /// true if the type is a controller; otherwise false. + protected override bool IsController(TypeInfo typeInfo) { + if (!typeInfo.IsClass) { + return false; + } + + if (typeInfo.IsAbstract) { + return false; + } + + if (typeInfo.ContainsGenericParameters) { + return false; + } + + if (typeInfo.IsDefined(typeof(Microsoft.AspNetCore.Mvc.NonControllerAttribute))) { + return false; + } + + if (!typeInfo.Name.EndsWith(ControllerTypeNameSuffix, StringComparison.OrdinalIgnoreCase) && + !typeInfo.IsDefined(typeof(Microsoft.AspNetCore.Mvc.ControllerAttribute))) { + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/HopFrame.Api/Extensions/ServiceCollectionExtensions.cs b/HopFrame.Api/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..6d0e3d2 --- /dev/null +++ b/HopFrame.Api/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,15 @@ +using HopFrame.Api.Controller; +using HopFrame.Database; +using HopFrame.Security.Authentication; +using Microsoft.Extensions.DependencyInjection; + +namespace HopFrame.Api.Extensions; + +public static class ServiceCollectionExtensions { + + public static void AddHopFrame(this IServiceCollection services) where TDbContext : HopDbContextBase { + services.AddMvcCore().UseSpecificControllers(typeof(SecurityController)); + services.AddHopFrameAuthentication(); + } + +}