Skip to content

Commit

Permalink
Update to .NET 8 (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
domi-b authored Aug 20, 2024
2 parents c32f270 + a24c0db commit 5750a2c
Show file tree
Hide file tree
Showing 25 changed files with 96 additions and 108 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: "7.0"
dotnet-version: "8.0"

- name: Install dependencies
run: dotnet restore Geopilot.sln
Expand All @@ -36,7 +36,7 @@ jobs:
run: npm run lint

- name: Start test db
run: docker compose up -d db
run: docker compose up -d --wait --wait-timeout 30 db

- name: Test
run: dotnet test Geopilot.sln -c Release --no-build --verbosity normal
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
- Expanded API health checks.
- Authenticated users are now registed in the database.
- First registered user is granted administrator privileges.
- Updated to .NET 8.0.
- The app now runs on port 8080 inside the docker container.

## v1.0.93 - 2024-05-14

Expand Down
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
<PackageProjectUrl>https://github.com/GeoWerkstatt/geopilot</PackageProjectUrl>
<RepositoryUrl>https://github.com/GeoWerkstatt/geopilot.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<AnalysisLevel>7.0-recommended</AnalysisLevel>
<AnalysisLevel>8.0-recommended</AnalysisLevel>
<IsPackable>false</IsPackable>
<VersionPrefix>1.0</VersionPrefix>
<VersionPrefix>1.1</VersionPrefix>
</PropertyGroup>

<ItemGroup Condition="'$(MSBuildProjectExtension)' != '.dcproj' And '$(MSBuildProjectExtension)' != '.esproj'">
Expand Down
17 changes: 6 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
ARG VERSION=0.0.1
ARG REVISION=0000000
Expand Down Expand Up @@ -48,7 +48,7 @@ RUN \
--customPath license.template.json \
--out ${PUBLISH_DIR}/wwwroot/license.json

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS final
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
ENV HOME=/app
ENV TZ=Europe/Zurich
ENV ASPNETCORE_ENVIRONMENT=Production
Expand All @@ -62,31 +62,26 @@ RUN \
DEBIAN_FRONTEND=noninteractive && \
mkdir -p /usr/share/man/man1 /usr/share/man/man2 && \
apt-get update && \
apt-get install -y curl sudo vim htop libcap2-bin && \
apt-get install -y curl sudo vim htop && \
rm -rf /var/lib/apt/lists/*

# Add non-root user
# Create directories
RUN \
useradd --uid 941 --user-group --home $HOME --shell /bin/bash abc && \
usermod --groups users abc && \
mkdir -p $Storage__UploadDirectory && \
mkdir -p $Storage__AssetsDirectory && \
mkdir -p $PublicAssetsOverride

EXPOSE 80
EXPOSE 8080
VOLUME $Storage__UploadDirectory
VOLUME $Storage__AssetsDirectory

# Set default locale
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8

# Allow dotnet to bind to well known ports
RUN setcap CAP_NET_BIND_SERVICE=+eip /usr/share/dotnet/dotnet

COPY --from=build /app/publish $HOME
COPY docker-entrypoint.sh /entrypoint.sh

HEALTHCHECK CMD curl --fail http://localhost/health || exit 1
HEALTHCHECK CMD curl --fail http://localhost:8080/health || exit 1

ENTRYPOINT ["/entrypoint.sh"]
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ services:
context: .
restart: unless-stopped
ports:
- 5173:80
- 5173:8080
environment:
ASPNETCORE_ENVIRONMENT: Development
ConnectionStrings__Context: Server=db;Port=5432;Database=geopilot;User Id=HAPPYWALK;Password=SOMBERSPORK;
Expand Down
12 changes: 6 additions & 6 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ set -e

# Change owner for our uploads folder
echo -n "Fix permissions for mounted volumes ..." && \
chown -R abc:abc $Storage__UploadDirectory && \
chown -R abc:abc $Storage__AssetsDirectory && \
chown -R abc:abc $PublicAssetsOverride && \
chown -R app:app $Storage__UploadDirectory && \
chown -R app:app $Storage__AssetsDirectory && \
chown -R app:app $PublicAssetsOverride && \
echo "done!"

# Override public assets in app's public directory.
Expand All @@ -15,11 +15,11 @@ echo "
--------------------------------------------------------------------------
http proxy: ${PROXY:-no proxy set}
http proxy exceptions: $([[ -n $NO_PROXY ]] && echo $NO_PROXY || echo undefined)
user uid: $(id -u abc)
user gid: $(id -g abc)
user uid: $(id -u app)
user gid: $(id -g app)
timezone: $TZ
--------------------------------------------------------------------------
"

echo -e "geopilot app is up and running!\n" && \
sudo -H --preserve-env --user abc dotnet Geopilot.Api.dll
sudo -H --preserve-env --user app dotnet Geopilot.Api.dll
10 changes: 6 additions & 4 deletions src/Geopilot.Api/ContextExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Bogus;
using Bogus.DataSets;
using Geopilot.Api.Models;
using Microsoft.EntityFrameworkCore;
using NetTopologySuite.Geometries;
Expand All @@ -13,6 +12,7 @@ namespace Geopilot.Api;
internal static class ContextExtensions
{
private static readonly double[] extentCh = new double[] { 7.536621, 46.521076, 9.398804, 47.476376 };
private static readonly DateTime referenceDateTime = DateTime.Parse("01.11.2023 00:00:00", new CultureInfo("de_CH", false));

/// <summary>
/// Retreives the user that matches the provided principal from the database.
Expand All @@ -30,9 +30,6 @@ public static void SeedTestData(this Context context)
{
var transaction = context.Database.BeginTransaction();

// Set Bogus Data System Clock
Date.SystemClock = () => DateTime.Parse("01.11.2023 00:00:00", new CultureInfo("de_CH", false));

context.SeedUsers();
context.SeedOrganisations();
context.SeedMandates();
Expand All @@ -46,6 +43,7 @@ public static void SeedTestData(this Context context)
public static void SeedUsers(this Context context)
{
var userFaker = new Faker<User>()
.UseDateTimeReference(referenceDateTime)
.StrictMode(true)
.RuleFor(u => u.Id, _ => 0)
.RuleFor(u => u.AuthIdentifier, f => f.Random.Uuid().ToString())
Expand Down Expand Up @@ -79,6 +77,7 @@ public static void SeedUsers(this Context context)
public static void SeedOrganisations(this Context context)
{
var organisationFaker = new Faker<Organisation>()
.UseDateTimeReference(referenceDateTime)
.StrictMode(true)
.RuleFor(o => o.Id, _ => 0)
.RuleFor(o => o.Name, f => f.Company.CompanyName())
Expand Down Expand Up @@ -114,6 +113,7 @@ public static void SeedMandates(this Context context)
{
var knownFileFormats = new string[] { ".xtf", ".gpkg", ".*", ".itf", ".xml", ".zip", ".csv" };
var mandateFaker = new Faker<Mandate>()
.UseDateTimeReference(referenceDateTime)
.RuleFor(o => o.Id, f => 0)
.RuleFor(o => o.Name, f => f.Commerce.ProductName())
.RuleFor(o => o.FileTypes, f => f.PickRandom(knownFileFormats, 4).Distinct().ToArray())
Expand All @@ -136,6 +136,7 @@ public static void SeedDeliveries(this Context context)
.ToList();

var deliveryFaker = new Faker<Delivery>()
.UseDateTimeReference(referenceDateTime)
.StrictMode(true)
.RuleFor(d => d.Id, 0)
.RuleFor(d => d.JobId, f => f.Random.Guid())
Expand All @@ -162,6 +163,7 @@ public static void SeedDeliveries(this Context context)
public static void SeedAssets(this Context context)
{
var assetFaker = new Faker<Asset>()
.UseDateTimeReference(referenceDateTime)
.StrictMode(true)
.RuleFor(a => a.Id, _ => 0)
.RuleFor(a => a.FileHash, f => SHA256.HashData(f.Random.Bytes(10)))
Expand Down
16 changes: 8 additions & 8 deletions src/Geopilot.Api/Controllers/DeliveryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public DeliveryController(ILogger<DeliveryController> logger, Context context, I
[HttpPost]
[Authorize(Policy = GeopilotPolicies.User)]
[SwaggerResponse(StatusCodes.Status201Created, "The delivery was created successfully.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), "application/json")]
[SwaggerResponse(StatusCodes.Status404NotFound, "The validation job or mandate could not be found.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely there was an error persisting the assets.", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely there was an error persisting the assets.", typeof(ProblemDetails), "application/json")]
public async Task<IActionResult> Create(DeliveryRequest declaration)
{
logger.LogInformation("Declaration for job with id <{JobId}> requested.", declaration.JobId);
Expand Down Expand Up @@ -128,7 +128,7 @@ public async Task<IActionResult> Create(DeliveryRequest declaration)
/// <returns>A list of <see cref="Delivery"/>.</returns>
[HttpGet]
[Authorize(Policy = GeopilotPolicies.User)]
[SwaggerResponse(StatusCodes.Status200OK, "A list matching filter criteria.", typeof(List<Delivery>), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status200OK, "A list matching filter criteria.", typeof(List<Delivery>), "application/json")]
[SwaggerResponse(StatusCodes.Status404NotFound, "Failed to find mandate.")]
public async Task<IActionResult> Get([FromQuery] int? mandateId = null)
{
Expand Down Expand Up @@ -165,9 +165,9 @@ public async Task<IActionResult> Get([FromQuery] int? mandateId = null)
[HttpDelete("{deliveryId}")]
[Authorize(Policy = GeopilotPolicies.Admin)]
[SwaggerResponse(StatusCodes.Status200OK, "The delivery was successfully deleted.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), "application/json")]
[SwaggerResponse(StatusCodes.Status404NotFound, "The delivery could be found.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely there was an error deleting the assets.", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely there was an error deleting the assets.", typeof(ProblemDetails), "application/json")]
public IActionResult Delete([FromRoute] int deliveryId)
{
logger.LogInformation("Deleting of delivery with id <{DeliveryId}> started.", deliveryId);
Expand Down Expand Up @@ -202,10 +202,10 @@ public IActionResult Delete([FromRoute] int deliveryId)
/// <returns>The asset file.</returns>
[HttpGet("assets/{assetId}")]
[Authorize(Policy = GeopilotPolicies.Admin)]
[SwaggerResponse(StatusCodes.Status200OK, "A file has been downloaded.", typeof(File), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status200OK, "A file has been downloaded.", typeof(File), "application/json")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The server cannot process the request due to invalid or malformed request.", typeof(ValidationProblemDetails), "application/json")]
[SwaggerResponse(StatusCodes.Status404NotFound, "The asset could be found.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely the file could not be read.", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. Likely the file could not be read.", typeof(ProblemDetails), "application/json")]
public async Task<IActionResult> DownloadAsync([FromRoute] int assetId)
{
logger.LogInformation("Downloading asset with id <{AssetId}> started.", assetId);
Expand Down
6 changes: 3 additions & 3 deletions src/Geopilot.Api/Controllers/MandateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public MandateController(ILogger<MandateController> logger, Context context, IVa
/// <returns>List of mandates matching optional filter criteria.</returns>
[HttpGet]
[Authorize(Policy = GeopilotPolicies.User)]
[SwaggerResponse(StatusCodes.Status200OK, "Returns list of mandates associated to the current user matching the optional filter criteria.", typeof(IEnumerable<Mandate>), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status200OK, "Returns list of mandates associated to the current user matching the optional filter criteria.", typeof(IEnumerable<Mandate>), "application/json")]
public async Task<IActionResult> Get(
[FromQuery, SwaggerParameter("Filter mandates matching validation job file extension.")]
Guid jobId = default)
Expand Down Expand Up @@ -86,7 +86,7 @@ public async Task<IActionResult> Get(
[SwaggerResponse(StatusCodes.Status201Created, "The mandate was created successfully.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The mandate could not be created due to invalid input.")]
[SwaggerResponse(StatusCodes.Status401Unauthorized, "The current user is not authorized to create a mandate.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), "application/json")]
public async Task<IActionResult> Create(Mandate mandate)
{
try
Expand Down Expand Up @@ -131,7 +131,7 @@ public async Task<IActionResult> Create(Mandate mandate)
[SwaggerResponse(StatusCodes.Status404NotFound, "The mandate could not be found.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The mandate could not be updated due to invalid input.")]
[SwaggerResponse(StatusCodes.Status401Unauthorized, "The current user is not authorized to edit a mandate.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), "application/json")]

public async Task<IActionResult> Edit(Mandate mandate)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Geopilot.Api/Controllers/OrganisationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public OrganisationController(ILogger<OrganisationController> logger, Context co
/// </summary>
[HttpGet]
[Authorize(Policy = GeopilotPolicies.Admin)]
[SwaggerResponse(StatusCodes.Status200OK, "Returns list of organisations.", typeof(IEnumerable<Organisation>), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status200OK, "Returns list of organisations.", typeof(IEnumerable<Organisation>), "application/json")]
public List<Organisation> Get()
{
logger.LogInformation("Getting organisations.");
Expand All @@ -53,7 +53,7 @@ public List<Organisation> Get()
[SwaggerResponse(StatusCodes.Status201Created, "The organisation was created successfully.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The organisation could not be created due to invalid input.")]
[SwaggerResponse(StatusCodes.Status401Unauthorized, "The current user is not authorized to create an organisation.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), "application/json")]
public async Task<IActionResult> Create(Organisation organisation)
{
try
Expand Down Expand Up @@ -100,7 +100,7 @@ public async Task<IActionResult> Create(Organisation organisation)
[SwaggerResponse(StatusCodes.Status404NotFound, "The organisation could not be found.")]
[SwaggerResponse(StatusCodes.Status400BadRequest, "The organisation could not be updated due to invalid input.")]
[SwaggerResponse(StatusCodes.Status401Unauthorized, "The current user is not authorized to edit an organisation.")]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), new[] { "application/json" })]
[SwaggerResponse(StatusCodes.Status500InternalServerError, "The server encountered an unexpected condition that prevented it from fulfilling the request. ", typeof(ProblemDetails), "application/json")]

public async Task<IActionResult> Edit(Organisation organisation)
{
Expand Down
Loading

0 comments on commit 5750a2c

Please sign in to comment.