diff --git a/backend/Core/Musify.Application/Albums/CreateAlbum.cs b/backend/Core/Musify.Application/Albums/CreateAlbum.cs index 39722ca..eac52f3 100644 --- a/backend/Core/Musify.Application/Albums/CreateAlbum.cs +++ b/backend/Core/Musify.Application/Albums/CreateAlbum.cs @@ -7,7 +7,6 @@ using Musify.Application.Configuration; using Musify.Application.Contracts; using Musify.Application.Events; using Musify.Application.Services; -using Musify.Application.Shared; using Musify.Domain.Entities; using Musify.Domain.ValueObjects; @@ -90,6 +89,7 @@ public class CreateAlbumCommandHandler( { try { + var sizes = albumConfiguration.PicturesSizes.ToImageSizes(albumConfiguration.Routes); await eventBus.PublishAsync( new CreateAlbumResourcesEvent( albumId, @@ -97,18 +97,9 @@ public class CreateAlbumCommandHandler( storageConfiguration.Bucket, pictureIntent.Key, finalPictureKey, - new ImageSize( - albumConfiguration.Routes.SmallPicturesPath, - albumConfiguration.PicturesSizes.SmallPictureWidth, - albumConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - albumConfiguration.Routes.MediumPicturesPath, - albumConfiguration.PicturesSizes.MediumPictureWidth, - albumConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - albumConfiguration.Routes.LargePicturesPath, - albumConfiguration.PicturesSizes.LargePictureWidth, - albumConfiguration.PicturesSizes.LargePictureHeight)), + sizes.Small, + sizes.Medium, + sizes.Large), cancellationToken); return new Success(); } diff --git a/backend/Core/Musify.Application/Albums/GetAlbumCover.cs b/backend/Core/Musify.Application/Albums/GetAlbumCover.cs index e4c0ddf..b9ca892 100644 --- a/backend/Core/Musify.Application/Albums/GetAlbumCover.cs +++ b/backend/Core/Musify.Application/Albums/GetAlbumCover.cs @@ -32,12 +32,14 @@ public class GetAlbumCoverQueryHandler( var pictures = owned.Pictures; var routes = albumConfiguration.Routes; - var (name, key) = request.Size.ToLowerInvariant() switch + var size = PictureSizeParser.Parse(request.Size); + var name = size switch { - "small" => (pictures.SmallName, BuildKey(routes.BuildSmallPicturePath, pictures.SmallName)), - "large" => (pictures.LargeName, BuildKey(routes.BuildLargePicturePath, pictures.LargeName)), - _ => (pictures.MediumName, BuildKey(routes.BuildMediumPicturePath, pictures.MediumName)) + PictureSize.Small => pictures.SmallName, + PictureSize.Large => pictures.LargeName, + _ => pictures.MediumName }; + var key = string.IsNullOrEmpty(name) ? null : routes.BuildPicturePath(size, name); // The resized files only exist once processing has finished; until then serve the original. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key)) @@ -52,7 +54,4 @@ public class GetAlbumCoverQueryHandler( var contentType = MimeUtility.GetMimeMapping(name); return new AlbumCoverLocation(storageConfiguration.Bucket, key, contentType); } - - private static string? BuildKey(Func builder, string? name) - => string.IsNullOrEmpty(name) ? null : builder(name); } diff --git a/backend/Core/Musify.Application/Albums/RequestAlbumPictureUpload.cs b/backend/Core/Musify.Application/Albums/RequestAlbumPictureUpload.cs index 09c3244..b689b71 100644 --- a/backend/Core/Musify.Application/Albums/RequestAlbumPictureUpload.cs +++ b/backend/Core/Musify.Application/Albums/RequestAlbumPictureUpload.cs @@ -44,7 +44,7 @@ public class RequestAlbumPictureUploadCommandHandler( var objectName = $"{Guid.NewGuid()}.{request.FileType.TrimStart('.').ToLowerInvariant()}"; - var tempKey = albumConfiguration.Routes.BuildTempPicturePath( + var tempKey = albumConfiguration.Routes.BuildTempPath( uploadIntentConfiguration.TempRootPrefix, request.UserId, objectName); try diff --git a/backend/Core/Musify.Application/Albums/UpdateAlbum.cs b/backend/Core/Musify.Application/Albums/UpdateAlbum.cs index f03bfcf..a6c9d7b 100644 --- a/backend/Core/Musify.Application/Albums/UpdateAlbum.cs +++ b/backend/Core/Musify.Application/Albums/UpdateAlbum.cs @@ -106,6 +106,7 @@ public class UpdateAlbumCommandHandler( { try { + var sizes = albumConfiguration.PicturesSizes.ToImageSizes(albumConfiguration.Routes); await eventBus.PublishAsync( new UpdateAlbumPictureSourceEvent( albumId, @@ -113,18 +114,9 @@ public class UpdateAlbumCommandHandler( storageConfiguration.Bucket, pictureIntent.Key, finalPictureKey, - new ImageSize( - albumConfiguration.Routes.SmallPicturesPath, - albumConfiguration.PicturesSizes.SmallPictureWidth, - albumConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - albumConfiguration.Routes.MediumPicturesPath, - albumConfiguration.PicturesSizes.MediumPictureWidth, - albumConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - albumConfiguration.Routes.LargePicturesPath, - albumConfiguration.PicturesSizes.LargePictureWidth, - albumConfiguration.PicturesSizes.LargePictureHeight)), + sizes.Small, + sizes.Medium, + sizes.Large), cancellationToken); return new Success(); } diff --git a/backend/Core/Musify.Application/ApplicationDependencyInjection.cs b/backend/Core/Musify.Application/ApplicationDependencyInjection.cs index 176157c..b1fb216 100644 --- a/backend/Core/Musify.Application/ApplicationDependencyInjection.cs +++ b/backend/Core/Musify.Application/ApplicationDependencyInjection.cs @@ -13,14 +13,14 @@ public static class ApplicationDependencyInjection services.AddScoped(); services.AddScoped(); - services.AddValidatedOptions(configuration, ApplicationStorageConfiguration.SectionName); - services.AddValidatedOptions(configuration, PlayListConfiguration.SectionName); - services.AddValidatedOptions(configuration, AlbumConfiguration.SectionName); - services.AddValidatedOptions(configuration, TrackConfiguration.SectionName); - services.AddValidatedOptions(configuration, MixConfiguration.SectionName); - services.AddValidatedOptions(configuration, StreamGatewayConfiguration.SectionName); - services.AddValidatedOptions(configuration, UploadIntentConfiguration.SectionName); - services.AddValidatedOptions(configuration, PlaybackConfiguration.SectionName); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); + services.AddValidatedOptions(configuration); return services; } diff --git a/backend/Core/Musify.Application/Configuration/AlbumConfiguration.cs b/backend/Core/Musify.Application/Configuration/AlbumConfiguration.cs index a505c99..c139a4d 100644 --- a/backend/Core/Musify.Application/Configuration/AlbumConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/AlbumConfiguration.cs @@ -1,78 +1,14 @@ using System.ComponentModel.DataAnnotations; -using Musify.Application.Shared; namespace Musify.Application.Configuration; -public class AlbumConfiguration +public class AlbumConfiguration : IConfigurationOptions, IPictureOwnerConfiguration { - public const string SectionName = "Album"; + public static string SectionName => "Album"; [Required] - public AlbumRoutes Routes { get; set; } = new AlbumRoutes(); + public PictureRoutes Routes { get; set; } = new() { ParentFolder = "Albums" }; [Required] - public AlbumPicturesSizes PicturesSizes { get; set; } = new AlbumPicturesSizes(); -} - -public class AlbumRoutes -{ - [Required] - public string UploadsFolder { get; set; } = "uploads"; - - [Required] - public string ParentFolders { get; set; } = "Albums"; - - [Required] - public string OriginalPicturesFolder { get; set; } = "OriginalPictures"; - - [Required] - public string SmallPicturesFolder { get; set; } = "SmallPictures"; - - [Required] - public string MediumPicturesFolder { get; set; } = "MediumPictures"; - - [Required] - public string LargePicturesFolder { get; set; } = "LargePictures"; - - public string SmallPicturesPath => StorageKey.Combine(ParentFolders, SmallPicturesFolder); - - public string MediumPicturesPath => StorageKey.Combine(ParentFolders, MediumPicturesFolder); - - public string LargePicturesPath => StorageKey.Combine(ParentFolders, LargePicturesFolder); - - public string OriginalPicturesPath => StorageKey.Combine(ParentFolders, OriginalPicturesFolder); - - public string BuildOriginalPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, OriginalPicturesFolder, pictureName); - - public string BuildOriginalPicturePath(long userId, string pictureName) => StorageKey.Combine(UploadsFolder, userId.ToString(), ParentFolders, OriginalPicturesFolder, pictureName); - - public string BuildSmallPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, SmallPicturesFolder, pictureName); - - public string BuildMediumPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, MediumPicturesFolder, pictureName); - - public string BuildLargePicturePath(string pictureName) => StorageKey.Combine(ParentFolders, LargePicturesFolder, pictureName); - - public string BuildTempPicturePath(string tempRootPrefix, long userId, string objectName) => - StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolders, objectName); -} - -public class AlbumPicturesSizes -{ - [Range(1, 1024)] - public int SmallPictureWidth { get; set; } = 128; - - [Range(1, 1024)] - public int SmallPictureHeight { get; set; } = 128; - - [Range(1, 1024)] - public int MediumPictureWidth { get; set; } = 256; - - [Range(1, 1024)] - public int MediumPictureHeight { get; set; } = 256; - - [Range(1, 1024)] - public int LargePictureWidth { get; set; } = 512; - - [Range(1, 1024)] - public int LargePictureHeight { get; set; } = 512; + public PictureSizes PicturesSizes { get; set; } = new(); } diff --git a/backend/Core/Musify.Application/Configuration/ApplicationStorageConfiguration.cs b/backend/Core/Musify.Application/Configuration/ApplicationStorageConfiguration.cs index b402a36..f6fedc4 100644 --- a/backend/Core/Musify.Application/Configuration/ApplicationStorageConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/ApplicationStorageConfiguration.cs @@ -2,9 +2,9 @@ using System.ComponentModel.DataAnnotations; namespace Musify.Application.Configuration; -public class ApplicationStorageConfiguration +public class ApplicationStorageConfiguration : IConfigurationOptions { - public const string SectionName = "ApplicationStorage"; + public static string SectionName => "ApplicationStorage"; [Required] [StringLength(128, MinimumLength = 1)] diff --git a/backend/Core/Musify.Application/Configuration/ConfigurationDependencyInjection.cs b/backend/Core/Musify.Application/Configuration/ConfigurationDependencyInjection.cs index 4c341f3..aa7fa1a 100644 --- a/backend/Core/Musify.Application/Configuration/ConfigurationDependencyInjection.cs +++ b/backend/Core/Musify.Application/Configuration/ConfigurationDependencyInjection.cs @@ -6,6 +6,10 @@ namespace Musify.Application.Configuration; public static class ConfigurationDependencyInjection { + public static IServiceCollection AddValidatedOptions(this IServiceCollection services, IConfiguration configuration) + where T : class, IConfigurationOptions => + services.AddValidatedOptions(configuration, T.SectionName); + public static IServiceCollection AddValidatedOptions( this IServiceCollection services, IConfiguration configuration, diff --git a/backend/Core/Musify.Application/Configuration/IConfigurationOptions.cs b/backend/Core/Musify.Application/Configuration/IConfigurationOptions.cs new file mode 100644 index 0000000..3864320 --- /dev/null +++ b/backend/Core/Musify.Application/Configuration/IConfigurationOptions.cs @@ -0,0 +1,6 @@ +namespace Musify.Application.Configuration; + +public interface IConfigurationOptions +{ + public static abstract string SectionName { get; } +} diff --git a/backend/Core/Musify.Application/Configuration/MixConfiguration.cs b/backend/Core/Musify.Application/Configuration/MixConfiguration.cs index af33d2c..bb16860 100644 --- a/backend/Core/Musify.Application/Configuration/MixConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/MixConfiguration.cs @@ -2,9 +2,9 @@ using System.ComponentModel.DataAnnotations; namespace Musify.Application.Configuration; -public class MixConfiguration +public class MixConfiguration : IConfigurationOptions { - public const string SectionName = "Mix"; + public static string SectionName => "Mix"; [Range(4, 100)] public int ItemsPerMix { get; set; } = 12; diff --git a/backend/Core/Musify.Application/Configuration/Pictures.cs b/backend/Core/Musify.Application/Configuration/Pictures.cs new file mode 100644 index 0000000..bed36ff --- /dev/null +++ b/backend/Core/Musify.Application/Configuration/Pictures.cs @@ -0,0 +1,90 @@ +using System.ComponentModel.DataAnnotations; +using Musify.Application.Shared; + +namespace Musify.Application.Configuration; + +public enum PictureSize +{ + Small, + Medium, + Large +} + +public class PictureRoutes +{ + [Required] + public string UploadsFolder { get; set; } = "uploads"; + + [Required] + public string ParentFolder { get; set; } = string.Empty; + + [Required] + public string OriginalPicturesFolder { get; set; } = "OriginalPictures"; + + [Required] + public string SmallPicturesFolder { get; set; } = "SmallPictures"; + + [Required] + public string MediumPicturesFolder { get; set; } = "MediumPictures"; + + [Required] + public string LargePicturesFolder { get; set; } = "LargePictures"; + + public string FolderPath(PictureSize size) => StorageKey.Combine(ParentFolder, size switch + { + PictureSize.Small => SmallPicturesFolder, + PictureSize.Medium => MediumPicturesFolder, + PictureSize.Large => LargePicturesFolder, + _ => throw new ArgumentOutOfRangeException(nameof(size), size, null) + }); + + 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); + + public string BuildTempPath(string tempRootPrefix, long userId, string objectName) => + StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolder, objectName); +} + +public class PictureSizes +{ + [Range(1, 1024)] + public int SmallWidth { get; set; } = 128; + + [Range(1, 1024)] + public int SmallHeight { get; set; } = 128; + + [Range(1, 1024)] + public int MediumWidth { get; set; } = 256; + + [Range(1, 1024)] + public int MediumHeight { get; set; } = 256; + + [Range(1, 1024)] + public int LargeWidth { get; set; } = 512; + + [Range(1, 1024)] + public int LargeHeight { get; set; } = 512; + + public ImageSizes ToImageSizes(PictureRoutes routes) => new( + new ImageSize(routes.FolderPath(PictureSize.Small), SmallWidth, SmallHeight), + new ImageSize(routes.FolderPath(PictureSize.Medium), MediumWidth, MediumHeight), + new ImageSize(routes.FolderPath(PictureSize.Large), LargeWidth, LargeHeight)); +} + +public interface IPictureOwnerConfiguration +{ + public PictureRoutes Routes { get; } + + public PictureSizes PicturesSizes { get; } +} + +public static class PictureSizeParser +{ + /// Parses the size query value; anything unknown means . + public static PictureSize Parse(string? value) => + Enum.TryParse(value, ignoreCase: true, out var size) && Enum.IsDefined(size) + ? size + : PictureSize.Medium; +} diff --git a/backend/Core/Musify.Application/Configuration/PlayListConfiguration.cs b/backend/Core/Musify.Application/Configuration/PlayListConfiguration.cs index 10b7051..10385a9 100644 --- a/backend/Core/Musify.Application/Configuration/PlayListConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/PlayListConfiguration.cs @@ -1,78 +1,14 @@ using System.ComponentModel.DataAnnotations; -using Musify.Application.Shared; namespace Musify.Application.Configuration; -public class PlayListConfiguration +public class PlayListConfiguration : IConfigurationOptions, IPictureOwnerConfiguration { - public const string SectionName = "PlayList"; + public static string SectionName => "PlayList"; [Required] - public PlayListRoutes Routes { get; set; } = new PlayListRoutes(); + public PictureRoutes Routes { get; set; } = new() { ParentFolder = "PlayLists" }; [Required] - public PlayListPicturesSizes PicturesSizes { get; set; } = new PlayListPicturesSizes(); -} - -public class PlayListRoutes -{ - [Required] - public string UploadsFolder { get; set; } = "uploads"; - - [Required] - public string ParentFolders { get; set; } = "PlayLists"; - - [Required] - public string OriginalPicturesFolder { get; set; } = "OriginalPictures"; - - [Required] - public string SmallPicturesFolder { get; set; } = "SmallPictures"; - - [Required] - public string MediumPicturesFolder { get; set; } = "MediumPictures"; - - [Required] - public string LargePicturesFolder { get; set; } = "LargePictures"; - - public string SmallPicturesPath => StorageKey.Combine(ParentFolders, SmallPicturesFolder); - - public string MediumPicturesPath => StorageKey.Combine(ParentFolders, MediumPicturesFolder); - - public string LargePicturesPath => StorageKey.Combine(ParentFolders, LargePicturesFolder); - - public string OriginalPicturesPath => StorageKey.Combine(ParentFolders, OriginalPicturesFolder); - - public string BuildOriginalPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, OriginalPicturesFolder, pictureName); - - public string BuildOriginalPicturePath(long userId, string pictureName) => StorageKey.Combine(UploadsFolder, userId.ToString(), ParentFolders, OriginalPicturesFolder, pictureName); - - public string BuildSmallPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, SmallPicturesFolder, pictureName); - - public string BuildMediumPicturePath(string pictureName) => StorageKey.Combine(ParentFolders, MediumPicturesFolder, pictureName); - - public string BuildLargePicturePath(string pictureName) => StorageKey.Combine(ParentFolders, LargePicturesFolder, pictureName); - - public string BuildTempPicturePath(string tempRootPrefix, long userId, string objectName) => - StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolders, objectName); -} - -public class PlayListPicturesSizes -{ - [Range(1, 1024)] - public int SmallPictureWidth { get; set; } = 128; - - [Range(1, 1024)] - public int SmallPictureHeight { get; set; } = 128; - - [Range(1, 1024)] - public int MediumPictureWidth { get; set; } = 256; - - [Range(1, 1024)] - public int MediumPictureHeight { get; set; } = 256; - - [Range(1, 1024)] - public int LargePictureWidth { get; set; } = 512; - - [Range(1, 1024)] - public int LargePictureHeight { get; set; } = 512; + public PictureSizes PicturesSizes { get; set; } = new(); } diff --git a/backend/Core/Musify.Application/Configuration/PlaybackConfiguration.cs b/backend/Core/Musify.Application/Configuration/PlaybackConfiguration.cs index 6a275bb..2fac12b 100644 --- a/backend/Core/Musify.Application/Configuration/PlaybackConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/PlaybackConfiguration.cs @@ -3,9 +3,9 @@ using System.ComponentModel.DataAnnotations; namespace Musify.Application.Configuration; -public sealed class PlaybackConfiguration +public sealed class PlaybackConfiguration : IConfigurationOptions { - public const string SectionName = "Playback"; + public static string SectionName => "Playback"; public bool AllowAnonymousListening { get; set; } diff --git a/backend/Core/Musify.Application/Configuration/StreamGatewayConfiguration.cs b/backend/Core/Musify.Application/Configuration/StreamGatewayConfiguration.cs index 03a3dcb..3c9ecb8 100644 --- a/backend/Core/Musify.Application/Configuration/StreamGatewayConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/StreamGatewayConfiguration.cs @@ -2,9 +2,9 @@ using System.ComponentModel.DataAnnotations; namespace Musify.Application.Configuration; -public class StreamGatewayConfiguration +public class StreamGatewayConfiguration : IConfigurationOptions { - public const string SectionName = "StreamGateway"; + public static string SectionName => "StreamGateway"; [Url] [Required] diff --git a/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs b/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs index 1e74b48..b391286 100644 --- a/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/TrackConfiguration.cs @@ -3,36 +3,25 @@ using Musify.Application.Shared; namespace Musify.Application.Configuration; -public class TrackConfiguration +public class TrackConfiguration : IConfigurationOptions, IPictureOwnerConfiguration { - public const string SectionName = "Track"; + public static string SectionName => "Track"; [Required] - public TrackRoutes Routes { get; set; } = new TrackRoutes(); + public TrackRoutes Routes { get; set; } = new(); [Required] - public TrackPicturesSizes PicturesSizes { get; set; } = new TrackPicturesSizes(); + public PictureSizes PicturesSizes { get; set; } = new(); + + PictureRoutes IPictureOwnerConfiguration.Routes => Routes; } -public class TrackRoutes +public class TrackRoutes : PictureRoutes { - [Required] - public string UploadsFolder { get; set; } = "uploads"; - - [Required] - public string ParentFolder { get; set; } = "Tracks"; - - [Required] - public string OriginalPicturesFolder { get; set; } = "OriginalPictures"; - - [Required] - public string SmallPicturesFolder { get; set; } = "SmallPictures"; - - [Required] - public string MediumPicturesFolder { get; set; } = "MediumPictures"; - - [Required] - public string LargePicturesFolder { get; set; } = "LargePictures"; + public TrackRoutes() + { + ParentFolder = "Tracks"; + } [Required] public string PresetOriginalPicture { get; set; } = "PresetOriginalPicture.webp"; @@ -50,13 +39,7 @@ public class TrackRoutes public string OriginalAudiosFolder { get; set; } = "OriginalAudios"; [Required] - public string ProcessedAudioFolder { get; set; } = "ProcessedAudios"; - - public string SmallPicturesPath => StorageKey.Combine(ParentFolder, SmallPicturesFolder); - - public string MediumPicturesPath => StorageKey.Combine(ParentFolder, MediumPicturesFolder); - - public string LargePicturesPath => StorageKey.Combine(ParentFolder, LargePicturesFolder); + public string ProcessedAudiosFolder { get; set; } = "ProcessedAudios"; public string PresetSmallPicturePath => StorageKey.Combine(ParentFolder, PresetSmallPicture); @@ -64,52 +47,9 @@ public class TrackRoutes public string PresetLargePicturePath => StorageKey.Combine(ParentFolder, PresetLargePicture); - public string OriginalPicturesPath => StorageKey.Combine(ParentFolder, OriginalPicturesFolder); + public string BuildOriginalAudioPath(long userId, string audioName) => + StorageKey.Combine(UploadsFolder, userId.ToString(), ParentFolder, OriginalAudiosFolder, audioName); - public string OriginalAudiosPath => StorageKey.Combine(ParentFolder, OriginalAudiosFolder); - - public string ProcessedAudiosPath => StorageKey.Combine(ParentFolder, ProcessedAudioFolder); - - public string BuildOriginalPicturePath(string pictureName) => StorageKey.Combine(OriginalPicturesPath, pictureName); - - public string BuildOriginalPicturePath(long userId, string pictureName) => StorageKey.Combine(UploadsFolder, userId.ToString(), OriginalPicturesPath, pictureName); - - public string BuildSmallPicturePath(string pictureName) => StorageKey.Combine(SmallPicturesPath, pictureName); - - public string BuildMediumPicturePath(string pictureName) => StorageKey.Combine(MediumPicturesPath, pictureName); - - public string BuildLargePicturePath(string pictureName) => StorageKey.Combine(LargePicturesPath, pictureName); - - public string BuildOriginalAudioPath(string audioName) => StorageKey.Combine(OriginalAudiosPath, audioName); - - public string BuildOriginalAudioPath(long userId, string audioName) => StorageKey.Combine(UploadsFolder, userId.ToString(), OriginalAudiosPath, audioName); - - public string BuildProcessedAudioPath(string audioName) => StorageKey.Combine(ProcessedAudiosPath, audioName); - - public string BuildTempPicturePath(string tempRootPrefix, long userId, string objectName) => - StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolder, objectName); - - public string BuildTempAudioPath(string tempRootPrefix, long userId, string objectName) => - StorageKey.Combine(tempRootPrefix, userId.ToString(), ParentFolder, objectName); -} - -public class TrackPicturesSizes -{ - [Range(1, 1024)] - public int SmallPictureWidth { get; set; } = 128; - - [Range(1, 1024)] - public int SmallPictureHeight { get; set; } = 128; - - [Range(1, 1024)] - public int MediumPictureWidth { get; set; } = 256; - - [Range(1, 1024)] - public int MediumPictureHeight { get; set; } = 256; - - [Range(1, 1024)] - public int LargePictureWidth { get; set; } = 512; - - [Range(1, 1024)] - public int LargePictureHeight { get; set; } = 512; + public string BuildProcessedAudioPath(string folderName) => + StorageKey.Combine(ParentFolder, ProcessedAudiosFolder, folderName); } diff --git a/backend/Core/Musify.Application/Configuration/UploadIntentConfiguration.cs b/backend/Core/Musify.Application/Configuration/UploadIntentConfiguration.cs index eb05dee..3b72185 100644 --- a/backend/Core/Musify.Application/Configuration/UploadIntentConfiguration.cs +++ b/backend/Core/Musify.Application/Configuration/UploadIntentConfiguration.cs @@ -2,9 +2,9 @@ using System.ComponentModel.DataAnnotations; namespace Musify.Application.Configuration; -public class UploadIntentConfiguration +public class UploadIntentConfiguration : IConfigurationOptions { - public const string SectionName = "UploadIntent"; + public static string SectionName => "UploadIntent"; [Range(10, 3600)] public int UploadUrlExpiresInSeconds { get; set; } = 120; diff --git a/backend/Core/Musify.Application/PlayLists/CreatePlayList.cs b/backend/Core/Musify.Application/PlayLists/CreatePlayList.cs index ba015de..d78024b 100644 --- a/backend/Core/Musify.Application/PlayLists/CreatePlayList.cs +++ b/backend/Core/Musify.Application/PlayLists/CreatePlayList.cs @@ -7,7 +7,6 @@ using Musify.Application.Contracts; using Musify.Application.Events; using Musify.Application.PlayLists.Responses; using Musify.Application.Services; -using Musify.Application.Shared; using Musify.Domain.Entities; using Musify.Domain.ValueObjects; @@ -108,6 +107,7 @@ public class CreatePlayListCommandHandler( { try { + var sizes = playListConfiguration.PicturesSizes.ToImageSizes(playListConfiguration.Routes); await eventBus.PublishAsync( new CreatePlayListResourcesEvent( playListId, @@ -115,18 +115,9 @@ public class CreatePlayListCommandHandler( storageConfiguration.Bucket, pictureIntent.Key, finalPictureKey, - new ImageSize( - playListConfiguration.Routes.SmallPicturesPath, - playListConfiguration.PicturesSizes.SmallPictureWidth, - playListConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - playListConfiguration.Routes.MediumPicturesPath, - playListConfiguration.PicturesSizes.MediumPictureWidth, - playListConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - playListConfiguration.Routes.LargePicturesPath, - playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)), + sizes.Small, + sizes.Medium, + sizes.Large), cancellationToken); return new Success(); } diff --git a/backend/Core/Musify.Application/PlayLists/GetPlayListCover.cs b/backend/Core/Musify.Application/PlayLists/GetPlayListCover.cs index 7660459..e456e7d 100644 --- a/backend/Core/Musify.Application/PlayLists/GetPlayListCover.cs +++ b/backend/Core/Musify.Application/PlayLists/GetPlayListCover.cs @@ -32,12 +32,14 @@ public class GetPlayListCoverQueryHandler( var pictures = owned.Pictures; var routes = playListConfiguration.Routes; - var (name, key) = request.Size.ToLowerInvariant() switch + var size = PictureSizeParser.Parse(request.Size); + var name = size switch { - "small" => (pictures.SmallName, BuildKey(routes.BuildSmallPicturePath, pictures.SmallName)), - "large" => (pictures.LargeName, BuildKey(routes.BuildLargePicturePath, pictures.LargeName)), - _ => (pictures.MediumName, BuildKey(routes.BuildMediumPicturePath, pictures.MediumName)) + PictureSize.Small => pictures.SmallName, + PictureSize.Large => pictures.LargeName, + _ => pictures.MediumName }; + var key = string.IsNullOrEmpty(name) ? null : routes.BuildPicturePath(size, name); // The resized files only exist once processing has finished; until then serve the original. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(key)) @@ -52,7 +54,4 @@ public class GetPlayListCoverQueryHandler( var contentType = MimeUtility.GetMimeMapping(name); return new PlayListCoverLocation(storageConfiguration.Bucket, key, contentType); } - - private static string? BuildKey(Func builder, string? name) - => string.IsNullOrEmpty(name) ? null : builder(name); } diff --git a/backend/Core/Musify.Application/PlayLists/RequestPlayListPictureUpload.cs b/backend/Core/Musify.Application/PlayLists/RequestPlayListPictureUpload.cs index 38c3a0f..6603940 100644 --- a/backend/Core/Musify.Application/PlayLists/RequestPlayListPictureUpload.cs +++ b/backend/Core/Musify.Application/PlayLists/RequestPlayListPictureUpload.cs @@ -44,7 +44,7 @@ public class RequestPlayListPictureUploadCommandHandler( var objectName = $"{Guid.NewGuid()}.{request.FileType.TrimStart('.').ToLowerInvariant()}"; - var tempKey = playListConfiguration.Routes.BuildTempPicturePath( + var tempKey = playListConfiguration.Routes.BuildTempPath( uploadIntentConfiguration.TempRootPrefix, request.UserId, objectName); try diff --git a/backend/Core/Musify.Application/PlayLists/UpdatePlayList.cs b/backend/Core/Musify.Application/PlayLists/UpdatePlayList.cs index 9516d44..e4c395a 100644 --- a/backend/Core/Musify.Application/PlayLists/UpdatePlayList.cs +++ b/backend/Core/Musify.Application/PlayLists/UpdatePlayList.cs @@ -111,6 +111,7 @@ public class UpdatePlayListCommandHandler( { try { + var sizes = playListConfiguration.PicturesSizes.ToImageSizes(playListConfiguration.Routes); await eventBus.PublishAsync( new UpdatePlayListPictureSourceEvent( playListId, @@ -118,18 +119,9 @@ public class UpdatePlayListCommandHandler( storageConfiguration.Bucket, pictureIntent.Key, finalPictureKey, - new ImageSize( - playListConfiguration.Routes.SmallPicturesPath, - playListConfiguration.PicturesSizes.SmallPictureWidth, - playListConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - playListConfiguration.Routes.MediumPicturesPath, - playListConfiguration.PicturesSizes.MediumPictureWidth, - playListConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - playListConfiguration.Routes.LargePicturesPath, - playListConfiguration.PicturesSizes.LargePictureWidth, - playListConfiguration.PicturesSizes.LargePictureHeight)), + sizes.Small, + sizes.Medium, + sizes.Large), cancellationToken); return new Success(); } diff --git a/backend/Core/Musify.Application/Shared/ImageSize.cs b/backend/Core/Musify.Application/Shared/ImageSize.cs index ba33f19..0a9ebb4 100644 --- a/backend/Core/Musify.Application/Shared/ImageSize.cs +++ b/backend/Core/Musify.Application/Shared/ImageSize.cs @@ -4,3 +4,8 @@ public record ImageSize( string SavePath, int Width, int Height); + +public record ImageSizes( + ImageSize Small, + ImageSize Medium, + ImageSize Large); diff --git a/backend/Core/Musify.Application/Tracks/CreateTrack.cs b/backend/Core/Musify.Application/Tracks/CreateTrack.cs index d16e848..1f2cfc1 100644 --- a/backend/Core/Musify.Application/Tracks/CreateTrack.cs +++ b/backend/Core/Musify.Application/Tracks/CreateTrack.cs @@ -6,7 +6,6 @@ using Musify.Application.Configuration; using Musify.Application.Contracts; 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; @@ -117,6 +116,7 @@ public class CreateTrackCommandHandler( try { + var sizes = trackConfiguration.PicturesSizes.ToImageSizes(trackConfiguration.Routes); await eventBus.PublishAsync( new CreateTrackResourcesEvent( trackEntity.Id, @@ -128,18 +128,9 @@ public class CreateTrackCommandHandler( audioIntent.Key, finalAudioKey, audioProcessedFolderKey, - new ImageSize( - trackConfiguration.Routes.SmallPicturesPath, - trackConfiguration.PicturesSizes.SmallPictureWidth, - trackConfiguration.PicturesSizes.SmallPictureHeight), - new ImageSize( - trackConfiguration.Routes.MediumPicturesPath, - trackConfiguration.PicturesSizes.MediumPictureWidth, - trackConfiguration.PicturesSizes.MediumPictureHeight), - new ImageSize( - trackConfiguration.Routes.LargePicturesPath, - trackConfiguration.PicturesSizes.LargePictureWidth, - trackConfiguration.PicturesSizes.LargePictureHeight)), + sizes.Small, + sizes.Medium, + sizes.Large), cancellationToken); } catch (Exception exception) diff --git a/backend/Core/Musify.Application/Tracks/GetTrackCover.cs b/backend/Core/Musify.Application/Tracks/GetTrackCover.cs index 39ab256..3e8f602 100644 --- a/backend/Core/Musify.Application/Tracks/GetTrackCover.cs +++ b/backend/Core/Musify.Application/Tracks/GetTrackCover.cs @@ -28,12 +28,14 @@ public class GetTrackCoverQueryHandler( return Error.NotFound(); var routes = trackConfiguration.Routes; - var (name, key) = request.Size.ToLowerInvariant() switch + var size = PictureSizeParser.Parse(request.Size); + var name = size switch { - "small" => (track.SmallName, BuildKey(routes.BuildSmallPicturePath, track.SmallName)), - "large" => (track.LargeName, BuildKey(routes.BuildLargePicturePath, track.LargeName)), - _ => (track.MediumName, BuildKey(routes.BuildMediumPicturePath, track.MediumName)) + PictureSize.Small => track.SmallName, + PictureSize.Large => track.LargeName, + _ => track.MediumName }; + var key = string.IsNullOrEmpty(name) ? null : routes.BuildPicturePath(size, name); if (string.IsNullOrEmpty(name) || key == null) return Error.NotFound(); @@ -46,7 +48,4 @@ public class GetTrackCoverQueryHandler( return new TrackCoverLocation(storageConfiguration.Bucket, key, contentType); } - - private static string? BuildKey(Func builder, string? name) - => string.IsNullOrEmpty(name) ? null : builder(name); } diff --git a/backend/Core/Musify.Application/Tracks/RequestTrackUploadUrls.cs b/backend/Core/Musify.Application/Tracks/RequestTrackUploadUrls.cs index 4d2fa1d..143dce0 100644 --- a/backend/Core/Musify.Application/Tracks/RequestTrackUploadUrls.cs +++ b/backend/Core/Musify.Application/Tracks/RequestTrackUploadUrls.cs @@ -50,9 +50,9 @@ public class RequestTrackUploadUrlsCommandHandler( var pictureObjectName = $"{Guid.NewGuid()}.{request.PictureFileType.TrimStart('.').ToLowerInvariant()}"; var audioObjectName = $"{Guid.NewGuid()}.{request.AudioFileType.TrimStart('.').ToLowerInvariant()}"; - var tempPictureKey = trackConfiguration.Routes.BuildTempPicturePath( + var tempPictureKey = trackConfiguration.Routes.BuildTempPath( uploadIntentConfiguration.TempRootPrefix, request.UserId, pictureObjectName); - var tempAudioKey = trackConfiguration.Routes.BuildTempAudioPath( + var tempAudioKey = trackConfiguration.Routes.BuildTempPath( uploadIntentConfiguration.TempRootPrefix, request.UserId, audioObjectName); try diff --git a/backend/Core/Musify.Infrastructure/Configuration/AudioConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/AudioConfiguration.cs index b4573a6..e2abd10 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/AudioConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/AudioConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class AudioConfiguration +public class AudioConfiguration : IConfigurationOptions { - public const string SectionName = "AudioTranscoder"; + public static string SectionName => "AudioTranscoder"; [Required] public TimeSpan TranscodingTimeout { get; set; } = TimeSpan.FromMinutes(5); diff --git a/backend/Core/Musify.Infrastructure/Configuration/DatabaseConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/DatabaseConfiguration.cs index 63a5eca..6df8c20 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/DatabaseConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/DatabaseConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class DatabaseConfiguration +public class DatabaseConfiguration : IConfigurationOptions { - public const string SectionName = "Database"; + public static string SectionName => "Database"; [Required] public required string ConnectionString { get; set; } diff --git a/backend/Core/Musify.Infrastructure/Configuration/InfrastructureStorageConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/InfrastructureStorageConfiguration.cs index 948c513..45738bf 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/InfrastructureStorageConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/InfrastructureStorageConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class InfrastructureStorageConfiguration +public class InfrastructureStorageConfiguration : IConfigurationOptions { - public const string SectionName = "InfrastructureStorage"; + public static string SectionName => "InfrastructureStorage"; [Url] [Required] diff --git a/backend/Core/Musify.Infrastructure/Configuration/MassTransitConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/MassTransitConfiguration.cs index 685492d..8472cbd 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/MassTransitConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/MassTransitConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class MassTransitConfiguration +public class MassTransitConfiguration : IConfigurationOptions { - public const string SectionName = "MassTransit"; + public static string SectionName => "MassTransit"; [Required] public required string Address { get; set; } diff --git a/backend/Core/Musify.Infrastructure/Configuration/OpenTelemetryConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/OpenTelemetryConfiguration.cs index 5c7d074..e12adcd 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/OpenTelemetryConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/OpenTelemetryConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class OpenTelemetryConfiguration +public class OpenTelemetryConfiguration : IConfigurationOptions { - public const string SectionName = "OpenTelemetry"; + public static string SectionName => "OpenTelemetry"; [Url] [Required] diff --git a/backend/Core/Musify.Infrastructure/Configuration/StreamTicketConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/StreamTicketConfiguration.cs index 9097609..26c9130 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/StreamTicketConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/StreamTicketConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class StreamTicketConfiguration +public class StreamTicketConfiguration : IConfigurationOptions { - public const string SectionName = "StreamTicket"; + public static string SectionName => "StreamTicket"; [Required] public required string PrivateKeyPath { get; set; } diff --git a/backend/Core/Musify.Infrastructure/Configuration/WorkerConfiguration.cs b/backend/Core/Musify.Infrastructure/Configuration/WorkerConfiguration.cs index 4cc48ed..3af6ef4 100644 --- a/backend/Core/Musify.Infrastructure/Configuration/WorkerConfiguration.cs +++ b/backend/Core/Musify.Infrastructure/Configuration/WorkerConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Configuration; -public class WorkerConfiguration +public class WorkerConfiguration : IConfigurationOptions { - public const string SectionName = "Workers"; + public static string SectionName => "Workers"; [Required] public WorkerRoutes Routes { get; set; } = new WorkerRoutes(); diff --git a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Options.cs b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Options.cs deleted file mode 100644 index 82ae90f..0000000 --- a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Options.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Musify.Infrastructure.MassTransit; - -public static partial class MassTransitDependencyInjection -{ - private static void RegisterValidatedOptions( - IServiceCollection services, - IConfiguration configuration, - string sectionName) - where TOptions : class - { - services - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(sectionName)) - .ValidateDataAnnotations(); - - services.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); - } -} diff --git a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs index 1e6c938..e125e39 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.cs @@ -5,20 +5,18 @@ 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; public static partial class MassTransitDependencyInjection { - public static IServiceCollection AddMassTransitClient(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddMassTransitClient(this IServiceCollection services, IConfiguration configuration) { - RegisterValidatedOptions( - serviceDescriptors, - configuration, - MassTransitConfiguration.SectionName); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddScoped(); - serviceDescriptors.AddMassTransit(options => + services.AddScoped(); + services.AddMassTransit(options => { options.AddEntityFrameworkOutbox(outbox => { @@ -35,24 +33,18 @@ public static partial class MassTransitDependencyInjection busRegistrationContext.GetRequiredService())); }); - return serviceDescriptors; + return services; } - public static IServiceCollection AddMassTransitConsumers(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddMassTransitConsumers(this IServiceCollection services, IConfiguration configuration) { - RegisterValidatedOptions( - serviceDescriptors, - configuration, - MassTransitConfiguration.SectionName); + services.AddValidatedOptions(configuration); - RegisterValidatedOptions( - serviceDescriptors, - configuration, - WorkerConfiguration.SectionName); + services.AddValidatedOptions(configuration); - RegisterRoutingSlipBuilders(serviceDescriptors); + RegisterRoutingSlipBuilders(services); - serviceDescriptors.AddMassTransit(options => + services.AddMassTransit(options => { options.AddEntityFrameworkOutbox(outbox => { @@ -107,7 +99,7 @@ public static partial class MassTransitDependencyInjection }); }); - return serviceDescriptors; + return services; } private static void UseStandardRetry(IReceiveEndpointConfigurator endpointConfigurator) => diff --git a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteAlbumRoutingSlipBuilder.cs b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteAlbumRoutingSlipBuilder.cs index 1618709..95011c6 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteAlbumRoutingSlipBuilder.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteAlbumRoutingSlipBuilder.cs @@ -59,7 +59,7 @@ public class DeleteAlbumRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildSmallPicturePath(smallName))); + routes.BuildPicturePath(PictureSize.Small, smallName))); } if (album.Pictures.MediumName is { } mediumName) @@ -69,7 +69,7 @@ public class DeleteAlbumRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildMediumPicturePath(mediumName))); + routes.BuildPicturePath(PictureSize.Medium, mediumName))); } if (album.Pictures.LargeName is { } largeName) @@ -79,7 +79,7 @@ public class DeleteAlbumRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildLargePicturePath(largeName))); + routes.BuildPicturePath(PictureSize.Large, largeName))); } } diff --git a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs index 306a11e..c05a4f0 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.cs @@ -59,7 +59,7 @@ public class DeletePlayListRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildSmallPicturePath(smallName))); + routes.BuildPicturePath(PictureSize.Small, smallName))); } if (playList.Pictures.MediumName is { } mediumName) @@ -69,7 +69,7 @@ public class DeletePlayListRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildMediumPicturePath(mediumName))); + routes.BuildPicturePath(PictureSize.Medium, mediumName))); } if (playList.Pictures.LargeName is { } largeName) @@ -79,7 +79,7 @@ public class DeletePlayListRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - routes.BuildLargePicturePath(largeName))); + routes.BuildPicturePath(PictureSize.Large, largeName))); } } diff --git a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs index a6da70c..bdd7062 100644 --- a/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs +++ b/backend/Core/Musify.Infrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.cs @@ -58,21 +58,21 @@ public class DeleteTrackRoutingSlipBuilder( EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - trackConfiguration.Routes.BuildSmallPicturePath(track.Pictures.SmallName))); + trackConfiguration.Routes.BuildPicturePath(PictureSize.Small, track.Pictures.SmallName))); routingSlipBuilder.AddActivity( ActivityNames.RemoveTrackMediumPicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - trackConfiguration.Routes.BuildMediumPicturePath(track.Pictures.MediumName))); + trackConfiguration.Routes.BuildPicturePath(PictureSize.Medium, track.Pictures.MediumName))); routingSlipBuilder.AddActivity( ActivityNames.RemoveTrackLargePicture, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), new RemoveFileFromBucketArguments( bucket, - trackConfiguration.Routes.BuildLargePicturePath(track.Pictures.LargeName))); + trackConfiguration.Routes.BuildPicturePath(PictureSize.Large, track.Pictures.LargeName))); } if (!string.IsNullOrEmpty(track.Audio.OriginalName)) diff --git a/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs b/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs index ca6adcc..83a513f 100644 --- a/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/Observability/OpenTelemetryDependencyInjection.cs @@ -1,35 +1,29 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; 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; public static class OpenTelemetryDependencyInjection { - public static IServiceCollection AddObservability(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddObservability(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(OpenTelemetryConfiguration.SectionName)) - .ValidateDataAnnotations(); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); - - serviceDescriptors + services .AddOptions() .Configure((exporterOptions, openTelemetryConfiguration) => { exporterOptions.Endpoint = new Uri(openTelemetryConfiguration.OtlpEndpoint); }); - serviceDescriptors + services .AddOpenTelemetry() .ConfigureResource(resource => { @@ -54,6 +48,6 @@ public static class OpenTelemetryDependencyInjection logging.AddOtlpExporter() ); - return serviceDescriptors; + return services; } } diff --git a/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs b/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs index 6e213f2..c21b070 100644 --- a/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/Persistence/DatabaseDependencyInjection.cs @@ -1,27 +1,21 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Musify.Application.Contracts; using Musify.Infrastructure.Configuration; +using Musify.Application.Configuration; namespace Musify.Infrastructure.Persistence; public static class DatabaseDependencyInjection { - public static IServiceCollection AddDatabase(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddDatabase(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(DatabaseConfiguration.SectionName)) - .ValidateDataAnnotations(); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); + services.AddDbContext(); - serviceDescriptors.AddDbContext(); + services.AddScoped(serviceProvider => serviceProvider.GetRequiredService()); - serviceDescriptors.AddScoped(serviceProvider => serviceProvider.GetRequiredService()); - - return serviceDescriptors; + return services; } } diff --git a/backend/Core/Musify.Infrastructure/Services/ServicesDependencyInjection.cs b/backend/Core/Musify.Infrastructure/Services/ServicesDependencyInjection.cs index 67e025d..e1ce0c5 100644 --- a/backend/Core/Musify.Infrastructure/Services/ServicesDependencyInjection.cs +++ b/backend/Core/Musify.Infrastructure/Services/ServicesDependencyInjection.cs @@ -3,7 +3,6 @@ using Hangfire; using Hangfire.PostgreSql; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Musify.Application.Configuration; using Musify.Application.Contracts; using Musify.Infrastructure.Configuration; @@ -13,17 +12,11 @@ namespace Musify.Infrastructure.Services; public static class ServicesDependencyInjection { - public static IServiceCollection AddStorageService(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddStorageService(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(InfrastructureStorageConfiguration.SectionName)) - .ValidateDataAnnotations(); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); - - serviceDescriptors.AddSingleton(serviceProvider => + services.AddSingleton(serviceProvider => { var configuration = serviceProvider.GetRequiredService(); var s3Configuration = new AmazonS3Config @@ -35,74 +28,62 @@ public static class ServicesDependencyInjection return new AmazonS3Client(configuration.AccessKey, configuration.SecretAccessKey, s3Configuration); }); - serviceDescriptors.AddScoped(); - return serviceDescriptors; + services.AddScoped(); + return services; } - public static IServiceCollection AddPictureService(this IServiceCollection serviceDescriptors) + public static IServiceCollection AddPictureService(this IServiceCollection services) { - serviceDescriptors.AddScoped(); - return serviceDescriptors; + services.AddScoped(); + return services; } - public static IServiceCollection AddUploadIntentConfiguration(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddUploadIntentConfiguration(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors.AddValidatedOptions(configuration, UploadIntentConfiguration.SectionName); + services.AddValidatedOptions(configuration); - return serviceDescriptors; + return services; } - public static IServiceCollection AddUploadIntentJobs(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddUploadIntentJobs(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors.AddUploadIntentConfiguration(configuration); + services.AddUploadIntentConfiguration(configuration); - serviceDescriptors.AddHostedService(); - serviceDescriptors.AddHostedService(); + services.AddHostedService(); + services.AddHostedService(); - return serviceDescriptors; + return services; } - public static IServiceCollection AddDailyMixGenerationJob(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddDailyMixGenerationJob(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors.AddHangfire((serviceProvider, hangfireConfiguration) => + services.AddHangfire((serviceProvider, hangfireConfiguration) => { var databaseConfiguration = serviceProvider.GetRequiredService(); hangfireConfiguration.UsePostgreSqlStorage(options => options.UseNpgsqlConnection(databaseConfiguration.ConnectionString)); }); - serviceDescriptors.AddHangfireServer(); - serviceDescriptors.AddScoped(); - serviceDescriptors.AddScoped(); + services.AddHangfireServer(); + services.AddScoped(); + services.AddScoped(); - return serviceDescriptors; + return services; } - public static IServiceCollection AddStreamTicketService(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddStreamTicketService(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(StreamTicketConfiguration.SectionName)) - .ValidateDataAnnotations(); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); - - serviceDescriptors.AddSingleton(); - return serviceDescriptors; + services.AddSingleton(); + return services; } - public static IServiceCollection AddAudioTranscoder(this IServiceCollection serviceDescriptors, IConfiguration configuration) + public static IServiceCollection AddAudioTranscoder(this IServiceCollection services, IConfiguration configuration) { - serviceDescriptors - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(AudioConfiguration.SectionName)) - .ValidateDataAnnotations(); + services.AddValidatedOptions(configuration); - serviceDescriptors.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); - - serviceDescriptors.AddScoped(); - return serviceDescriptors; + services.AddScoped(); + return services; } } diff --git a/backend/Hosts/Musify.Api/Authentication/AuthenticationConfiguration.cs b/backend/Hosts/Musify.Api/Authentication/AuthenticationConfiguration.cs index 5646260..f7196c1 100644 --- a/backend/Hosts/Musify.Api/Authentication/AuthenticationConfiguration.cs +++ b/backend/Hosts/Musify.Api/Authentication/AuthenticationConfiguration.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; +using Musify.Application.Configuration; namespace Musify.Api.Authentication; -public sealed class AuthenticationConfiguration +public sealed class AuthenticationConfiguration : IConfigurationOptions { - public const string SectionName = "Authentication"; + public static string SectionName => "Authentication"; [Required] [Url] diff --git a/backend/Hosts/Musify.Api/Authentication/AuthenticationExtensions.cs b/backend/Hosts/Musify.Api/Authentication/AuthenticationExtensions.cs index 45a31b9..6052f50 100644 --- a/backend/Hosts/Musify.Api/Authentication/AuthenticationExtensions.cs +++ b/backend/Hosts/Musify.Api/Authentication/AuthenticationExtensions.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Options; +using Musify.Application.Configuration; namespace Musify.Api.Authentication; @@ -9,13 +9,7 @@ public static class AuthenticationExtensions this IServiceCollection services, IConfiguration configuration) { - services - .AddOptionsWithValidateOnStart() - .Bind(configuration.GetRequiredSection(AuthenticationConfiguration.SectionName)) - .ValidateDataAnnotations(); - - services.AddSingleton(serviceProvider => - serviceProvider.GetRequiredService>().Value); + services.AddValidatedOptions(configuration); services.AddMemoryCache(); services.AddHttpClient(); diff --git a/backend/Hosts/Musify.Api/appsettings.json b/backend/Hosts/Musify.Api/appsettings.json index e771a5e..c981d4a 100644 --- a/backend/Hosts/Musify.Api/appsettings.json +++ b/backend/Hosts/Musify.Api/appsettings.json @@ -59,37 +59,37 @@ "PlayList": { "Routes": { "UploadsFolder": "uploads", - "ParentFolders": "PlayLists", + "ParentFolder": "PlayLists", "OriginalPicturesFolder": "OriginalPictures", "SmallPicturesFolder": "SmallPictures", "MediumPicturesFolder": "MediumPictures", "LargePicturesFolder": "LargePictures" }, "PicturesSizes": { - "SmallPictureWidth": 128, - "SmallPictureHeight": 128, - "MediumPictureWidth": 256, - "MediumPictureHeight": 256, - "LargePictureWidth": 512, - "LargePictureHeight": 512 + "SmallWidth": 128, + "SmallHeight": 128, + "MediumWidth": 256, + "MediumHeight": 256, + "LargeWidth": 512, + "LargeHeight": 512 } }, "Album": { "Routes": { "UploadsFolder": "uploads", - "ParentFolders": "Albums", + "ParentFolder": "Albums", "OriginalPicturesFolder": "OriginalPictures", "SmallPicturesFolder": "SmallPictures", "MediumPicturesFolder": "MediumPictures", "LargePicturesFolder": "LargePictures" }, "PicturesSizes": { - "SmallPictureWidth": 128, - "SmallPictureHeight": 128, - "MediumPictureWidth": 256, - "MediumPictureHeight": 256, - "LargePictureWidth": 512, - "LargePictureHeight": 512 + "SmallWidth": 128, + "SmallHeight": 128, + "MediumWidth": 256, + "MediumHeight": 256, + "LargeWidth": 512, + "LargeHeight": 512 } }, "Track": { @@ -105,15 +105,15 @@ "PresetMediumPicture": "PresetMediumPicture.webp", "PresetLargePicture": "PresetLargePicture.webp", "OriginalAudiosFolder": "OriginalAudios", - "ProcessedAudioFolder": "ProcessedAudios" + "ProcessedAudiosFolder": "ProcessedAudios" }, "PicturesSizes": { - "SmallPictureWidth": 128, - "SmallPictureHeight": 128, - "MediumPictureWidth": 256, - "MediumPictureHeight": 256, - "LargePictureWidth": 512, - "LargePictureHeight": 512 + "SmallWidth": 128, + "SmallHeight": 128, + "MediumWidth": 256, + "MediumHeight": 256, + "LargeWidth": 512, + "LargeHeight": 512 } }, "UploadIntent": { diff --git a/backend/Hosts/Musify.StreamingGateway/Authentication/TicketValidator.cs b/backend/Hosts/Musify.StreamingGateway/Authentication/TicketValidator.cs index b2d3a59..5782c4b 100644 --- a/backend/Hosts/Musify.StreamingGateway/Authentication/TicketValidator.cs +++ b/backend/Hosts/Musify.StreamingGateway/Authentication/TicketValidator.cs @@ -1,5 +1,4 @@ using System.Security.Cryptography; -using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using Musify.StreamingGateway.Configuration; @@ -15,14 +14,14 @@ public sealed record TicketValidationResult(string Prefix, long? MaxBytes) public sealed class TicketValidator : IDisposable { - private readonly StreamTicketValidationOptions _options; + private readonly StreamTicketValidationConfiguration _options; private readonly RSA _rsa; private readonly TokenValidationParameters _validationParameters; private readonly JsonWebTokenHandler _handler = new(); - public TicketValidator(IOptions options) + public TicketValidator(StreamTicketValidationConfiguration options) { - _options = options.Value; + _options = options; _rsa = RSA.Create(); _rsa.ImportFromPem(File.ReadAllText(_options.PublicKeyPath)); diff --git a/backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationOptions.cs b/backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationConfiguration.cs similarity index 90% rename from backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationOptions.cs rename to backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationConfiguration.cs index 8f21c17..3d9a0ff 100644 --- a/backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationOptions.cs +++ b/backend/Hosts/Musify.StreamingGateway/Configuration/StreamTicketValidationConfiguration.cs @@ -2,7 +2,7 @@ using System.ComponentModel.DataAnnotations; namespace Musify.StreamingGateway.Configuration; -public sealed class StreamTicketValidationOptions +public sealed class StreamTicketValidationConfiguration { public const string SectionName = "StreamTicket"; diff --git a/backend/Hosts/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs b/backend/Hosts/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs index 89da5f8..3aae1f1 100644 --- a/backend/Hosts/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs +++ b/backend/Hosts/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs @@ -1,4 +1,3 @@ -using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; using Musify.StreamingGateway.Authentication; @@ -9,11 +8,9 @@ namespace Musify.StreamingGateway.Middleware; public sealed class TicketValidationMiddleware( RequestDelegate next, TicketValidator ticketValidator, - IOptions options, + StreamTicketValidationConfiguration options, ILogger logger) { - private readonly StreamTicketValidationOptions options = options.Value; - public async Task InvokeAsync(HttpContext context) { var path = context.Request.Path; diff --git a/backend/Hosts/Musify.StreamingGateway/Program.cs b/backend/Hosts/Musify.StreamingGateway/Program.cs index 464f784..2997e5d 100644 --- a/backend/Hosts/Musify.StreamingGateway/Program.cs +++ b/backend/Hosts/Musify.StreamingGateway/Program.cs @@ -1,3 +1,4 @@ +using Microsoft.Extensions.Options; using Musify.StreamingGateway.Authentication; using Musify.StreamingGateway.Configuration; using Musify.StreamingGateway.Middleware; @@ -5,11 +6,14 @@ using Musify.StreamingGateway.Middleware; var builder = WebApplication.CreateBuilder(); builder.Services - .AddOptions() - .Bind(builder.Configuration.GetRequiredSection(StreamTicketValidationOptions.SectionName)) + .AddOptions() + .Bind(builder.Configuration.GetRequiredSection(StreamTicketValidationConfiguration.SectionName)) .ValidateDataAnnotations() .ValidateOnStart(); +builder.Services.AddSingleton(serviceProvider => + serviceProvider.GetRequiredService>().Value); + builder.Services.AddSingleton(); const string corsPolicy = "media-clients"; diff --git a/backend/Hosts/Musify.Worker/Program.cs b/backend/Hosts/Musify.Worker/Program.cs index 92389ba..30947c4 100644 --- a/backend/Hosts/Musify.Worker/Program.cs +++ b/backend/Hosts/Musify.Worker/Program.cs @@ -17,10 +17,10 @@ var configuration = builder.Configuration; var services = builder.Services; -services.AddValidatedOptions(configuration, ApplicationStorageConfiguration.SectionName); -services.AddValidatedOptions(configuration, PlayListConfiguration.SectionName); -services.AddValidatedOptions(configuration, TrackConfiguration.SectionName); -services.AddValidatedOptions(configuration, MixConfiguration.SectionName); +services.AddValidatedOptions(configuration); +services.AddValidatedOptions(configuration); +services.AddValidatedOptions(configuration); +services.AddValidatedOptions(configuration); services.AddStorageService(configuration); services.AddAudioTranscoder(configuration); services.AddPictureService(); diff --git a/backend/Hosts/Musify.Worker/appsettings.json b/backend/Hosts/Musify.Worker/appsettings.json index 394b30e..b7f7360 100644 --- a/backend/Hosts/Musify.Worker/appsettings.json +++ b/backend/Hosts/Musify.Worker/appsettings.json @@ -31,19 +31,19 @@ }, "PlayList": { "Routes": { - "ParentFolders": "PlayLists", + "ParentFolder": "PlayLists", "OriginalPicturesFolder": "OriginalPictures", "SmallPicturesFolder": "SmallPictures", "MediumPicturesFolder": "MediumPictures", "LargePicturesFolder": "LargePictures" }, "PicturesSizes": { - "SmallPictureWidth": 128, - "SmallPictureHeight": 128, - "MediumPictureWidth": 256, - "MediumPictureHeight": 256, - "LargePictureWidth": 512, - "LargePictureHeight": 512 + "SmallWidth": 128, + "SmallHeight": 128, + "MediumWidth": 256, + "MediumHeight": 256, + "LargeWidth": 512, + "LargeHeight": 512 } }, "Track": { @@ -58,15 +58,15 @@ "PresetMediumPicture": "PresetMediumPicture.webp", "PresetLargePicture": "PresetLargePicture.webp", "OriginalAudiosFolder": "OriginalAudios", - "ProcessedAudioFolder": "ProcessedAudios" + "ProcessedAudiosFolder": "ProcessedAudios" }, "PicturesSizes": { - "SmallPictureWidth": 128, - "SmallPictureHeight": 128, - "MediumPictureWidth": 256, - "MediumPictureHeight": 256, - "LargePictureWidth": 512, - "LargePictureHeight": 512 + "SmallWidth": 128, + "SmallHeight": 128, + "MediumWidth": 256, + "MediumHeight": 256, + "LargeWidth": 512, + "LargeHeight": 512 } }, "AudioTranscoder": { diff --git a/backend/Tests/Musify.Application.Tests/Configuration/PicturesConfigurationTests.cs b/backend/Tests/Musify.Application.Tests/Configuration/PicturesConfigurationTests.cs new file mode 100644 index 0000000..d2d0603 --- /dev/null +++ b/backend/Tests/Musify.Application.Tests/Configuration/PicturesConfigurationTests.cs @@ -0,0 +1,50 @@ +using Musify.Application.Configuration; +using Xunit; + +namespace Musify.Application.Tests.Configuration; + +public sealed class PicturesConfigurationTests +{ + [Fact] + public void AlbumRoutes_BuildTheSameKeysAsBefore() + { + var routes = new AlbumConfiguration().Routes; + + Assert.Equal("Albums/SmallPictures/a.webp", routes.BuildPicturePath(PictureSize.Small, "a.webp")); + Assert.Equal("Albums/MediumPictures/a.webp", routes.BuildPicturePath(PictureSize.Medium, "a.webp")); + Assert.Equal("Albums/LargePictures/a.webp", routes.BuildPicturePath(PictureSize.Large, "a.webp")); + Assert.Equal("uploads/7/Albums/OriginalPictures/a.webp", routes.BuildOriginalPicturePath(7, "a.webp")); + Assert.Equal("temp/7/Albums/obj.webp", routes.BuildTempPath("temp", 7, "obj.webp")); + } + + [Fact] + public void TrackRoutes_KeepTheTrackFolderLayout() + { + var routes = new TrackConfiguration().Routes; + + Assert.Equal("Tracks/ProcessedAudios/folder", routes.BuildProcessedAudioPath("folder")); + Assert.Equal("uploads/7/Tracks/OriginalAudios/song.mp3", routes.BuildOriginalAudioPath(7, "song.mp3")); + Assert.Equal("Tracks/PresetSmallPicture.webp", routes.PresetSmallPicturePath); + } + + [Fact] + public void ToImageSizes_UsesTheRoutesFolders() + { + var configuration = new PlayListConfiguration(); + + var sizes = configuration.PicturesSizes.ToImageSizes(configuration.Routes); + + Assert.Equal("PlayLists/SmallPictures", sizes.Small.SavePath); + Assert.Equal(128, sizes.Small.Width); + Assert.Equal(512, sizes.Large.Width); + } + + [Theory] + [InlineData("small", PictureSize.Small)] + [InlineData("LARGE", PictureSize.Large)] + [InlineData("medium", PictureSize.Medium)] + [InlineData("whatever", PictureSize.Medium)] + [InlineData(null, PictureSize.Medium)] + public void PictureSizeParser_DefaultsToMedium(string? value, PictureSize expected) => + Assert.Equal(expected, PictureSizeParser.Parse(value)); +} diff --git a/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs b/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs index 18f3946..801e9b6 100644 --- a/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs +++ b/backend/Tests/Musify.StreamingGateway.Tests/Authentication/TicketValidatorTests.cs @@ -1,5 +1,4 @@ using System.Security.Cryptography; -using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using Musify.StreamingGateway.Authentication; @@ -25,12 +24,12 @@ public sealed class TicketValidatorTests : IDisposable File.Delete(publicKeyPath); } - private TicketValidator CreateValidator() => new(Options.Create(new StreamTicketValidationOptions + private TicketValidator CreateValidator() => new(new StreamTicketValidationConfiguration { PublicKeyPath = publicKeyPath, Audience = Audience, Issuer = Issuer - })); + }); private string IssueToken(string prefix = "Tracks/ProcessedAudios/abc/", string issuer = Issuer, string audience = Audience, DateTime? expires = null, DateTime? notBefore = null, long? maxBytes = null) diff --git a/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs b/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs index caedf74..a4735f0 100644 --- a/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs +++ b/backend/Tests/Musify.StreamingGateway.Tests/Middleware/TicketValidationMiddlewareTests.cs @@ -1,7 +1,6 @@ using System.Security.Cryptography; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; using Musify.StreamingGateway.Authentication; @@ -17,12 +16,12 @@ public sealed class TicketValidationMiddlewareTests : IDisposable private readonly string publicKeyPath = Path.GetTempFileName(); private readonly RSA rsa = RSA.Create(2048); - private readonly StreamTicketValidationOptions options; + private readonly StreamTicketValidationConfiguration options; public TicketValidationMiddlewareTests() { File.WriteAllText(publicKeyPath, rsa.ExportSubjectPublicKeyInfoPem()); - options = new StreamTicketValidationOptions + options = new StreamTicketValidationConfiguration { PublicKeyPath = publicKeyPath, Audience = "media-gateway", @@ -57,8 +56,8 @@ public sealed class TicketValidationMiddlewareTests : IDisposable { var nextCalled = false; RequestDelegate next = _ => { nextCalled = true; return Task.CompletedTask; }; - var validator = new TicketValidator(Options.Create(options)); - var middleware = new TicketValidationMiddleware(next, validator, Options.Create(options), NullLogger.Instance); + var validator = new TicketValidator(options); + var middleware = new TicketValidationMiddleware(next, validator, options, NullLogger.Instance); return (middleware, () => nextCalled); }