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/ClaimSetEditorTests/OverrideDefaultAuthorizationStrategyCommandTests.cs b/Application/EdFi.Ods.AdminApi.DBTests/ClaimSetEditorTests/OverrideDefaultAuthorizationStrategyCommandTests.cs index 4b67f922b..2338a0eac 100644 --- a/Application/EdFi.Ods.AdminApi.DBTests/ClaimSetEditorTests/OverrideDefaultAuthorizationStrategyCommandTests.cs +++ b/Application/EdFi.Ods.AdminApi.DBTests/ClaimSetEditorTests/OverrideDefaultAuthorizationStrategyCommandTests.cs @@ -144,7 +144,7 @@ public void ShouldOverrideAuthorizationStrategiesForSpecificResourcesOnClaimSetD resultResourceClaim1.AuthStrategyOverridesForCRUD.Count.ShouldBe(1); resultResourceClaim1.AuthStrategyOverridesForCRUD[0].ActionName.ShouldBe("Create"); - resultResourceClaim1.AuthStrategyOverridesForCRUD[0].AuthorizationStrategies.First().AuthStrategyName.ShouldBe("TestAuthStrategy1"); + resultResourceClaim1.AuthStrategyOverridesForCRUD[0].AuthorizationStrategies.Any(x => x.AuthStrategyName.Equals("TestAuthStrategy1")).ShouldBeTrue(); var resultResourceClaim2 = resourceClaimsForClaimSet.Single(x => x.Id == testResource2ToNotEdit.ResourceClaimId); 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/E2E Tests/gh-action-setup/.automation.env b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation.env index 56f60075a..b4712b5db 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation.env +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/gh-action-setup/.automation.env @@ -7,7 +7,7 @@ LOGS_FOLDER=/tmp/logs # For Authentication AUTHORITY=http://localhost/${ADMIN_API_VIRTUAL_NAME} ISSUER_URL=https://localhost/${ADMIN_API_VIRTUAL_NAME} -SIGNING_KEY=qhkaKdYaomlkwUKcsAw22w== +SIGNING_KEY=TDMyNH0lJmo7aDRnNXYoSmAwSXQpV09nbitHSWJTKn0= # For Postgres only POSTGRES_USER=postgres 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/Properties/launchSettings.json b/Application/EdFi.Ods.AdminApi/Properties/launchSettings.json index 501325eb6..c354c73cc 100644 --- a/Application/EdFi.Ods.AdminApi/Properties/launchSettings.json +++ b/Application/EdFi.Ods.AdminApi/Properties/launchSettings.json @@ -27,14 +27,14 @@ "launchBrowser": true, "launchUrl": "swagger", "applicationUrl": "https://localhost:7214;http://localhost:5214", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Production", - "AUTHENTICATION__AUTHORITY": "https://localhost:7214", - "AUTHENTICATION__ISSUERURL": "https://localhost:7214", - "AUTHENTICATION__SIGNINGKEY": "dGhlKndlYnNpdGVfSVNf8J+Glw==", - "AUTHENTICATION__ALLOWREGISTRATION": "true", - "SWAGGERSETTINGS__ENABLESWAGGER": "true" - } + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production", + "AUTHENTICATION__AUTHORITY": "https://localhost:7214", + "AUTHENTICATION__ISSUERURL": "https://localhost:7214", + "AUTHENTICATION__SIGNINGKEY": "TDMyNH0lJmo7aDRnNXYoSmAwSXQpV09nbitHSWJTKn0=", + "AUTHENTICATION__ALLOWREGISTRATION": "true", + "SWAGGERSETTINGS__ENABLESWAGGER": "true" + } }, "EdFi.Ods.AdminApi (Docker)": { "commandName": "Docker", diff --git a/Docker/api.Dockerfile b/Docker/api.Dockerfile index d50b95c65..f5657209b 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 @@ -18,6 +18,7 @@ LABEL maintainer="Ed-Fi Alliance, LLC and Contributors " # Disable the globaliztion invariant mode (set in base image) ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false ARG VERSION=latest +ENV ASPNETCORE_HTTP_PORTS=80 WORKDIR /app @@ -40,7 +41,7 @@ RUN umask 0077 && \ apk del unzip dos2unix curl && \ chown -R edfi /app -EXPOSE 443 +EXPOSE ${ASPNETCORE_HTTP_PORTS} USER edfi ENTRYPOINT [ "/app/run.sh" ] diff --git a/Docker/dev.Dockerfile b/Docker/dev.Dockerfile index e523960a0..0808ae829 100644 --- a/Docker/dev.Dockerfile +++ b/Docker/dev.Dockerfile @@ -7,6 +7,7 @@ # code. The next two layers use the dotnet/aspnet image to run the built code. # The extra layers in the middle support caching of base layers. +#tag sdk:8.0-alpine FROM mcr.microsoft.com/dotnet/sdk:8.0.203-alpine3.18@sha256:2a8dca3af111071172b1629c12eefaeca0d6c2954887c4489195771c9e90833c as buildBase FROM buildbase as build @@ -22,11 +23,11 @@ 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 +36,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 . @@ -49,8 +51,7 @@ RUN cp /app/log4net.txt /app/log4net.config && \ chmod 500 /app/*.sh -- ** && \ chown -R edfi /app -EXPOSE 443 +EXPOSE ${ASPNETCORE_HTTP_PORTS} USER edfi -WORKDIR /app ENTRYPOINT ["/app/run.sh"]