From 097b2b9445c42b922b04848ee358eea8d4b841a7 Mon Sep 17 00:00:00 2001 From: jvyden Date: Tue, 1 Feb 2022 00:18:14 -0500 Subject: [PATCH] Add swagger support --- .../Controllers/Api/GetSlotEndpoint.cs | 27 ------------------ .../{GetSlotsEndpoint.cs => SlotEndpoints.cs} | 15 ++++++++-- ...ticsEndpoint.cs => StatisticsEndpoints.cs} | 2 +- .../{GetUserEndpoint.cs => UserEndpoints.cs} | 6 ++-- .../GameApi/Slots/PublishController.cs | 6 ++-- .../GameApi/Slots/ReviewController.cs | 4 +-- .../GameApi/Slots/ScoreController.cs | 6 ++-- .../GameApi/Slots/SlotsController.cs | 14 +++++----- .../Controllers/GameApi/UserController.cs | 6 ++-- ProjectLighthouse/Helpers/SwaggerFilter.cs | 15 ++++++++++ ProjectLighthouse/ProjectLighthouse.csproj | 6 ++++ ProjectLighthouse/Startup/Startup.cs | 28 ++++++++++++++++++- ...piEndpoint.cs => ApiEndpointController.cs} | 2 +- 13 files changed, 83 insertions(+), 54 deletions(-) delete mode 100644 ProjectLighthouse/Controllers/Api/GetSlotEndpoint.cs rename ProjectLighthouse/Controllers/Api/{GetSlotsEndpoint.cs => SlotEndpoints.cs} (62%) rename ProjectLighthouse/Controllers/Api/{StatisticsEndpoint.cs => StatisticsEndpoints.cs} (92%) rename ProjectLighthouse/Controllers/Api/{GetUserEndpoint.cs => UserEndpoints.cs} (77%) create mode 100644 ProjectLighthouse/Helpers/SwaggerFilter.cs rename ProjectLighthouse/Types/{ApiEndpoint.cs => ApiEndpointController.cs} (73%) diff --git a/ProjectLighthouse/Controllers/Api/GetSlotEndpoint.cs b/ProjectLighthouse/Controllers/Api/GetSlotEndpoint.cs deleted file mode 100644 index 395ccce9..00000000 --- a/ProjectLighthouse/Controllers/Api/GetSlotEndpoint.cs +++ /dev/null @@ -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 OnGet(int id) - { - Slot? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id); - if (slot == null) return this.NotFound(); - - return this.Ok(slot); - } -} \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/Api/GetSlotsEndpoint.cs b/ProjectLighthouse/Controllers/Api/SlotEndpoints.cs similarity index 62% rename from ProjectLighthouse/Controllers/Api/GetSlotsEndpoint.cs rename to ProjectLighthouse/Controllers/Api/SlotEndpoints.cs index f1ed2b55..23a70fe2 100644 --- a/ProjectLighthouse/Controllers/Api/GetSlotsEndpoint.cs +++ b/ProjectLighthouse/Controllers/Api/SlotEndpoints.cs @@ -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 OnGet([FromQuery] int limit = 20, [FromQuery] int skip = 0) + public async Task 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 GetSlot(int id) + { + Slot? slot = await this.database.Slots.FirstOrDefaultAsync(u => u.SlotId == id); + if (slot == null) return this.NotFound(); + + return this.Ok(slot); + } } \ No newline at end of file diff --git a/ProjectLighthouse/Controllers/Api/StatisticsEndpoint.cs b/ProjectLighthouse/Controllers/Api/StatisticsEndpoints.cs similarity index 92% rename from ProjectLighthouse/Controllers/Api/StatisticsEndpoint.cs rename to ProjectLighthouse/Controllers/Api/StatisticsEndpoints.cs index 7ca24c7e..b21f4b6e 100644 --- a/ProjectLighthouse/Controllers/Api/StatisticsEndpoint.cs +++ b/ProjectLighthouse/Controllers/Api/StatisticsEndpoints.cs @@ -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 OnGet() diff --git a/ProjectLighthouse/Controllers/Api/GetUserEndpoint.cs b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs similarity index 77% rename from ProjectLighthouse/Controllers/Api/GetUserEndpoint.cs rename to ProjectLighthouse/Controllers/Api/UserEndpoints.cs index 40291cac..0f2ebafb 100644 --- a/ProjectLighthouse/Controllers/Api/GetUserEndpoint.cs +++ b/ProjectLighthouse/Controllers/Api/UserEndpoints.cs @@ -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 OnGet(int id) + public async Task GetUser(int id) { User? user = await this.database.Users.FirstOrDefaultAsync(u => u.UserId == id); if (user == null) return this.NotFound(); diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs index ce4d8639..c0e3e6f4 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/PublishController.cs @@ -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 GetSlotFromBody() + private async Task getSlotFromBody() { this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs index 2cf42605..6389d02f 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/ReviewController.cs @@ -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 GetReviewFromBody() + private async Task getReviewFromBody() { this.Request.Body.Position = 0; string bodyString = await new StreamReader(this.Request.Body).ReadToEndAsync(); diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/ScoreController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/ScoreController.cs index ad36a321..e92785ba 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/ScoreController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/ScoreController.cs @@ -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 diff --git a/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs b/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs index 25038f69..5cd7247a 100644 --- a/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs +++ b/ProjectLighthouse/Controllers/GameApi/Slots/SlotsController.cs @@ -235,7 +235,7 @@ public class SlotsController : ControllerBase Random rand = new(); - IEnumerable slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion) + IEnumerable 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 slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion) + IEnumerable 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 slots = this.FilterByRequest(gameFilterType, dateFilterType, token.GameVersion) + IEnumerable 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 FilterByRequest(string? gameFilterType, string? dateFilterType, GameVersion version) + private IQueryable 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 whereSlots; diff --git a/ProjectLighthouse/Controllers/GameApi/UserController.cs b/ProjectLighthouse/Controllers/GameApi/UserController.cs index 2b788c86..90c8f227 100644 --- a/ProjectLighthouse/Controllers/GameApi/UserController.cs +++ b/ProjectLighthouse/Controllers/GameApi/UserController.cs @@ -26,7 +26,7 @@ public class UserController : ControllerBase this.database = database; } - public async Task GetSerializedUser(string username, GameVersion gameVersion = GameVersion.LittleBigPlanet1) + private async Task 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 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); diff --git a/ProjectLighthouse/Helpers/SwaggerFilter.cs b/ProjectLighthouse/Helpers/SwaggerFilter.cs new file mode 100644 index 00000000..90b333c9 --- /dev/null +++ b/ProjectLighthouse/Helpers/SwaggerFilter.cs @@ -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> nonApiRoutes = swaggerDoc.Paths.Where(x => !x.Key.ToLower().StartsWith("/api/v1")).ToList(); + nonApiRoutes.ForEach(x => swaggerDoc.Paths.Remove(x.Key)); + } +} \ No newline at end of file diff --git a/ProjectLighthouse/ProjectLighthouse.csproj b/ProjectLighthouse/ProjectLighthouse.csproj index 4cc4e34e..e875510a 100644 --- a/ProjectLighthouse/ProjectLighthouse.csproj +++ b/ProjectLighthouse/ProjectLighthouse.csproj @@ -7,6 +7,11 @@ LBPUnion.ProjectLighthouse + + true + $(NoWarn);1591 + + @@ -23,6 +28,7 @@ + diff --git a/ProjectLighthouse/Startup/Startup.cs b/ProjectLighthouse/Startup/Startup.cs index 48ab0895..bf428bde 100644 --- a/ProjectLighthouse/Startup/Startup.cs +++ b/ProjectLighthouse/Startup/Startup.cs @@ -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(); + } + ); + #if DEBUG services.AddSingleton(); #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" diff --git a/ProjectLighthouse/Types/ApiEndpoint.cs b/ProjectLighthouse/Types/ApiEndpointController.cs similarity index 73% rename from ProjectLighthouse/Types/ApiEndpoint.cs rename to ProjectLighthouse/Types/ApiEndpointController.cs index ced32880..e026df83 100644 --- a/ProjectLighthouse/Types/ApiEndpoint.cs +++ b/ProjectLighthouse/Types/ApiEndpointController.cs @@ -5,5 +5,5 @@ namespace LBPUnion.ProjectLighthouse.Types; [ApiController] [Route("/api/v1/")] [Produces("application/json")] -public class ApiEndpoint : ControllerBase +public class ApiEndpointController : ControllerBase {} \ No newline at end of file