Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
827143e
chore(deps): bump Microsoft.EntityFrameworkCore, Microsoft.Extensions…
dependabot[bot] Apr 9, 2025
62bb2d7
Merge pull request #636 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
73d14fa
chore(deps): bump Microsoft.AspNetCore.Authentication.JwtBearer
dependabot[bot] Apr 9, 2025
53d8444
Merge pull request #637 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
a541dfd
chore(deps): bump Microsoft.Extensions.Diagnostics.HealthChecks
dependabot[bot] Apr 9, 2025
663a665
Merge pull request #641 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
afe9093
chore(deps): bump Microsoft.EntityFrameworkCore, Microsoft.Extensions…
dependabot[bot] Apr 9, 2025
9aad531
Merge pull request #642 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
99cde93
chore(deps): bump Microsoft.AspNetCore.Authentication.JwtBearer
dependabot[bot] Apr 9, 2025
343e5af
Merge pull request #643 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
ce6133c
chore(deps): bump Microsoft.Data.Sqlite.Core and Microsoft.EntityFram…
dependabot[bot] Apr 9, 2025
dba3a7a
Merge pull request #645 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
133eda6
chore(deps): bump Microsoft.EntityFrameworkCore.InMemory
dependabot[bot] Apr 9, 2025
84ca74e
Merge pull request #647 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
62beb16
chore(deps): bump Microsoft.Extensions.Diagnostics.HealthChecks
dependabot[bot] Apr 9, 2025
f7e3838
Merge pull request #648 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
9ee0fae
chore(deps): bump Microsoft.AspNetCore.Authorization
dependabot[bot] Apr 9, 2025
df8e8ed
Merge pull request #639 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
1b5ae8e
chore(deps): bump Microsoft.AspNetCore.Authentication.MicrosoftAccount
dependabot[bot] Apr 9, 2025
e93d499
chore(deps): bump Microsoft.AspNetCore.Authentication.MicrosoftAccount
dependabot[bot] Apr 9, 2025
114c60a
Merge pull request #640 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
075054c
Merge pull request #646 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 9, 2025
5b21f72
chore(deps): bump Microsoft.EntityFrameworkCore, Microsoft.EntityFram…
dependabot[bot] Apr 10, 2025
d8fa0d1
Merge pull request #650 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 10, 2025
67b89b5
chore(deps): bump Swashbuckle.AspNetCore in /PathfinderHonorManager
dependabot[bot] Apr 10, 2025
44610ca
Merge pull request #651 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 10, 2025
c77f378
chore(deps): bump Microsoft.EntityFrameworkCore, Microsoft.EntityFram…
dependabot[bot] Apr 10, 2025
c1f7311
Merge pull request #652 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 10, 2025
f964f0c
chore(deps): bump Swashbuckle.AspNetCore
dependabot[bot] Apr 10, 2025
31af091
Merge pull request #653 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 10, 2025
4549f1f
chore(deps): bump Microsoft.AspNetCore.Authentication.JwtBearer and M…
dependabot[bot] Apr 29, 2025
c64e3d5
Merge pull request #654 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 29, 2025
0981e50
chore(deps): bump Microsoft.AspNetCore.Authentication.JwtBearer and M…
dependabot[bot] Apr 29, 2025
16c8c51
Merge pull request #655 from PathfinderHonorManager/dependabot/nuget/…
github-actions[bot] Apr 29, 2025
f588d03
Added club controller post
May 1, 2025
c138f9e
Added club to controller
May 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.3" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
<PackageReference Include="FluentValidation.Validators.UnitTestExtension" Version="1.11.0.2" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
63 changes: 60 additions & 3 deletions PathfinderHonorManager/Controllers/ClubController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
using PathfinderHonorManager.Service.Interfaces;
using Microsoft.Extensions.Logging;
using System.Linq;
using PathfinderHonorManager.Dto.Incoming;
using FluentValidation;
using Microsoft.EntityFrameworkCore;

namespace PathfinderHonorManager.Controllers
{
Expand All @@ -19,15 +22,20 @@ namespace PathfinderHonorManager.Controllers
[Consumes("application/json")]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
public class ClubsController : ControllerBase
public class ClubsController : CustomApiController
{
private readonly IClubService _clubService;
private readonly ILogger<ClubsController> _logger;
private readonly IValidator<ClubDto> _validator;

public ClubsController(IClubService clubService, ILogger<ClubsController> logger)
public ClubsController(
IClubService clubService,
ILogger<ClubsController> logger,
IValidator<ClubDto> validator)
{
_clubService = clubService;
_logger = logger;
_validator = validator;
}

// GET Clubs
Expand Down Expand Up @@ -80,7 +88,7 @@ public async Task<ActionResult<IEnumerable<Club>>> GetClubs(CancellationToken to
/// <returns></returns>
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[HttpGet("{id:guid}")]
[HttpGet("{id:guid}", Name = "GetClubById")]
public async Task<IActionResult> GetByIdAsync(Guid id, CancellationToken token)
{
_logger.LogInformation("Getting club with ID {ClubId}", id);
Expand All @@ -95,5 +103,54 @@ public async Task<IActionResult> GetByIdAsync(Guid id, CancellationToken token)
_logger.LogInformation("Retrieved club with ID {ClubId}", id);
return Ok(club);
}

[Authorize("CreateClubs")]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[HttpPost]
public async Task<IActionResult> CreateAsync([FromBody] ClubDto club, CancellationToken token)
{
_logger.LogInformation("Creating new club with code {ClubCode}", club.ClubCode);

try
{
var createdClub = await _clubService.CreateAsync(club, token);
return CreatedAtRoute("GetClubById", new { id = createdClub.ClubID }, createdClub);
}
catch (FluentValidation.ValidationException ex)
{
_logger.LogWarning(ex, "Validation failed while creating club with code {ClubCode}", club.ClubCode);
UpdateModelState(ex);
return ValidationProblem(ModelState);
}
}

[Authorize("UpdateClubs")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[HttpPut("{id:guid}")]
public async Task<IActionResult> UpdateAsync(Guid id, [FromBody] ClubDto club, CancellationToken token)
{
_logger.LogInformation("Updating club with ID {ClubId}", id);

try
{
var updatedClub = await _clubService.UpdateAsync(id, club, token);
if (updatedClub == default)
{
_logger.LogWarning("Club with ID {ClubId} not found for update", id);
return NotFound();
}

return Ok(updatedClub);
}
catch (FluentValidation.ValidationException ex)
{
_logger.LogWarning(ex, "Validation failed while updating club with ID {ClubId}", id);
UpdateModelState(ex);
return ValidationProblem(ModelState);
}
}
}
}
1 change: 1 addition & 0 deletions PathfinderHonorManager/Mapping/AutoMapperConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ private void RegisterHonorMappings()
private void RegisterClubMappings()
{
CreateMap<Club, Outgoing.ClubDto>();
CreateMap<Incoming.ClubDto, Club>();
}

private void RegisterPathfinderHonorMappings()
Expand Down
20 changes: 10 additions & 10 deletions PathfinderHonorManager/PathfinderHonorManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,23 @@
<ItemGroup>
<PackageReference Include="FluentValidation" Version="11.11.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
<PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.4" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.4" />
<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="9.0.3" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.6.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="9.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="9.0.4" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.8.4" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.23.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.22.0" />
</ItemGroup>
Expand Down
50 changes: 50 additions & 0 deletions PathfinderHonorManager/Service/ClubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
using System.Threading;
using System.Threading.Tasks;
using Outgoing = PathfinderHonorManager.Dto.Outgoing;
using Incoming = PathfinderHonorManager.Dto.Incoming;
using PathfinderHonorManager.Model;
using PathfinderHonorManager.DataAccess;
using PathfinderHonorManager.Service.Interfaces;
using System.Collections.Generic;
using System.Linq;
using FluentValidation;

namespace PathfinderHonorManager.Service
{
Expand Down Expand Up @@ -79,5 +81,53 @@ public ClubService(
_logger.LogInformation("Retrieved club: {ClubName} (Code: {ClubCode})", entity.Name, code);
return _mapper.Map<Outgoing.ClubDto>(entity);
}

public async Task<Outgoing.ClubDto> CreateAsync(Incoming.ClubDto club, CancellationToken token)
{
_logger.LogInformation("Creating new club with code: {ClubCode}", club.ClubCode);

try
{
var entity = _mapper.Map<Club>(club);
await _dbContext.Clubs.AddAsync(entity, token);
await _dbContext.SaveChangesAsync(token);

_logger.LogInformation("Created club: {ClubName} (ID: {ClubId})", entity.Name, entity.ClubID);
return _mapper.Map<Outgoing.ClubDto>(entity);
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database error while creating club with code {ClubCode}", club.ClubCode);
throw new ValidationException("Failed to create club. The club code may already be in use.");
}
}

public async Task<Outgoing.ClubDto> UpdateAsync(Guid id, Incoming.ClubDto club, CancellationToken token)
{
_logger.LogInformation("Updating club with ID: {ClubId}", id);

try
{
var entity = await _dbContext.Clubs
.SingleOrDefaultAsync(c => c.ClubID == id, token);

if (entity == default)
{
_logger.LogWarning("Club with ID {ClubId} not found", id);
return default;
}

_mapper.Map(club, entity);
await _dbContext.SaveChangesAsync(token);

_logger.LogInformation("Updated club: {ClubName} (ID: {ClubId})", entity.Name, id);
return _mapper.Map<Outgoing.ClubDto>(entity);
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database error while updating club with ID {ClubId}", id);
throw new ValidationException("Failed to update club. The club code may already be in use.");
}
}
}
}
10 changes: 10 additions & 0 deletions PathfinderHonorManager/Service/Interfaces/IClubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Threading;
using System.Threading.Tasks;
using Outgoing = PathfinderHonorManager.Dto.Outgoing;
using Incoming = PathfinderHonorManager.Dto.Incoming;

namespace PathfinderHonorManager.Service.Interfaces
{
Expand All @@ -18,5 +19,14 @@ public interface IClubService

Task<ICollection<Outgoing.ClubDto>> GetAllAsync(
CancellationToken token);

Task<Outgoing.ClubDto> CreateAsync(
Incoming.ClubDto club,
CancellationToken token);

Task<Outgoing.ClubDto> UpdateAsync(
Guid id,
Incoming.ClubDto club,
CancellationToken token);
}
}