forked from leaderboardsgg/leaderboard-backend-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create JudgementsController (leaderboardsgg#82)
* Create Files * Change Model Fields * Add CreateJudgement * Return 500 as Intended, and Remove <remarks> Tags <remarks> tags don't work for non-controller actions * Add Second Condition * Get Rid of Null Mod Check We already check if the user exists in authZ, cuz we need to know if they're a mod. * Add JudgementViewModel for Controller Actions * Uncomment Admin User Check for Authz * Add RunService to Program * Simplify creating JudgementViewModels * Add/change docs to be agreeable w/ Swashbuckle Can't have fields explicitly defined in record structs; Swagger won't generate. * Fixed IsMod auth decorator and CreateJudgement * Wrote test for CreateJudgement route 200 path * Fixed IsMod to actually load modships so it doesn't always fail * CreatedAtAction was being called in a way that caused it to fail * Using Utc in example timestamp `Now` doesn't work in NPGSql, it has to be Utc ok epic * Allow admins to do mod things I forgot we said I was gonna include this too * Reorder ResponseType Attribute * Convert ViewModel to be A Public Record * Update CONTRIBUTING to link to the separate style guide * If This Actually Needs to be Done * Fix tests, move ViewModels folder Co-authored-by: Sim <[email protected]> Co-authored-by: RageCage64 <[email protected]>
- Loading branch information
1 parent
5e00513
commit ac93960
Showing
18 changed files
with
1,801 additions
and
461 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
using LeaderboardBackend.Models.Entities; | ||
using LeaderboardBackend.Models.Requests; | ||
using LeaderboardBackend.Test.Lib; | ||
using LeaderboardBackend.Test.TestApi; | ||
using LeaderboardBackend.Test.TestApi.Extensions; | ||
using LeaderboardBackend.Models.ViewModels; | ||
using NUnit.Framework; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace LeaderboardBackend.Test; | ||
|
||
[TestFixture] | ||
internal class Judgements | ||
{ | ||
private static TestApiFactory Factory = null!; | ||
private static TestApiClient ApiClient = null!; | ||
private static Leaderboard DefaultLeaderboard = null!; | ||
private static string? Jwt; | ||
|
||
private static readonly string ValidUsername = "Test"; | ||
private static readonly string ValidPassword = "c00l_pAssword"; | ||
private static readonly string ValidEmail = "[email protected]"; | ||
|
||
[SetUp] | ||
public static async Task SetUp() | ||
{ | ||
Factory = new TestApiFactory(); | ||
ApiClient = Factory.CreateTestApiClient(); | ||
|
||
// Set up a default Leaderboard and a mod user for that leaderboard to use as the Jwt for tests | ||
string adminJwt = (await ApiClient.LoginAdminUser()).Token; | ||
User mod = await ApiClient.RegisterUser( | ||
ValidUsername, | ||
ValidEmail, | ||
ValidPassword | ||
); | ||
DefaultLeaderboard = await ApiClient.Post<Leaderboard>( | ||
"/api/leaderboards", | ||
new() | ||
{ | ||
Body = new CreateLeaderboardRequest | ||
{ | ||
Name = Generators.GenerateRandomString(), | ||
Slug = Generators.GenerateRandomString(), | ||
}, | ||
Jwt = adminJwt, | ||
} | ||
); | ||
Modship modship = await ApiClient.Post<Modship>( | ||
"/api/modships", | ||
new() | ||
{ | ||
Body = new CreateModshipRequest | ||
{ | ||
LeaderboardId = DefaultLeaderboard.Id, | ||
UserId = mod.Id, | ||
}, | ||
Jwt = adminJwt, | ||
} | ||
); | ||
|
||
Jwt = (await ApiClient.LoginUser(ValidEmail, ValidPassword)).Token; | ||
} | ||
|
||
[Test] | ||
public async Task CreateJudgement_OK() | ||
{ | ||
Run run = await CreateRun(); | ||
|
||
JudgementViewModel? createdJudgement = await ApiClient.Post<JudgementViewModel>( | ||
"/api/judgements", | ||
new() | ||
{ | ||
Body = new CreateJudgementRequest | ||
{ | ||
RunId = run.Id, | ||
Note = "It is a cool run", | ||
Approved = true, | ||
}, | ||
Jwt = Jwt, | ||
} | ||
); | ||
|
||
Assert.NotNull(createdJudgement); | ||
} | ||
|
||
private async Task<Run> CreateRun() | ||
{ | ||
return await ApiClient.Post<Run>( | ||
"/api/runs", | ||
new() | ||
{ | ||
Body = new CreateRunRequest | ||
{ | ||
Played = DateTime.UtcNow, | ||
Submitted = DateTime.UtcNow, | ||
Status = RunStatus.SUBMITTED, | ||
}, | ||
Jwt = Jwt, | ||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using LeaderboardBackend.Authorization; | ||
using LeaderboardBackend.Controllers.Annotations; | ||
using LeaderboardBackend.Models.Entities; | ||
using LeaderboardBackend.Models.Requests; | ||
using LeaderboardBackend.Services; | ||
using LeaderboardBackend.Models.ViewModels; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Mvc; | ||
|
||
namespace LeaderboardBackend.Controllers; | ||
|
||
[Route("api/[controller]")] | ||
[ApiController] | ||
[Produces("application/json")] | ||
public class JudgementsController : ControllerBase | ||
{ | ||
private readonly ILogger _logger; | ||
private readonly IJudgementService _judgementService; | ||
private readonly IRunService _runService; | ||
private readonly IUserService _userService; | ||
|
||
public JudgementsController( | ||
ILogger<JudgementsController> logger, | ||
IJudgementService judgementService, | ||
IRunService runService, | ||
IUserService userService | ||
) | ||
{ | ||
_logger = logger; | ||
_judgementService = judgementService; | ||
_runService = runService; | ||
_userService = userService; | ||
} | ||
|
||
/// <summary>Gets a Judgement from its ID.</summary> | ||
/// <response code="200">The Judgement with the provided ID.</response> | ||
/// <response code="404">If no Judgement can be found.</response> | ||
[ApiConventionMethod(typeof(Conventions), | ||
nameof(Conventions.Get))] | ||
[AllowAnonymous] | ||
[HttpGet("{id}")] | ||
public async Task<ActionResult<JudgementViewModel>> GetJudgement(long id) | ||
{ | ||
Judgement? judgement = await _judgementService.GetJudgement(id); | ||
if (judgement is null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
return Ok(new JudgementViewModel(judgement)); | ||
} | ||
|
||
/// <summary>Creates a judgement for a run.</summary> | ||
/// <response code="201">The created judgement.</response> | ||
/// <response code="400">The request body is malformed.</response> | ||
/// <response code="404">For an invalid judgement.</response> | ||
[ApiConventionMethod(typeof(Conventions), | ||
nameof(Conventions.Post))] | ||
[Authorize(Policy = UserTypes.Mod)] | ||
[HttpPost] | ||
public async Task<ActionResult<JudgementViewModel>> CreateJudgement([FromBody] CreateJudgementRequest body) | ||
{ | ||
User? mod = await _userService.GetUserFromClaims(HttpContext.User); | ||
Run? run = await _runService.GetRun(body.RunId); | ||
|
||
if (run is null) | ||
{ | ||
_logger.LogError($"CreateJudgement: run is null. ID = {body.RunId}"); | ||
return NotFound($"Run not found for ID = {body.RunId}"); | ||
} | ||
|
||
if (run.Status == RunStatus.CREATED) | ||
{ | ||
_logger.LogError($"CreateJudgement: run has pending participations (i.e. run status == CREATED). ID = {body.RunId}"); | ||
return BadRequest($"Run has pending Participations. ID = {body.RunId}"); | ||
} | ||
|
||
// TODO: Update run status on body.Approved's value | ||
Judgement judgement = new() | ||
{ | ||
Approved = body.Approved, | ||
Mod = mod!, | ||
ModId = mod!.Id, | ||
Note = body.Note, | ||
Run = run, | ||
RunId = run.Id, | ||
}; | ||
|
||
await _judgementService.CreateJudgement(judgement); | ||
|
||
JudgementViewModel judgementView = new(judgement); | ||
|
||
return CreatedAtAction(nameof(GetJudgement), new { id = judgementView.Id }, judgementView); | ||
} | ||
} |
Oops, something went wrong.