Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 10 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#
# multi-stage target: dev
#
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS dev
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS dev

ENV ASPNETCORE_URLS=http://*:5000 \
ASPNETCORE_ENVIRONMENT=DEVELOPMENT

WORKDIR /app
COPY . /app

WORKDIR /app/src/Gameboard.Api
Expand All @@ -15,18 +16,21 @@ CMD ["dotnet", "run"]
#
# multi-stage target: prod
#
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS prod
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS prod
ARG commit
ENV COMMIT=$commit

# install tools for PNG generation on the server
RUN apt-get update && apt-get install -y wget && apt-get clean
RUN wget -O ~/wkhtmltopdf.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.bookworm_amd64.deb
RUN apt-get install -y ~/wkhtmltopdf.deb
RUN rm ~/wkhtmltopdf.deb
RUN apt-get update \
&& apt-get install -y --no-install-recommends wkhtmltopdf \
&& rm -rf /var/lib/apt/lists/*

# sanity check so CI fails early if package layout changes
RUN which wkhtmltoimage && wkhtmltoimage --version

COPY --from=dev /app/dist /app
COPY --from=dev /app/LICENSE.md /app/LICENSE.md

WORKDIR /app
EXPOSE 80
ENV ASPNETCORE_URLS=http://*:80
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Gameboard.Api.Tests.Integration</RootNamespace>
Expand All @@ -11,27 +11,27 @@
<ItemGroup>
<PackageReference Include="Autofixture" Version="4.18.1" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="shouldly" Version="4.2.1" />
<PackageReference Include="Testcontainers" Version="3.9.0" />
<PackageReference Include="Testcontainers.PostgreSql" Version="3.9.0" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="shouldly" Version="4.3.0" />
<PackageReference Include="Testcontainers" Version="4.9.0" />
<PackageReference Include="Testcontainers.PostgreSql" Version="4.9.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Gameboard.Api.Tests.Shared</RootNamespace>
Expand All @@ -9,7 +9,7 @@
<ItemGroup>
<PackageReference Include="Autofixture" Version="4.18.1" />
<PackageReference Include="Autofixture.Xunit2" Version="4.18.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
18 changes: 9 additions & 9 deletions src/Gameboard.Api.Tests.Unit/Gameboard.Api.Tests.Unit.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Gameboard.Api.Tests.Unit</RootNamespace>
Expand All @@ -13,17 +13,17 @@
<PackageReference Include="Autofixture.AutoFakeItEasy" Version="4.18.1" />
<PackageReference Include="Autofixture.Xunit2" Version="4.18.1" />
<PackageReference Include="FakeItEasy" Version="8.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="MockQueryable.FakeItEasy" Version="7.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="shouldly" Version="4.2.1" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="MockQueryable.FakeItEasy" Version="10.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="shouldly" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ public class EnrollmentReportServiceTests
[Theory, GameboardAutoData]
public async Task GetResults_WithOnePlayerAndChallenge_ReportsCompleteSolve(IFixture fixture)
{
// given
// given
var sponsors = new Data.Sponsor
{
Id = "good-people",
Name = "The Good People",
Logo = "good-people.jpg"
}
.ToEnumerable()
.BuildMock();
.ToEnumerable().ToList().BuildMock();

var challenge = fixture.Create<Data.Challenge>();
challenge.Points = 50;
Expand Down Expand Up @@ -57,7 +56,7 @@ public async Task GetResults_WithOnePlayerAndChallenge_ReportsCompleteSolve(IFix
[Theory, GameboardAutoData]
public async Task GetResults_WithOneTeamRecord_ReportsExpectedValues(string gameId, IFixture fixture)
{
// given
// given
var sponsors = new List<Data.Sponsor>
{
new()
Expand Down Expand Up @@ -124,7 +123,7 @@ public async Task GetResults_WithOneTeamRecord_ReportsExpectedValues(string game
[Theory, GameboardAutoData]
public async Task GetResults_WithGameInPracAndChallengeInComp_ReportsOneResult(IFixture fixture)
{
// given
// given
var sponsors = new List<Data.Sponsor>
{
new()
Expand Down Expand Up @@ -169,7 +168,7 @@ public async Task GetResults_WithGameInPracAndChallengeInComp_ReportsOneResult(I
[Theory, GameboardAutoData]
public async Task GetResults_WithPlayerWithNoChallenges_IsIncluded(IFixture fixture)
{
// given
// given
var sponsors = new List<Data.Sponsor>
{
new()
Expand All @@ -184,7 +183,7 @@ public async Task GetResults_WithPlayerWithNoChallenges_IsIncluded(IFixture fixt
player.Challenges = Array.Empty<Data.Challenge>();
player.Game = fixture.Create<Data.Game>();
player.Sponsor = sponsors.First();
var players = player.ToEnumerable().BuildMock();
var players = player.ToEnumerable().ToList().BuildMock();

var reportsService = A.Fake<IReportsService>();
A.CallTo(() => reportsService.ParseMultiSelectCriteria(string.Empty))
Expand Down
4 changes: 2 additions & 2 deletions src/Gameboard.Api/Data/Store/Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public interface IStore
Task<int> ExecuteUpdateAsync<TEntity>
(
Expression<Func<TEntity, bool>> predicate,
Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls
Action<UpdateSettersBuilder<TEntity>> setPropertyCalls
) where TEntity : class, IEntity;
Task<bool> Exists<TEntity>(string id) where TEntity : class, IEntity;
Task<TEntity> FirstOrDefaultAsync<TEntity>(CancellationToken cancellationToken) where TEntity : class, IEntity;
Expand Down Expand Up @@ -99,7 +99,7 @@ public async Task DoTransaction(Func<GameboardDbContext, Task> operation, Cancel
public Task<int> ExecuteUpdateAsync<TEntity>
(
Expression<Func<TEntity, bool>> predicate,
Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls
Action<UpdateSettersBuilder<TEntity>> setPropertyCalls
) where TEntity : class, IEntity
=> _dbContext
.Set<TEntity>()
Expand Down
16 changes: 5 additions & 11 deletions src/Gameboard.Api/Extensions/SwaggerStartupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Reflection;
using Gameboard.Api;
using Microsoft.AspNetCore.Builder;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;

namespace Microsoft.Extensions.DependencyInjection
{
Expand Down Expand Up @@ -63,16 +63,10 @@ OpenApiOptions openapi
},
});

options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
},
new[] { oidc.Audience }
}
});
options.AddSecurityRequirement((document) => new OpenApiSecurityRequirement
{
{ new OpenApiSecuritySchemeReference("oauth2", document), [oidc.Audience] }
});
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Duende.IdentityModel.Client;
using Gameboard.Api.Data;

namespace Gameboard.Api.Features.Extensions;
Expand Down
5 changes: 3 additions & 2 deletions src/Gameboard.Api/Features/Game/GameController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public async Task<IEnumerable<Game>> List([FromQuery] GameSearchFilter model)

/// <summary>
/// List games for admin interfaces.
///
///
/// NOTE: This endpoint will eventually replace /api/games and take its path - it's just a modernized
/// expression of the same utility.
/// </summary>
Expand Down Expand Up @@ -207,7 +207,8 @@ public async Task<ImportedGame[]> ImportGames([FromForm] ImportGamesRequest requ
}

[HttpPost("/api/games/import/preview")]
public async Task<GameImportExportBatch> PreviewImportPackage([FromForm] IFormFile packageFile, CancellationToken cancellationToken)
[Consumes("multipart/form-data")]
public async Task<GameImportExportBatch> PreviewImportPackage(IFormFile packageFile, CancellationToken cancellationToken)
{
var package = await packageFile.ToBytes(cancellationToken);
return await mediator.Send(new PreviewImportPackageQuery(package), cancellationToken);
Expand Down
22 changes: 15 additions & 7 deletions src/Gameboard.Api/Features/Sponsor/SponsorController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Gameboard.Api.Common.Services;
using Gameboard.Api.Features.Sponsors;
using Gameboard.Api.Features.Users;
using Gameboard.Api.Services;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MediatR;
using Gameboard.Api.Features.Sponsors;
using Gameboard.Api.Services;
using Gameboard.Api.Common.Services;
using Gameboard.Api.Features.Users;

namespace Gameboard.Api.Controllers;

Expand Down Expand Up @@ -95,8 +95,16 @@ public Task<Sponsor> Update([FromBody] UpdateSponsorRequest model)

[HttpPut("api/sponsor/{sponsorId}/avatar")]
[Authorize]
public Task UpdateSponsorAvatar([FromRoute] string sponsorId, [FromForm] IFormFile avatarFile, CancellationToken cancellationToken)
=> _mediator.Send(new SetSponsorAvatarCommand(sponsorId, avatarFile, _actingUserService.Get()), cancellationToken);
[Consumes("multipart/form-data")]
public Task UpdateSponsorAvatar(
[FromRoute] string sponsorId,
IFormFile avatarFile, // <- no [FromForm] on IFormFile
CancellationToken cancellationToken
)
=> _mediator.Send(
new SetSponsorAvatarCommand(sponsorId, avatarFile, _actingUserService.Get()),
cancellationToken
);

/// <summary>
/// Delete sponsor
Expand Down
38 changes: 19 additions & 19 deletions src/Gameboard.Api/Gameboard.Api.csproj
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<ItemGroup>
<PackageReference Include="Crucible.Common.Authentication" Version="0.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.8" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.7" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="9.0.9" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PackageReference Include="Crucible.Common.Authentication" Version="0.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="AutoMapper" Version="12.0.1" />
<PackageReference Include="Alloy.Api.Client" Version="1.1.1" />
<PackageReference Include="mediatr" Version="12.0.1" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
<PackageReference Include="IdentityModel" Version="3.10.10" />
<PackageReference Include="Serilog" Version="4.2.0" />
<PackageReference Include="Serilog.AspnetCore" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="IdentityModel" Version="7.0.0" />
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.AspnetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
<PackageReference Include="ServiceStack.Text" Version="8.5.2" />
<PackageReference Include="SharpCompress" Version="0.38.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="ServiceStack.Text" Version="10.0.0" />
<PackageReference Include="SharpCompress" Version="0.42.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.0.1" />
<PackageReference Include="TopoMojo.Api.Client" Version="2.3.11" />
<PackageReference Include="YamlDotNet" Version="13.1.1" />
<PackageReference Include="YamlDotNet" Version="16.3.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -35,7 +35,7 @@
</ItemGroup>

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
Expand Down
Loading
Loading