Skip to content

Commit

Permalink
Merge branch 'main' into add-description
Browse files Browse the repository at this point in the history
  • Loading branch information
tschumpr authored May 6, 2024
2 parents 78e2057 + b0b804b commit aca6497
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

[CHANGELOG.md]
end_of_line = lf

[*.{cs,sql,config,csx,fsx}]
; https://github.com/editorconfig/editorconfig/issues/297
charset = utf-8-bom
Expand Down
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,5 @@
*.svg text eol=lf

# *nix shell scripts always use LF (see .editorconfig)
*.sh eol=lf
*.sh text eol=lf
CHANGELOG.md text eol=lf
11 changes: 10 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:

patch-changelog:
runs-on: ubuntu-latest
name: Patch CHANGELOG.md
name: Patch CHANGELOG.md and update GitHub release notes

steps:
- name: Checkout repository
Expand All @@ -74,6 +74,15 @@ jobs:
run: |
echo GIT_BRANCH_NAME=mark-version-${TAG_NAME#v}-as-released >> $GITHUB_ENV
echo GIT_COMMIT_MESSAGE=Mark version ${TAG_NAME#v} as released >> $GITHUB_ENV
echo RELEASE_ID=$(gh api -H "Accept: application/vnd.github+json" /repos/${GITHUB_REPOSITORY}/releases/tags/${TAG_NAME} | jq '.id') >> $GITHUB_ENV
- name: Get changelog for this specific release and update release notes
run: |
gh api \
--method PATCH \
--header "Accept: application/vnd.github+json" \
/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID} \
-f body="$(./get-changelog.sh)"
- name: Checkout new branch and patch changelog
run: |
Expand Down
12 changes: 8 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@

## [Unreleased]

### Added

- When releasing a GitHub pre-release, the release notes are automatically updated with the corresponding entries from the `CHANGELOG.md` file.

## v1.0.87 - 2024-04-26

### Added

- Add licensing information to the about page
- Show delivery comment in STAC browser and on admin page
- Add licensing information to the about page.
- Show delivery comment in STAC browser and on admin page.

### Changed

- Sort delivery mandates alphabetically
- Sort delivery mandates alphabetically.

### Fixed

- Spatial extent in STAC browser
- Spatial extent in STAC browser.
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.4"

services:
stac-browser:
image: ghcr.io/geowerkstatt/stac-browser:latest
Expand Down
23 changes: 23 additions & 0 deletions get-changelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
# This script gets all changelog entries from CHANGELOG.md since last release.

set -e

tempDir="$(mktemp -d)"
tempFile=$tempDir/gh_release_notes.md

# Get changelog entries since last release
cat CHANGELOG.md | \
grep -Pazo '(?s)(?<=\#{2} \[Unreleased\]\n{2}).*?(?=\n\#{2} v|$)' \
> $tempFile

# Improve readability and add some icons
sed -i -E 's/(###) (Added)/\1 🚀 \2/' $tempFile
sed -i -E 's/(###) (Changed)/\1 🔨 \2/' $tempFile
sed -i -E 's/(###) (Fixed)/\1 🐛 \2/' $tempFile
sed -i 's/\x0//g' $tempFile

cat $tempFile

# Cleanup temporary files
trap 'rm -rf -- "$tempDir"' EXIT
14 changes: 7 additions & 7 deletions src/Geopilot.Api/Controllers/MandateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public MandateController(ILogger<MandateController> logger, Context context, IVa
[SwaggerResponse(StatusCodes.Status200OK, "Returns list of mandates associated to the current user matching the optional filter criteria.", typeof(IEnumerable<DeliveryMandate>), new[] { "application/json" })]
public async Task<IActionResult> Get(
[FromQuery, SwaggerParameter("Filter mandates matching validation job file extension.")]
string jobId = "")
Guid jobId = default)
{
logger.LogInformation("Getting mandates for job with id <{JobId}>.", jobId.ReplaceLineEndings(string.Empty));
logger.LogInformation("Getting mandates for job with id <{JobId}>.", jobId);

var user = await context.GetUserByPrincipalAsync(User);
if (user == null)
Expand All @@ -53,24 +53,24 @@ public async Task<IActionResult> Get(
var mandates = context.DeliveryMandates
.Where(m => m.Organisations.SelectMany(o => o.Users).Any(u => u.Id == user.Id));

if (Guid.TryParse(jobId, out var guid))
if (jobId != default)
{
var job = validationService.GetJob(guid);
var job = validationService.GetJob(jobId);
if (job is null)
{
logger.LogTrace("Validation job with id <{JobId}> was not found.", guid.ToString());
logger.LogTrace("Validation job with id <{JobId}> was not found.", jobId);
return Ok(Array.Empty<DeliveryMandate>());
}

logger.LogTrace("Filtering mandates for job with id <{JobId}>", guid.ToString());
logger.LogTrace("Filtering mandates for job with id <{JobId}>", jobId);
var extension = Path.GetExtension(job.OriginalFileName);
mandates = mandates
.Where(m => m.FileTypes.Contains(".*") || m.FileTypes.Contains(extension));
}

var result = await mandates.ToListAsync();

logger.LogInformation("Getting mandates with for job with id <{JobId}> resulted in <{MatchingMandatesCount}> matching mandates.", guid.ToString(), result.Count);
logger.LogInformation("Getting mandates with for job with id <{JobId}> resulted in <{MatchingMandatesCount}> matching mandates.", jobId, result.Count);
return Ok(mandates);
}
}
17 changes: 8 additions & 9 deletions src/Geopilot.Api/Controllers/ValidationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Swashbuckle.AspNetCore.Annotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Web;

namespace Geopilot.Api.Controllers;

Expand Down Expand Up @@ -166,9 +167,7 @@ public IActionResult GetStatus(Guid jobId)
[SwaggerResponse(StatusCodes.Status404NotFound, "The job or log file cannot be found.", typeof(ProblemDetails), new[] { "application/json" })]
public IActionResult Download(Guid jobId, string file)
{
var sanitizedFilename = Path.GetFileName(file.Trim().ReplaceLineEndings(string.Empty));

logger.LogInformation("Download file <{File}> for job <{JobId}> requested.", sanitizedFilename, jobId.ToString());
logger.LogInformation("Download file <{File}> for job <{JobId}> requested.", HttpUtility.HtmlEncode(file), jobId);
fileProvider.Initialize(jobId);

var validationJob = validationService.GetJob(jobId);
Expand All @@ -178,15 +177,15 @@ public IActionResult Download(Guid jobId, string file)
return Problem($"No job information available for job id <{jobId}>", statusCode: StatusCodes.Status404NotFound);
}

if (!fileProvider.Exists(sanitizedFilename))
if (!fileProvider.Exists(file))
{
logger.LogTrace("No log file <{File}> found for job id <{JobId}>", sanitizedFilename, jobId);
return Problem($"No log file <{sanitizedFilename}> found for job id <{jobId}>", statusCode: StatusCodes.Status404NotFound);
logger.LogTrace("No log file <{File}> found for job id <{JobId}>", HttpUtility.HtmlEncode(file), jobId);
return Problem($"No log file <{file}> found for job id <{jobId}>", statusCode: StatusCodes.Status404NotFound);
}

var logFile = fileProvider.Open(sanitizedFilename);
var contentType = contentTypeProvider.GetContentTypeAsString(sanitizedFilename);
var logFileName = Path.GetFileNameWithoutExtension(validationJob.OriginalFileName) + "_log" + Path.GetExtension(sanitizedFilename);
var logFile = fileProvider.Open(file);
var contentType = contentTypeProvider.GetContentTypeAsString(file);
var logFileName = Path.GetFileNameWithoutExtension(validationJob.OriginalFileName) + "_log" + Path.GetExtension(file);
return File(logFile, contentType, logFileName);
}
}
2 changes: 1 addition & 1 deletion src/Geopilot.Api/FileAccess/PhysicalFileProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public Stream Open(string file)
/// <inheritdoc/>
public bool Exists(string file)
{
return File.Exists(Path.Combine(HomeDirectory.FullName, file));
return File.Exists(Path.Combine(HomeDirectory.FullName, file.SanitizeFileName()));
}

/// <inheritdoc/>
Expand Down
30 changes: 30 additions & 0 deletions src/Geopilot.Api/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Geopilot.Api;

/// <summary>
/// GeoPilot API string extensions.
/// </summary>
public static class StringExtensions
{
/// <summary>
/// Sanitizes a file name by removing invalid characters.
/// </summary>
/// <param name="fileName">The file name to sanitize.</param>
/// <returns>The sanitized file name.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="fileName"/> is <c>null</c>,
/// empty or white space.</exception>"
public static string SanitizeFileName(this string fileName)
{
if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentNullException(nameof(fileName));

// Get invalid characters for file names and add some platform-specific ones.
var invalidFileNameChars = Path.GetInvalidFileNameChars()
.Concat(new[] { '?', '$', '*', '|', '<', '>', '"', ':', '\\' }).ToArray();

return Path.GetFileName(new string(fileName
.Trim()
.ReplaceLineEndings(string.Empty)
.Replace("..", string.Empty)
.Replace("./", string.Empty)
.Where(x => !invalidFileNameChars.Contains(x)).ToArray()));
}
}
1 change: 1 addition & 0 deletions tests/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
[*.cs]
dotnet_diagnostic.CA1001.severity = none
dotnet_diagnostic.SA0001.severity = none
dotnet_diagnostic.CS8604.severity = none
dotnet_diagnostic.CS8618.severity = none
6 changes: 3 additions & 3 deletions tests/Geopilot.Api.Test/Controllers/MandateControllerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public async Task GetWithJobIdIncludesMatchingMandates()
.Setup(m => m.GetJob(jobId))
.Returns(new ValidationJob(jobId, "Original.xtf", "tmp.xtf"));

var result = (await mandateController.Get(jobId.ToString())) as OkObjectResult;
var result = (await mandateController.Get(jobId)) as OkObjectResult;
var mandates = (result?.Value as IEnumerable<DeliveryMandate>)?.ToList();

Assert.IsNotNull(mandates);
Expand All @@ -88,7 +88,7 @@ public async Task GetWithJobIdExcludesNonMatchinMandates()
.Setup(m => m.GetJob(jobId))
.Returns(new ValidationJob(jobId, "Original.csv", "tmp.csv"));

var result = (await mandateController.Get(jobId: jobId.ToString())) as OkObjectResult;
var result = (await mandateController.Get(jobId)) as OkObjectResult;
var mandates = (result?.Value as IEnumerable<DeliveryMandate>)?.ToList();

Assert.IsNotNull(mandates);
Expand All @@ -106,7 +106,7 @@ public async Task GetWithInvalidJobIdReturnsEmptyArray()
.Setup(m => m.GetJob(jobId))
.Returns(() => null);

var result = (await mandateController.Get(jobId: jobId.ToString())) as OkObjectResult;
var result = (await mandateController.Get(jobId)) as OkObjectResult;
var mandates = (result?.Value as IEnumerable<DeliveryMandate>)?.ToList();

Assert.IsNotNull(mandates);
Expand Down
44 changes: 44 additions & 0 deletions tests/Geopilot.Api.Test/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace Geopilot.Api.Controllers;

[TestClass]
public class StringExtensions
{
[TestMethod]
[DataRow("SQUIRRELGENESIS", "SQUIRRELGENESIS")]
[DataRow("JUNIORARK.xyz", "JUNIORARK.xyz")]
[DataRow("PEEVEDBEAM-ANT.MESS.abc", "PEEVEDBEAM-ANT.MESS.abc")]
[DataRow("WEIRD WATER.example", "WEIRD WATER.example")]
[DataRow("AUTOFIRE123.doc", "AUTOFIRE123.doc")]
[DataRow("SUNNY(1).doc", "SUNNY(1).doc")]
[DataRow("ODD_MONKEY.doc", "ODD_MONKEY.doc")]
[DataRow("SILLY,MONKEY.docx", "SILLY,MONKEY.docx")]
[DataRow("CamelCase.bat", "CamelCase.bat")]
[DataRow("SLICKER-CHIPMUNK.bat", "SLICKER-CHIPMUNK.bat")]
public void SanitizeFileNameForValidFileNames(string expected, string fileName)
=> Assert.AreEqual(expected, fileName.SanitizeFileName());

[TestMethod]
[DataRow("CHIPMUNKWALK", " CHIPMUNKWALK ")]
[DataRow("SLEEPYBOUNCE", "SLEEPYBOUNCE\n")]
[DataRow("PLOWARK", "PLOWARK\r")]
[DataRow("JUNIORGLEE", "JUNIORGLEE\t")]
[DataRow("SILLYWATER", "SILLYWATER\r\n")]
[DataRow("LATENTROUTE34", "LATENTROUTE?34")]
[DataRow("TRAWLSOUFFLE", "/TRAWLSOUFFLE*")]
[DataRow("VIOLENTIRON", "><VIOLENTIRON\"|")]
[DataRow("YELLOWBAGEL", "YELLOWBAGEL://")]
[DataRow("ZANYWATER", "ZANYWATER$")]
[DataRow("SLICKERCANDID", "..\\SLICKERCANDID")]
[DataRow("DIREFOOT", "./DIREFOOT:")]
[DataRow("FIREFOOT", ".../...//FIREFOOT\\")]
public void SanitizeFileNameForInvalidFileNames(string expected, string fileName)
=> Assert.AreEqual(expected, fileName.SanitizeFileName());

[TestMethod]
public void SanitizeFileNameForInvalid()
{
Assert.ThrowsException<ArgumentNullException>(() => string.Empty.SanitizeFileName());
Assert.ThrowsException<ArgumentNullException>(() => " ".SanitizeFileName());
Assert.ThrowsException<ArgumentNullException>(() => (null as string).SanitizeFileName());
}
}

0 comments on commit aca6497

Please sign in to comment.