Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET 8 Upgrade (Multi Framework targetting) #2181

Merged
merged 17 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7d8028e
Update dependencies and project files to .net8. Also fix nullable iss…
seantleonard Mar 28, 2024
f145905
Update targerframeworks for all projects to include net8 and net6.
seantleonard Apr 22, 2024
1063902
Merge branch 'main' into dev/sean/dotnet8upgrade
seantleonard Apr 22, 2024
4518169
updated formatting and merge conflict errors.
seantleonard Apr 22, 2024
1ab7ee5
update build pipeline to use .net8 and add comment.
seantleonard Apr 22, 2024
dea4d4d
merge main added using in mutation engine and used Dockerfile content…
seantleonard May 2, 2024
ee9694d
update jwt tests to use option "MapInboundClaims==false" so legacy cl…
seantleonard May 3, 2024
036c7a4
Merge branch 'main' into dev/sean/dotnet8upgrade
seantleonard May 3, 2024
903c4da
add both net6 and net8 sdks to all pipelines.
seantleonard May 3, 2024
402ad76
Merge branch 'dev/sean/dotnet8upgrade' of https://github.com/Azure/da…
seantleonard May 3, 2024
021d1c3
ignore correct serializationdeserializationtest and add .net8/6 sdk i…
seantleonard May 3, 2024
e339832
update pipelines to json substitute connection strings for all net6 a…
seantleonard May 3, 2024
c6dc14e
another attempt to get filetransform task to do json replace of conne…
seantleonard May 3, 2024
0e9ad76
updates the publish.ps1 script to run dotnet publish for both net6.0 …
seantleonard May 6, 2024
2cdc94d
Merge branch 'main' into dev/sean/dotnet8upgrade
seantleonard May 6, 2024
2a8d46e
updating TestDictionaryDatabaseObjectSerializationDeserialization tes…
seantleonard May 9, 2024
0dffcbf
Merge branch 'main' into dev/sean/dotnet8upgrade
seantleonard May 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions .pipelines/templates/build-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ steps:
echo "##vso[task.setvariable variable=\$id]$schemaId"
displayName: Set dab version

# The .NET CLI commands in proceeding tasks use the .NET SDK version specified here.
# Per Microsoft Learn Docs, "Selecting the .NET SDK version is independent from
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
# specifying the runtime version a project targets."
- task: UseDotNet@2
displayName: Setup .NET SDK v6.0.x
displayName: Setup .NET SDK v8.0.x
inputs:
packageType: sdk
version: 6.0.x
version: 8.0.x
installationPath: $(Agent.ToolsDirectory)/dotnet

- task: NuGetToolInstaller@1
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#
# Version values referenced from https://hub.docker.com/_/microsoft-dotnet-aspnet

FROM mcr.microsoft.com/dotnet/sdk:6.0-cbl-mariner2.0. AS build
FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0. AS build
WORKDIR /src
FROM mcr.microsoft.com/dotnet/aspnet:6.0-cbl-mariner2.0 AS runtime
FROM mcr.microsoft.com/dotnet/aspnet:8.0-cbl-mariner2.0 AS runtime

# The ./src/out path below points to the finalized build bits created by the pipeline.
# The path is relative to the "Docker build context" specified by the parameter dockerFileContextPath
Expand Down
2 changes: 1 addition & 1 deletion Nuget.config
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<configuration>
<packageSources>
<clear />
<add key="data_api_builder_build_packages" value="https://pkgs.dev.azure.com/sqldab/fcb212b3-b288-4c9e-b55a-5842a268b16d/_packaging/data_api_builder_build_packages/nuget/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
</packageSources>
<disabledPackageSources>
<clear />
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.100",
"version": "8.0.100",
"rollForward": "latestFeature"
}
}
2 changes: 1 addition & 1 deletion src/Auth/Azure.DataApiBuilder.Auth.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputPath>$(BaseOutputPath)\engine</OutputPath>
Expand Down
7 changes: 5 additions & 2 deletions src/Cli.Tests/Cli.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
Expand All @@ -14,7 +14,10 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.msbuild" />
<PackageReference Include="coverlet.msbuild">
<PrivateAssets>all</PrivateAssets>
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="MSTest.TestAdapter" />
Expand Down
2 changes: 1 addition & 1 deletion src/Cli.Tests/StringLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class StringLogger : ILogger
{
public List<string> Messages { get; } = new();

public IDisposable BeginScope<TState>(TState state)
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
return new Mock<IDisposable>().Object;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Cli/Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<RootNamespace>Cli</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
4 changes: 1 addition & 3 deletions src/Cli/CustomLoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ public bool IsEnabled(LogLevel logLevel)
{
return true;
}

/// <inheritdoc/>
public IDisposable BeginScope<TState>(TState state)
public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
throw new NotImplementedException();
}
Expand Down
2 changes: 1 addition & 1 deletion src/Config/Azure.DataApiBuilder.Config.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<OutputPath>$(BaseOutputPath)\engine</OutputPath>
Expand Down
4 changes: 2 additions & 2 deletions src/Core/AuthenticationHelpers/AppServiceAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ public class AppServiceClaim
{
ClaimsIdentity? identity = null;

if (context.Request.Headers.TryGetValue(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, out StringValues header))
if (context.Request.Headers.TryGetValue(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, out StringValues headerValues) && headerValues.Count == 1)
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
string encodedPrincipalData = header[0];
string encodedPrincipalData = headerValues.ToString();
byte[] decodedPrincpalData = Convert.FromBase64String(encodedPrincipalData);
string json = Encoding.UTF8.GetString(decodedPrincpalData);
AppServiceClientPrincipal? principal = JsonSerializer.Deserialize<AppServiceClientPrincipal>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@ namespace Azure.DataApiBuilder.Core.AuthenticationHelpers.AuthenticationSimulato
/// </summary>
public class SimulatorAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
#if NET8_0_OR_GREATER
/// <summary>
/// Constructor for the SimulatorAuthenticationHandler.
/// Note the parameters are required by the base class.
/// </summary>
/// <param name="runtimeConfigProvider">Runtime configuration provider.</param>
/// <param name="options">Simulator authentication options.</param>
/// <param name="logger">Logger factory.</param>
/// <param name="encoder">URL encoder.</param>
/// <param name="clock">System clock.</param>
public SimulatorAuthenticationHandler(
RuntimeConfigProvider runtimeConfigProvider,
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder)
// ISystemClock is obsolete in .NET 8.0 and later
// https://learn.microsoft.com/dotnet/core/compatibility/aspnet-core/8.0/isystemclock-obsolete
: base(options, logger, encoder)
{
}
#else
/// <summary>
/// Constructor for the SimulatorAuthenticationHandler.
/// Note the parameters are required by the base class.
Expand All @@ -36,10 +57,10 @@ public class SimulatorAuthenticationHandler : AuthenticationHandler<Authenticati
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock
) : base(options, logger, encoder, clock)
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
#endif

/// <summary>
/// Gets any authentication data for a request. When a client role header is present,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public async Task InvokeAsync(HttpContext httpContext)
// in an authenticated requests.
if (isAuthenticatedRequest)
{
clientDefinedRole = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER];
clientDefinedRole = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER].ToString();
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
Expand Down
24 changes: 21 additions & 3 deletions src/Core/AuthenticationHelpers/EasyAuthAuthenticationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,40 @@ namespace Azure.DataApiBuilder.Core.AuthenticationHelpers;
/// </summary>
public class EasyAuthAuthenticationHandler : AuthenticationHandler<EasyAuthAuthenticationOptions>
{
#if NET8_0_OR_GREATER
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>
/// Constructor for the EasyAuthAuthenticationHandler.
/// Note the parameters are required by the base class.
/// </summary>
/// <param name="options">EasyAuth authentication options.</param>
/// <param name="logger">Logger factory.</param>
/// <param name="encoder">URL encoder.</param>
public EasyAuthAuthenticationHandler(
IOptionsMonitor<EasyAuthAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder)
// ISystemClock is obsolete in .NET 8.0 and later
// https://learn.microsoft.com/dotnet/core/compatibility/aspnet-core/8.0/isystemclock-obsolete
: base(options, logger, encoder)
{
}
#else
/// <summary>
/// Constructor for the EasyAuthAuthenticationHandler.
/// Note the parameters are required by the base class.
/// </summary>
/// <param name="options">EasyAuth authentication options.</param>
/// <param name="logger">Logger factory.</param>
/// <param name="encoder">URL encoder.</param>
/// <param name="clock">System clock.</param>
public EasyAuthAuthenticationHandler(
IOptionsMonitor<EasyAuthAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock
) : base(options, logger, encoder, clock)
ISystemClock clock)
: base(options, logger, encoder, clock)
{
}
#endif

/// <summary>
/// Attempts processing of a request's authentication metadata.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ public class StaticWebAppsClientPrincipal
StaticWebAppsClientPrincipal principal = new();
try
{
if (context.Request.Headers.TryGetValue(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, out StringValues headerPayload))
if (context.Request.Headers.TryGetValue(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, out StringValues headerPayload) && headerPayload.Count == 1)
{
string data = headerPayload[0];
string data = headerPayload.ToString();
byte[] decoded = Convert.FromBase64String(data);
string json = Encoding.UTF8.GetString(decoded);
principal = JsonSerializer.Deserialize<StaticWebAppsClientPrincipal>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? new();
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Authorization/RestAuthorizationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public Task HandleAsync(AuthorizationHandlerContext context)
);
}

string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER];
string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER].ToString();
IEnumerable<EntityActionOperation> operations = HttpVerbToOperations(httpContext.Request.Method);

foreach (EntityActionOperation operation in operations)
Expand Down Expand Up @@ -140,7 +140,7 @@ public Task HandleAsync(AuthorizationHandlerContext context)
}

string entityName = restContext.EntityName;
string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER];
string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER].ToString();
IEnumerable<EntityActionOperation> operations = HttpVerbToOperations(httpContext.Request.Method);

// Delete operations do not have column level restrictions.
Expand Down Expand Up @@ -224,7 +224,7 @@ public Task HandleAsync(AuthorizationHandlerContext context)
);
}

string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER];
string roleName = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER].ToString();
Enum.TryParse<SupportedHttpVerb>(httpContext.Request.Method, ignoreCase: true, out SupportedHttpVerb httpVerb);
bool isAuthorized = _authorizationResolver.IsStoredProcedureExecutionPermitted(entityName, roleName, httpVerb);
if (!isAuthorized)
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Azure.DataApiBuilder.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Models/GraphQLFilterParsers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public GQLFilterParser(RuntimeConfigProvider runtimeConfigProvider, IMetadataPro

bool columnAccessPermitted = queryStructure.AuthorizationResolver.AreColumnsAllowedForOperation(
entityName: originalEntityName,
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER],
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER].ToString(),
seantleonard marked this conversation as resolved.
Show resolved Hide resolved
operation: EntityActionOperation.Read,
columns: new[] { name });

Expand Down Expand Up @@ -300,7 +300,7 @@ public GQLFilterParser(RuntimeConfigProvider runtimeConfigProvider, IMetadataPro
// Validate that the field referenced in the nested input filter can be accessed.
bool entityAccessPermitted = queryStructure.AuthorizationResolver.AreRoleAndOperationDefinedForEntity(
entityIdentifier: entityType,
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER],
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER].ToString(),
operation: EntityActionOperation.Read);

if (!entityAccessPermitted)
Expand Down Expand Up @@ -389,7 +389,7 @@ public GQLFilterParser(RuntimeConfigProvider runtimeConfigProvider, IMetadataPro
// Validate that the field referenced in the nested input filter can be accessed.
bool entityAccessPermitted = queryStructure.AuthorizationResolver.AreRoleAndOperationDefinedForEntity(
entityIdentifier: nestedFilterEntityName,
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER],
roleName: GetHttpContextFromMiddlewareContext(ctx).Request.Headers[CLIENT_ROLE_HEADER].ToString(),
operation: EntityActionOperation.Read);

if (!entityAccessPermitted)
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Resolvers/QueryExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public class QueryExecutor<TConnection> : IQueryExecutor
{
if (DbExceptionParser.IsTransientException((DbException)e) && retryAttempt < _maxRetryCount + 1)
{
throw e;
throw;
}
else
{
Expand Down
11 changes: 10 additions & 1 deletion src/Core/Resolvers/SqlMutationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;

namespace Azure.DataApiBuilder.Core.Resolvers
{
Expand Down Expand Up @@ -458,7 +459,15 @@ private static bool IsPointMutation(IMiddlewareContext context)
}
else
{
string roleName = GetHttpContext().Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER];
if (!GetHttpContext().Request.Headers.TryGetValue(AuthorizationResolver.CLIENT_ROLE_HEADER, out StringValues headerValues) && headerValues.Count != 1)
{
throw new DataApiBuilderException(
message: $"No role found.",
statusCode: HttpStatusCode.Forbidden,
subStatusCode: DataApiBuilderException.SubStatusCodes.AuthorizationCheckFailed);
}

string roleName = headerValues.ToString();
bool isReadPermissionConfiguredForRole = _authorizationResolver.AreRoleAndOperationDefinedForEntity(context.EntityName, roleName, EntityActionOperation.Read);
bool isDatabasePolicyDefinedForReadAction = false;
JsonDocument? selectOperationResponse = null;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Services/Cache/DabCacheService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public DabCacheService(IFusionCache cache, ILogger<DabCacheService>? logger, IHt
string cacheKey = CreateCacheKey(queryMetadata);
JsonElement? result = await _cache.GetOrSetAsync(
key: cacheKey,
async (FusionCacheFactoryExecutionContext<JsonElement> ctx, CancellationToken ct) =>
async (FusionCacheFactoryExecutionContext<JsonElement?> ctx, CancellationToken ct) =>
{
// Need to handle undesirable results like db errors or null.
JsonElement? result = await queryExecutor.ExecuteQueryAsync(
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Services/OpenAPI/OpenApiDocumentor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public void CreateDocument()
},
Servers = new List<OpenApiServer>
{
new OpenApiServer { Url = url }
new() { Url = url }
},
Paths = BuildPaths(),
Components = components
Expand Down