some work (need to thing about client and server data model as next step)
This commit is contained in:
@@ -14,7 +14,7 @@ internal class LoginApi(ServerContext server) : IApiEndpoint
|
|||||||
|
|
||||||
private IResult Login(string username, [FromHeader(Name = "X-USER-PASSWORD")] string password)
|
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
|
return TypedResults.Ok(new LoginResponse
|
||||||
{
|
{
|
||||||
Secret = server.Login(account),
|
Secret = server.Login(account),
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
using OwnChar.Data;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using OwnChar.Model;
|
using OwnChar.Model;
|
||||||
using Pilz.Configuration;
|
using Pilz.Configuration;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using ILogger = Castle.Core.Logging.ILogger;
|
||||||
|
|
||||||
namespace OwnChar.ServerNew.Api;
|
namespace OwnChar.ServerNew.Api;
|
||||||
|
|
||||||
public interface IServer
|
public interface IServer
|
||||||
{
|
{
|
||||||
ISettings Settings { get; }
|
ISettings Settings { get; }
|
||||||
IDataProvider? Data { get; }
|
DbContext? Data { get; }
|
||||||
|
ILogger Log { get; }
|
||||||
|
|
||||||
[MemberNotNull(nameof(Data))]
|
[MemberNotNull(nameof(Data))]
|
||||||
void CheckLogin(string secret);
|
void CheckLogin(string secret);
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
namespace OwnChar.ServerNew.Api.Plugins;
|
|
||||||
|
|
||||||
public interface IPluginLoadContextServer
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Castle.Core" Version="5.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.7" />
|
||||||
<PackageReference Include="Pilz.Configuration" Version="3.1.2" />
|
<PackageReference Include="Pilz.Configuration" Version="3.1.2" />
|
||||||
<PackageReference Include="Pilz.Cryptography" Version="2.0.1" />
|
<PackageReference Include="Pilz.Cryptography" Version="2.0.1" />
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
using OwnChar.Data;
|
|
||||||
using OwnChar.Plugins;
|
using OwnChar.Plugins;
|
||||||
using OwnChar.ServerNew.Api.Endpoint;
|
|
||||||
using OwnChar.ServerNew.Api.Endpoint.Implementations;
|
|
||||||
using OwnChar.ServerNew.Api.Plugins;
|
using OwnChar.ServerNew.Api.Plugins;
|
||||||
using Pilz.Configuration;
|
using Pilz.Configuration;
|
||||||
using Pilz.Plugins;
|
|
||||||
using Pilz.Plugins.Advanced;
|
|
||||||
|
|
||||||
namespace OwnChar.ServerNew;
|
namespace OwnChar.ServerNew;
|
||||||
|
|
||||||
@@ -24,46 +19,18 @@ internal class Program
|
|||||||
// Create server context
|
// Create server context
|
||||||
var server = new ServerContext(SettingsManager.Instance);
|
var server = new ServerContext(SettingsManager.Instance);
|
||||||
|
|
||||||
|
// Load log
|
||||||
|
// ...
|
||||||
|
|
||||||
// Load plugins
|
// Load plugins
|
||||||
|
server.Log.Debug("Loading plugins");
|
||||||
var pluginPath = Path.Combine(AppTempFolder, "Plugins");
|
var pluginPath = Path.Combine(AppTempFolder, "Plugins");
|
||||||
Directory.CreateDirectory(pluginPath);
|
Directory.CreateDirectory(pluginPath);
|
||||||
var pluginPaths = Directory.GetDirectories(pluginPath, "*", SearchOption.TopDirectoryOnly).Select(n => Path.Combine(n, n + ".dll")).ToArray();
|
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.
|
// Start server app
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
server.Start(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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +1,107 @@
|
|||||||
using OwnChar.Data;
|
using Castle.Core.Logging;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using OwnChar.Data;
|
||||||
using OwnChar.Model;
|
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 OwnChar.ServerNew.Api.Plugins;
|
||||||
using Pilz.Configuration;
|
using Pilz.Configuration;
|
||||||
using Pilz.Cryptography;
|
using Pilz.Cryptography;
|
||||||
|
using Pilz.Plugins.Advanced;
|
||||||
|
using ILogger = Castle.Core.Logging.ILogger;
|
||||||
|
|
||||||
namespace OwnChar.ServerNew;
|
namespace OwnChar.ServerNew;
|
||||||
|
|
||||||
internal class ServerContext(ISettings settings) : IServer, IPluginLoadContextServer
|
internal class ServerContext(ISettings settings) : Api.IServer
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, UserAccount> users = [];
|
private readonly Dictionary<string, UserAccount> users = [];
|
||||||
|
|
||||||
public IDataProvider? Data { get; private set; }
|
public DbContext? Data { get; private set; }
|
||||||
|
|
||||||
public ISettings Settings { get; } = settings;
|
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)
|
public string Login(UserAccount account)
|
||||||
{
|
{
|
||||||
var secret = new UniquieID(UniquieIDGenerationMode.GenerateOnInit).ID;
|
var secret = new UniquieID(UniquieIDGenerationMode.GenerateOnInit).ID;
|
||||||
users.Add(secret, account);
|
users.Add(secret, account);
|
||||||
|
Log.DebugFormat("Logged-in out user with secret {0}", secret);
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Logout(string secret)
|
public void Logout(string secret)
|
||||||
{
|
{
|
||||||
users.Remove(secret);
|
users.Remove(secret);
|
||||||
|
Log.DebugFormat("Logged-out user with secret {0}", secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLoggedIn(string secret)
|
public bool IsLoggedIn(string secret)
|
||||||
{
|
{
|
||||||
|
Log.DebugFormat("Deleting user with secret {0}", secret);
|
||||||
return users.ContainsKey(secret);
|
return users.ContainsKey(secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckLogin(string secret)
|
public void CheckLogin(string secret)
|
||||||
{
|
{
|
||||||
|
Log.DebugFormat("Checking login for user with secret {0}", secret);
|
||||||
if (!IsLoggedIn(secret))
|
if (!IsLoggedIn(secret))
|
||||||
throw new UnauthorizedAccessException();
|
throw new UnauthorizedAccessException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserAccount? GetUser(string secret)
|
public UserAccount? GetUser(string secret)
|
||||||
{
|
{
|
||||||
|
Log.DebugFormat("Getting user with secret {0}", secret);
|
||||||
if (users.TryGetValue(secret, out UserAccount? value))
|
if (users.TryGetValue(secret, out UserAccount? value))
|
||||||
return value;
|
return value;
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
19
OwnChar.Server/ServerSettings.cs
Normal file
19
OwnChar.Server/ServerSettings.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user