Added Rule and Route system
This commit is contained in:
		
							
								
								
									
										6
									
								
								VirtualDDNSRouter.Server/Interfaces/IYamlParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								VirtualDDNSRouter.Server/Interfaces/IYamlParser.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
namespace VirtualDDNSRouter.Server.Interfaces;
 | 
			
		||||
 | 
			
		||||
public interface IYamlParser
 | 
			
		||||
{
 | 
			
		||||
    Task<List<Models.Rule>> GetRules();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								VirtualDDNSRouter.Server/Models/Rule.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								VirtualDDNSRouter.Server/Models/Rule.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
using System.Net;
 | 
			
		||||
using YamlDotNet.Serialization;
 | 
			
		||||
 | 
			
		||||
namespace VirtualDDNSRouter.Server.Models;
 | 
			
		||||
 | 
			
		||||
public record Rule
 | 
			
		||||
{
 | 
			
		||||
    public string name { get; init; } = string.Empty;
 | 
			
		||||
    public string apiKey { get; init; } = string.Empty;
 | 
			
		||||
    public string path { get; init; } = string.Empty;
 | 
			
		||||
 | 
			
		||||
    public Rule() { } // Needed for AOT static deserializer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public record Route
 | 
			
		||||
{
 | 
			
		||||
    public string path { get; set; } = string.Empty;
 | 
			
		||||
    public IPAddress ipAddress { get; set; } = IPAddress.None;
 | 
			
		||||
 | 
			
		||||
    public UInt16 port { get; set; } = 80;
 | 
			
		||||
 | 
			
		||||
    public Route() { }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,10 @@
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
using Microsoft.AspNetCore.Http.HttpResults;
 | 
			
		||||
using VirtualDDNSRouter.Server.Interfaces;
 | 
			
		||||
using VirtualDDNSRouter.Server.Models;
 | 
			
		||||
using VirtualDDNSRouter.Server.Services;
 | 
			
		||||
using Route = VirtualDDNSRouter.Server.Models.Route;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var builder = WebApplication.CreateSlimBuilder(args);
 | 
			
		||||
 | 
			
		||||
@@ -8,6 +13,8 @@ builder.Services.ConfigureHttpJsonOptions(options =>
 | 
			
		||||
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
builder.Services.AddSingleton<IYamlParser, YamlParser>();
 | 
			
		||||
 | 
			
		||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
 | 
			
		||||
builder.Services.AddOpenApi();
 | 
			
		||||
 | 
			
		||||
@@ -18,12 +25,42 @@ if (app.Environment.IsDevelopment())
 | 
			
		||||
    app.MapOpenApi();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
List<Route> routes = new List<Route>();
 | 
			
		||||
 | 
			
		||||
app.MapPut("/setip/{path}/{port}/{apiKey}", async (IYamlParser yamlParser ,HttpContext context, string path, UInt16 port, string apiKey) =>
 | 
			
		||||
{
 | 
			
		||||
    var rules = await yamlParser.GetRules();
 | 
			
		||||
    var ruleValid = rules.Any(r => r.path == path && r.apiKey == apiKey);
 | 
			
		||||
    if (!ruleValid)
 | 
			
		||||
    {
 | 
			
		||||
        return Results.StatusCode(StatusCodes.Status403Forbidden);
 | 
			
		||||
    }
 | 
			
		||||
    var clientIp = context.Connection.RemoteIpAddress;
 | 
			
		||||
    if (clientIp is null) return Results.BadRequest("Could not get the client ip address");
 | 
			
		||||
    routes.Add(new Route
 | 
			
		||||
    {
 | 
			
		||||
        ipAddress = clientIp,
 | 
			
		||||
        path = path,
 | 
			
		||||
        port = port
 | 
			
		||||
    });
 | 
			
		||||
    return Results.Created();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.MapGet("/goto/{path}", async (string path) =>
 | 
			
		||||
{
 | 
			
		||||
    var ruleExists = routes.Any(r => r.path == path);
 | 
			
		||||
    if (!ruleExists) Results.NoContent();
 | 
			
		||||
    var redirectRoute = routes.FirstOrDefault(r => r.path == path);
 | 
			
		||||
    return Results.Redirect($"http://{redirectRoute.ipAddress}:{redirectRoute.port}");
 | 
			
		||||
    
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.Run();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[JsonSerializable(typeof(Object))]
 | 
			
		||||
 | 
			
		||||
//[JsonSerializable(typeof(Rule))]
 | 
			
		||||
[JsonSerializable(typeof(Route))]
 | 
			
		||||
internal partial class AppJsonSerializerContext : JsonSerializerContext
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								VirtualDDNSRouter.Server/Services/YamlParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								VirtualDDNSRouter.Server/Services/YamlParser.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using VirtualDDNSRouter.Server.Interfaces;
 | 
			
		||||
using VirtualDDNSRouter.Server.Models;
 | 
			
		||||
using YamlDotNet.Serialization;
 | 
			
		||||
using YamlDotNet.Serialization.NamingConventions;
 | 
			
		||||
 | 
			
		||||
namespace VirtualDDNSRouter.Server.Services;
 | 
			
		||||
 | 
			
		||||
public class YamlParser : IYamlParser
 | 
			
		||||
{
 | 
			
		||||
    private readonly string _yamlFilePath = "rules.yaml";
 | 
			
		||||
 | 
			
		||||
    public async Task<List<Rule>> GetRules()
 | 
			
		||||
    {
 | 
			
		||||
        if (!File.Exists(_yamlFilePath))
 | 
			
		||||
            throw new FileNotFoundException($"YAML file not found: {_yamlFilePath}");
 | 
			
		||||
 | 
			
		||||
        var yamlContent = await File.ReadAllTextAsync(_yamlFilePath).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        // Build the deserializer with explicit naming convention
 | 
			
		||||
        var deserializer = new DeserializerBuilder()
 | 
			
		||||
            .WithNamingConvention(UnderscoredNamingConvention.Instance) // maps api_key -> apiKey
 | 
			
		||||
            .IgnoreUnmatchedProperties()
 | 
			
		||||
            .Build();
 | 
			
		||||
 | 
			
		||||
        // Deserialize into a list of Rule
 | 
			
		||||
        var rules = deserializer.Deserialize<List<Rule>>(yamlContent);
 | 
			
		||||
 | 
			
		||||
        return rules ?? new List<Rule>();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,6 +12,7 @@
 | 
			
		||||
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.6.25358.103"/>
 | 
			
		||||
        <PackageReference Include="Vecc.YamlDotNet.Analyzers.StaticGenerator" Version="16.3.0" />
 | 
			
		||||
        <PackageReference Include="YamlDotNet" Version="16.3.0" />
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								VirtualDDNSRouter.Server/rules.example.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								VirtualDDNSRouter.Server/rules.example.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
Rules:
 | 
			
		||||
  - Name: "B"
 | 
			
		||||
    ApiKey: "abc123XYZ"
 | 
			
		||||
    Route: "B"
 | 
			
		||||
 | 
			
		||||
  - Name: "A"
 | 
			
		||||
    ApiKey: "def456ABC"
 | 
			
		||||
    Route: "A"
 | 
			
		||||
		Reference in New Issue
	
	Block a user