diff --git a/.github/workflows/on-prerelease.yml b/.github/workflows/on-prerelease.yml index 9626b3b07..f417bc64f 100644 --- a/.github/workflows/on-prerelease.yml +++ b/.github/workflows/on-prerelease.yml @@ -53,11 +53,6 @@ jobs: # SemVer "admin-api-semver=$($apiVersion -Replace $apiPrefix)" >> $env:GITHUB_OUTPUT - - name: Setup .NET - uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3 - with: - dotnet-version: 6.0.x - - name: Publish .NET Assemblies run: | $apiVersion = "${{ steps.versions.outputs.admin-api-semver }}" diff --git a/.github/workflows/on-pullrequest.yml b/.github/workflows/on-pullrequest.yml index 33c66d126..57df65431 100644 --- a/.github/workflows/on-pullrequest.yml +++ b/.github/workflows/on-pullrequest.yml @@ -41,10 +41,6 @@ jobs: steps: - name: Checkout the Repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - name: Setup .NET - uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3 - with: - dotnet-version: 6.0.x - name: Build run: ./build.ps1 -Command Build -Configuration Debug diff --git a/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj b/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj index 17f748ea6..0682be199 100644 --- a/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj +++ b/Application/EdFi.Ods.AdminApi.DBTests/EdFi.Ods.AdminApi.DBTests.csproj @@ -1,38 +1,31 @@ - - - net6.0 - - - - - - - - - - - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - Always - - - + + net8.0 + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + Always + + + \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminApi.DBTests/MockExtensions.cs b/Application/EdFi.Ods.AdminApi.DBTests/MockExtensions.cs deleted file mode 100644 index 405dbe394..000000000 --- a/Application/EdFi.Ods.AdminApi.DBTests/MockExtensions.cs +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Licensed to the Ed-Fi Alliance under one or more agreements. -// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. -// See the LICENSE and NOTICES files in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Data.Entity; -using System.Data.Entity.Infrastructure; -using System.Linq; -using Moq; - -namespace EdFi.Ods.AdminApi.DBTests -{ - public static class MockExtensions - { - public static Mock> MockDbSet(List underlyingData) where T : class - { - var mockSet = new Mock>(); - mockSet.ConfigureDbSetWithData(underlyingData); - - return mockSet; - } - - public static Mock> EmptyMockDbSet() where T : class - { - var mockSet = new Mock>(); - var underlyingData = new List(); - - ConfigureDbSetWithData(mockSet, underlyingData); - - return mockSet; - } - - public static Mock> ConfigureDbSetWithData(this Mock> mockSet, List underlyingData) where T : class - { - mockSet.As>() - .Setup(m => m.GetAsyncEnumerator()) - .Returns(() => new TestDbAsyncEnumerator(underlyingData.GetEnumerator())); - - mockSet.As>() - .Setup(m => m.Provider) - .Returns(() => new TestDbAsyncQueryProvider(underlyingData.AsQueryable().Provider)); - - mockSet.As>().Setup(m => m.Expression).Returns(() => underlyingData.AsQueryable().Expression); - mockSet.As>().Setup(m => m.ElementType).Returns(() => underlyingData.AsQueryable().ElementType); - mockSet.As>().Setup(m => m.GetEnumerator()).Returns(() => underlyingData.AsQueryable().GetEnumerator()); - - mockSet.Setup(m => m.Add(It.IsAny())).Callback((T x) => underlyingData.Add(x)); - mockSet.Setup(m => m.AddRange(It.IsAny>())).Callback((IEnumerable x) => underlyingData.AddRange(x)); - mockSet.Setup(m => m.Remove(It.IsAny())).Callback((T x) => underlyingData.Remove(x)); - mockSet.Setup(m => m.RemoveRange(It.IsAny>())).Callback((IEnumerable x) => underlyingData.RemoveAll(x.Contains)); - - return mockSet; - } - } -} diff --git a/Application/EdFi.Ods.AdminApi.DBTests/TestDbAsyncEnumerator.cs b/Application/EdFi.Ods.AdminApi.DBTests/TestDbAsyncEnumerator.cs deleted file mode 100644 index 3853e6499..000000000 --- a/Application/EdFi.Ods.AdminApi.DBTests/TestDbAsyncEnumerator.cs +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Licensed to the Ed-Fi Alliance under one or more agreements. -// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. -// See the LICENSE and NOTICES files in the project root for more information. - -using System.Collections.Generic; -using System.Data.Entity.Infrastructure; -using System.Linq; -using System.Linq.Expressions; -using System.Threading; -using System.Threading.Tasks; - -namespace EdFi.Ods.AdminApi.DBTests; - -//Classes to assist with mocking a DBSet -- see https://msdn.microsoft.com/en-us/library/dn314429.aspx - -internal class TestDbAsyncQueryProvider : IDbAsyncQueryProvider -{ - private readonly IQueryProvider _inner; - - internal TestDbAsyncQueryProvider(IQueryProvider inner) - { - _inner = inner; - } - - public IQueryable CreateQuery(Expression expression) - { - return new TestDbAsyncEnumerable(expression); - } - - public IQueryable CreateQuery(Expression expression) - { - return new TestDbAsyncEnumerable(expression); - } - - public object Execute(Expression expression) - { - return _inner.Execute(expression); - } - - public TResult Execute(Expression expression) - { - return _inner.Execute(expression); - } - - public Task ExecuteAsync(Expression expression, CancellationToken cancellationToken) - { - return Task.FromResult(Execute(expression)); - } - - public Task ExecuteAsync(Expression expression, CancellationToken cancellationToken) - { - return Task.FromResult(Execute(expression)); - } -} - -internal class TestDbAsyncEnumerable : EnumerableQuery, IDbAsyncEnumerable, IQueryable -{ - public TestDbAsyncEnumerable(IEnumerable enumerable) - : base(enumerable) - { } - - public TestDbAsyncEnumerable(Expression expression) - : base(expression) - { } - - public IDbAsyncEnumerator GetAsyncEnumerator() - { - return new TestDbAsyncEnumerator(this.AsEnumerable().GetEnumerator()); - } - - IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() - { - return GetAsyncEnumerator(); - } - - IQueryProvider IQueryable.Provider - { - get { return new TestDbAsyncQueryProvider(this); } - } -} - -internal class TestDbAsyncEnumerator : IDbAsyncEnumerator -{ - private readonly IEnumerator _inner; - - public TestDbAsyncEnumerator(IEnumerator inner) - { - _inner = inner; - } - - public void Dispose() - { - _inner.Dispose(); - } - - public Task MoveNextAsync(CancellationToken cancellationToken) - { - return Task.FromResult(_inner.MoveNext()); - } - - public T Current - { - get { return _inner.Current; } - } - - object IDbAsyncEnumerator.Current - { - get { return Current; } - } -} diff --git a/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj b/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj index d43feb191..9d6c4657d 100644 --- a/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj +++ b/Application/EdFi.Ods.AdminApi.UnitTests/EdFi.Ods.AdminApi.UnitTests.csproj @@ -1,15 +1,13 @@ - - net6.0 + net8.0 Debug;Release Copyright © 2023 Ed-Fi Alliance - - - + + @@ -20,9 +18,7 @@ - - - + \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Actions.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Actions.postman_collection.json index bdbabb6f4..ce0bbc342 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Actions.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Actions.postman_collection.json @@ -26,9 +26,11 @@ "const response = pm.response.json();\r", "\r", "pm.test(\"GET Actions: Response matches success format\", function () {\r", - " pm.expect(response[0]).to.have.property(\"id\");\r", - " pm.expect(response[0]).to.have.property(\"name\");\r", - " pm.expect(response[0]).to.have.property(\"uri\");\r", + " if (response && response.length > 0) {\r", + " pm.expect(response[0]).to.have.property(\"id\");\r", + " pm.expect(response[0]).to.have.property(\"name\");\r", + " pm.expect(response[0]).to.have.property(\"uri\");\r", + " }\r", "});\r", "\r", "const GetActionsSchema = {\r", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - AuthStrategies.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - AuthStrategies.postman_collection.json index 750f874ff..3526862d9 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - AuthStrategies.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - AuthStrategies.postman_collection.json @@ -26,9 +26,11 @@ "const response = pm.response.json();\r", "\r", "pm.test(\"GET AuthorizationStrategies: Response matches success format\", function () {\r", - " pm.expect(response[0]).to.have.property(\"id\");\r", - " pm.expect(response[0]).to.have.property(\"name\");\r", - " pm.expect(response[0]).to.have.property(\"displayName\");\r", + " if (response && response.length > 0) {\r", + " pm.expect(response[0]).to.have.property(\"id\");\r", + " pm.expect(response[0]).to.have.property(\"name\");\r", + " pm.expect(response[0]).to.have.property(\"displayName\");\r", + " }\r", "});\r", "\r", "const GetAuthStrategiesSchema = {\r", diff --git a/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj b/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj index af26b9894..80714347a 100644 --- a/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj +++ b/Application/EdFi.Ods.AdminApi/EdFi.Ods.AdminApi.csproj @@ -1,7 +1,6 @@ - - net6.0 + net8.0 enable enable true @@ -13,15 +12,13 @@ .env adminapi-dev - - - + @@ -30,24 +27,23 @@ - - + + - - - - - - - + + + + + + + - - + \ No newline at end of file diff --git a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ResourceClaims/EditAuthStrategy.cs b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ResourceClaims/EditAuthStrategy.cs index 3b20e4058..0315afb4d 100644 --- a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ResourceClaims/EditAuthStrategy.cs +++ b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ResourceClaims/EditAuthStrategy.cs @@ -109,7 +109,7 @@ public OverrideAuthStategyOnClaimSetValidator(IGetResourcesByClaimSetIdQuery get var authStrategies = getAllAuthorizationStrategiesQuery.Execute(); foreach (var authStrategyName in overrideAuthStategyOnClaimSetRequest.AuthorizationStrategies!) { - var validAuthStrategyName = authStrategies + var validAuthStrategyName = authStrategies.AsEnumerable() .FirstOrDefault(a => a.AuthStrategyName!.ToLower() == authStrategyName!.ToLower()); if (validAuthStrategyName == null) diff --git a/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs b/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs index 9e6a7dd87..354e09dd4 100644 --- a/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs +++ b/Application/EdFi.Ods.AdminApi/Features/RequestLoggingMiddleware.cs @@ -45,7 +45,8 @@ public async Task Invoke(HttpContext context, ILogger case ValidationException validationException: var validationResponse = new { - title = "Validation failed", + title = "Validation failed", + status = (int)HttpStatusCode.BadRequest, errors = new Dictionary>() }; @@ -67,7 +68,8 @@ public async Task Invoke(HttpContext context, ILogger case INotFoundException notFoundException: var notFoundResponse = new { - title = notFoundException.Message, + title = notFoundException.Message, + status = (int)HttpStatusCode.NotFound }; logger.LogDebug(JsonSerializer.Serialize(new { message = notFoundResponse, traceId = context.TraceIdentifier })); diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Services/ClaimSetEditor/AuthStrategyResolver.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Services/ClaimSetEditor/AuthStrategyResolver.cs index 831e591fb..bb66b981b 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Services/ClaimSetEditor/AuthStrategyResolver.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Services/ClaimSetEditor/AuthStrategyResolver.cs @@ -36,7 +36,7 @@ public IEnumerable ResolveAuthStrategies(IEnumerable x.AuthorizationStrategyName.Equals( strategy.AuthStrategyName, StringComparison.InvariantCultureIgnoreCase)); diff --git a/Application/EdFi.Ods.AdminApi/appsettings.Docker.json b/Application/EdFi.Ods.AdminApi/appsettings.Docker.json index 3b6e7859a..531df2eb8 100644 --- a/Application/EdFi.Ods.AdminApi/appsettings.Docker.json +++ b/Application/EdFi.Ods.AdminApi/appsettings.Docker.json @@ -28,7 +28,8 @@ "LogLevel": { "Default": "Information", "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.Hosting.Lifetime": "Information", + "Microsoft.AspNetCore.DataProtection": "Information" } }, "AllowedHosts": "*" diff --git a/Application/EdFi.Ods.AdminApi/appsettings.json b/Application/EdFi.Ods.AdminApi/appsettings.json index 03c4da066..d1ebcd3e2 100644 --- a/Application/EdFi.Ods.AdminApi/appsettings.json +++ b/Application/EdFi.Ods.AdminApi/appsettings.json @@ -18,8 +18,8 @@ }, "EnableDockerEnvironment": false, "ConnectionStrings": { - "EdFi_Admin": "Data Source=.\\;Initial Catalog=EdFi_Admin;Integrated Security=True", - "EdFi_Security": "Data Source=.\\;Initial Catalog=EdFi_Security;Integrated Security=True" + "EdFi_Admin": "Data Source=.\\;Initial Catalog=EdFi_Admin;Integrated Security=True;Encrypt=False", + "EdFi_Security": "Data Source=.\\;Initial Catalog=EdFi_Security;Integrated Security=True;Encrypt=False" }, "Log4NetCore": { "Log4NetConfigFileName": "log4net\\log4net.config" @@ -46,7 +46,7 @@ { "Endpoint": "POST:/Connect/Register", "Period": "1m", - "Limit": 3 + "Limit": 1000 } ] } diff --git a/Docker/api.Dockerfile b/Docker/api.Dockerfile index d50b95c65..ca0b4f59a 100644 --- a/Docker/api.Dockerfile +++ b/Docker/api.Dockerfile @@ -3,11 +3,11 @@ # The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. # See the LICENSE and NOTICES files in the project root for more information. -#tag 6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet@sha256:201cedd60cb295b2ebea7184561a45c5c0ee337e37300ea0f25cff5a2c762538 AS base +#tag 8.0-alpine +FROM mcr.microsoft.com/dotnet/aspnet:8.0.3-alpine3.19-amd64@sha256:a531d9d123928514405b9da9ff28a3aa81bd6f7d7d8cfb6207b66c007e7b3075 as base ARG DB=pgsql -RUN apk --no-cache add curl=~8 unzip=~6 dos2unix=~7 bash=~5 gettext=~0 jq=~1 icu=~72 && \ +RUN apk --no-cache add curl=~8 unzip=~6 dos2unix=~7 bash=~5 gettext=~0 jq=~1 icu=~74 && \ if [ "$DB" = "pgsql" ]; then apk --no-cache add postgresql13-client=~13; fi && \ addgroup -S edfi && adduser -S edfi -G edfi diff --git a/Docker/dbadmin.Dockerfile b/Docker/dbadmin.Dockerfile index 6af729210..12685f85a 100644 --- a/Docker/dbadmin.Dockerfile +++ b/Docker/dbadmin.Dockerfile @@ -5,7 +5,6 @@ FROM edfialliance/ods-api-db-admin:7.1 LABEL maintainer="Ed-Fi Alliance, LLC and Contributors " - ENV POSTGRES_USER=${POSTGRES_USER} ENV POSTGRES_PASSWORD=${POSTGRES_PASSWORD} ENV POSTGRES_DB=postgres diff --git a/Docker/dev.Dockerfile b/Docker/dev.Dockerfile index e523960a0..7e86b3355 100644 --- a/Docker/dev.Dockerfile +++ b/Docker/dev.Dockerfile @@ -21,12 +21,11 @@ WORKDIR /source/EdFi.Ods.AdminApi RUN dotnet restore && dotnet build -c Release RUN dotnet publish -c Release /p:EnvironmentName=Production --no-build -o /app/EdFi.Ods.AdminApi -# TODO: update to .NET 8, will be handled in AdminAPI-983 -#tag aspnet:6.0-alpine -FROM mcr.microsoft.com/dotnet/aspnet@sha256:201cedd60cb295b2ebea7184561a45c5c0ee337e37300ea0f25cff5a2c762538 AS runtimebase +#tag aspnet:8.0-alpine +FROM mcr.microsoft.com/dotnet/aspnet:8.0.3-alpine3.19-amd64@sha256:a531d9d123928514405b9da9ff28a3aa81bd6f7d7d8cfb6207b66c007e7b3075 AS runtimebase FROM runtimebase AS runtime -RUN apk --no-cache add curl=~8 dos2unix=~7 bash=~5 gettext=~0 icu=~72 && \ +RUN apk --no-cache add curl=~8 dos2unix=~7 bash=~5 gettext=~0 icu=~74 && \ addgroup -S edfi && adduser -S edfi -G edfi FROM runtime AS setup @@ -35,6 +34,7 @@ LABEL maintainer="Ed-Fi Alliance, LLC and Contributors " # Disable the globaliztion invariant mode (set in base image) ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false ENV ASPNETCORE_ENVIRONMENT=Production +ENV ASPNETCORE_HTTP_PORTS=80 WORKDIR /app COPY --from=publish /app/EdFi.Ods.AdminApi . @@ -47,9 +47,12 @@ RUN cp /app/log4net.txt /app/log4net.config && \ dos2unix /app/*.sh && \ dos2unix /app/log4net.config && \ chmod 500 /app/*.sh -- ** && \ + rm -f /app/log4net.txt && \ + rm -f /app/*.exe && \ + apk del dos2unix && \ chown -R edfi /app -EXPOSE 443 +EXPOSE ${ASPNETCORE_HTTP_PORTS} USER edfi WORKDIR /app