diff --git a/code/backend/Cleanuparr.Api.Tests/Features/Arr/ArrConfigControllerTests.cs b/code/backend/Cleanuparr.Api.Tests/Features/Arr/ArrConfigControllerTests.cs index e6cf1e6e..b700a444 100644 --- a/code/backend/Cleanuparr.Api.Tests/Features/Arr/ArrConfigControllerTests.cs +++ b/code/backend/Cleanuparr.Api.Tests/Features/Arr/ArrConfigControllerTests.cs @@ -4,7 +4,7 @@ using Cleanuparr.Api.Features.Arr.Controllers; using Cleanuparr.Api.Tests.TestHelpers; using Cleanuparr.Domain.Enums; using Cleanuparr.Infrastructure.Events.Interfaces; -using Cleanuparr.Infrastructure.Features.Arr.Dtos; +using Cleanuparr.Api.Features.Arr.Contracts.Responses; using Cleanuparr.Infrastructure.Features.Arr.Interfaces; using Cleanuparr.Persistence; using Cleanuparr.Persistence.Models.Configuration.Arr; @@ -60,7 +60,7 @@ public class ArrConfigControllerTests : IDisposable // Assert var ok = result.ShouldBeOfType(); - var dto = ok.Value.ShouldBeOfType(); + var dto = ok.Value.ShouldBeOfType(); dto.Type.ShouldBe(type); } @@ -79,7 +79,7 @@ public class ArrConfigControllerTests : IDisposable // Assert var ok = result.ShouldBeOfType(); - var dto = ok.Value.ShouldBeOfType(); + var dto = ok.Value.ShouldBeOfType(); dto.Instances[0].Name.ShouldBe("a"); dto.Instances[1].Name.ShouldBe("z"); } @@ -137,7 +137,7 @@ public class ArrConfigControllerTests : IDisposable // Assert var created = result.ShouldBeOfType(); - var dto = created.Value.ShouldBeOfType(); + var dto = created.Value.ShouldBeOfType(); dto.Name.ShouldBe("test"); var sonarrConfig = await _dataContext.ArrConfigs .Include(c => c.Instances) @@ -427,12 +427,12 @@ public class ArrConfigControllerTests : IDisposable // Act + Assert: create IActionResult created = await DispatchCreate(type, request); - ArrInstanceDto dto = created.ShouldBeOfType().Value.ShouldBeOfType(); + ArrInstanceResponse dto = created.ShouldBeOfType().Value.ShouldBeOfType(); // Act + Assert: update Guid id = dto.Id.ShouldNotBeNull(); IActionResult updated = await DispatchUpdate(type, id, request with { Name = "rewired" }); - updated.ShouldBeOfType().Value.ShouldBeOfType().Name.ShouldBe("rewired"); + updated.ShouldBeOfType().Value.ShouldBeOfType().Name.ShouldBe("rewired"); // Act + Assert: connection test IActionResult tested = await DispatchTest(type, new TestArrInstanceRequest diff --git a/code/backend/Cleanuparr.Api.Tests/Features/SensitiveData/SensitiveDataResolverTests.cs b/code/backend/Cleanuparr.Api.Tests/Features/SensitiveData/SensitiveDataResolverTests.cs index d59a0813..5f5ed6aa 100644 --- a/code/backend/Cleanuparr.Api.Tests/Features/SensitiveData/SensitiveDataResolverTests.cs +++ b/code/backend/Cleanuparr.Api.Tests/Features/SensitiveData/SensitiveDataResolverTests.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization.Metadata; using Cleanuparr.Api.Json; using Cleanuparr.Domain.Enums; -using Cleanuparr.Infrastructure.Features.Arr.Dtos; +using Cleanuparr.Api.Features.Arr.Contracts.Responses; using Cleanuparr.Persistence.Models.Configuration; using Cleanuparr.Persistence.Models.Configuration.Arr; using Cleanuparr.Persistence.Models.Configuration.Notification; @@ -74,7 +74,7 @@ public class SensitiveDataResolverTests public void ArrInstance_NullApiKey_RemainsNull() { // ApiKey is required, but let's test with the DTO which might handle null - var dto = new ArrInstanceDto + var dto = new ArrInstanceResponse { Name = "Sonarr", Url = "http://sonarr:8989", @@ -90,12 +90,12 @@ public class SensitiveDataResolverTests #endregion - #region ArrInstanceDto + #region ArrInstanceResponse [Fact] public void ArrInstanceDto_ApiKey_IsMasked() { - var dto = new ArrInstanceDto + var dto = new ArrInstanceResponse { Id = Guid.NewGuid(), Name = "Radarr", diff --git a/code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrConfigResponse.cs b/code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrConfigResponse.cs new file mode 100644 index 00000000..0a77f973 --- /dev/null +++ b/code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrConfigResponse.cs @@ -0,0 +1,14 @@ +using Cleanuparr.Domain.Enums; + +namespace Cleanuparr.Api.Features.Arr.Contracts.Responses; + +public sealed record ArrConfigResponse +{ + public required Guid Id { get; init; } + + public required InstanceType Type { get; init; } + + public short FailedImportMaxStrikes { get; init; } = -1; + + public List Instances { get; init; } = []; +} diff --git a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrInstanceDto.cs b/code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrInstanceResponse.cs similarity index 68% rename from code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrInstanceDto.cs rename to code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrInstanceResponse.cs index f5e03beb..38672bbd 100644 --- a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrInstanceDto.cs +++ b/code/backend/Cleanuparr.Api/Features/Arr/Contracts/Responses/ArrInstanceResponse.cs @@ -1,31 +1,31 @@ using System.ComponentModel.DataAnnotations; using Cleanuparr.Shared.Attributes; -namespace Cleanuparr.Infrastructure.Features.Arr.Dtos; +namespace Cleanuparr.Api.Features.Arr.Contracts.Responses; /// -/// DTO for Arr instances that can handle both existing (with ID) and new (without ID) instances +/// Response shape for Arr instances, covering both existing (with ID) and new (without ID) instances. /// -public record ArrInstanceDto +public sealed record ArrInstanceResponse { /// /// ID for existing instances, null for new instances /// public Guid? Id { get; init; } - + public bool Enabled { get; init; } = true; - - public float Version { get; set; } - + + public float Version { get; init; } + [Required] public required string Name { get; init; } - + [Required] public required string Url { get; init; } - + [Required] [SensitiveData] public required string ApiKey { get; init; } public string? ExternalUrl { get; init; } -} \ No newline at end of file +} diff --git a/code/backend/Cleanuparr.Api/Features/Arr/Controllers/ArrConfigController.cs b/code/backend/Cleanuparr.Api/Features/Arr/Controllers/ArrConfigController.cs index 6f0be759..07491e58 100644 --- a/code/backend/Cleanuparr.Api/Features/Arr/Controllers/ArrConfigController.cs +++ b/code/backend/Cleanuparr.Api/Features/Arr/Controllers/ArrConfigController.cs @@ -2,7 +2,7 @@ using Cleanuparr.Api.Features.Arr.Contracts.Requests; using Cleanuparr.Domain.Enums; using Cleanuparr.Infrastructure.Events.Interfaces; -using Cleanuparr.Infrastructure.Features.Arr.Dtos; +using Cleanuparr.Api.Features.Arr.Contracts.Responses; using Cleanuparr.Infrastructure.Health; using Cleanuparr.Persistence; using Cleanuparr.Persistence.Models.Configuration.Arr; @@ -413,7 +413,7 @@ public sealed class ArrConfigController : ControllerBase } } - private static ArrConfigDto ToDto(ArrConfig config) => new() + private static ArrConfigResponse ToDto(ArrConfig config) => new() { Id = config.Id, Type = config.Type, @@ -421,7 +421,7 @@ public sealed class ArrConfigController : ControllerBase Instances = config.Instances.Select(ToDto).ToList(), }; - private static ArrInstanceDto ToDto(ArrInstance instance) => new() + private static ArrInstanceResponse ToDto(ArrInstance instance) => new() { Id = instance.Id, Enabled = instance.Enabled, diff --git a/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AccountController.cs b/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AccountController.cs index e1fa92b4..ae1b3b7e 100644 --- a/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AccountController.cs +++ b/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AccountController.cs @@ -102,7 +102,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("Password changed for user {Username}", user.Username); - return Ok(new { message = "Password changed" }); + return Ok(new { Message = "Password changed" }); } finally { @@ -158,7 +158,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("Username changed from {PreviousUsername} to {Username}", previousUsername.SanitizeForLog(), newUsername.SanitizeForLog()); - return Ok(new { message = "Username changed" }); + return Ok(new { Message = "Username changed" }); } finally { @@ -303,7 +303,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("2FA enabled for user {Username}", user.Username); - return Ok(new { message = "2FA enabled" }); + return Ok(new { Message = "2FA enabled" }); } finally { @@ -382,7 +382,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("2FA disabled for user {Username}", user.Username); - return Ok(new { message = "2FA disabled" }); + return Ok(new { Message = "2FA disabled" }); } [HttpGet("api-key")] @@ -491,7 +491,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("Plex account unlinked for user {Username}", user.Username); - return Ok(new { message = "Plex account unlinked" }); + return Ok(new { Message = "Plex account unlinked" }); } [HttpGet("oidc")] @@ -524,7 +524,7 @@ public sealed class AccountController : ControllerBase user.UpdatedAt = _timeProvider.GetUtcNow(); await _usersContext.SaveChangesAsync(); - return Ok(new { message = "OIDC configuration updated" }); + return Ok(new { Message = "OIDC configuration updated" }); } finally { @@ -637,7 +637,7 @@ public sealed class AccountController : ControllerBase _logger.LogInformation("OIDC account unlinked for user {Username}", user.Username); - return Ok(new { message = "OIDC account unlinked" }); + return Ok(new { Message = "OIDC account unlinked" }); } finally { diff --git a/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AuthController.cs b/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AuthController.cs index 19f2d2e4..7e45f4dd 100644 --- a/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AuthController.cs +++ b/code/backend/Cleanuparr.Api/Features/Auth/Controllers/AuthController.cs @@ -198,7 +198,7 @@ public sealed class AuthController : ControllerBase _logger.LogInformation("2FA enabled for user {Username}", user.Username); - return Ok(new { message = "2FA verified and enabled" }); + return Ok(new { Message = "2FA verified and enabled" }); } finally { @@ -229,7 +229,7 @@ public sealed class AuthController : ControllerBase _logger.LogInformation("Setup completed for user {Username}", user.Username); - return Ok(new { message = "Setup complete" }); + return Ok(new { Message = "Setup complete" }); } finally { @@ -420,7 +420,7 @@ public sealed class AuthController : ControllerBase await _usersContext.SaveChangesAsync(); } - return Ok(new { message = "Logged out" }); + return Ok(new { Message = "Logged out" }); } finally { diff --git a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrConfigDto.cs b/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrConfigDto.cs deleted file mode 100644 index 18e50786..00000000 --- a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/ArrConfigDto.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Cleanuparr.Domain.Enums; - -namespace Cleanuparr.Infrastructure.Features.Arr.Dtos; - -public class ArrConfigDto -{ - public Guid Id { get; set; } - - public required InstanceType Type { get; set; } - - public short FailedImportMaxStrikes { get; set; } = -1; - - public List Instances { get; set; } = []; -} \ No newline at end of file diff --git a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/CreateArrInstanceDto.cs b/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/CreateArrInstanceDto.cs deleted file mode 100644 index 86beec3c..00000000 --- a/code/backend/Cleanuparr.Infrastructure/Features/Arr/Dtos/CreateArrInstanceDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Cleanuparr.Infrastructure.Features.Arr.Dtos; - -/// -/// DTO for creating new Arr instances without requiring an ID -/// -public record CreateArrInstanceDto -{ - public bool Enabled { get; init; } = true; - - [Required] - public required string Name { get; init; } - - [Required] - public required string Url { get; init; } - - [Required] - public required string ApiKey { get; init; } -} \ No newline at end of file