some work (need to thing about client and server data model as next step)

This commit is contained in:
2024-07-18 16:42:35 +02:00
parent ee2d734d33
commit ecbb3c0ab7
7 changed files with 99 additions and 53 deletions

View File

@@ -14,7 +14,7 @@ internal class LoginApi(ServerContext server) : IApiEndpoint
private IResult Login(string username, [FromHeader(Name = "X-USER-PASSWORD")] string password)
{
if (server.Data != null && server.Data.GetAll<UserAccount>()?.FirstOrDefault(n => n.Username == username && n.Password == password) is UserAccount account)
if (server.Data != null && server.Data.Set<UserAccount>()?.FirstOrDefault(n => n.Username == username && n.Password == password) is UserAccount account)
return TypedResults.Ok(new LoginResponse
{
Secret = server.Login(account),

View File

@@ -1,14 +1,16 @@
using OwnChar.Data;
using Microsoft.EntityFrameworkCore;
using OwnChar.Model;
using Pilz.Configuration;
using System.Diagnostics.CodeAnalysis;
using ILogger = Castle.Core.Logging.ILogger;
namespace OwnChar.ServerNew.Api;
public interface IServer
{
ISettings Settings { get; }
IDataProvider? Data { get; }
DbContext? Data { get; }
ILogger Log { get; }
[MemberNotNull(nameof(Data))]
void CheckLogin(string secret);

View File

@@ -1,5 +0,0 @@
namespace OwnChar.ServerNew.Api.Plugins;
public interface IPluginLoadContextServer
{
}

View File

@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Castle.Core" Version="5.1.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
<PackageReference Include="Pilz.Configuration" Version="3.1.2" />
<PackageReference Include="Pilz.Cryptography" Version="2.0.1" />

View File

@@ -1,11 +1,6 @@
using OwnChar.Data;
using OwnChar.Plugins;
using OwnChar.ServerNew.Api.Endpoint;
using OwnChar.ServerNew.Api.Endpoint.Implementations;
using OwnChar.ServerNew.Api.Plugins;
using Pilz.Configuration;
using Pilz.Plugins;
using Pilz.Plugins.Advanced;
namespace OwnChar.ServerNew;
@@ -24,46 +19,18 @@ internal class Program
// Create server context
var server = new ServerContext(SettingsManager.Instance);
// Load log
// ...
// Load plugins
server.Log.Debug("Loading plugins");
var pluginPath = Path.Combine(AppTempFolder, "Plugins");
Directory.CreateDirectory(pluginPath);
var pluginPaths = Directory.GetDirectories(pluginPath, "*", SearchOption.TopDirectoryOnly).Select(n => Path.Combine(n, n + ".dll")).ToArray();
OwnCharPlugins.Instance.LoadPlugins(pluginPaths, new OwnCharServerPluginInitParams(server));
var plugins = OwnCharPlugins.Instance.LoadPlugins(pluginPaths, new OwnCharServerPluginInitParams(server));
server.Log.InfoFormat("{0} plugins loaded", plugins.Count());
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Build app
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
// Built-in endpoints
var apibuilder = new ApiBuilder(app);
new LoginApi(server).Initialize(apibuilder);
new UsersApi(server).Initialize(apibuilder);
new GroupsApi(server).Initialize(apibuilder);
new CharactersApi(server).Initialize(apibuilder);
// Plugin endpoints
var endpoints = PluginFeatureController.Instance.Features.Get(ApiEndpointFeature.FeatureType).OfType<IApiEndpoint>();
if (endpoints.Any())
{
foreach (var endpoint in endpoints)
endpoint.Initialize(apibuilder);
}
// Run server
app.Run();
// Start server app
server.Start(args);
}
}

View File

@@ -1,45 +1,107 @@
using OwnChar.Data;
using Castle.Core.Logging;
using Microsoft.EntityFrameworkCore;
using OwnChar.Data;
using OwnChar.Model;
using OwnChar.ServerNew.Api;
using OwnChar.Server;
using OwnChar.ServerNew.Api.Endpoint;
using OwnChar.ServerNew.Api.Endpoint.Implementations;
using OwnChar.ServerNew.Api.Plugins;
using Pilz.Configuration;
using Pilz.Cryptography;
using Pilz.Plugins.Advanced;
using ILogger = Castle.Core.Logging.ILogger;
namespace OwnChar.ServerNew;
internal class ServerContext(ISettings settings) : IServer, IPluginLoadContextServer
internal class ServerContext(ISettings settings) : Api.IServer
{
private readonly Dictionary<string, UserAccount> users = [];
public IDataProvider? Data { get; private set; }
public DbContext? Data { get; private set; }
public ISettings Settings { get; } = settings;
public ILogger Log { get; set; } = NullLogger.Instance;
public void Start(string[] args)
{
Log.Info("Prepairing server context");
// Add services to the container.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Build app
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
// Load database
Log.Debug("Loading database");
var settings = Settings.Get<ServerSettings>();
Data = new DatabaseContext(settings.DbServer, settings.DbUser, settings.DbPassword);
// Built-in endpoints
Log.Debug("Loading internal api endpoints");
var apibuilder = new ApiBuilder(app);
new LoginApi(this).Initialize(apibuilder);
new UsersApi(this).Initialize(apibuilder);
new GroupsApi(this).Initialize(apibuilder);
new CharactersApi(this).Initialize(apibuilder);
// Plugin endpoints
Log.Debug("Loading plugin api endpoints");
var endpoints = PluginFeatureController.Instance.Features.Get(ApiEndpointFeature.FeatureType).OfType<IApiEndpoint>();
if (endpoints.Any())
{
foreach (var endpoint in endpoints)
endpoint.Initialize(apibuilder);
}
// Run server
Log.Info("Starting webserver");
app.Run();
}
public string Login(UserAccount account)
{
var secret = new UniquieID(UniquieIDGenerationMode.GenerateOnInit).ID;
users.Add(secret, account);
Log.DebugFormat("Logged-in out user with secret {0}", secret);
return secret;
}
public void Logout(string secret)
{
users.Remove(secret);
Log.DebugFormat("Logged-out user with secret {0}", secret);
}
public bool IsLoggedIn(string secret)
{
Log.DebugFormat("Deleting user with secret {0}", secret);
return users.ContainsKey(secret);
}
public void CheckLogin(string secret)
{
Log.DebugFormat("Checking login for user with secret {0}", secret);
if (!IsLoggedIn(secret))
throw new UnauthorizedAccessException();
}
public UserAccount? GetUser(string secret)
{
Log.DebugFormat("Getting user with secret {0}", secret);
if (users.TryGetValue(secret, out UserAccount? value))
return value;
return null;

View File

@@ -0,0 +1,19 @@
using Pilz.Configuration;
namespace OwnChar.Server;
public class ServerSettings : IChildSettings, ISettingsIdentifier
{
public static string Identifier => "ownchar.server.data.sql";
public string? DbServer { get; set; }
public string? DbUser { get; set; }
public string? DbPassword { get; set; }
public void Reset()
{
DbServer = null;
DbUser = null;
DbPassword = null;
}
}