Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/build-test-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ on:
SONAR_TOKEN:
required: true
env:
DOTNET_VERSION: '8.0.x'
EF_VERSION: '6.0.5'
DOTNET_VERSION: '10.0.x'
EF_VERSION: '10.0.0'
JAVA_VERSION: '17'

jobs:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docker-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
run: docker save -o ${{ steps.build.outputs.imageid }}.tar ${{ steps.build.outputs.imageid }}

- name: Scan Docker image for CVEs
uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 # 0.30.0
uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # 0.34.2
with:
input: ${{ steps.build.outputs.imageid }}.tar
format: 'sarif'
Expand All @@ -56,6 +56,6 @@ jobs:

- name: Upload scan results to GitHub Security
uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3
if: always()
if: always() && hashFiles('trivy-results.sarif') != ''
with:
sarif_file: 'trivy-results.sarif'
2 changes: 1 addition & 1 deletion .github/workflows/pack-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
dotnet-version: '10.0.x'

- name: Install GitVersion (v5)
uses: gittools/actions/gitversion/setup@v0.9
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ All notable changes to this service will be documented in this file.

## [1.1.4] – Public Beta
### Notes
- Updated CoreLibs Security package to support ExtIdentityValidator for multi-tenancy.
- Updated CoreLibs Security package to support ExtIdentityValidator for multi-tenancy.

## [1.1.5] – Public Beta
### Notes
- Upgraded to .NET10
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- See https://aka.ms/dotnet/msbuild/customize for more details on customizing your build -->
<!-- See https://aka.ms/dotnet/msbuild/customize for more details on customizing your build -->
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
18 changes: 9 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ARG DOTNET_VERSION=8.0
ARG DOTNET_VERSION=10.0

# ============================================================
# Stage 1 - Build + Install Playwright (Ubuntu SDK)
# ============================================================
FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-jammy AS build
FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-noble AS build
WORKDIR /build
ARG CI
ENV CI=${CI}
Expand Down Expand Up @@ -37,7 +37,7 @@ WORKDIR /build
ENV PATH=$PATH:/root/.dotnet/tools
ENV DOTNET_ROOT=/usr/share/dotnet

RUN dotnet tool install --global dotnet-ef --version 8.*
RUN dotnet tool install --global dotnet-ef --version 10.*

RUN mkdir /sql

Expand All @@ -64,30 +64,30 @@ COPY --from=build /app/appsettings* /DfE.ExternalApplications.Api/
# Stage 4 - Final Runtime (Ubuntu) + Playwright Runtime Support
# ============================================================

FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-jammy AS final
FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-noble AS final
WORKDIR /app

# Install Playwright required system dependencies
RUN apt-get update && \
apt-get install -y \
libnss3 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libcups2 \
libatk1.0-0t64 \
libatk-bridge2.0-0t64 \
libcups2t64 \
libdbus-1-3 \
libdrm2 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
libgbm1 \
libasound2 \
libasound2t64 \
libxshmfence1 \
libxkbcommon0 \
libxext6 \
libxfixes3 \
libx11-6 \
libx11-xcb1 \
libglib2.0-0 \
libglib2.0-0t64 \
libgl1 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<UserSecretsId>f714ca7a-fc08-46ff-b0cc-373d6f04cf4c</UserSecretsId>
<Version>1.1.4</Version>
<InformationalVersion>1.1.4</InformationalVersion>
<Version>1.1.5</Version>
<InformationalVersion>1.1.5</InformationalVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.20.1" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Contracts" Version="1.0.54" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Http" Version="1.0.10" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.23.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.18" />
<PackageReference Include="Microsoft.AspNetCore.HeaderPropagation" Version="8.0.18" />
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.31.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.18">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="10.0.3" />
<PackageReference Include="Microsoft.AspNetCore.HeaderPropagation" Version="10.0.3" />
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.32.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.18" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.13.0" />
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="4.0.0" />
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" Version="4.4.0" />
<PackageReference Include="NetEscapades.AspNetCore.SecurityHeaders" Version="1.1.0" />
<PackageReference Include="NSwag.AspNetCore" Version="14.1.0" />
<PackageReference Include="NSwag.MSBuild" Version="14.1.0">
<PackageReference Include="NSwag.AspNetCore" Version="14.6.3" />
<PackageReference Include="NSwag.MSBuild" Version="14.6.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.ApplicationInsights" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.8.1" />
<PackageReference Include="Microsoft.OpenApi" Version="2.4.1" ExcludeFromPruning="true" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="10.1.4" />
<PackageReference Include="TimeZoneConverter" Version="6.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

<ItemGroup>
Expand All @@ -61,7 +60,7 @@
</ItemGroup>

<Target Name="NSwag" BeforeTargets="AfterBuild" Condition="'$(CI)'!='true'">
<Exec ConsoleToMSBuild="true" ContinueOnError="true" Command="$(NSwagExe_Net80) run ../GovUK.Dfe.ExternalApplications.Api.Client/nswag.json">
<Exec ConsoleToMSBuild="true" ContinueOnError="true" Command="$(NSwagExe_Net90) run ../GovUK.Dfe.ExternalApplications.Api.Client/nswag.json">
<Output TaskParameter="ExitCode" PropertyName="NSwagExitCode" />
<Output TaskParameter="ConsoleOutput" PropertyName="NSwagOutput" />
</Exec>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class TenantResolutionMiddleware
{
public const string TenantIdHeader = "X-Tenant-ID";

private static readonly string[] BypassPaths = { "/swagger", "/health", "/_" };
private static readonly string[] BypassPaths = { "/swagger", "/health", "/_", "/favicon.ico" };

private readonly RequestDelegate _next;
private readonly ITenantConfigurationProvider _tenantConfigurationProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace DfE.ExternalApplications.Api.Swagger
Expand All @@ -9,17 +9,10 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Security ??= new List<OpenApiSecurityRequirement>();

var userScheme = new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
};
var userScheme = new OpenApiSecuritySchemeReference("Bearer");
operation.Security.Add(new OpenApiSecurityRequirement
{
[userScheme] = Array.Empty<string>()
[userScheme] = new List<string>()
});
}
}
Expand Down
9 changes: 2 additions & 7 deletions src/DfE.ExternalApplications.Api/Swagger/SwaggerOptions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Asp.Versioning.ApiExplorer;
using DfE.ExternalApplications.Domain.Tenancy;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace DfE.ExternalApplications.Api.Swagger
Expand Down Expand Up @@ -52,12 +52,7 @@ public void Configure(SwaggerGenOptions options)
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
BearerFormat = "JWT"
});
options.OperationFilter<AuthenticationHeaderOperationFilter>();
options.OperationFilter<TenantHeaderOperationFilter>(_tenantConfigurationProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.Json.Nodes;
using DfE.ExternalApplications.Api.Middleware;
using DfE.ExternalApplications.Domain.Tenancy;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace DfE.ExternalApplications.Api.Swagger;
Expand All @@ -20,17 +20,14 @@ public TenantHeaderOperationFilter(ITenantConfigurationProvider tenantConfigurat

public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters ??= new List<OpenApiParameter>();
operation.Parameters ??= new List<IOpenApiParameter>();

var tenants = _tenantConfigurationProvider.GetAllTenants();

// Create enum values for the dropdown
var tenantOptions = tenants
.Select(t => new OpenApiString(t.Id.ToString()))
.Cast<IOpenApiAny>()
.Select(t => (JsonNode)JsonValue.Create(t.Id.ToString())!)
.ToList();

// Build description with tenant names for reference
var tenantDescriptions = string.Join("\n",
tenants.Select(t => $"- `{t.Id}` = {t.Name}"));

Expand All @@ -42,7 +39,7 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context)
Description = $"Tenant identifier (GUID). Available tenants:\n{tenantDescriptions}",
Schema = new OpenApiSchema
{
Type = "string",
Type = JsonSchemaType.String,
Format = "uuid",
Enum = tenantOptions.Any() ? tenantOptions : null,
Default = tenantOptions.FirstOrDefault()
Expand All @@ -52,4 +49,3 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context)
operation.Parameters.Insert(0, parameter);
}
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

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

<ItemGroup>
Expand All @@ -16,8 +16,6 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="GovUK.Dfe.CoreLibs.AsyncProcessing" Version="1.0.12" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Caching" Version="1.0.12" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Contracts" Version="1.0.54" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Email" Version="0.1.1" />
<PackageReference Include="GovUK.Dfe.CoreLibs.FileStorage" Version="0.1.5-prerelease-36" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Messaging.Contracts" Version="0.1.3" />
Expand All @@ -27,9 +25,8 @@
<PackageReference Include="GovUK.Dfe.CoreLibs.Utilities" Version="1.0.16" />
<PackageReference Include="FluentValidation" Version="12.0.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.18" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
<PackageReference Include="Scrutor" Version="4.2.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.10.0" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

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

<ItemGroup>
<PackageReference Include="GovUK.Dfe.CoreLibs.Caching" Version="1.0.12" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Contracts" Version="1.0.54" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Caching" Version="1.0.13" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Contracts" Version="1.0.56" />
<PackageReference Include="FluentValidation" Version="12.0.0" />
<PackageReference Include="MediatR" Version="12.5.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
optionsBuilder.UseSqlServer(connectionString);
}

var mediator = _serviceProvider.GetRequiredService<IMediator>();
optionsBuilder.AddInterceptors(new DomainEventDispatcherInterceptor(mediator));
var mediator = _serviceProvider?.GetService<IMediator>();
if (mediator != null)
{
optionsBuilder.AddInterceptors(new DomainEventDispatcherInterceptor(mediator));
}
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
Expand Down
Loading
Loading