Add swagger support

This commit is contained in:
jvyden 2022-02-01 00:18:14 -05:00
parent 219e02d6cb
commit 097b2b9445
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
13 changed files with 83 additions and 54 deletions

View file

@ -1,27 +0,0 @@
#nullable enable
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Api;
public class GetSlotEndpoint : ApiEndpoint
{
private readonly Database database;
public GetSlotEndpoint(Database database)
{
this.database = database;
}
[HttpGet("slot/{id:int}")]
public async Task<IActionResult> OnGet(int id)
{
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id);
if (slot == null) return this.NotFound();
return this.Ok(slot);
}
}

View file

@ -10,17 +10,17 @@ using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Api;
public class GetSlotsEndpoint : ApiEndpoint
public class SlotEndpoints : ApiEndpointController
{
private readonly Database database;
public GetSlotsEndpoint(Database database)
public SlotEndpoints(Database database)
{
this.database = database;
}
[HttpGet("slots")]
public async Task<IActionResult> OnGet([FromQuery] int limit = 20, [FromQuery] int skip = 0)
public async Task<IActionResult> GetSlots([FromQuery] int limit = 20, [FromQuery] int skip = 0)
{
limit = Math.Min(ServerStatics.PageSize, limit);
@ -29,4 +29,13 @@ public class GetSlotsEndpoint : ApiEndpoint
return this.Ok(minimalSlots);
}
[HttpGet("slot/{id:int}")]
public async Task<IActionResult> GetSlot(int id)
{
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id);
if (slot == null) return this.NotFound();
return this.Ok(slot);
}
}

View file

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Controllers.Api;
public class StatisticsEndpoint : ApiEndpoint
public class StatisticsEndpoints : ApiEndpointController
{
[HttpGet("statistics")]
public async Task<IActionResult> OnGet()

View file

@ -6,17 +6,17 @@ using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Api;
public class GetUserEndpoint : ApiEndpoint
public class UserEndpoints : ApiEndpointController
{
private readonly Database database;
public GetUserEndpoint(Database database)
public UserEndpoints(Database database)
{
this.database = database;
}
[HttpGet("user/{id:int}")]
public async Task<IActionResult> OnGet(int id)
public async Task<IActionResult> GetUser(int id)
{
User? user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (user == null) return this.NotFound();

View file

@ -38,7 +38,7 @@ public class PublishController : ControllerBase
if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest();
Slot? slot = await this.GetSlotFromBody();
Slot? slot = await this.getSlotFromBody();
if (slot == null) return this.BadRequest(); // if the level cant be parsed then it obviously cant be uploaded
if (string.IsNullOrEmpty(slot.RootLevel)) return this.BadRequest();
@ -79,7 +79,7 @@ public class PublishController : ControllerBase
if (user.UsedSlots >= ServerSettings.Instance.EntitledSlots) return this.BadRequest();
Slot? slot = await this.GetSlotFromBody();
Slot? slot = await this.getSlotFromBody();
if (slot?.Location == null) return this.BadRequest();
// Republish logic
@ -186,7 +186,7 @@ public class PublishController : ControllerBase
return this.Ok();
}
public async Task<Slot?> GetSlotFromBody()
private async Task<Slot?> getSlotFromBody()
{
this.Request.Body.Position = 0;
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();

View file

@ -91,7 +91,7 @@ public class ReviewController : ControllerBase
if (user == null) return this.StatusCode(403, "");
Review? review = await this.database.Reviews.FirstOrDefaultAsync(r => r.SlotId == slotId && r.ReviewerId == user.UserId);
Review? newReview = await this.GetReviewFromBody();
Review? newReview = await this.getReviewFromBody();
if (newReview == null) return this.BadRequest();
if (review == null)
@ -317,7 +317,7 @@ public class ReviewController : ControllerBase
return this.Ok();
}
public async Task<Review?> GetReviewFromBody()
private async Task<Review?> getReviewFromBody()
{
this.Request.Body.Position = 0;
string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync();

View file

@ -80,7 +80,7 @@ public class ScoreController : ControllerBase
await this.database.SaveChangesAsync();
string myRanking = this.GetScores(score.SlotId, score.Type, user);
string myRanking = this.getScores(score.SlotId, score.Type, user);
return this.Ok(myRanking);
}
@ -99,11 +99,11 @@ public class ScoreController : ControllerBase
if (user == null) return this.StatusCode(403, "");
return this.Ok(this.GetScores(slotId, type, user, pageStart, pageSize));
return this.Ok(this.getScores(slotId, type, user, pageStart, pageSize));
}
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
public string GetScores(int slotId, int type, User user, int pageStart = -1, int pageSize = 5)
private string getScores(int slotId, int type, User user, int pageStart = -1, int pageSize = 5)
{
// This is hella ugly but it technically assigns the proper rank to a score
// var needed for Anonymous type returned from SELECT

View file

@ -235,7 +235,7 @@ public class SlotsController : ControllerBase
Random rand = new();
IEnumerable<Slot> slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion)
IEnumerable<Slot> slots = this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion)
.AsEnumerable()
.OrderByDescending(s => s.Thumbsup)
.ThenBy(_ => rand.Next())
@ -279,14 +279,14 @@ public class SlotsController : ControllerBase
Random rand = new();
IEnumerable<Slot> slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion)
IEnumerable<Slot> slots = this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion)
.AsEnumerable()
.OrderByDescending
(
// probably not the best way to do this?
s =>
{
return this.GetGameFilter(gameFilterType, token.GameVersion) switch
return this.getGameFilter(gameFilterType, token.GameVersion) switch
{
GameVersion.LittleBigPlanet1 => s.PlaysLBP1Unique,
GameVersion.LittleBigPlanet2 => s.PlaysLBP2Unique,
@ -337,7 +337,7 @@ public class SlotsController : ControllerBase
Random rand = new();
IEnumerable<Slot> slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion)
IEnumerable<Slot> slots = this.filterByRequest(gameFilterType, dateFilterType, token.GameVersion)
.AsEnumerable()
.OrderByDescending(s => s.Hearts)
.ThenBy(_ => rand.Next())
@ -365,7 +365,7 @@ public class SlotsController : ControllerBase
);
}
public GameVersion GetGameFilter(string? gameFilterType, GameVersion version)
private GameVersion getGameFilter(string? gameFilterType, GameVersion version)
{
if (version == GameVersion.LittleBigPlanetVita) return GameVersion.LittleBigPlanetVita;
if (version == GameVersion.LittleBigPlanetPSP) return GameVersion.LittleBigPlanetPSP;
@ -381,7 +381,7 @@ public class SlotsController : ControllerBase
};
}
public IQueryable<Slot> FilterByRequest(string? gameFilterType, string? dateFilterType, GameVersion version)
private IQueryable<Slot> filterByRequest(string? gameFilterType, string? dateFilterType, GameVersion version)
{
string _dateFilterType = dateFilterType ?? "";
@ -392,7 +392,7 @@ public class SlotsController : ControllerBase
_ => 0,
};
GameVersion gameVersion = this.GetGameFilter(gameFilterType, version);
GameVersion gameVersion = this.getGameFilter(gameFilterType, version);
IQueryable<Slot> whereSlots;

View file

@ -26,7 +26,7 @@ public class UserController : ControllerBase
this.database = database;
}
public async Task<string?> GetSerializedUser(string username, GameVersion gameVersion = GameVersion.LittleBigPlanet1)
private async Task<string?> getSerializedUser(string username, GameVersion gameVersion = GameVersion.LittleBigPlanet1)
{
User? user = await this.database.Users.Include(u => u.Location).FirstOrDefaultAsync(u => u.Username == username);
return user?.Serialize(gameVersion);
@ -38,7 +38,7 @@ public class UserController : ControllerBase
GameToken? token = await this.database.GameTokenFromRequest(this.Request);
if (token == null) return this.StatusCode(403, "");
string? user = await this.GetSerializedUser(username, token.GameVersion);
string? user = await this.getSerializedUser(username, token.GameVersion);
if (user == null) return this.NotFound();
return this.Ok(user);
@ -51,7 +51,7 @@ public class UserController : ControllerBase
if (token == null) return this.StatusCode(403, "");
List<string?> serializedUsers = new();
foreach (string userId in u) serializedUsers.Add(await this.GetSerializedUser(userId, token.GameVersion));
foreach (string userId in u) serializedUsers.Add(await this.getSerializedUser(userId, token.GameVersion));
string serialized = serializedUsers.Aggregate(string.Empty, (current, user) => user == null ? current : current + user);

View file

@ -0,0 +1,15 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace LBPUnion.ProjectLighthouse.Helpers;
public class SwaggerFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
List<KeyValuePair<string, OpenApiPathItem>> nonApiRoutes = swaggerDoc.Paths.Where(x => !x.Key.ToLower().StartsWith("/api/v1")).ToList();
nonApiRoutes.ForEach(x => swaggerDoc.Paths.Remove(x.Key));
}
}

View file

@ -7,6 +7,11 @@
<RootNamespace>LBPUnion.ProjectLighthouse</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2"/>
<PackageReference Include="DDSReader" Version="1.0.8-pre"/>
@ -23,6 +28,7 @@
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0"/>
<PackageReference Include="SharpZipLib" Version="1.3.3"/>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3"/>
</ItemGroup>
<ItemGroup>

View file

@ -13,8 +13,8 @@ using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.Internal;
using Microsoft.Extensions.Primitives;
using Microsoft.OpenApi.Models;
namespace LBPUnion.ProjectLighthouse.Startup;
@ -56,6 +56,23 @@ public class Startup
}
);
services.AddSwaggerGen
(
c =>
{
c.SwaggerDoc
(
"v1",
new OpenApiInfo
{
Title = "Project Lighthouse API",
Version = "v1",
}
);
c.DocumentFilter<SwaggerFilter>();
}
);
#if DEBUG
services.AddSingleton<IHostLifetime, DebugWarmupLifetime>();
#else
@ -85,6 +102,15 @@ public class Startup
app.UseForwardedHeaders();
app.UseSwagger();
app.UseSwaggerUI
(
c =>
{
c.SwaggerEndpoint("v1/swagger.json", "Project Lighthouse API");
}
);
// Logs every request and the response to it
// Example: "200, 13ms: GET /LITTLEBIGPLANETPS3_XML/news"
// Example: "404, 127ms: GET /asdasd?query=osucookiezi727ppbluezenithtopplayhdhr"

View file

@ -5,5 +5,5 @@ namespace LBPUnion.ProjectLighthouse.Types;
[ApiController]
[Route("/api/v1/")]
[Produces("application/json")]
public class ApiEndpoint : ControllerBase
public class ApiEndpointController : ControllerBase
{}