Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Orbit.Api/Controllers/ProfileController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
}

[HttpPut("ai-memory")]
[Obsolete("AI memory is deprecated and will be removed.")]

Check warning on line 108 in src/Orbit.Api/Controllers/ProfileController.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=thomasluizon_orbit-api&issues=AaFS2zV7Z2pN_ZCizBYo&open=AaFS2zV7Z2pN_ZCizBYo&pullRequest=771
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
Expand Down
3 changes: 3 additions & 0 deletions src/Orbit.Api/Controllers/UserFactsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
public record BulkDeleteUserFactsRequest(IReadOnlyList<Guid> FactIds);

[HttpGet]
[Obsolete("AI memory is deprecated and will be removed.")]

Check warning on line 23 in src/Orbit.Api/Controllers/UserFactsController.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=thomasluizon_orbit-api&issues=AaFS2zYMZ2pN_ZCizBYp&open=AaFS2zYMZ2pN_ZCizBYp&pullRequest=771
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
Expand All @@ -31,6 +32,7 @@
}

[HttpDelete("{id:guid}")]
[Obsolete("AI memory is deprecated and will be removed.")]

Check warning on line 35 in src/Orbit.Api/Controllers/UserFactsController.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=thomasluizon_orbit-api&issues=AaFS2zYMZ2pN_ZCizBYr&open=AaFS2zYMZ2pN_ZCizBYr&pullRequest=771
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
Expand All @@ -46,6 +48,7 @@
}

[HttpDelete("bulk")]
[Obsolete("AI memory is deprecated and will be removed.")]

Check warning on line 51 in src/Orbit.Api/Controllers/UserFactsController.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=thomasluizon_orbit-api&issues=AaFS2zYMZ2pN_ZCizBYq&open=AaFS2zYMZ2pN_ZCizBYq&pullRequest=771
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
builder.Services.AddApiVersioning(options =>
{
options.ApiVersionReader = new HeaderApiVersionReader("api-version");
options.AssumeDefaultVersionWhenUnspecified = true;

Check warning on line 318 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Build

AssumeDefaultVersionWhenUnspecified = true is only necessary for existing APIs that do not have an explicit API version (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0016.html)

Check warning on line 318 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Unit Tests

AssumeDefaultVersionWhenUnspecified = true is only necessary for existing APIs that do not have an explicit API version (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0016.html)

Check warning on line 318 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

AssumeDefaultVersionWhenUnspecified = true is only necessary for existing APIs that do not have an explicit API version (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0016.html)
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ReportApiVersions = true;
options.UnsupportedApiVersionStatusCode = StatusCodes.Status400BadRequest;
Expand All @@ -323,8 +323,8 @@
.AddMvc()
.AddApiExplorer(options => options.GroupNameFormat = "'v'VVV");

builder.Services.AddOpenApi("v1", options => ConfigureOrbitOpenApi(options, "1.0"));

Check warning on line 326 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Build

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)

Check warning on line 326 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Unit Tests

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)

Check warning on line 326 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)
builder.Services.AddOpenApi("v2", options => ConfigureOrbitOpenApi(options, "2.0"));

Check warning on line 327 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Build

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)

Check warning on line 327 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Unit Tests

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)

Check warning on line 327 in src/Orbit.Api/Extensions/ServiceCollectionExtensions.Infrastructure.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

AddApiVersioning().AddOpenApi() registers the OpenAPI services that describe API versions (https://dotnet.github.io/aspnet-api-versioning/diagnostic/av0029.html)
}

private static void ConfigureOrbitOpenApi(Microsoft.AspNetCore.OpenApi.OpenApiOptions options, string version)
Expand All @@ -342,6 +342,12 @@
operation.Deprecated = true;
return Task.CompletedTask;
});
options.AddSchemaTransformer((schema, context, _) =>
{
if (context.JsonPropertyInfo?.AttributeProvider?.IsDefined(typeof(ObsoleteAttribute), false) == true)
schema.Deprecated = true;
return Task.CompletedTask;
});
}

private static void AddResponseCompression(WebApplicationBuilder builder)
Expand Down
15 changes: 10 additions & 5 deletions src/Orbit.Api/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -11665,7 +11665,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/Profile/ai-summary": {
Expand Down Expand Up @@ -15156,7 +15157,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/user-facts/{id}": {
Expand Down Expand Up @@ -15226,7 +15228,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/user-facts/bulk": {
Expand Down Expand Up @@ -15307,7 +15310,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/Waitlist": {
Expand Down Expand Up @@ -18567,7 +18571,8 @@
]
},
"aiMemoryEnabled": {
"type": "boolean"
"type": "boolean",
"deprecated": true
},
"aiSummaryEnabled": {
"type": "boolean"
Expand Down
15 changes: 10 additions & 5 deletions src/Orbit.Api/openapi_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -11818,7 +11818,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/Profile/ai-summary": {
Expand Down Expand Up @@ -15354,7 +15355,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/user-facts/{id}": {
Expand Down Expand Up @@ -15425,7 +15427,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/user-facts/bulk": {
Expand Down Expand Up @@ -15507,7 +15510,8 @@
}
}
}
}
},
"deprecated": true
}
},
"/api/Waitlist": {
Expand Down Expand Up @@ -18768,7 +18772,8 @@
]
},
"aiMemoryEnabled": {
"type": "boolean"
"type": "boolean",
"deprecated": true
},
"aiSummaryEnabled": {
"type": "boolean"
Expand Down
1 change: 1 addition & 0 deletions src/Orbit.Application/Profile/Queries/GetProfileQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
string Name,
string Email,
string? TimeZone,
[property: Obsolete("AI memory is deprecated and will be removed.")]

Check warning on line 19 in src/Orbit.Application/Profile/Queries/GetProfileQuery.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=thomasluizon_orbit-api&issues=AaFS2zaAZ2pN_ZCizBYs&open=AaFS2zaAZ2pN_ZCizBYs&pullRequest=771

Check warning on line 19 in src/Orbit.Application/Profile/Queries/GetProfileQuery.cs

View workflow job for this annotation

GitHub Actions / SonarCloud Analysis

Do not forget to remove this deprecated code someday.
bool AiMemoryEnabled,
bool AiSummaryEnabled,
bool HasCompletedOnboarding,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Reflection;
using System.Text.Json;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Routing;
using Orbit.Api.Controllers;

namespace Orbit.Infrastructure.Tests.Controllers;

public class AiMemoryDeprecationTests
{
[Theory]
[InlineData(typeof(UserFactsController), "GetUserFacts", null, "GET")]
[InlineData(typeof(UserFactsController), "DeleteUserFact", "{id:guid}", "DELETE")]
[InlineData(typeof(UserFactsController), "BulkDeleteUserFacts", "bulk", "DELETE")]
[InlineData(typeof(ProfileController), "SetAiMemory", "ai-memory", "PUT")]
public void RouteRemainsAvailableAndDeprecated(Type controller, string action, string? template, string verb)
{
var method = controller.GetMethod(action);

method.Should().NotBeNull();
var route = method!.GetCustomAttributes<HttpMethodAttribute>().Should().ContainSingle().Subject;
route.Template.Should().Be(template);
route.HttpMethods.Should().ContainSingle().Which.Should().Be(verb);
method.GetCustomAttributes<ObsoleteAttribute>().Should().ContainSingle();
}

[Theory]
[InlineData("openapi.json", "/api/user-facts", "get")]
[InlineData("openapi.json", "/api/user-facts/{id}", "delete")]
[InlineData("openapi.json", "/api/user-facts/bulk", "delete")]
[InlineData("openapi.json", "/api/Profile/ai-memory", "put")]
[InlineData("openapi_v2.json", "/api/user-facts", "get")]
[InlineData("openapi_v2.json", "/api/user-facts/{id}", "delete")]
[InlineData("openapi_v2.json", "/api/user-facts/bulk", "delete")]
[InlineData("openapi_v2.json", "/api/Profile/ai-memory", "put")]
public void GeneratedOpenApiMarksRouteDeprecated(string file, string route, string verb)
{
using var document = ReadOpenApi(file);
var operation = document.RootElement.GetProperty("paths").GetProperty(route).GetProperty(verb);

operation.TryGetProperty("deprecated", out var deprecated).Should().BeTrue();
deprecated.GetBoolean().Should().BeTrue();
}

[Theory]
[InlineData("openapi.json")]
[InlineData("openapi_v2.json")]
public void GeneratedOpenApiKeepsMemorySettingRequiredAndMarksItDeprecated(string file)
{
using var document = ReadOpenApi(file);
var profile = document.RootElement.GetProperty("components").GetProperty("schemas").GetProperty("ProfileResponse");
var setting = profile.GetProperty("properties").GetProperty("aiMemoryEnabled");

profile.GetProperty("required").EnumerateArray().Select(value => value.GetString())
.Should().Contain("aiMemoryEnabled");
setting.GetProperty("type").GetString().Should().Be("boolean");
setting.TryGetProperty("deprecated", out var deprecated).Should().BeTrue();
deprecated.GetBoolean().Should().BeTrue();
}

private static JsonDocument ReadOpenApi(string file)
{
var path = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory,
"../../../../..", "src/Orbit.Api", file));
return JsonDocument.Parse(File.ReadAllText(path));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public async Task SetTimezone_Failure_ReturnsBadRequest()
}

[Fact]
[Obsolete("Covers the deprecated PUT /api/Profile/ai-memory route.")]
public async Task SetAiMemory_Success_ReturnsNoContent()
{
_mediator.Send(Arg.Any<SetAiMemoryCommand>(), Arg.Any<CancellationToken>())
Expand All @@ -109,6 +110,7 @@ public async Task SetAiMemory_Success_ReturnsNoContent()
}

[Fact]
[Obsolete("Covers the deprecated PUT /api/Profile/ai-memory route.")]
public async Task SetAiMemory_Failure_ReturnsBadRequest()
{
_mediator.Send(Arg.Any<SetAiMemoryCommand>(), Arg.Any<CancellationToken>())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public UserFactsControllerTests()
}

[Fact]
[Obsolete("Covers the deprecated GET /api/user-facts route.")]
public async Task GetUserFacts_Success_ReturnsOk()
{
_mediator.Send(Arg.Any<GetUserFactsQuery>(), Arg.Any<CancellationToken>())
Expand All @@ -44,6 +45,7 @@ public async Task GetUserFacts_Success_ReturnsOk()
}

[Fact]
[Obsolete("Covers the deprecated GET /api/user-facts route.")]
public async Task GetUserFacts_Failure_ReturnsBadRequest()
{
_mediator.Send(Arg.Any<GetUserFactsQuery>(), Arg.Any<CancellationToken>())
Expand All @@ -55,6 +57,7 @@ public async Task GetUserFacts_Failure_ReturnsBadRequest()
}

[Fact]
[Obsolete("Covers the deprecated DELETE /api/user-facts/{id} route.")]
public async Task DeleteUserFact_Success_ReturnsNoContent()
{
_mediator.Send(Arg.Any<DeleteUserFactCommand>(), Arg.Any<CancellationToken>())
Expand All @@ -66,6 +69,7 @@ public async Task DeleteUserFact_Success_ReturnsNoContent()
}

[Fact]
[Obsolete("Covers the deprecated DELETE /api/user-facts/{id} route.")]
public async Task DeleteUserFact_NotFound_ReturnsNotFound()
{
_mediator.Send(Arg.Any<DeleteUserFactCommand>(), Arg.Any<CancellationToken>())
Expand All @@ -77,6 +81,7 @@ public async Task DeleteUserFact_NotFound_ReturnsNotFound()
}

[Fact]
[Obsolete("Covers the deprecated DELETE /api/user-facts/bulk route.")]
public async Task BulkDeleteUserFacts_Success_ReturnsOk()
{
_mediator.Send(Arg.Any<BulkDeleteUserFactsCommand>(), Arg.Any<CancellationToken>())
Expand All @@ -89,6 +94,7 @@ public async Task BulkDeleteUserFacts_Success_ReturnsOk()
}

[Fact]
[Obsolete("Covers the deprecated DELETE /api/user-facts/bulk route.")]
public async Task BulkDeleteUserFacts_Failure_ReturnsBadRequest()
{
_mediator.Send(Arg.Any<BulkDeleteUserFactsCommand>(), Arg.Any<CancellationToken>())
Expand Down
Loading