From 28a7c4a98c4ef9b40745cb05193d3cf7417db5f4 Mon Sep 17 00:00:00 2001 From: XShine555 Date: Thu, 24 Sep 2026 12:57:53 +0200 Subject: [PATCH] Enable more analyzers, drop log-and-rethrow in file activities and apply dotnet format Use invariant culture when formatting ids, put cancellation tokens last in endpoint handlers, remove the CS8618 pragmas and keep only the analyzer overrides that still apply. --- backend/.editorconfig | 27 ++++++---- .../Configuration/Pictures.cs | 5 +- .../Configuration/TrackConfiguration.cs | 3 +- .../Genres/GetAvailableGenres.cs | 2 +- .../Musify.Application/Genres/GetGenres.cs | 2 +- .../Mixes/GenerateMixesForUser.cs | 2 +- .../Musify.Application/Tracks/CreateTrack.cs | 2 +- .../Tracks/StartListening.cs | 3 +- .../Musify.Application/Users/GetUserById.cs | 2 +- backend/Core/Musify.Domain/Entities/Mix.cs | 3 +- .../Musify.Domain/ValueObjects/TrackAudio.cs | 1 - .../ValueObjects/TrackPictures.cs | 1 - .../Files/CopyFileInBucketActivity.cs | 30 ++++------- .../Files/DownloadFileFromBucketActivity.cs | 40 ++++++-------- .../Files/RemoveFileFromBucketActivity.cs | 7 --- .../Files/TransferFilesToBucketActivity.cs | 26 +++------ .../Files/UploadFileToBucketActivity.cs | 24 +++------ .../Pictures/ResizePictureActivity.cs | 54 ++++++++----------- .../Consumers/RoutingSlipCleanUpConsumer.cs | 8 +-- ...TransitDependencyInjection.Registration.cs | 2 +- .../MassTransitDependencyInjection.cs | 2 +- .../Builders/DeleteRoutingSlipBuilder.cs | 2 +- .../OpenTelemetryDependencyInjection.cs | 2 +- .../DatabaseDependencyInjection.cs | 2 +- .../Services/StreamTicketService.cs | 5 +- .../Authentication/JwtBearerEventsHandler.cs | 18 +++---- .../Musify.Api/Endpoints/AlbumEndpoints.cs | 12 ++--- .../Musify.Api/Endpoints/LikeEndpoints.cs | 4 +- .../Musify.Api/Endpoints/PlayListEndpoints.cs | 8 +-- .../Musify.Api/Endpoints/TrackEndpoints.cs | 8 +-- .../Musify.Api/Endpoints/UserEndpoints.cs | 12 ++--- .../Endpoints/AlbumEndpointsTests.cs | 2 +- .../TestSupport/ApiTestFixture.cs | 3 +- .../GetAvailableGenresQueryHandlerTests.cs | 2 +- .../TestSupport/HandlerTestBase.cs | 6 ++- .../DeleteRoutingSlipBuilderTests.cs | 10 +++- .../TestSupport/InfrastructureTestFixture.cs | 4 +- .../Authentication/TicketValidatorTests.cs | 3 +- .../TicketValidationMiddlewareTests.cs | 3 +- 39 files changed, 160 insertions(+), 192 deletions(-) diff --git a/backend/.editorconfig b/backend/.editorconfig index 8af7303..bcc34a2 100644 --- a/backend/.editorconfig +++ b/backend/.editorconfig @@ -41,6 +41,13 @@ dotnet_naming_symbols.private_fields.applicable_accessibilities = private dotnet_naming_symbols.private_fields.required_modifiers = dotnet_naming_style.camel_case.capitalization = camel_case +dotnet_naming_rule.private_static_readonly.symbols = private_static_readonly +dotnet_naming_rule.private_static_readonly.style = pascal_case +dotnet_naming_rule.private_static_readonly.severity = warning +dotnet_naming_symbols.private_static_readonly.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly.required_modifiers = static, readonly + dotnet_naming_rule.private_constants.symbols = private_constants dotnet_naming_rule.private_constants.style = pascal_case dotnet_naming_rule.private_constants.severity = warning @@ -48,18 +55,16 @@ dotnet_naming_symbols.private_constants.applicable_kinds = field dotnet_naming_symbols.private_constants.required_modifiers = const dotnet_naming_style.pascal_case.capitalization = pascal_case -# Analyzer rules that would need behaviour or API changes; downgraded in P0, revisit in P15. +# CA1848/CA1873 would turn every log call into a [LoggerMessage] source-generated method; CA1716 flags the +# EF-style IDatabase.Set() and the Musify.Application.Shared namespace, whose names are deliberate. dotnet_diagnostic.CA1848.severity = suggestion dotnet_diagnostic.CA1873.severity = suggestion -dotnet_diagnostic.CA1305.severity = suggestion -dotnet_diagnostic.CA1707.severity = suggestion -dotnet_diagnostic.CA1859.severity = suggestion dotnet_diagnostic.CA1716.severity = suggestion -dotnet_diagnostic.CA1000.severity = suggestion -dotnet_diagnostic.CA1725.severity = suggestion -dotnet_diagnostic.CA1816.severity = suggestion +# The routing slip builders are stateless services resolved from DI; they stay instance members. dotnet_diagnostic.CA1822.severity = suggestion -dotnet_diagnostic.CA1852.severity = suggestion -dotnet_diagnostic.CA1068.severity = suggestion -dotnet_diagnostic.CA1711.severity = suggestion -dotnet_diagnostic.CA1861.severity = suggestion + +# Test names follow Method_Scenario_Expected. +[Tests/**.cs] +dotnet_diagnostic.CA1707.severity = none +# xUnit collection fixtures are conventionally named ...Collection. +dotnet_diagnostic.CA1711.severity = none diff --git a/backend/Core/Musify.Application/Configuration/Pictures.cs b/backend/Core/Musify.Application/Configuration/Pictures.cs index bed36ff..5e71035 100644 --- a/backend/Core/Musify.Application/Configuration/Pictures.cs +++ b/backend/Core/Musify.Application/Configuration/Pictures.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Globalization; using Musify.Application.Shared; namespace Musify.Application.Configuration; @@ -41,10 +42,10 @@ public class PictureRoutes public string BuildPicturePath(PictureSize size, string pictureName) => StorageKey.Combine(FolderPath(size), pictureName); public string BuildOriginalPicturePath(long userId, string pictureName) => - StorageKey.Combine(UploadsFolder, userId.ToString(), ParentFolder, OriginalPicturesFolder, pictureName); + StorageKey.Combine(UploadsFolder, userId.ToString(CultureInfo.InvariantCulture), ParentFolder, OriginalPicturesFolder, pictureName); public string BuildTempPath(string tempRootPrefix, long userId, string objectName) => - StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolder, objectName); + StorageKey.Combine(tempRootPrefix, userId.ToString(CultureInfo.InvariantCulture), ParentFolder, objectName); } public class PictureSizes diff --git a/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs b/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs index b391286..80b8df3 100644 --- a/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Globalization; using Musify.Application.Shared; namespace Musify.Application.Configuration; @@ -48,7 +49,7 @@ public class TrackRoutes : PictureRoutes public string PresetLargePicturePath => StorageKey.Combine(ParentFolder, PresetLargePicture); public string BuildOriginalAudioPath(long userId, string audioName) => - StorageKey.Combine(UploadsFolder, userId.ToString(), ParentFolder, OriginalAudiosFolder, audioName); + StorageKey.Combine(UploadsFolder, userId.ToString(CultureInfo.InvariantCulture), ParentFolder, OriginalAudiosFolder, audioName); public string BuildProcessedAudioPath(string folderName) => StorageKey.Combine(ParentFolder, ProcessedAudiosFolder, folderName); diff --git a/backend/Core/Musify.Application/Genres/GetAvailableGenres.cs b/backend/Core/Musify.Application/Genres/GetAvailableGenres.cs index cffdd5f..694c9cd 100644 --- a/backend/Core/Musify.Application/Genres/GetAvailableGenres.cs +++ b/backend/Core/Musify.Application/Genres/GetAvailableGenres.cs @@ -1,6 +1,6 @@ using Mediator; -using Musify.Domain.ValueObjects; using Musify.Application.Genres.Responses; +using Musify.Domain.ValueObjects; namespace Musify.Application.Genres; diff --git a/backend/Core/Musify.Application/Genres/GetGenres.cs b/backend/Core/Musify.Application/Genres/GetGenres.cs index 396db60..6ad2465 100644 --- a/backend/Core/Musify.Application/Genres/GetGenres.cs +++ b/backend/Core/Musify.Application/Genres/GetGenres.cs @@ -1,8 +1,8 @@ using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; -using Musify.Domain.ValueObjects; using Musify.Application.Genres.Responses; +using Musify.Domain.ValueObjects; namespace Musify.Application.Genres; diff --git a/backend/Core/Musify.Application/Mixes/GenerateMixesForUser.cs b/backend/Core/Musify.Application/Mixes/GenerateMixesForUser.cs index e5c6a26..0bf792f 100644 --- a/backend/Core/Musify.Application/Mixes/GenerateMixesForUser.cs +++ b/backend/Core/Musify.Application/Mixes/GenerateMixesForUser.cs @@ -79,7 +79,7 @@ public class GenerateMixesForUserCommandHandler( private static List Shuffle(IEnumerable trackIds) => [.. trackIds.OrderBy(_ => Guid.NewGuid())]; - private static List Interleave(IReadOnlyList first, IReadOnlyList second) + private static List Interleave(List first, List second) { var merged = new List(first.Count + second.Count); for (var index = 0; index < Math.Max(first.Count, second.Count); index++) diff --git a/backend/Core/Musify.Application/Tracks/CreateTrack.cs b/backend/Core/Musify.Application/Tracks/CreateTrack.cs index 6c42b75..52ec80d 100644 --- a/backend/Core/Musify.Application/Tracks/CreateTrack.cs +++ b/backend/Core/Musify.Application/Tracks/CreateTrack.cs @@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Musify.Application.Configuration; using Musify.Application.Contracts; -using Musify.Application.Shared; using Musify.Application.Events; using Musify.Application.Services; +using Musify.Application.Shared; using Musify.Application.Tracks.Responses; using Musify.Domain.Entities; using Musify.Domain.ValueObjects; diff --git a/backend/Core/Musify.Application/Tracks/StartListening.cs b/backend/Core/Musify.Application/Tracks/StartListening.cs index d580698..ef3aeb1 100644 --- a/backend/Core/Musify.Application/Tracks/StartListening.cs +++ b/backend/Core/Musify.Application/Tracks/StartListening.cs @@ -1,3 +1,4 @@ +using System.Globalization; using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; @@ -48,7 +49,7 @@ public class StartListeningCommandHandler( listenId = listen.Id; } - logger.LogInformation("Issued stream ticket for track {TrackId} to user {UserId}", request.TrackId, request.UserId?.ToString() ?? "(anonymous)"); + logger.LogInformation("Issued stream ticket for track {TrackId} to user {UserId}", request.TrackId, request.UserId?.ToString(CultureInfo.InvariantCulture) ?? "(anonymous)"); return streamIssuer.Issue(track.Audio.FolderName, request.UserId, listenId); } diff --git a/backend/Core/Musify.Application/Users/GetUserById.cs b/backend/Core/Musify.Application/Users/GetUserById.cs index 3069355..0d6eab3 100644 --- a/backend/Core/Musify.Application/Users/GetUserById.cs +++ b/backend/Core/Musify.Application/Users/GetUserById.cs @@ -2,8 +2,8 @@ using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; -using Musify.Application.Users.Responses; using Musify.Application.Shared; +using Musify.Application.Users.Responses; namespace Musify.Application.Users; diff --git a/backend/Core/Musify.Domain/Entities/Mix.cs b/backend/Core/Musify.Domain/Entities/Mix.cs index 52df127..4951abe 100644 --- a/backend/Core/Musify.Domain/Entities/Mix.cs +++ b/backend/Core/Musify.Domain/Entities/Mix.cs @@ -1,8 +1,7 @@ using System.ComponentModel.DataAnnotations; -using Musify.Domain.ValueObjects; using System.ComponentModel.DataAnnotations.Schema; - using Musify.Domain.Abstractions; +using Musify.Domain.ValueObjects; namespace Musify.Domain.Entities; diff --git a/backend/Core/Musify.Domain/ValueObjects/TrackAudio.cs b/backend/Core/Musify.Domain/ValueObjects/TrackAudio.cs index a558d13..8ed8584 100644 --- a/backend/Core/Musify.Domain/ValueObjects/TrackAudio.cs +++ b/backend/Core/Musify.Domain/ValueObjects/TrackAudio.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Musify.Domain.ValueObjects; -#pragma warning disable CS8618 public class TrackAudio { public string? OriginalName { get; set; } diff --git a/backend/Core/Musify.Domain/ValueObjects/TrackPictures.cs b/backend/Core/Musify.Domain/ValueObjects/TrackPictures.cs index 511f658..05a57d8 100644 --- a/backend/Core/Musify.Domain/ValueObjects/TrackPictures.cs +++ b/backend/Core/Musify.Domain/ValueObjects/TrackPictures.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; namespace Musify.Domain.ValueObjects; -#pragma warning disable CS8618 public class TrackPictures { public string? OriginalName { get; set; } diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs index b6e4861..5662355 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/CopyFileInBucketActivity.cs @@ -15,28 +15,16 @@ internal class CopyFileInBucketActivity( public async Task Execute(ExecuteContext executeContext) { - try - { - await storageService.CopyFileAsync( - executeContext.Arguments.SourceBucket, - executeContext.Arguments.SourceKey, - executeContext.Arguments.DestinationBucket, - executeContext.Arguments.DestinationKey, - executeContext.CancellationToken); + await storageService.CopyFileAsync( + executeContext.Arguments.SourceBucket, + executeContext.Arguments.SourceKey, + executeContext.Arguments.DestinationBucket, + executeContext.Arguments.DestinationKey, + executeContext.CancellationToken); - return executeContext.Completed(new CopyFileInBucketLog( - executeContext.Arguments.DestinationBucket, - executeContext.Arguments.DestinationKey)); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to copy {SourceBucket}/{SourceKey} to {DestinationBucket}/{DestinationKey}", - executeContext.Arguments.SourceBucket, - executeContext.Arguments.SourceKey, - executeContext.Arguments.DestinationBucket, - executeContext.Arguments.DestinationKey); - throw; - } + return executeContext.Completed(new CopyFileInBucketLog( + executeContext.Arguments.DestinationBucket, + executeContext.Arguments.DestinationKey)); } public async Task Compensate(CompensateContext compensateContext) diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/DownloadFileFromBucketActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/DownloadFileFromBucketActivity.cs index 6b246a5..3faab94 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/DownloadFileFromBucketActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/DownloadFileFromBucketActivity.cs @@ -18,33 +18,25 @@ internal class DownloadFileFromBucketActivity( var destinationPath = executeContext.GetVariable(executeContext.Arguments.DestinationFilePathVariable); ArgumentNullException.ThrowIfNull(destinationPath); - try - { - using var fileStream = await storageService.GetFileAsync( - executeContext.Arguments.Bucket, - executeContext.Arguments.Key, - executeContext.CancellationToken) - ?? throw new FileNotFoundException($"Object {executeContext.Arguments.Bucket}/{executeContext.Arguments.Key} was not found."); + using var fileStream = await storageService.GetFileAsync( + executeContext.Arguments.Bucket, + executeContext.Arguments.Key, + executeContext.CancellationToken) + ?? throw new FileNotFoundException($"Object {executeContext.Arguments.Bucket}/{executeContext.Arguments.Key} was not found."); - var destinationDirectory = Path.GetDirectoryName(destinationPath); - if (!string.IsNullOrWhiteSpace(destinationDirectory)) - Directory.CreateDirectory(destinationDirectory); + var destinationDirectory = Path.GetDirectoryName(destinationPath); + if (!string.IsNullOrWhiteSpace(destinationDirectory)) + Directory.CreateDirectory(destinationDirectory); - if (fileStream.CanSeek) - fileStream.Position = 0; + if (fileStream.CanSeek) + fileStream.Position = 0; - using var destinationStream = File.Create(destinationPath); - await fileStream.CopyToAsync(destinationStream, executeContext.CancellationToken); - return executeContext.Completed(new DownloadFileFromBucketLog( - executeContext.Arguments.Bucket, - executeContext.Arguments.Key, - destinationPath)); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to download file from bucket"); - throw; - } + using var destinationStream = File.Create(destinationPath); + await fileStream.CopyToAsync(destinationStream, executeContext.CancellationToken); + return executeContext.Completed(new DownloadFileFromBucketLog( + executeContext.Arguments.Bucket, + executeContext.Arguments.Key, + destinationPath)); } public Task Compensate(CompensateContext compensateContext) diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/RemoveFileFromBucketActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/RemoveFileFromBucketActivity.cs index 73c737b..e5fce5d 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/RemoveFileFromBucketActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/RemoveFileFromBucketActivity.cs @@ -34,12 +34,5 @@ internal class RemoveFileFromBucketActivity( executeContext.Arguments.Bucket); return executeContext.Completed(); } - catch (Exception exception) - { - logger.LogError(exception, "Failed to remove {Key} from bucket {Bucket}", - executeContext.Arguments.Key, - executeContext.Arguments.Bucket); - throw; - } } } diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/TransferFilesToBucketActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/TransferFilesToBucketActivity.cs index eb397d8..7b5f310 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/TransferFilesToBucketActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/TransferFilesToBucketActivity.cs @@ -20,25 +20,15 @@ internal class TransferFilesToBucketActivity( var destinationKey = executeContext.Arguments.DestinationKey; ArgumentNullException.ThrowIfNull(destinationKey); - try - { - var uploadedKeys = await storageService.TransferFilesAsync( - folderPath, - executeContext.Arguments.DestinationBucket, - destinationKey, - executeContext.CancellationToken); + var uploadedKeys = await storageService.TransferFilesAsync( + folderPath, + executeContext.Arguments.DestinationBucket, + destinationKey, + executeContext.CancellationToken); - return executeContext.Completed(new TransferFilesToBucketLog( - executeContext.Arguments.DestinationBucket, - uploadedKeys.ToArray())); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to transfer files from {FolderPath} to {DestinationBucket}", - folderPath, - executeContext.Arguments.DestinationBucket); - throw; - } + return executeContext.Completed(new TransferFilesToBucketLog( + executeContext.Arguments.DestinationBucket, + uploadedKeys.ToArray())); } public async Task Compensate(CompensateContext compensateContext) diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.cs index c9adc6f..f66d1db 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.cs @@ -21,22 +21,14 @@ internal class UploadFileToBucketActivity(IStorageService storageService, .Where(static s => !string.IsNullOrWhiteSpace(s)) .Select(static s => s.Trim().Trim('/', '\\'))); - try - { - await storageService.UploadFileAsync( - sourceFilePath, - executeContext.Arguments.DestinationBucket, - destinationKey, - executeContext.CancellationToken); - return executeContext.CompletedWithVariables(new UploadFileToBucketLog( - executeContext.Arguments.DestinationBucket, - destinationKey)); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to upload file to bucket"); - throw; - } + await storageService.UploadFileAsync( + sourceFilePath, + executeContext.Arguments.DestinationBucket, + destinationKey, + executeContext.CancellationToken); + return executeContext.CompletedWithVariables(new UploadFileToBucketLog( + executeContext.Arguments.DestinationBucket, + destinationKey)); } public async Task Compensate(CompensateContext compensateContext) diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Pictures/ResizePictureActivity.cs b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Pictures/ResizePictureActivity.cs index f3614ba..94c7758 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Activities/Pictures/ResizePictureActivity.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Activities/Pictures/ResizePictureActivity.cs @@ -20,39 +20,31 @@ internal class ResizePictureActivity( var destinationFilePath = executeContext.GetVariable(executeContext.Arguments.DestinationFilePathVariable); ArgumentNullException.ThrowIfNull(destinationFilePath); - try + if (!File.Exists(sourceFilePath)) { - if (!File.Exists(sourceFilePath)) - { - logger.LogWarning("Source file not found: {SourceFilePath}", sourceFilePath); - throw new FileNotFoundException($"Source file not found: {sourceFilePath}"); - } - - await using var fileStream = File.OpenRead(sourceFilePath); - - await using var resizedPicture = await pictureHandler.ResizePictureAsWebpAsync( - fileStream, - executeContext.Arguments.Width, - executeContext.Arguments.Height, - executeContext.CancellationToken); - - var destinationDirectory = Path.GetDirectoryName(destinationFilePath); - if (!string.IsNullOrEmpty(destinationDirectory)) - Directory.CreateDirectory(destinationDirectory); - - await using var destinationStream = File.Create(destinationFilePath); - await resizedPicture.CopyToAsync(destinationStream, executeContext.CancellationToken); - - logger.LogDebug("Resized picture from {SourceFilePath} to {DestinationFilePath}", - sourceFilePath, - destinationFilePath); - return executeContext.Completed(new ResizePictureLog(destinationFilePath)); - } - catch (Exception exception) - { - logger.LogError(exception, "Failed to resize picture {SourceFilePath}", sourceFilePath); - throw; + logger.LogWarning("Source file not found: {SourceFilePath}", sourceFilePath); + throw new FileNotFoundException($"Source file not found: {sourceFilePath}"); } + + await using var fileStream = File.OpenRead(sourceFilePath); + + await using var resizedPicture = await pictureHandler.ResizePictureAsWebpAsync( + fileStream, + executeContext.Arguments.Width, + executeContext.Arguments.Height, + executeContext.CancellationToken); + + var destinationDirectory = Path.GetDirectoryName(destinationFilePath); + if (!string.IsNullOrEmpty(destinationDirectory)) + Directory.CreateDirectory(destinationDirectory); + + await using var destinationStream = File.Create(destinationFilePath); + await resizedPicture.CopyToAsync(destinationStream, executeContext.CancellationToken); + + logger.LogDebug("Resized picture from {SourceFilePath} to {DestinationFilePath}", + sourceFilePath, + destinationFilePath); + return executeContext.Completed(new ResizePictureLog(destinationFilePath)); } public Task Compensate(CompensateContext compensateContext) diff --git a/backend/Core/Musify.Infrastructure/MassTransit/Consumers/RoutingSlipCleanUpConsumer.cs b/backend/Core/Musify.Infrastructure/MassTransit/Consumers/RoutingSlipCleanUpConsumer.cs index 870e010..0239bd4 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/Consumers/RoutingSlipCleanUpConsumer.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/Consumers/RoutingSlipCleanUpConsumer.cs @@ -12,11 +12,11 @@ public class RoutingSlipCleanUpConsumer( { public const string QueueName = "routing-slip-clean-up"; - public Task Consume(ConsumeContext consumeContext) - => DeleteFolder(consumeContext.Message.Variables); + public Task Consume(ConsumeContext context) + => DeleteFolder(context.Message.Variables); - public Task Consume(ConsumeContext consumeContext) - => DeleteFolder(consumeContext.Message.Variables); + public Task Consume(ConsumeContext context) + => DeleteFolder(context.Message.Variables); private Task DeleteFolder(IDictionary variables) { diff --git a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs index b039d5a..0053b0d 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Musify.Infrastructure.MassTransit.Activities.Albums; using Musify.Infrastructure.MassTransit.Activities.Audio; using Musify.Infrastructure.MassTransit.Activities.Files; +using Musify.Infrastructure.MassTransit.Activities.LifeCycle; using Musify.Infrastructure.MassTransit.Activities.Pictures; using Musify.Infrastructure.MassTransit.Activities.PlayLists; using Musify.Infrastructure.MassTransit.Activities.Tracks; @@ -11,7 +12,6 @@ using Musify.Infrastructure.MassTransit.Arguments; using Musify.Infrastructure.MassTransit.Consumers; using Musify.Infrastructure.MassTransit.Logs; using Musify.Infrastructure.MassTransit.RoutingSlip.Builders; -using Musify.Infrastructure.MassTransit.Activities.LifeCycle; namespace Musify.Infrastructure.MassTransit; diff --git a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs index f5ec69a..3ddf79f 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs @@ -1,11 +1,11 @@ using MassTransit; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Musify.Application.Configuration; using Musify.Application.Contracts; using Musify.Infrastructure.Configuration; using Musify.Infrastructure.MassTransit.Sagas; using Musify.Infrastructure.Persistence; -using Musify.Application.Configuration; namespace Musify.Infrastructure.MassTransit; diff --git a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteRoutingSlipBuilder.cs b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteRoutingSlipBuilder.cs index b13d252..694c7ff 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteRoutingSlipBuilder.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteRoutingSlipBuilder.cs @@ -3,8 +3,8 @@ using Microsoft.EntityFrameworkCore; using Musify.Application.Configuration; using Musify.Application.Contracts; using Musify.Domain.ValueObjects; -using Musify.Infrastructure.MassTransit.Arguments; using Musify.Infrastructure.MassTransit.Activities.LifeCycle; +using Musify.Infrastructure.MassTransit.Arguments; namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders; diff --git a/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs b/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs index 83a513f..2178791 100644 --- a/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs @@ -1,12 +1,12 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Musify.Application.Configuration; using Musify.Infrastructure.Configuration; using OpenTelemetry.Exporter; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; -using Musify.Application.Configuration; namespace Musify.Infrastructure.Observability; diff --git a/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs b/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs index c21b070..9ba10fe 100644 --- a/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs @@ -1,8 +1,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Musify.Application.Configuration; using Musify.Application.Contracts; using Musify.Infrastructure.Configuration; -using Musify.Application.Configuration; namespace Musify.Infrastructure.Persistence; diff --git a/backend/Core/Musify.Infrastructure/Services/StreamTicketService.cs b/backend/Core/Musify.Infrastructure/Services/StreamTicketService.cs index f5c8d17..f52e92a 100644 --- a/backend/Core/Musify.Infrastructure/Services/StreamTicketService.cs +++ b/backend/Core/Musify.Infrastructure/Services/StreamTicketService.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Security.Cryptography; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -30,9 +31,9 @@ public sealed class StreamTicketService : IStreamTicketService, IDisposable var claims = new Dictionary { ["prefix"] = keyPrefix }; if (userId != null) - claims["sub"] = userId.Value.ToString(); + claims["sub"] = userId.Value.ToString(CultureInfo.InvariantCulture); if (maxBytes != null) - claims["maxBytes"] = maxBytes.Value.ToString(); + claims["maxBytes"] = maxBytes.Value.ToString(CultureInfo.InvariantCulture); var descriptor = new SecurityTokenDescriptor { diff --git a/backend/Hosts/Musify.Api/Authentication/JwtBearerEventsHandler.cs b/backend/Hosts/Musify.Api/Authentication/JwtBearerEventsHandler.cs index 6f65216..2a705c9 100644 --- a/backend/Hosts/Musify.Api/Authentication/JwtBearerEventsHandler.cs +++ b/backend/Hosts/Musify.Api/Authentication/JwtBearerEventsHandler.cs @@ -26,9 +26,9 @@ public sealed class JwtBearerEventsHandler( [property: JsonPropertyName("family_name")] string? FamilyName, [property: JsonPropertyName("picture")] string? Picture); - public override async Task TokenValidated(TokenValidatedContext tokenValidatedContext) + public override async Task TokenValidated(TokenValidatedContext context) { - var principal = tokenValidatedContext.Principal!; + var principal = context.Principal!; var rawId = principal.FindFirstValue(ClaimTypes.NameIdentifier); if (!long.TryParse(rawId, out var userId)) @@ -41,7 +41,7 @@ public sealed class JwtBearerEventsHandler( if (cache.TryGetValue(cacheKey, out _)) return; - var userInfo = await FetchUserInfoAsync(tokenValidatedContext, tokenValidatedContext.HttpContext.RequestAborted); + var userInfo = await FetchUserInfoAsync(context, context.HttpContext.RequestAborted); var username = userInfo?.Name ?? userInfo?.PreferredUsername @@ -65,7 +65,7 @@ public sealed class JwtBearerEventsHandler( { await mediator.Send( new SyncUserCommand(userId, username, firstName, lastName, profilePictureUrl), - tokenValidatedContext.HttpContext.RequestAborted); + context.HttpContext.RequestAborted); cache.Set(cacheKey, true, UserSyncCacheTtl); } @@ -76,9 +76,9 @@ public sealed class JwtBearerEventsHandler( } private async Task FetchUserInfoAsync( - TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken) + TokenValidatedContext context, CancellationToken cancellationToken) { - var authorizationHeader = tokenValidatedContext.HttpContext.Request.Headers.Authorization.ToString(); + var authorizationHeader = context.HttpContext.Request.Headers.Authorization.ToString(); if (!authorizationHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) return null; @@ -88,7 +88,7 @@ public sealed class JwtBearerEventsHandler( try { - var userInfoEndpoint = await ResolveUserInfoEndpointAsync(tokenValidatedContext, cancellationToken); + var userInfoEndpoint = await ResolveUserInfoEndpointAsync(context, cancellationToken); var client = httpClientFactory.CreateClient(); using var request = new HttpRequestMessage(HttpMethod.Get, userInfoEndpoint) @@ -113,9 +113,9 @@ public sealed class JwtBearerEventsHandler( } private async Task ResolveUserInfoEndpointAsync( - TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken) + TokenValidatedContext context, CancellationToken cancellationToken) { - var configurationManager = tokenValidatedContext.Options.ConfigurationManager; + var configurationManager = context.Options.ConfigurationManager; if (configurationManager != null) { var configuration = await configurationManager.GetConfigurationAsync(cancellationToken); diff --git a/backend/Hosts/Musify.Api/Endpoints/AlbumEndpoints.cs b/backend/Hosts/Musify.Api/Endpoints/AlbumEndpoints.cs index 1e56399..2d7a4df 100644 --- a/backend/Hosts/Musify.Api/Endpoints/AlbumEndpoints.cs +++ b/backend/Hosts/Musify.Api/Endpoints/AlbumEndpoints.cs @@ -129,9 +129,9 @@ public static class AlbumEndpoints private static async Task GetAlbums( IMediator mediator, - CancellationToken cancellationToken, string? title, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetAlbumsQuery(title, page.PageNumber, page.PageSize), cancellationToken); return Results.Ok(result); @@ -149,8 +149,8 @@ public static class AlbumEndpoints private static async Task GetAlbumsByUserId( IMediator mediator, long userId, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetAlbumsByUserIdQuery(userId, page.PageNumber, page.PageSize), cancellationToken); return result.ToHttpResult(); @@ -177,8 +177,8 @@ public static class AlbumEndpoints private static async Task GetAlbumTracks( IMediator mediator, Guid id, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetAlbumTracksQuery(id, page.PageNumber, page.PageSize), cancellationToken); return result.ToHttpResult(); diff --git a/backend/Hosts/Musify.Api/Endpoints/LikeEndpoints.cs b/backend/Hosts/Musify.Api/Endpoints/LikeEndpoints.cs index 6d1ec73..af30182 100644 --- a/backend/Hosts/Musify.Api/Endpoints/LikeEndpoints.cs +++ b/backend/Hosts/Musify.Api/Endpoints/LikeEndpoints.cs @@ -38,8 +38,8 @@ public static class LikeEndpoints private static async Task GetLikedTracks( IMediator mediator, CurrentUser currentUser, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetLikedTracksQuery(currentUser.RequiredId, page.PageNumber, page.PageSize), cancellationToken); return Results.Ok(result); diff --git a/backend/Hosts/Musify.Api/Endpoints/PlayListEndpoints.cs b/backend/Hosts/Musify.Api/Endpoints/PlayListEndpoints.cs index 74d51ac..d21d8b4 100644 --- a/backend/Hosts/Musify.Api/Endpoints/PlayListEndpoints.cs +++ b/backend/Hosts/Musify.Api/Endpoints/PlayListEndpoints.cs @@ -125,9 +125,9 @@ public static class PlayListEndpoints IMediator mediator, CurrentUser currentUser, long userId, - CancellationToken cancellationToken, string? name, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetPlayListsByUserIdQuery(userId, name, page.PageNumber, page.PageSize, currentUser.Id), cancellationToken); return Results.Ok(result); @@ -137,8 +137,8 @@ public static class PlayListEndpoints IMediator mediator, CurrentUser currentUser, Guid id, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetPlayListTracksQuery(id, page.PageNumber, page.PageSize, currentUser.Id), cancellationToken); return result.ToHttpResult(); diff --git a/backend/Hosts/Musify.Api/Endpoints/TrackEndpoints.cs b/backend/Hosts/Musify.Api/Endpoints/TrackEndpoints.cs index 3db1c4e..c8ee6e1 100644 --- a/backend/Hosts/Musify.Api/Endpoints/TrackEndpoints.cs +++ b/backend/Hosts/Musify.Api/Endpoints/TrackEndpoints.cs @@ -97,10 +97,10 @@ public static class TrackEndpoints private static async Task GetTracks( IMediator mediator, - CancellationToken cancellationToken, string? name, GenreParameter? genre, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetTracksQuery(name, page.PageNumber, page.PageSize, genre?.Value), cancellationToken); return Results.Ok(result); @@ -152,9 +152,9 @@ public static class TrackEndpoints private static async Task GetTracksByUserId( IMediator mediator, long userId, - CancellationToken cancellationToken, string? name, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetTracksByUserIdQuery(userId, name, page.PageNumber, page.PageSize), cancellationToken); return result.ToHttpResult(); diff --git a/backend/Hosts/Musify.Api/Endpoints/UserEndpoints.cs b/backend/Hosts/Musify.Api/Endpoints/UserEndpoints.cs index 5eaac41..1c6815e 100644 --- a/backend/Hosts/Musify.Api/Endpoints/UserEndpoints.cs +++ b/backend/Hosts/Musify.Api/Endpoints/UserEndpoints.cs @@ -100,9 +100,9 @@ public static class UserEndpoints private static async Task GetUsers( IMediator mediator, CurrentUser currentUser, - CancellationToken cancellationToken, string? usernameSearch, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetUsersQuery(page.PageNumber, page.PageSize, usernameSearch, currentUser.Id), cancellationToken); return Results.Ok(result); @@ -162,8 +162,8 @@ public static class UserEndpoints IMediator mediator, CurrentUser currentUser, long id, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetUserFollowersQuery(currentUser.Id, id, page.PageNumber, page.PageSize), cancellationToken); return result.ToHttpResult(); @@ -173,8 +173,8 @@ public static class UserEndpoints IMediator mediator, CurrentUser currentUser, long id, - CancellationToken cancellationToken, - [AsParameters] PageQuery page) + [AsParameters] PageQuery page, + CancellationToken cancellationToken) { var result = await mediator.Send(new GetUserFollowingQuery(currentUser.Id, id, page.PageNumber, page.PageSize), cancellationToken); return result.ToHttpResult(); diff --git a/backend/Tests/Musify.Api.Tests/Endpoints/AlbumEndpointsTests.cs b/backend/Tests/Musify.Api.Tests/Endpoints/AlbumEndpointsTests.cs index 4a7f5c9..0a79070 100644 --- a/backend/Tests/Musify.Api.Tests/Endpoints/AlbumEndpointsTests.cs +++ b/backend/Tests/Musify.Api.Tests/Endpoints/AlbumEndpointsTests.cs @@ -4,8 +4,8 @@ using Musify.Api.DataTransferObjects; using Musify.Api.DataTransferObjects.Albums; using Musify.Api.Tests.TestSupport; using Musify.Application.Albums.Responses; -using Musify.Application.Pictures.Responses; using Musify.Application.Contracts; +using Musify.Application.Pictures.Responses; using NSubstitute; using Xunit; diff --git a/backend/Tests/Musify.Api.Tests/TestSupport/ApiTestFixture.cs b/backend/Tests/Musify.Api.Tests/TestSupport/ApiTestFixture.cs index e2a5961..83751b4 100644 --- a/backend/Tests/Musify.Api.Tests/TestSupport/ApiTestFixture.cs +++ b/backend/Tests/Musify.Api.Tests/TestSupport/ApiTestFixture.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; @@ -64,7 +65,7 @@ public sealed class ApiTestFixture : WebApplicationFactory, IAsyncLifet public HttpClient CreateAuthenticatedClient(long userId, string userName = "test-user") { var client = CreateClient(); - client.DefaultRequestHeaders.Add(FakeAuthenticationHandler.UserIdHeader, userId.ToString()); + client.DefaultRequestHeaders.Add(FakeAuthenticationHandler.UserIdHeader, userId.ToString(CultureInfo.InvariantCulture)); client.DefaultRequestHeaders.Add("X-Test-User-Name", userName); return client; } diff --git a/backend/Tests/Musify.Application.Tests/Genres/GetAvailableGenresQueryHandlerTests.cs b/backend/Tests/Musify.Application.Tests/Genres/GetAvailableGenresQueryHandlerTests.cs index 29fd50d..9e63b58 100644 --- a/backend/Tests/Musify.Application.Tests/Genres/GetAvailableGenresQueryHandlerTests.cs +++ b/backend/Tests/Musify.Application.Tests/Genres/GetAvailableGenresQueryHandlerTests.cs @@ -1,7 +1,7 @@ using Musify.Application.Genres; +using Musify.Application.Genres.Responses; using Musify.Domain.ValueObjects; using Xunit; -using Musify.Application.Genres.Responses; namespace Musify.Application.Tests.Genres; diff --git a/backend/Tests/Musify.Application.Tests/TestSupport/HandlerTestBase.cs b/backend/Tests/Musify.Application.Tests/TestSupport/HandlerTestBase.cs index 42b925f..544efda 100644 --- a/backend/Tests/Musify.Application.Tests/TestSupport/HandlerTestBase.cs +++ b/backend/Tests/Musify.Application.Tests/TestSupport/HandlerTestBase.cs @@ -12,7 +12,11 @@ public abstract class HandlerTestBase : IAsyncLifetime public async ValueTask InitializeAsync() => database = await TestDatabase.CreateAsync(); - public ValueTask DisposeAsync() => database.DisposeAsync(); + public ValueTask DisposeAsync() + { + GC.SuppressFinalize(this); + return database.DisposeAsync(); + } protected static ILogger NoOpLogger() => NullLogger.Instance; diff --git a/backend/Tests/Musify.Infrastructure.Tests/MassTransit/DeleteRoutingSlipBuilderTests.cs b/backend/Tests/Musify.Infrastructure.Tests/MassTransit/DeleteRoutingSlipBuilderTests.cs index a2b7af5..d1a0705 100644 --- a/backend/Tests/Musify.Infrastructure.Tests/MassTransit/DeleteRoutingSlipBuilderTests.cs +++ b/backend/Tests/Musify.Infrastructure.Tests/MassTransit/DeleteRoutingSlipBuilderTests.cs @@ -18,7 +18,10 @@ public sealed class DeleteRoutingSlipBuilderTests(InfrastructureTestFixture fixt { var album = await SeedAlbumAsync(new EntityPictures { - OriginalName = "original.webp", SmallName = "small.webp", MediumName = "medium.webp", LargeName = "large.webp" + OriginalName = "original.webp", + SmallName = "small.webp", + MediumName = "medium.webp", + LargeName = "large.webp" }); await using var database = fixture.CreateDatabase(); @@ -116,7 +119,10 @@ public sealed class DeleteRoutingSlipBuilderTests(InfrastructureTestFixture fixt var track = await SeedTrackAsync( new TrackPictures { - OriginalName = "original.webp", SmallName = "s.webp", MediumName = "m.webp", LargeName = "l.webp", + OriginalName = "original.webp", + SmallName = "s.webp", + MediumName = "m.webp", + LargeName = "l.webp", ProcessingStatus = ProcessingStatus.Completed }, new TrackAudio { OriginalName = "audio.mp3", FolderName = "folder", TranscodeStatus = ProcessingStatus.Completed }); diff --git a/backend/Tests/Musify.Infrastructure.Tests/TestSupport/InfrastructureTestFixture.cs b/backend/Tests/Musify.Infrastructure.Tests/TestSupport/InfrastructureTestFixture.cs index a504aa2..7ccc578 100644 --- a/backend/Tests/Musify.Infrastructure.Tests/TestSupport/InfrastructureTestFixture.cs +++ b/backend/Tests/Musify.Infrastructure.Tests/TestSupport/InfrastructureTestFixture.cs @@ -18,6 +18,8 @@ public sealed class InfrastructureTestFixture : IAsyncLifetime public const string S3SecretKey = "musify-test-secret"; public const string S3Bucket = "musify-test-bucket"; + private static readonly string[] S3Actions = ["Admin", "Read", "Write"]; + private readonly PostgreSqlContainer postgres = new PostgreSqlBuilder("postgres:17-alpine") .WithDatabase("musify_test") .WithUsername("postgres") @@ -83,7 +85,7 @@ public sealed class InfrastructureTestFixture : IAsyncLifetime { name = "musify-test", credentials = new[] { new { accessKey = S3AccessKey, secretKey = S3SecretKey } }, - actions = new[] { "Admin", "Read", "Write" } + actions = S3Actions } } }); diff --git a/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs b/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs index 801e9b6..d96b479 100644 --- a/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs +++ b/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Security.Cryptography; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -36,7 +37,7 @@ public sealed class TicketValidatorTests : IDisposable { var claims = new Dictionary { ["prefix"] = prefix }; if (maxBytes != null) - claims["maxBytes"] = maxBytes.Value.ToString(); + claims["maxBytes"] = maxBytes.Value.ToString(CultureInfo.InvariantCulture); var descriptor = new SecurityTokenDescriptor { diff --git a/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs b/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs index a4735f0..96fe153 100644 --- a/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs +++ b/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Security.Cryptography; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging.Abstractions; @@ -39,7 +40,7 @@ public sealed class TicketValidationMiddlewareTests : IDisposable { var claims = new Dictionary { ["prefix"] = prefix }; if (maxBytes != null) - claims["maxBytes"] = maxBytes.Value.ToString(); + claims["maxBytes"] = maxBytes.Value.ToString(CultureInfo.InvariantCulture); return new JsonWebTokenHandler().CreateToken(new SecurityTokenDescriptor {