feat: error class, world checking middleware

This commit is contained in:
CyberL1 2024-06-10 14:22:26 +02:00
parent 4a27cc028e
commit 26fa8813dd
13 changed files with 118 additions and 41 deletions

View File

@ -0,0 +1,13 @@
using Minecraft_Realms_Emulator.Entities;
namespace Minecraft_Realms_Emulator.Attributes
{
[AttributeUsage(AttributeTargets.Method)]
public class CheckForWorldAttribute : Attribute
{
public bool WorldExists(World world)
{
return world != null;
}
}
}

View File

@ -27,9 +27,10 @@ namespace Minecraft_Realms_Emulator.Controllers.Admin
}
[HttpGet("{wId}")]
[CheckForWorld]
public ActionResult<World> GetWorld(int wId) {
var world = _context.Worlds.ToList().Find(w => w.Id == wId);
return Ok(world);
}
@ -59,12 +60,10 @@ namespace Minecraft_Realms_Emulator.Controllers.Admin
}
[HttpPut("{wId}/open")]
[CheckForWorld]
public ActionResult<bool> OpenServer(int wId)
{
var world = _context.Worlds.ToList().Find(w => w.Id == wId);
if (world == null) return BadRequest("World not found");
world.State = "OPEN";
_context.SaveChanges();
@ -74,12 +73,11 @@ namespace Minecraft_Realms_Emulator.Controllers.Admin
}
[HttpPut("{wId}/close")]
[CheckForWorld]
public ActionResult<bool> CloseServer(int wId)
{
var world = _context.Worlds.ToList().Find(w => w.Id == wId);
if (world == null) return BadRequest("World not found");
world.State = "CLOSED";
_context.SaveChanges();

View File

@ -0,0 +1,41 @@
using Minecraft_Realms_Emulator.Attributes;
using Minecraft_Realms_Emulator.Data;
using Minecraft_Realms_Emulator.Entities;
using Minecraft_Realms_Emulator.Responses;
namespace Minecraft_Realms_Emulator.Middlewares
{
public class CheckForWorldMiddleware(RequestDelegate next)
{
private readonly RequestDelegate _next = next;
public async Task Invoke(HttpContext httpContext, DataContext db)
{
var endpoint = httpContext.GetEndpoint();
var attribute = endpoint?.Metadata.GetMetadata<CheckForWorldAttribute>();
if (attribute == null)
{
await _next(httpContext);
return;
}
World world = db.Worlds.FirstOrDefault(w => w.Id == int.Parse(httpContext.Request.RouteValues["wId"].ToString()));
if (!attribute.WorldExists(world))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 404,
ErrorMsg = "World not found"
};
httpContext.Response.StatusCode = 404;
await httpContext.Response.WriteAsJsonAsync(errorResponse);
return;
}
await _next(httpContext);
}
}
}

View File

@ -94,6 +94,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<World>> InvitePlayer(int wId, PlayerRequest body)
{
@ -104,8 +105,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = await _context.Worlds.Include(w => w.Players).FirstOrDefaultAsync(w => w.Id == wId);
if (world == null) return NotFound("World not found");
// Get player UUID
var playerInfo = await new HttpClient().GetFromJsonAsync<MinecraftPlayerInfo>($"https://api.mojang.com/users/profiles/minecraft/{body.Name}");
@ -138,13 +137,12 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpDelete("{wId}/invite/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<bool>> DeleteInvite(int wId, string uuid)
{
var world = await _context.Worlds.FirstOrDefaultAsync(w => w.Id == wId);
if (world == null) return NotFound("World not found");
var player = _context.Players.Where(p => p.World.Id == wId).FirstOrDefault(p => p.Uuid == uuid);
_context.Players.Remove(player);
@ -159,6 +157,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpDelete("{wId}")]
[CheckForWorld]
public async Task<ActionResult<bool>> LeaveWorld(int wId)
{
string cookie = Request.Headers.Cookie;
@ -166,8 +165,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = await _context.Worlds.FirstOrDefaultAsync(w => w.Id == wId);
if (world == null) return NotFound("World not found");
var player = _context.Players.Where(p => p.World.Id == wId).FirstOrDefault(p => p.Uuid == playerUUID);
_context.Players.Remove(player);

View File

@ -18,6 +18,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<OpsResponse> OpPlayer(int wId, string uuid)
{
@ -47,6 +48,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpDelete("{wId}/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<OpsResponse> DeopPlayer(int wId, string uuid)
{

View File

@ -18,6 +18,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
_context = context;
}
[HttpGet("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<SubscriptionResponse>> Get(int wId)
{

View File

@ -141,6 +141,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpGet("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<WorldResponse>> GetWorldById(int wId)
{
@ -149,8 +150,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = await _context.Worlds.Include(w => w.Players).Include(w => w.Subscription).Include(w => w.Slots).FirstOrDefaultAsync(w => w.Id == wId);
if (world?.Subscription == null) return NotFound("World not found");
Slot activeSlot = world.Slots.Find(s => s.SlotId == world.ActiveSlot);
List<SlotResponse> slots = [];
@ -211,6 +210,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}/initialize")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<World>> Initialize(int wId, WorldCreateRequest body)
{
@ -221,8 +221,16 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = worlds.Find(w => w.Id == wId);
if (world == null) return NotFound("World not found");
if (world.State != nameof(StateEnum.UNINITIALIZED)) return NotFound("World already initialized");
if (world.State != nameof(StateEnum.UNINITIALIZED))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 401,
ErrorMsg = "World already initialized",
};
return StatusCode(401, errorResponse);
}
var subscription = new Subscription
{
@ -273,6 +281,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}/reset")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<bool> Reset(int wId)
{
@ -281,6 +290,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPut("{wId}/open")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<bool>> Open(int wId)
{
@ -288,8 +298,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = worlds.Find(w => w.Id == wId);
if (world == null) return NotFound("World not found");
world.State = nameof(StateEnum.OPEN);
_context.SaveChanges();
@ -298,6 +306,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPut("{wId}/close")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<bool>> Close(int wId)
{
@ -305,8 +314,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = worlds.FirstOrDefault(w => w.Id == wId);
if (world == null) return NotFound("World not found");
world.State = nameof(StateEnum.CLOSED);
_context.SaveChanges();
@ -315,6 +322,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<bool>> UpdateWorld(int wId, WorldCreateRequest body)
{
@ -322,8 +330,6 @@ namespace Minecraft_Realms_Emulator.Modes.External
var world = worlds.Find(w => w.Id == wId);
if (world == null) return NotFound("World not found");
world.Name = body.Name;
world.Motd = body.Description;
@ -333,6 +339,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPost("{wId}/slot/{sId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<bool>> UpdateSlotAsync(int wId, int sId, SlotOptionsRequest body)
{
@ -356,13 +363,12 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpPut("{wId}/slot/{sId}")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<bool> SwitchSlot(int wId, int sId)
{
var world = _context.Worlds.Find(wId);
if (world == null) return NotFound("World not found");
var slot = _context.Slots.Where(s => s.World.Id == wId).Where(s => s.SlotId == sId).Any();
if (!slot)
@ -397,6 +403,7 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpGet("{wId}/backups")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<BackupsResponse>> GetBackups(int wId)
{
@ -419,13 +426,12 @@ namespace Minecraft_Realms_Emulator.Modes.External
}
[HttpDelete("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<bool> DeleteRealm(int wId)
{
var world = _context.Worlds.Find(wId);
if (world == null) return NotFound("World not found");
_context.Worlds.Remove(world);
_context.SaveChanges();

View File

@ -94,6 +94,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<World>> InvitePlayer(int wId, PlayerRequest body)
@ -139,6 +140,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpDelete("{wId}/invite/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<bool>> DeleteInvite(int wId, string uuid)
@ -161,6 +163,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpDelete("{wId}")]
[CheckForWorld]
public async Task<ActionResult<bool>> LeaveWorld(int wId)
{
string cookie = Request.Headers.Cookie;

View File

@ -18,6 +18,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public ActionResult<OpsResponse> OpPlayer(int wId, string uuid)
@ -48,6 +49,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpDelete("{wId}/{uuid}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public ActionResult<OpsResponse> DeopPlayer(int wId, string uuid)

View File

@ -18,6 +18,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
_context = context;
}
[HttpGet("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<SubscriptionResponse>> Get(int wId)
{

View File

@ -144,6 +144,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpGet("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<WorldResponse>> GetWorldById(int wId)
{
@ -152,8 +153,6 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
var world = await _context.Worlds.Include(w => w.Players).Include(w => w.Subscription).Include(w => w.Slots).FirstOrDefaultAsync(w => w.Id == wId);
if (world?.Subscription == null) return NotFound("World not found");
Slot activeSlot = world.Slots.Find(s => s.SlotId == world.ActiveSlot);
List<SlotResponse> slots = [];
@ -214,6 +213,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}/initialize")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<World>> Initialize(int wId, WorldCreateRequest body)
{
@ -223,9 +223,16 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
var worlds = await _context.Worlds.ToListAsync();
var world = worlds.Find(w => w.Id == wId);
if (world.State != nameof(StateEnum.UNINITIALIZED))
{
ErrorResponse errorResponse = new()
{
ErrorCode = 401,
ErrorMsg = "World already initialized",
};
if (world == null) return NotFound("World not found");
if (world.State != nameof(StateEnum.UNINITIALIZED)) return NotFound("World already initialized");
return StatusCode(401, errorResponse);
}
var subscription = new Subscription
{
@ -289,6 +296,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}/reset")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public ActionResult<bool> Reset(int wId)
@ -298,6 +306,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPut("{wId}/open")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<bool>> Open(int wId)
@ -306,8 +315,6 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
var world = worlds.Find(w => w.Id == wId);
if (world == null) return NotFound("World not found");
new DockerHelper(world).StartServer();
world.State = nameof(StateEnum.OPEN);
@ -318,6 +325,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPut("{wId}/close")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<bool>> Close(int wId)
@ -326,8 +334,6 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
var world = worlds.FirstOrDefault(w => w.Id == wId);
if (world == null) return NotFound("World not found");
new DockerHelper(world).StopServer();
world.State = nameof(StateEnum.CLOSED);
@ -338,6 +344,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<bool>> UpdateWorld(int wId, WorldCreateRequest body)
@ -346,8 +353,6 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
var world = worlds.Find(w => w.Id == wId);
if (world == null) return NotFound("World not found");
world.Name = body.Name;
world.Motd = body.Description;
@ -357,6 +362,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPost("{wId}/slot/{sId}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public async Task<ActionResult<bool>> UpdateSlotAsync(int wId, int sId, SlotOptionsRequest body)
@ -381,14 +387,13 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpPut("{wId}/slot/{sId}")]
[CheckForWorld]
[CheckRealmOwner]
[CheckActiveSubscription]
public ActionResult<bool> SwitchSlot(int wId, int sId)
{
var world = _context.Worlds.Find(wId);
if (world == null) return NotFound("World not found");
var slot = _context.Slots.Where(s => s.World.Id == wId).Where(s => s.SlotId == sId).Any();
if (!slot)
@ -423,6 +428,7 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpGet("{wId}/backups")]
[CheckForWorld]
[CheckRealmOwner]
public async Task<ActionResult<BackupsResponse>> GetBackups(int wId)
{
@ -445,13 +451,12 @@ namespace Minecraft_Realms_Emulator.Modes.Realms.Controllers
}
[HttpDelete("{wId}")]
[CheckForWorld]
[CheckRealmOwner]
public ActionResult<bool> DeleteRealm(int wId)
{
var world = _context.Worlds.Find(wId);
if (world == null) return NotFound("World not found");
new DockerHelper(world).DeleteServer();
_context.Worlds.Remove(world);

View File

@ -4,7 +4,6 @@ using Minecraft_Realms_Emulator.Data;
using Minecraft_Realms_Emulator.Enums;
using Minecraft_Realms_Emulator.Helpers;
using Minecraft_Realms_Emulator.Middlewares;
using Minecraft_Realms_Emulator.Modes.Realms.Helpers;
using Npgsql;
using System.Diagnostics;
using System.Reflection;
@ -125,6 +124,7 @@ app.UseMiddleware<MinecraftCookieMiddleware>();
app.UseMiddleware<CheckRealmOwnerMiddleware>();
app.UseMiddleware<ActiveSubscriptionMiddleware>();
app.UseMiddleware<AdminKeyMiddleware>();
app.UseMiddleware<CheckForWorldMiddleware>();
Console.WriteLine($"Running in {mode.Value} mode");
app.Run();

View File

@ -0,0 +1,8 @@
namespace Minecraft_Realms_Emulator.Responses
{
public class ErrorResponse
{
public int ErrorCode { get; set; }
public string ErrorMsg { get; set; } = string.Empty;
}
}