begin new and last rework
This commit is contained in:
25
OwnChar.Server/Api/Endpoint/ApiBuilder.cs
Normal file
25
OwnChar.Server/Api/Endpoint/ApiBuilder.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint;
|
||||
|
||||
internal class ApiBuilder(WebApplication app) : IApiBuilder
|
||||
{
|
||||
public void Map(string method, string pattern, Delegate action)
|
||||
{
|
||||
if (method == ApiRequestMethods.Get)
|
||||
app.MapGet(pattern, action);
|
||||
else if (method == ApiRequestMethods.Post)
|
||||
app.MapPost(pattern, action);
|
||||
else if (method == ApiRequestMethods.Put)
|
||||
app.MapPut(pattern, action);
|
||||
else if (method == ApiRequestMethods.Patch)
|
||||
app.MapPatch(pattern, action);
|
||||
else if (method == ApiRequestMethods.Delete)
|
||||
app.MapDelete(pattern, action);
|
||||
else
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Map(string pattern, Delegate action)
|
||||
{
|
||||
app.Map(pattern, action);
|
||||
}
|
||||
}
|
||||
12
OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs
Normal file
12
OwnChar.Server/Api/Endpoint/ApiRequestMethods.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
namespace OwnChar.ServerNew.Api.Endpoint;
|
||||
|
||||
public static class ApiRequestMethods
|
||||
{
|
||||
public static string Get => WebRequestMethods.Http.Get;
|
||||
public static string Put => WebRequestMethods.Http.Put;
|
||||
public static string Post => WebRequestMethods.Http.Post;
|
||||
public static string Patch => "PATCH";
|
||||
public static string Delete => "DELETE";
|
||||
}
|
||||
6
OwnChar.Server/Api/Endpoint/IApiBuilder.cs
Normal file
6
OwnChar.Server/Api/Endpoint/IApiBuilder.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint;
|
||||
|
||||
public interface IApiBuilder
|
||||
{
|
||||
void Map(string path, Delegate action);
|
||||
}
|
||||
6
OwnChar.Server/Api/Endpoint/IApiEndpoint.cs
Normal file
6
OwnChar.Server/Api/Endpoint/IApiEndpoint.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint;
|
||||
|
||||
internal interface IApiEndpoint
|
||||
{
|
||||
void Initialize(IApiBuilder builder);
|
||||
}
|
||||
34
OwnChar.Server/Api/Endpoint/Implementations/CharactersApi.cs
Normal file
34
OwnChar.Server/Api/Endpoint/Implementations/CharactersApi.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint.Implementations;
|
||||
|
||||
internal class CharactersApi(IServer server) : IApiEndpoint
|
||||
{
|
||||
public void Initialize(IApiBuilder builder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private IResult GetCharacter(long characterId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult CreateGroupCharacter(string name, long groupId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult CreateUserCharacter(string name, long userId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult UpdateCharacter(long characterId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult DeleteCharacter(long characterId)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
48
OwnChar.Server/Api/Endpoint/Implementations/GroupsApi.cs
Normal file
48
OwnChar.Server/Api/Endpoint/Implementations/GroupsApi.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint.Implementations;
|
||||
|
||||
internal class GroupsApi(IServer server) : IApiEndpoint
|
||||
{
|
||||
public void Initialize(IApiBuilder builder)
|
||||
{
|
||||
}
|
||||
|
||||
private IResult GetGroups()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult GetGroups(long characterId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult GetGroup(long groupId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult CreateGroup(string name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult UpdateGroup(int groupId, string name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult DeleteGroup(int groupId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult AddMember(int groupId, long memberId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult RemoveMember(int groupId, long memberId)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
31
OwnChar.Server/Api/Endpoint/Implementations/LoginApi.cs
Normal file
31
OwnChar.Server/Api/Endpoint/Implementations/LoginApi.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OwnChar.Api.Responses;
|
||||
using OwnChar.Model;
|
||||
|
||||
namespace OwnChar.ServerNew.Api.Endpoint.Implementations;
|
||||
|
||||
internal class LoginApi(ServerContext server) : IApiEndpoint
|
||||
{
|
||||
public void Initialize(IApiBuilder builder)
|
||||
{
|
||||
builder.Map("/auth/login/{username}", Login);
|
||||
builder.Map("/auth/logout/{secret}", Logout);
|
||||
}
|
||||
|
||||
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)
|
||||
return TypedResults.Ok(new LoginResponse
|
||||
{
|
||||
Secret = server.Login(account),
|
||||
UserAccount = account,
|
||||
});
|
||||
return TypedResults.Unauthorized();
|
||||
}
|
||||
|
||||
private IResult Logout([FromHeader(Name = "X-AUTH-SECRET")] string secret)
|
||||
{
|
||||
server.Logout(secret);
|
||||
return TypedResults.Ok();
|
||||
}
|
||||
}
|
||||
44
OwnChar.Server/Api/Endpoint/Implementations/UsersApi.cs
Normal file
44
OwnChar.Server/Api/Endpoint/Implementations/UsersApi.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace OwnChar.ServerNew.Api.Endpoint.Implementations;
|
||||
|
||||
internal class UsersApi(IServer server) : IApiEndpoint
|
||||
{
|
||||
public void Initialize(IApiBuilder builder)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private IResult GetUsers()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult GetUser(long userId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult GetUserProfile(long userId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult CreateUser(string username, string password)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult DeleteUser(long userId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult UpdateUserPassword(long userId, string username, string password)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private IResult UpdateUserProfile(long profileId, string displayName)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
21
OwnChar.Server/Api/IServer.cs
Normal file
21
OwnChar.Server/Api/IServer.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using OwnChar.Data;
|
||||
using OwnChar.Model;
|
||||
using Pilz.Configuration;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace OwnChar.ServerNew.Api;
|
||||
|
||||
public interface IServer
|
||||
{
|
||||
ISettings Settings { get; }
|
||||
IDataProvider? Data { get; }
|
||||
|
||||
[MemberNotNull(nameof(Data))]
|
||||
void CheckLogin(string secret);
|
||||
|
||||
[MemberNotNullWhen(true, nameof(Data))]
|
||||
bool IsLoggedIn(string secret);
|
||||
|
||||
[MemberNotNullWhen(true, nameof(Data))]
|
||||
UserAccount? GetUser(string secret);
|
||||
}
|
||||
11
OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs
Normal file
11
OwnChar.Server/Api/Plugins/ApiEndpointFeature.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using OwnChar.ServerNew.Api.Endpoint;
|
||||
using Pilz.Plugins.Advanced;
|
||||
|
||||
namespace OwnChar.ServerNew.Api.Plugins;
|
||||
|
||||
public abstract class ApiEndpointFeature(string identifier) : PluginFeature(FeatureType, identifier), IApiEndpoint
|
||||
{
|
||||
public static string FeatureType => "ownchar.server.apiep";
|
||||
|
||||
public abstract void Initialize(IApiBuilder builder);
|
||||
}
|
||||
5
OwnChar.Server/Api/Plugins/IPluginLoadContextServer.cs
Normal file
5
OwnChar.Server/Api/Plugins/IPluginLoadContextServer.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace OwnChar.ServerNew.Api.Plugins;
|
||||
|
||||
public interface IPluginLoadContextServer
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using OwnChar.Plugins;
|
||||
|
||||
namespace OwnChar.ServerNew.Api.Plugins;
|
||||
|
||||
public class OwnCharServerPluginInitParams(IServer server) : OwnCharPluginInitParams
|
||||
{
|
||||
public IServer Server { get; } = server;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Pilz.Plugins.Advanced;
|
||||
|
||||
namespace OwnChar.Server.Commands
|
||||
{
|
||||
public class CmdSave() : PluginFunction(IServerCommand.FeatureCode, "ownchar.save"), IPluginFeatureProvider<CmdSave>, IServerCommand
|
||||
{
|
||||
public static CmdSave Instance { get; } = new();
|
||||
|
||||
public string Command => "save";
|
||||
public string Description => "Saves the current state to disk.";
|
||||
|
||||
protected override object? ExecuteFunction(PluginFunctionParameter? @params)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Pilz.Plugins.Advanced;
|
||||
|
||||
namespace OwnChar.Server.Commands
|
||||
{
|
||||
public interface IServerCommand
|
||||
{
|
||||
// Shared
|
||||
public const string FeatureCode = "ownchar.server.command";
|
||||
public IEnumerable<IServerCommand> Commands => PluginFeatureController.Instance.Features.Get(FeatureCode).Cast<PluginFunction>().Select(f => (IServerCommand)f.Execute()!);
|
||||
|
||||
// Interface
|
||||
public string Command { get; }
|
||||
public string Description { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Pilz.Plugins.Advanced;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OwnChar.Server.Data
|
||||
{
|
||||
public class ClientServerDataProvider() : PluginFunction(IServerDataProvider.FeatureCode, "ownchar.clientserver"), IServerDataProvider
|
||||
{
|
||||
protected override object? ExecuteFunction(PluginFunctionParameter? @params)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Pilz.Plugins.Advanced;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OwnChar.Server.Data
|
||||
{
|
||||
public interface IServerDataProvider
|
||||
{
|
||||
// Shared
|
||||
public const string FeatureCode = "ownchar.server.dataprovider";
|
||||
public IEnumerable<IServerDataProvider> DataProviders => PluginFeatureController.Instance.Features.Get(FeatureCode).Cast<PluginFunction>().Select(f => (IServerDataProvider)f.Execute()!);
|
||||
|
||||
// Interface
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OwnChar.Server.Network
|
||||
{
|
||||
public class NetworkHandler
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OwnChar.Server.Network
|
||||
{
|
||||
public class NetworkManager
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Pilz.Plugins" Version="2.1.5" />
|
||||
<PackageReference Include="Pilz.Plugins.Advanced" Version="2.7.3" />
|
||||
<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" />
|
||||
<PackageReference Include="Pilz.Plugins" Version="2.1.9" />
|
||||
<PackageReference Include="Pilz.Plugins.Advanced" Version="2.10.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OwnChar.Plugins\OwnChar.Plugins\OwnChar.Plugins.csproj" />
|
||||
<ProjectReference Include="..\OwnChar\OwnChar\OwnChar.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
6
OwnChar.Server/OwnChar.Server.http
Normal file
6
OwnChar.Server/OwnChar.Server.http
Normal file
@@ -0,0 +1,6 @@
|
||||
@OwnChar.ServerNew_HostAddress = http://localhost:5208
|
||||
|
||||
GET {{OwnChar.ServerNew_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -1,10 +1,69 @@
|
||||
namespace OwnChar.Server
|
||||
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;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
internal class Program
|
||||
public static string? AppTempFolder { get; private set; }
|
||||
public static ISettingsManager? SettingsManager { get; private set; }
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
static void Main(string[] args)
|
||||
// Load settings
|
||||
AppTempFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "OwnChar", "Server");
|
||||
Directory.CreateDirectory(AppTempFolder);
|
||||
SettingsManager = new SettingsManager(Path.Combine(AppTempFolder, "Settings.json"), true);
|
||||
|
||||
// Create server context
|
||||
var server = new ServerContext(SettingsManager.Instance);
|
||||
|
||||
// Load 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));
|
||||
|
||||
// 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())
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
41
OwnChar.Server/Properties/launchSettings.json
Normal file
41
OwnChar.Server/Properties/launchSettings.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:48428",
|
||||
"sslPort": 44302
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5208",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7174;http://localhost:5208",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
OwnChar.Server/ServerContext.cs
Normal file
47
OwnChar.Server/ServerContext.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using OwnChar.Data;
|
||||
using OwnChar.Model;
|
||||
using OwnChar.ServerNew.Api;
|
||||
using OwnChar.ServerNew.Api.Plugins;
|
||||
using Pilz.Configuration;
|
||||
using Pilz.Cryptography;
|
||||
|
||||
namespace OwnChar.ServerNew;
|
||||
|
||||
internal class ServerContext(ISettings settings) : IServer, IPluginLoadContextServer
|
||||
{
|
||||
private readonly Dictionary<string, UserAccount> users = [];
|
||||
|
||||
public IDataProvider? Data { get; private set; }
|
||||
|
||||
public ISettings Settings { get; } = settings;
|
||||
|
||||
public string Login(UserAccount account)
|
||||
{
|
||||
var secret = new UniquieID(UniquieIDGenerationMode.GenerateOnInit).ID;
|
||||
users.Add(secret, account);
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void Logout(string secret)
|
||||
{
|
||||
users.Remove(secret);
|
||||
}
|
||||
|
||||
public bool IsLoggedIn(string secret)
|
||||
{
|
||||
return users.ContainsKey(secret);
|
||||
}
|
||||
|
||||
public void CheckLogin(string secret)
|
||||
{
|
||||
if (!IsLoggedIn(secret))
|
||||
throw new UnauthorizedAccessException();
|
||||
}
|
||||
|
||||
public UserAccount? GetUser(string secret)
|
||||
{
|
||||
if (users.TryGetValue(secret, out UserAccount? value))
|
||||
return value;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
8
OwnChar.Server/appsettings.Development.json
Normal file
8
OwnChar.Server/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
OwnChar.Server/appsettings.json
Normal file
9
OwnChar.Server/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Reference in New Issue
Block a user