From d1777af9cad700478ca1f4541b230712f2e3043e Mon Sep 17 00:00:00 2001 From: Imran Sh Date: Wed, 8 Feb 2023 14:26:30 +0100 Subject: [PATCH 01/28] Update appsettings.Docker.json Because of the breaking change in behavior of .net 7 ef core, it should be trusted, otherwise wouldn't work. https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes#mitigations --- src/Web/appsettings.Docker.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Web/appsettings.Docker.json b/src/Web/appsettings.Docker.json index bac53d6..07ea75e 100644 --- a/src/Web/appsettings.Docker.json +++ b/src/Web/appsettings.Docker.json @@ -1,7 +1,7 @@ { "ConnectionStrings": { - "CatalogConnection": "Server=sqlserver,1433;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;User Id=sa;Password=@someThingComplicated1234;Trusted_Connection=false;", - "IdentityConnection": "Server=sqlserver,1433;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;User Id=sa;Password=@someThingComplicated1234;Trusted_Connection=false;" + "CatalogConnection": "Server=sqlserver,1433;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;User Id=sa;Password=@someThingComplicated1234;Trusted_Connection=false;TrustServerCertificate=true;", + "IdentityConnection": "Server=sqlserver,1433;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;User Id=sa;Password=@someThingComplicated1234;Trusted_Connection=false;TrustServerCertificate=true;" }, "baseUrls": { "apiBase": "http://localhost:5200/api/", From e6d2962b84efabad9ec53cd12fb1322cb14b7ecd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 14:58:52 +0000 Subject: [PATCH 02/28] Bump Microsoft.AspNetCore.Authentication.JwtBearer from 7.0.2 to 7.0.3 Bumps [Microsoft.AspNetCore.Authentication.JwtBearer](https://github.com/dotnet/aspnetcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/commits) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1297b91..86dae5a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,7 @@ - + From d3e1bcd9566480131cd856222579d22b4acde2b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 18:01:29 +0000 Subject: [PATCH 03/28] Bump Microsoft.VisualStudio.Web.CodeGeneration.Design Bumps [Microsoft.VisualStudio.Web.CodeGeneration.Design](https://github.com/dotnet/Scaffolding) from 7.0.2 to 7.0.4. - [Release notes](https://github.com/dotnet/Scaffolding/releases) - [Commits](https://github.com/dotnet/Scaffolding/commits) --- updated-dependencies: - dependency-name: Microsoft.VisualStudio.Web.CodeGeneration.Design dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 86dae5a..9be697c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,7 +29,7 @@ - + From fab23fec41679eb6e3f3629e98d497d82515edb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 14:58:32 +0000 Subject: [PATCH 04/28] Bump Microsoft.EntityFrameworkCore.Tools from 7.0.2 to 7.0.3 Bumps [Microsoft.EntityFrameworkCore.Tools](https://github.com/dotnet/efcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/efcore/releases) - [Commits](https://github.com/dotnet/efcore/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: Microsoft.EntityFrameworkCore.Tools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9be697c..a64fa4c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -33,7 +33,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From f35fa849461ec0ef53f2a6eb17e13a2752d4f6b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 14:58:55 +0000 Subject: [PATCH 05/28] Bump Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore Bumps [Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore](https://github.com/dotnet/aspnetcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9be697c..15bbee8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - + From 9f77f194d393f1e925320321e57f328a31e59122 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:58:51 +0000 Subject: [PATCH 06/28] Bump System.IdentityModel.Tokens.Jwt from 6.25.1 to 6.27.0 Bumps [System.IdentityModel.Tokens.Jwt](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) from 6.25.1 to 6.27.0. - [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases) - [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md) - [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/commits) --- updated-dependencies: - dependency-name: System.IdentityModel.Tokens.Jwt dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9be697c..b6f7e3c 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -42,7 +42,7 @@ - + From 2e2c0316d0af679961483b64cbbe1bf54d26eab6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:03:25 +0000 Subject: [PATCH 07/28] Bump FluentValidation from 11.4.0 to 11.5.1 Bumps [FluentValidation](https://github.com/JeremySkinner/fluentvalidation) from 11.4.0 to 11.5.1. - [Release notes](https://github.com/JeremySkinner/fluentvalidation/releases) - [Changelog](https://github.com/FluentValidation/FluentValidation/blob/main/Changelog.txt) - [Commits](https://github.com/JeremySkinner/fluentvalidation/compare/11.4.0...11.5.1) --- updated-dependencies: - dependency-name: FluentValidation dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 9be697c..36d9a60 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + From 3e645ceff85dbf86180cb2ff52661c022e49eb14 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:53:04 -0500 Subject: [PATCH 08/28] Bump Microsoft.NET.Test.Sdk from 17.4.1 to 17.5.0 (#858) Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.4.1 to 17.5.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.4.1...v17.5.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 0b28506..837079a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -48,7 +48,7 @@ - + all From 4bf18c430501c46379464240b9d48350c475729f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:53:55 -0500 Subject: [PATCH 09/28] Bump Microsoft.EntityFrameworkCore.SqlServer from 7.0.2 to 7.0.3 (#857) Bumps [Microsoft.EntityFrameworkCore.SqlServer](https://github.com/dotnet/efcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/efcore/releases) - [Commits](https://github.com/dotnet/efcore/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: Microsoft.EntityFrameworkCore.SqlServer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 837079a..91f2a3b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -32,7 +32,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 3359d2894b6cdc04fecfe952616ee9d9126bd814 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:54:06 -0500 Subject: [PATCH 10/28] Bump Microsoft.Extensions.Identity.Core from 7.0.2 to 7.0.3 (#859) Bumps [Microsoft.Extensions.Identity.Core](https://github.com/dotnet/aspnetcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: Microsoft.Extensions.Identity.Core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 91f2a3b..96677e9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,7 +27,7 @@ - + From 2f07effa180049c227b81f6857565def812ea181 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:54:46 -0500 Subject: [PATCH 11/28] Bump Microsoft.EntityFrameworkCore.InMemory from 7.0.2 to 7.0.3 (#860) Bumps [Microsoft.EntityFrameworkCore.InMemory](https://github.com/dotnet/efcore) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/dotnet/efcore/releases) - [Commits](https://github.com/dotnet/efcore/compare/v7.0.2...v7.0.3) --- updated-dependencies: - dependency-name: Microsoft.EntityFrameworkCore.InMemory dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Steve Smith --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 96677e9..b45cc26 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,7 +31,7 @@ - + all From be413887a1c46e9e35f55e55757ce72e51d8cfdc Mon Sep 17 00:00:00 2001 From: flomader <40666690+flomader@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:55:56 +0100 Subject: [PATCH 12/28] bugfix unhandled ex in case of duplicateexception (#862) Co-authored-by: Florian Mader --- src/PublicApi/Middleware/ExceptionMiddleware.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/PublicApi/Middleware/ExceptionMiddleware.cs b/src/PublicApi/Middleware/ExceptionMiddleware.cs index ebd19a5..5773c2e 100644 --- a/src/PublicApi/Middleware/ExceptionMiddleware.cs +++ b/src/PublicApi/Middleware/ExceptionMiddleware.cs @@ -41,12 +41,14 @@ public class ExceptionMiddleware Message = duplicationException.Message }.ToString()); } - - context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - await context.Response.WriteAsync(new ErrorDetails() + else { - StatusCode = context.Response.StatusCode, - Message = exception.Message - }.ToString()); + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + await context.Response.WriteAsync(new ErrorDetails() + { + StatusCode = context.Response.StatusCode, + Message = exception.Message + }.ToString()); + } } } From 74e067a7341d58b4eaadf0da9dd20bfe9e696ebf Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Tue, 28 Feb 2023 15:12:24 -0500 Subject: [PATCH 13/28] package updates --- Directory.Packages.props | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index b45cc26..97bb40a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,7 @@ - + @@ -17,15 +17,15 @@ - - - - - - + + + + + + - + @@ -41,13 +41,13 @@ - + - + From 0542c52d79e5ba304a0bf9ea5974ba5bb223a93f Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Tue, 28 Feb 2023 15:15:46 -0500 Subject: [PATCH 14/28] update mediatR --- Directory.Packages.props | 3 +-- src/Web/Configuration/ConfigureWebServices.cs | 3 ++- src/Web/Web.csproj | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 97bb40a..94352b7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,8 +15,7 @@ - - + diff --git a/src/Web/Configuration/ConfigureWebServices.cs b/src/Web/Configuration/ConfigureWebServices.cs index f89a99a..e282276 100644 --- a/src/Web/Configuration/ConfigureWebServices.cs +++ b/src/Web/Configuration/ConfigureWebServices.cs @@ -8,7 +8,8 @@ public static class ConfigureWebServices { public static IServiceCollection AddWebServices(this IServiceCollection services, IConfiguration configuration) { - services.AddMediatR(typeof(BasketViewModelService).Assembly); + services.AddMediatR(cfg => + cfg.RegisterServicesFromAssembly(typeof(BasketViewModelService).Assembly)); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 5e2f3ee..fdb6574 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -17,7 +17,6 @@ - From 4304545f19bc404562e16a693e20bbcbdb878d43 Mon Sep 17 00:00:00 2001 From: Said Haouaouchi <54531034+linkprada@users.noreply.github.com> Date: Tue, 28 Feb 2023 21:16:39 +0100 Subject: [PATCH 15/28] Fix Multiple DbContext Registration (#703) Hi, i noticed that in the WebTestFixture used for FunctionalTests the DbContexts were registered without removing the existing ones in Program.cs which leads to duplication --- tests/FunctionalTests/Web/WebTestFixture.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/FunctionalTests/Web/WebTestFixture.cs b/tests/FunctionalTests/Web/WebTestFixture.cs index 55b2e74..d9bb491 100644 --- a/tests/FunctionalTests/Web/WebTestFixture.cs +++ b/tests/FunctionalTests/Web/WebTestFixture.cs @@ -23,6 +23,16 @@ public class TestApplication : WebApplicationFactory // Add mock/test services to the builder here builder.ConfigureServices(services => { + var descriptors = services.Where(d => + d.ServiceType == typeof(DbContextOptions) || + d.ServiceType == typeof(DbContextOptions)) + .ToList(); + + foreach (var descriptor in descriptors) + { + services.Remove(descriptor); + } + services.AddScoped(sp => { // Replace SQLite with in-memory database for tests From f93107659a6e96e8121ed36cc6d33cff586a36dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 13:26:34 -0400 Subject: [PATCH 16/28] Bump Microsoft.AspNetCore.Identity.UI from 7.0.3 to 7.0.4 (#870) Bumps [Microsoft.AspNetCore.Identity.UI](https://github.com/dotnet/aspnetcore) from 7.0.3 to 7.0.4. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.3...v7.0.4) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Identity.UI dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 94352b7..2863b8f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -24,7 +24,7 @@ - + From af2052efaa898b15a9d66996e426af2f1f800390 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 13:27:32 -0400 Subject: [PATCH 17/28] Bump Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore (#869) Bumps [Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore](https://github.com/dotnet/aspnetcore) from 7.0.3 to 7.0.4. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.3...v7.0.4) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Steve Smith --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2863b8f..c066132 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,7 @@ - + From c15c71c1e1732d83a3b71f117918706a67982fc2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Mar 2023 13:27:53 -0400 Subject: [PATCH 18/28] Bump Microsoft.AspNetCore.Components.WebAssembly.Authentication (#868) Bumps [Microsoft.AspNetCore.Components.WebAssembly.Authentication](https://github.com/dotnet/aspnetcore) from 7.0.3 to 7.0.4. - [Release notes](https://github.com/dotnet/aspnetcore/releases) - [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md) - [Commits](https://github.com/dotnet/aspnetcore/compare/v7.0.3...v7.0.4) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Components.WebAssembly.Authentication dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index c066132..04f73e4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -18,7 +18,7 @@ - + From a2ebd3fe262957db466cc4031fe63b9d0da48092 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Tue, 14 Mar 2023 14:19:38 -0400 Subject: [PATCH 19/28] Update references --- Directory.Packages.props | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 04f73e4..a719109 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,23 +16,23 @@ - - + + - - - - + + + + - + - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -46,7 +46,7 @@ - + From 465ce673ae0239080d76d3f92c31fac420fd0106 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:58:38 +0000 Subject: [PATCH 20/28] Bump Microsoft.VisualStudio.Web.CodeGeneration.Design Bumps [Microsoft.VisualStudio.Web.CodeGeneration.Design](https://github.com/dotnet/Scaffolding) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/dotnet/Scaffolding/releases) - [Commits](https://github.com/dotnet/Scaffolding/commits) --- updated-dependencies: - dependency-name: Microsoft.VisualStudio.Web.CodeGeneration.Design dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a719109..067e5cf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -28,7 +28,7 @@ - + From 26adf8aac3e6354750f0e89b6b531d2e786ef2c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:58:45 +0000 Subject: [PATCH 21/28] Bump System.Net.Http.Json from 7.0.0 to 7.0.1 Bumps [System.Net.Http.Json](https://github.com/dotnet/runtime) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v7.0.0...v7.0.1) --- updated-dependencies: - dependency-name: System.Net.Http.Json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a719109..4f4428e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,7 +38,7 @@ - + From d2412a84a993d48e59ea73e217011c5e4aab0332 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Mon, 20 Mar 2023 11:52:14 -0400 Subject: [PATCH 22/28] Fix Null Warnings (#874) * Fixing null warnings * Fix null warnings Fix other compiler warnings --- .editorconfig | 8 +- Directory.Packages.props | 1 + Everything.sln | 92 +++++++++++++++ src/Infrastructure/Dependencies.cs | 4 +- .../Identity/AppIdentityDbContextSeed.cs | 5 +- .../Identity/IdentityTokenClaimService.cs | 1 + .../Identity/UserNotFoundException.cs | 10 ++ .../AuthenticateEndpoint.ClaimValue.cs | 11 +- .../AuthenticateEndpoint.UserInfo.cs | 11 +- .../AuthEndpoints/AuthenticateEndpoint.cs | 3 +- ...gedEndpoint.ListPagedCatalogItemRequest.cs | 4 +- .../CatalogItemListPagedEndpoint.cs | 6 +- .../UpdateCatalogItemEndpoint.cs | 4 + src/PublicApi/Program.cs | 23 ++-- .../Identity/Pages/Account/Login.cshtml.cs | 5 +- .../Identity/Pages/Account/Register.cshtml.cs | 6 +- .../Configuration/ConfigureCoreServices.cs | 7 +- src/Web/Controllers/ManageController.cs | 24 ++-- src/Web/Pages/Index.cshtml.cs | 2 +- src/Web/Program.cs | 18 ++- .../Services/CachedCatalogViewModelService.cs | 12 +- src/Web/ViewModels/CatalogIndexViewModel.cs | 9 +- .../ViewModels/Manage/RemoveLoginViewModel.cs | 10 +- src/Web/ViewModels/OrderViewModel.cs | 6 +- src/Web/Views/Manage/ShowRecoverCodes.cshtml | 9 +- src/Web/Views/Order/Detail.cshtml | 6 +- src/Web/Views/Shared/_LoginPartial.cshtml | 2 +- .../Web/Controllers/OrderControllerIndex.cs | 2 +- .../Web/Pages/Basket/BasketPageCheckout.cs | 2 +- .../Web/Pages/Basket/CheckoutTest.cs | 2 +- .../Web/Pages/Basket/IndexTest.cs | 4 +- tests/FunctionalTests/Web/WebPageHelpers.cs | 2 +- .../AuthEndpoints/AuthenticateEndpointTest.cs | 45 ++++--- .../CatalogItemGetByIdEndpointTest.cs | 37 +++--- .../CatalogItemListPagedEndpoint.cs | 111 +++++++++--------- .../CreateCatalogItemEndpointTest.cs | 101 ++++++++-------- .../DeleteCatalogItemEndpointTest.cs | 47 ++++---- .../PublicApiIntegrationTests/ProgramTest.cs | 33 +++--- 38 files changed, 400 insertions(+), 285 deletions(-) create mode 100644 Everything.sln create mode 100644 src/Infrastructure/Identity/UserNotFoundException.cs diff --git a/.editorconfig b/.editorconfig index 88b30b0..459d752 100644 --- a/.editorconfig +++ b/.editorconfig @@ -141,4 +141,10 @@ csharp_preserve_single_line_blocks = true ############################### [*.vb] # Modifier preferences -visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion \ No newline at end of file +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion############################### +###################################### +# Configure Nullable Reference Types # +###################################### +[{**/*Dto.cs,**/*Request.cs,**/*Response.cs}] +# CS8618: Non-nullable field is uninitialized. Consider declaring as nullable. +dotnet_diagnostic.CS8618.severity = none diff --git a/Directory.Packages.props b/Directory.Packages.props index a719109..a4eebe2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,7 @@ true + true net7.0 diff --git a/Everything.sln b/Everything.sln new file mode 100644 index 0000000..037da0d --- /dev/null +++ b/Everything.sln @@ -0,0 +1,92 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationCore", "src\ApplicationCore\ApplicationCore.csproj", "{1A5759FF-9990-4CF5-AD78-528452C5EFCC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorAdmin", "src\BlazorAdmin\BlazorAdmin.csproj", "{7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorShared", "src\BlazorShared\BlazorShared.csproj", "{6FD75683-D186-4BE3-ABD0-2324650B46B5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{35457566-83CE-44FC-A650-265CC9C544DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PublicApi", "src\PublicApi\PublicApi.csproj", "{7F226129-E8B0-4274-87A7-347AA4F7D374}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "src\Web\Web.csproj", "{7559FA9E-7CFC-4615-8D09-3CDEFC765455}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{BAA5312D-B54C-42D6-A3B9-504DD12F8250}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunctionalTests", "tests\FunctionalTests\FunctionalTests.csproj", "{020545FF-D985-4274-9FDB-FD8B9B32D2ED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests", "tests\IntegrationTests\IntegrationTests.csproj", "{D6829485-DD9C-42CE-BEDE-4EB0E81021AC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PublicApiIntegrationTests", "tests\PublicApiIntegrationTests\PublicApiIntegrationTests.csproj", "{698594AE-78D3-429F-B5CC-3A6F6BCE397A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests\UnitTests.csproj", "{EAD6CF0B-2979-462C-BBB9-AF723B1EB570}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1A5759FF-9990-4CF5-AD78-528452C5EFCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A5759FF-9990-4CF5-AD78-528452C5EFCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A5759FF-9990-4CF5-AD78-528452C5EFCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A5759FF-9990-4CF5-AD78-528452C5EFCC}.Release|Any CPU.Build.0 = Release|Any CPU + {7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970}.Release|Any CPU.Build.0 = Release|Any CPU + {6FD75683-D186-4BE3-ABD0-2324650B46B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FD75683-D186-4BE3-ABD0-2324650B46B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FD75683-D186-4BE3-ABD0-2324650B46B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FD75683-D186-4BE3-ABD0-2324650B46B5}.Release|Any CPU.Build.0 = Release|Any CPU + {35457566-83CE-44FC-A650-265CC9C544DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35457566-83CE-44FC-A650-265CC9C544DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35457566-83CE-44FC-A650-265CC9C544DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35457566-83CE-44FC-A650-265CC9C544DC}.Release|Any CPU.Build.0 = Release|Any CPU + {7F226129-E8B0-4274-87A7-347AA4F7D374}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F226129-E8B0-4274-87A7-347AA4F7D374}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F226129-E8B0-4274-87A7-347AA4F7D374}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F226129-E8B0-4274-87A7-347AA4F7D374}.Release|Any CPU.Build.0 = Release|Any CPU + {7559FA9E-7CFC-4615-8D09-3CDEFC765455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7559FA9E-7CFC-4615-8D09-3CDEFC765455}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7559FA9E-7CFC-4615-8D09-3CDEFC765455}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7559FA9E-7CFC-4615-8D09-3CDEFC765455}.Release|Any CPU.Build.0 = Release|Any CPU + {020545FF-D985-4274-9FDB-FD8B9B32D2ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {020545FF-D985-4274-9FDB-FD8B9B32D2ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {020545FF-D985-4274-9FDB-FD8B9B32D2ED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {020545FF-D985-4274-9FDB-FD8B9B32D2ED}.Release|Any CPU.Build.0 = Release|Any CPU + {D6829485-DD9C-42CE-BEDE-4EB0E81021AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6829485-DD9C-42CE-BEDE-4EB0E81021AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6829485-DD9C-42CE-BEDE-4EB0E81021AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6829485-DD9C-42CE-BEDE-4EB0E81021AC}.Release|Any CPU.Build.0 = Release|Any CPU + {698594AE-78D3-429F-B5CC-3A6F6BCE397A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {698594AE-78D3-429F-B5CC-3A6F6BCE397A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {698594AE-78D3-429F-B5CC-3A6F6BCE397A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {698594AE-78D3-429F-B5CC-3A6F6BCE397A}.Release|Any CPU.Build.0 = Release|Any CPU + {EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EAD6CF0B-2979-462C-BBB9-AF723B1EB570}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1A5759FF-9990-4CF5-AD78-528452C5EFCC} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {7D7D0B73-4153-4E9B-BBD1-C9D7C8AEE970} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {6FD75683-D186-4BE3-ABD0-2324650B46B5} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {35457566-83CE-44FC-A650-265CC9C544DC} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {7F226129-E8B0-4274-87A7-347AA4F7D374} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {7559FA9E-7CFC-4615-8D09-3CDEFC765455} = {8FF16BDB-352E-42A2-A25F-0B5BC3A17FD7} + {020545FF-D985-4274-9FDB-FD8B9B32D2ED} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250} + {D6829485-DD9C-42CE-BEDE-4EB0E81021AC} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250} + {698594AE-78D3-429F-B5CC-3A6F6BCE397A} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250} + {EAD6CF0B-2979-462C-BBB9-AF723B1EB570} = {BAA5312D-B54C-42D6-A3B9-504DD12F8250} + EndGlobalSection +EndGlobal diff --git a/src/Infrastructure/Dependencies.cs b/src/Infrastructure/Dependencies.cs index d049a96..9645676 100644 --- a/src/Infrastructure/Dependencies.cs +++ b/src/Infrastructure/Dependencies.cs @@ -10,10 +10,10 @@ public static class Dependencies { public static void ConfigureServices(IConfiguration configuration, IServiceCollection services) { - var useOnlyInMemoryDatabase = false; + bool useOnlyInMemoryDatabase = false; if (configuration["UseOnlyInMemoryDatabase"] != null) { - useOnlyInMemoryDatabase = bool.Parse(configuration["UseOnlyInMemoryDatabase"]); + useOnlyInMemoryDatabase = bool.Parse(configuration["UseOnlyInMemoryDatabase"]!); } if (useOnlyInMemoryDatabase) diff --git a/src/Infrastructure/Identity/AppIdentityDbContextSeed.cs b/src/Infrastructure/Identity/AppIdentityDbContextSeed.cs index 3531005..8be12f6 100644 --- a/src/Infrastructure/Identity/AppIdentityDbContextSeed.cs +++ b/src/Infrastructure/Identity/AppIdentityDbContextSeed.cs @@ -24,6 +24,9 @@ public class AppIdentityDbContextSeed var adminUser = new ApplicationUser { UserName = adminUserName, Email = adminUserName }; await userManager.CreateAsync(adminUser, AuthorizationConstants.DEFAULT_PASSWORD); adminUser = await userManager.FindByNameAsync(adminUserName); - await userManager.AddToRoleAsync(adminUser, BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS); + if (adminUser != null) + { + await userManager.AddToRoleAsync(adminUser, BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS); + } } } diff --git a/src/Infrastructure/Identity/IdentityTokenClaimService.cs b/src/Infrastructure/Identity/IdentityTokenClaimService.cs index c45f355..36de7ae 100644 --- a/src/Infrastructure/Identity/IdentityTokenClaimService.cs +++ b/src/Infrastructure/Identity/IdentityTokenClaimService.cs @@ -25,6 +25,7 @@ public class IdentityTokenClaimService : ITokenClaimsService var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(AuthorizationConstants.JWT_SECRET_KEY); var user = await _userManager.FindByNameAsync(userName); + if (user == null) throw new UserNotFoundException(userName); var roles = await _userManager.GetRolesAsync(user); var claims = new List { new Claim(ClaimTypes.Name, userName) }; diff --git a/src/Infrastructure/Identity/UserNotFoundException.cs b/src/Infrastructure/Identity/UserNotFoundException.cs new file mode 100644 index 0000000..0a98b9e --- /dev/null +++ b/src/Infrastructure/Identity/UserNotFoundException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Microsoft.eShopWeb.Infrastructure.Identity; + +public class UserNotFoundException : Exception +{ + public UserNotFoundException(string userName) : base($"No user found with username: {userName}") + { + } +} diff --git a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.ClaimValue.cs b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.ClaimValue.cs index 5296e71..9571c3a 100644 --- a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.ClaimValue.cs +++ b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.ClaimValue.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints; +namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints; public class ClaimValue { @@ -17,6 +12,6 @@ public class ClaimValue Value = value; } - public string Type { get; set; } - public string Value { get; set; } + public string Type { get; set; } = string.Empty; + public string Value { get; set; } = string.Empty; } diff --git a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.UserInfo.cs b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.UserInfo.cs index 8c55fbb..8a4eaf8 100644 --- a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.UserInfo.cs +++ b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.UserInfo.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints; @@ -9,7 +6,7 @@ public class UserInfo { public static readonly UserInfo Anonymous = new UserInfo(); public bool IsAuthenticated { get; set; } - public string NameClaimType { get; set; } - public string RoleClaimType { get; set; } - public IEnumerable Claims { get; set; } + public string NameClaimType { get; set; } = string.Empty; + public string RoleClaimType { get; set; } = string.Empty; + public IEnumerable Claims { get; set; } = new List(); } diff --git a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs index 0d5bece..c5cce65 100644 --- a/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs +++ b/src/PublicApi/AuthEndpoints/AuthenticateEndpoint.cs @@ -33,7 +33,8 @@ public class AuthenticateEndpoint : EndpointBaseAsync OperationId = "auth.authenticate", Tags = new[] { "AuthEndpoints" }) ] - public override async Task> HandleAsync(AuthenticateRequest request, CancellationToken cancellationToken = default) + public override async Task> HandleAsync(AuthenticateRequest request, + CancellationToken cancellationToken = default) { var response = new AuthenticateResponse(request.CorrelationId()); diff --git a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.ListPagedCatalogItemRequest.cs b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.ListPagedCatalogItemRequest.cs index e9744d8..19691af 100644 --- a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.ListPagedCatalogItemRequest.cs +++ b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.ListPagedCatalogItemRequest.cs @@ -2,8 +2,8 @@ public class ListPagedCatalogItemRequest : BaseRequest { - public int? PageSize { get; init; } - public int? PageIndex { get; init; } + public int PageSize { get; init; } + public int PageIndex { get; init; } public int? CatalogBrandId { get; init; } public int? CatalogTypeId { get; init; } diff --git a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs index 920fe4f..3e36d2f 100644 --- a/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs +++ b/src/PublicApi/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs @@ -46,8 +46,8 @@ public class CatalogItemListPagedEndpoint : IEndpoint 0) { - response.PageCount = int.Parse(Math.Ceiling((decimal)totalItems / request.PageSize.Value).ToString()); + response.PageCount = int.Parse(Math.Ceiling((decimal)totalItems / request.PageSize).ToString()); } else { diff --git a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs index b923322..15efa68 100644 --- a/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs +++ b/src/PublicApi/CatalogItemEndpoints/UpdateCatalogItemEndpoint.cs @@ -39,6 +39,10 @@ public class UpdateCatalogItemEndpoint : IEndpoint() builder.Services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); builder.Services.AddScoped(typeof(IReadRepository<>), typeof(EfRepository<>)); builder.Services.Configure(builder.Configuration); -builder.Services.AddSingleton(new UriComposer(builder.Configuration.Get())); +var catalogSettings = builder.Configuration.Get() ?? new CatalogSettings(); +builder.Services.AddSingleton(new UriComposer(catalogSettings)); builder.Services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>)); builder.Services.AddScoped(); @@ -73,12 +73,12 @@ const string CORS_POLICY = "CorsPolicy"; builder.Services.AddCors(options => { options.AddPolicy(name: CORS_POLICY, - corsPolicyBuilder => - { - corsPolicyBuilder.WithOrigins(baseUrlConfig.WebBase.Replace("host.docker.internal", "localhost").TrimEnd('/')); - corsPolicyBuilder.AllowAnyMethod(); - corsPolicyBuilder.AllowAnyHeader(); - }); + corsPolicyBuilder => + { + corsPolicyBuilder.WithOrigins(baseUrlConfig!.WebBase.Replace("host.docker.internal", "localhost").TrimEnd('/')); + corsPolicyBuilder.AllowAnyMethod(); + corsPolicyBuilder.AllowAnyHeader(); + }); }); builder.Services.AddControllers(); @@ -172,12 +172,9 @@ app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); }); -app.UseEndpoints(endpoints => -{ - endpoints.MapControllers(); -}); - +app.MapControllers(); app.MapEndpoints(); + app.Logger.LogInformation("LAUNCHING PublicApi"); app.Run(); diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs index fdf4b1f..fe22ef7 100644 --- a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -25,7 +25,7 @@ public class LoginModel : PageModel } [BindProperty] - public InputModel? Input { get; set; } + public required InputModel Input { get; set; } public IList? ExternalLogins { get; set; } @@ -74,7 +74,8 @@ public class LoginModel : PageModel // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, set lockoutOnFailure: true //var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true); - var result = await _signInManager.PasswordSignInAsync(Input?.Email, Input?.Password, false, true); + var result = await _signInManager.PasswordSignInAsync(Input!.Email!, Input!.Password!, + false, true); if (result.Succeeded) { diff --git a/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs index ce66e9e..f0165fa 100644 --- a/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs +++ b/src/Web/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -35,7 +35,7 @@ public class RegisterModel : PageModel } [BindProperty] - public InputModel? Input { get; set; } + public required InputModel Input { get; set; } public string? ReturnUrl { get; set; } @@ -69,7 +69,7 @@ public class RegisterModel : PageModel if (ModelState.IsValid) { var user = new ApplicationUser { UserName = Input?.Email, Email = Input?.Email }; - var result = await _userManager.CreateAsync(user, Input?.Password); + var result = await _userManager.CreateAsync(user, Input?.Password!); if (result.Succeeded) { _logger.LogInformation("User created a new account with password."); @@ -82,7 +82,7 @@ public class RegisterModel : PageModel protocol: Request.Scheme); Guard.Against.Null(callbackUrl, nameof(callbackUrl)); - await _emailSender.SendEmailAsync(Input?.Email, "Confirm your email", + await _emailSender.SendEmailAsync(Input!.Email!, "Confirm your email", $"Please confirm your account by clicking here."); await _signInManager.SignInAsync(user, isPersistent: false); diff --git a/src/Web/Configuration/ConfigureCoreServices.cs b/src/Web/Configuration/ConfigureCoreServices.cs index f38657d..cf39e9a 100644 --- a/src/Web/Configuration/ConfigureCoreServices.cs +++ b/src/Web/Configuration/ConfigureCoreServices.cs @@ -4,8 +4,6 @@ using Microsoft.eShopWeb.Infrastructure.Data; using Microsoft.eShopWeb.Infrastructure.Data.Queries; using Microsoft.eShopWeb.Infrastructure.Logging; using Microsoft.eShopWeb.Infrastructure.Services; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; namespace Microsoft.eShopWeb.Web.Configuration; @@ -20,7 +18,10 @@ public static class ConfigureCoreServices services.AddScoped(); services.AddScoped(); services.AddScoped(); - services.AddSingleton(new UriComposer(configuration.Get())); + + var catalogSettings = configuration.Get() ?? new CatalogSettings(); + services.AddSingleton(new UriComposer(catalogSettings)); + services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>)); services.AddTransient(); diff --git a/src/Web/Controllers/ManageController.cs b/src/Web/Controllers/ManageController.cs index 779fa36..d97473c 100644 --- a/src/Web/Controllers/ManageController.cs +++ b/src/Web/Controllers/ManageController.cs @@ -122,6 +122,11 @@ public class ManageController : Controller var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); Guard.Against.Null(callbackUrl, nameof(callbackUrl)); var email = user.Email; + if (email == null) + { + throw new ApplicationException($"No email associated with user {user.UserName}'."); + } + await _emailSender.SendEmailConfirmationAsync(email, callbackUrl); StatusMessage = "Verification email sent. Please check your email."; @@ -162,7 +167,8 @@ public class ManageController : Controller throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - var changePasswordResult = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); + var changePasswordResult = await _userManager + .ChangePasswordAsync(user, model.OldPassword!, model.NewPassword!); if (!changePasswordResult.Succeeded) { AddErrors(changePasswordResult); @@ -211,7 +217,7 @@ public class ManageController : Controller throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } - var addPasswordResult = await _userManager.AddPasswordAsync(user, model.NewPassword); + var addPasswordResult = await _userManager.AddPasswordAsync(user, model.NewPassword!); if (!addPasswordResult.Succeeded) { AddErrors(addPasswordResult); @@ -293,6 +299,10 @@ public class ManageController : Controller { throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); } + if (!ModelState.IsValid) + { + return View(model); + } var result = await _userManager.RemoveLoginAsync(user, model.LoginProvider, model.ProviderKey); if (!result.Succeeded) @@ -407,7 +417,7 @@ public class ManageController : Controller } // Strip spaces and hypens - var verificationCode = model.Code?.Replace(" ", string.Empty).Replace("-", string.Empty); + string verificationCode = model.Code?.Replace(" ", string.Empty).Replace("-", string.Empty) ?? ""; var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); @@ -421,7 +431,7 @@ public class ManageController : Controller await _userManager.SetTwoFactorEnabledAsync(user, true); _logger.LogInformation("User with ID {UserId} has enabled 2FA with an authenticator app.", user.Id); - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10) ?? new List(); TempData[RecoveryCodesKey] = recoveryCodes.ToArray(); return RedirectToAction(nameof(ShowRecoveryCodes)); @@ -465,7 +475,7 @@ public class ManageController : Controller throw new ApplicationException($"Cannot generate recovery codes for user with ID '{user.Id}' as they do not have 2FA enabled."); } - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10) ?? new List(); _logger.LogInformation("User with ID {UserId} has generated new 2FA recovery codes.", user.Id); var model = new ShowRecoveryCodesViewModel { RecoveryCodes = recoveryCodes.ToArray() }; @@ -533,8 +543,8 @@ public class ManageController : Controller unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); } - model.SharedKey = FormatKey(unformattedKey); - model.AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey); + model.SharedKey = FormatKey(unformattedKey!); + model.AuthenticatorUri = GenerateQrCodeUri(user.Email!, unformattedKey!); } } diff --git a/src/Web/Pages/Index.cshtml.cs b/src/Web/Pages/Index.cshtml.cs index f2dd2cf..ad6a81e 100644 --- a/src/Web/Pages/Index.cshtml.cs +++ b/src/Web/Pages/Index.cshtml.cs @@ -13,7 +13,7 @@ public class IndexModel : PageModel _catalogViewModelService = catalogViewModelService; } - public CatalogIndexViewModel CatalogModel { get; set; } = new CatalogIndexViewModel(); + public required CatalogIndexViewModel CatalogModel { get; set; } = new CatalogIndexViewModel(); public async Task OnGet(CatalogIndexViewModel catalogModel, int? pageId) { diff --git a/src/Web/Program.cs b/src/Web/Program.cs index dd9a4ad..c5dbcc1 100644 --- a/src/Web/Program.cs +++ b/src/Web/Program.cs @@ -82,7 +82,7 @@ var baseUrlConfig = configSection.Get(); // Blazor Admin Required Services for Prerendering builder.Services.AddScoped(s => new HttpClient { - BaseAddress = new Uri(baseUrlConfig.WebBase) + BaseAddress = new Uri(baseUrlConfig!.WebBase) }); // add blazor services @@ -171,15 +171,13 @@ app.UseCookiePolicy(); app.UseAuthentication(); app.UseAuthorization(); -app.UseEndpoints(endpoints => -{ - endpoints.MapControllerRoute("default", "{controller:slugify=Home}/{action:slugify=Index}/{id?}"); - endpoints.MapRazorPages(); - endpoints.MapHealthChecks("home_page_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("homePageHealthCheck") }); - endpoints.MapHealthChecks("api_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("apiHealthCheck") }); - //endpoints.MapBlazorHub("/admin"); - endpoints.MapFallbackToFile("index.html"); -}); + +app.MapControllerRoute("default", "{controller:slugify=Home}/{action:slugify=Index}/{id?}"); +app.MapRazorPages(); +app.MapHealthChecks("home_page_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("homePageHealthCheck") }); +app.MapHealthChecks("api_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("apiHealthCheck") }); +//endpoints.MapBlazorHub("/admin"); +app.MapFallbackToFile("index.html"); app.Logger.LogInformation("LAUNCHING"); app.Run(); diff --git a/src/Web/Services/CachedCatalogViewModelService.cs b/src/Web/Services/CachedCatalogViewModelService.cs index d190d43..e7a506b 100644 --- a/src/Web/Services/CachedCatalogViewModelService.cs +++ b/src/Web/Services/CachedCatalogViewModelService.cs @@ -21,30 +21,30 @@ public class CachedCatalogViewModelService : ICatalogViewModelService public async Task> GetBrands() { - return await _cache.GetOrCreateAsync(CacheHelpers.GenerateBrandsCacheKey(), async entry => + return (await _cache.GetOrCreateAsync(CacheHelpers.GenerateBrandsCacheKey(), async entry => { entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration; return await _catalogViewModelService.GetBrands(); - }); + })) ?? new List(); } public async Task GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId) { var cacheKey = CacheHelpers.GenerateCatalogItemCacheKey(pageIndex, Constants.ITEMS_PER_PAGE, brandId, typeId); - return await _cache.GetOrCreateAsync(cacheKey, async entry => + return (await _cache.GetOrCreateAsync(cacheKey, async entry => { entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration; return await _catalogViewModelService.GetCatalogItems(pageIndex, itemsPage, brandId, typeId); - }); + })) ?? new CatalogIndexViewModel(); } public async Task> GetTypes() { - return await _cache.GetOrCreateAsync(CacheHelpers.GenerateTypesCacheKey(), async entry => + return (await _cache.GetOrCreateAsync(CacheHelpers.GenerateTypesCacheKey(), async entry => { entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration; return await _catalogViewModelService.GetTypes(); - }); + })) ?? new List(); } } diff --git a/src/Web/ViewModels/CatalogIndexViewModel.cs b/src/Web/ViewModels/CatalogIndexViewModel.cs index 247afe5..69e09e3 100644 --- a/src/Web/ViewModels/CatalogIndexViewModel.cs +++ b/src/Web/ViewModels/CatalogIndexViewModel.cs @@ -1,13 +1,12 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.Rendering; namespace Microsoft.eShopWeb.Web.ViewModels; public class CatalogIndexViewModel { - public List? CatalogItems { get; set; } - public List? Brands { get; set; } - public List? Types { get; set; } + public List CatalogItems { get; set; } = new List(); + public List? Brands { get; set; } = new List(); + public List? Types { get; set; } = new List(); public int? BrandFilterApplied { get; set; } public int? TypesFilterApplied { get; set; } public PaginationInfoViewModel? PaginationInfo { get; set; } diff --git a/src/Web/ViewModels/Manage/RemoveLoginViewModel.cs b/src/Web/ViewModels/Manage/RemoveLoginViewModel.cs index 45a5975..78ddac1 100644 --- a/src/Web/ViewModels/Manage/RemoveLoginViewModel.cs +++ b/src/Web/ViewModels/Manage/RemoveLoginViewModel.cs @@ -1,7 +1,11 @@ -namespace Microsoft.eShopWeb.Web.ViewModels.Manage; +using System.ComponentModel.DataAnnotations; + +namespace Microsoft.eShopWeb.Web.ViewModels.Manage; public class RemoveLoginViewModel { - public string? LoginProvider { get; set; } - public string? ProviderKey { get; set; } + [Required] + public string LoginProvider { get; set; } = string.Empty; + [Required] + public string ProviderKey { get; set; } = string.Empty; } diff --git a/src/Web/ViewModels/OrderViewModel.cs b/src/Web/ViewModels/OrderViewModel.cs index 7ecfd90..582a504 100644 --- a/src/Web/ViewModels/OrderViewModel.cs +++ b/src/Web/ViewModels/OrderViewModel.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; +using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate; namespace Microsoft.eShopWeb.Web.ViewModels; @@ -13,5 +11,5 @@ public class OrderViewModel public decimal Total { get; set; } public string Status => DEFAULT_STATUS; public Address? ShippingAddress { get; set; } - public List OrderItems { get; set; } = new List(); + public List OrderItems { get; set; } = new(); } diff --git a/src/Web/Views/Manage/ShowRecoverCodes.cshtml b/src/Web/Views/Manage/ShowRecoverCodes.cshtml index ed6bc95..0d012e2 100644 --- a/src/Web/Views/Manage/ShowRecoverCodes.cshtml +++ b/src/Web/Views/Manage/ShowRecoverCodes.cshtml @@ -16,10 +16,13 @@
- @for (var row = 0; row < Model.RecoveryCodes.Length; row += 2) + @if (Model.RecoveryCodes != null) { - @Model.RecoveryCodes[row] @Model.RecoveryCodes[row + 1]
+ @for (var row = 0; row < Model.RecoveryCodes.Length; row += 2) + { + @Model.RecoveryCodes[row] @Model.RecoveryCodes[row + 1]
+ } }
-© 2021 GitHub, Inc. \ No newline at end of file +© 2023 GitHub, Inc. \ No newline at end of file diff --git a/src/Web/Views/Order/Detail.cshtml b/src/Web/Views/Order/Detail.cshtml index cb5db3f..097d17e 100644 --- a/src/Web/Views/Order/Detail.cshtml +++ b/src/Web/Views/Order/Detail.cshtml @@ -30,15 +30,15 @@
-
@Model.ShippingAddress.Street
+
@Model.ShippingAddress?.Street
-
@Model.ShippingAddress.City
+
@Model.ShippingAddress?.City
-
@Model.ShippingAddress.Country
+
@Model.ShippingAddress?.Country
diff --git a/src/Web/Views/Shared/_LoginPartial.cshtml b/src/Web/Views/Shared/_LoginPartial.cshtml index ac3f106..0e52fea 100644 --- a/src/Web/Views/Shared/_LoginPartial.cshtml +++ b/src/Web/Views/Shared/_LoginPartial.cshtml @@ -1,4 +1,4 @@ -@if (Context.User.Identity.IsAuthenticated) +@if (Context!.User!.Identity!.IsAuthenticated) {
diff --git a/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs b/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs index 72d1f23..88b37bf 100644 --- a/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs +++ b/tests/FunctionalTests/Web/Controllers/OrderControllerIndex.cs @@ -23,7 +23,7 @@ public class OrderIndexOnGet : IClassFixture public async Task ReturnsRedirectGivenAnonymousUser() { var response = await Client.GetAsync("/order/my-orders"); - var redirectLocation = response.Headers.Location.OriginalString; + var redirectLocation = response!.Headers.Location!.OriginalString; Assert.Equal(HttpStatusCode.Redirect, response.StatusCode); Assert.Contains("/Account/Login", redirectLocation); diff --git a/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs b/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs index dd19a71..be2dbb0 100644 --- a/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs +++ b/tests/FunctionalTests/Web/Pages/Basket/BasketPageCheckout.cs @@ -45,6 +45,6 @@ public class BasketPageCheckout : IClassFixture formContent = new FormUrlEncodedContent(keyValues); var postResponse2 = await Client.PostAsync("/Basket/Checkout", formContent); - Assert.Contains("/Identity/Account/Login", postResponse2.RequestMessage.RequestUri.ToString()); + Assert.Contains("/Identity/Account/Login", postResponse2!.RequestMessage!.RequestUri!.ToString()!); } } diff --git a/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs b/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs index 4657d77..8d6c0be 100644 --- a/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs +++ b/tests/FunctionalTests/Web/Pages/Basket/CheckoutTest.cs @@ -62,7 +62,7 @@ public class CheckoutTest : IClassFixture var checkOutResponse = await Client.PostAsync("/basket/checkout", checkOutContent); var stringCheckOutResponse = await checkOutResponse.Content.ReadAsStringAsync(); - Assert.Contains("/Basket/Success", checkOutResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("/Basket/Success", checkOutResponse.RequestMessage!.RequestUri!.ToString()); Assert.Contains("Thanks for your Order!", stringCheckOutResponse); } } diff --git a/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs b/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs index cd36458..1f68da7 100644 --- a/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs +++ b/tests/FunctionalTests/Web/Pages/Basket/IndexTest.cs @@ -52,7 +52,7 @@ public class IndexTest : IClassFixture var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync(); - Assert.Contains("/basket/update", updateResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("/basket/update", updateResponse!.RequestMessage!.RequestUri!.ToString()!); decimal expectedTotalAmount = 416.50M; Assert.Contains(expectedTotalAmount.ToString("N2"), stringUpdateResponse); } @@ -92,7 +92,7 @@ public class IndexTest : IClassFixture var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync(); - Assert.Contains("/basket/update", updateResponse.RequestMessage.RequestUri.ToString()); + Assert.Contains("/basket/update", updateResponse!.RequestMessage!.RequestUri!.ToString()!); Assert.Contains("Basket is empty", stringUpdateResponse); } } diff --git a/tests/FunctionalTests/Web/WebPageHelpers.cs b/tests/FunctionalTests/Web/WebPageHelpers.cs index d858bfb..1259c9e 100644 --- a/tests/FunctionalTests/Web/WebPageHelpers.cs +++ b/tests/FunctionalTests/Web/WebPageHelpers.cs @@ -22,6 +22,6 @@ public static class WebPageHelpers { var regex = new Regex(regexpression); var match = regex.Match(input); - return match.Groups.Values.LastOrDefault().Value; + return match!.Groups!.Values!.LastOrDefault()!.Value; } } diff --git a/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs b/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs index 03a969c..62550e6 100644 --- a/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs +++ b/tests/PublicApiIntegrationTests/AuthEndpoints/AuthenticateEndpointTest.cs @@ -7,29 +7,28 @@ using Microsoft.eShopWeb.ApplicationCore.Constants; using Microsoft.eShopWeb.PublicApi.AuthEndpoints; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace PublicApiIntegrationTests.AuthEndpoints -{ - [TestClass] - public class AuthenticateEndpoint - { - [TestMethod] - [DataRow("demouser@microsoft.com", AuthorizationConstants.DEFAULT_PASSWORD, true)] - [DataRow("demouser@microsoft.com", "badpassword", false)] - [DataRow("baduser@microsoft.com", "badpassword", false)] - public async Task ReturnsExpectedResultGivenCredentials(string testUsername, string testPassword, bool expectedResult) - { - var request = new AuthenticateRequest() - { - Username = testUsername, - Password = testPassword - }; - var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); - var response = await ProgramTest.NewClient.PostAsync("api/authenticate", jsonContent); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); +namespace PublicApiIntegrationTests.AuthEndpoints; - Assert.AreEqual(expectedResult, model.Result); - } +[TestClass] +public class AuthenticateEndpoint +{ + [TestMethod] + [DataRow("demouser@microsoft.com", AuthorizationConstants.DEFAULT_PASSWORD, true)] + [DataRow("demouser@microsoft.com", "badpassword", false)] + [DataRow("baduser@microsoft.com", "badpassword", false)] + public async Task ReturnsExpectedResultGivenCredentials(string testUsername, string testPassword, bool expectedResult) + { + var request = new AuthenticateRequest() + { + Username = testUsername, + Password = testPassword + }; + var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); + var response = await ProgramTest.NewClient.PostAsync("api/authenticate", jsonContent); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); + + Assert.AreEqual(expectedResult, model!.Result); } } diff --git a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemGetByIdEndpointTest.cs b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemGetByIdEndpointTest.cs index 5882db0..9baefde 100644 --- a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemGetByIdEndpointTest.cs +++ b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemGetByIdEndpointTest.cs @@ -4,29 +4,28 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Net; using System.Threading.Tasks; -namespace PublicApiIntegrationTests.CatalogItemEndpoints +namespace PublicApiIntegrationTests.CatalogItemEndpoints; + +[TestClass] +public class CatalogItemGetByIdEndpointTest { - [TestClass] - public class CatalogItemGetByIdEndpointTest + [TestMethod] + public async Task ReturnsItemGivenValidId() { - [TestMethod] - public async Task ReturnsItemGivenValidId() - { - var response = await ProgramTest.NewClient.GetAsync("api/catalog-items/5"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); + var response = await ProgramTest.NewClient.GetAsync("api/catalog-items/5"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); - Assert.AreEqual(5, model.CatalogItem.Id); - Assert.AreEqual("Roslyn Red Sheet", model.CatalogItem.Name); - } + Assert.AreEqual(5, model!.CatalogItem.Id); + Assert.AreEqual("Roslyn Red Sheet", model.CatalogItem.Name); + } - [TestMethod] - public async Task ReturnsNotFoundGivenInvalidId() - { - var response = await ProgramTest.NewClient.GetAsync("api/catalog-items/0"); + [TestMethod] + public async Task ReturnsNotFoundGivenInvalidId() + { + var response = await ProgramTest.NewClient.GetAsync("api/catalog-items/0"); - Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); - } + Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs index 5eb3036..5470111 100644 --- a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs +++ b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CatalogItemListPagedEndpoint.cs @@ -8,66 +8,65 @@ using System.Net.Http; using System.Net; using System.Threading.Tasks; -namespace PublicApiIntegrationTests.CatalogItemEndpoints +namespace PublicApiIntegrationTests.CatalogItemEndpoints; + +[TestClass] +public class CatalogItemListPagedEndpoint { - [TestClass] - public class CatalogItemListPagedEndpoint + [TestMethod] + public async Task ReturnsFirst10CatalogItems() { - [TestMethod] - public async Task ReturnsFirst10CatalogItems() + var client = ProgramTest.NewClient; + var response = await client.GetAsync("/api/catalog-items?pageSize=10"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); + + Assert.AreEqual(10, model!.CatalogItems.Count()); + } + + [TestMethod] + public async Task ReturnsCorrectCatalogItemsGivenPageIndex1() + { + + var pageSize = 10; + var pageIndex = 1; + + var client = ProgramTest.NewClient; + var response = await client.GetAsync($"/api/catalog-items"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); + var totalItem = model!.CatalogItems.Count(); + + var response2 = await client.GetAsync($"/api/catalog-items?pageSize={pageSize}&pageIndex={pageIndex}"); + response.EnsureSuccessStatusCode(); + var stringResponse2 = await response2.Content.ReadAsStringAsync(); + var model2 = stringResponse2.FromJson(); + + var totalExpected = totalItem - (pageSize * pageIndex); + + Assert.AreEqual(totalExpected, model2!.CatalogItems.Count()); + } + + [DataTestMethod] + [DataRow("catalog-items")] + [DataRow("catalog-brands")] + [DataRow("catalog-types")] + [DataRow("catalog-items/1")] + public async Task SuccessFullMutipleParallelCall(string endpointName) + { + var client = ProgramTest.NewClient; + var tasks = new List>(); + + for (int i = 0; i < 100; i++) { - var client = ProgramTest.NewClient; - var response = await client.GetAsync("/api/catalog-items?pageSize=10"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); - - Assert.AreEqual(10, model.CatalogItems.Count()); + var task = client.GetAsync($"/api/{endpointName}"); + tasks.Add(task); } + await Task.WhenAll(tasks.ToList()); + var totalKO = tasks.Count(t => t.Result.StatusCode != HttpStatusCode.OK); - [TestMethod] - public async Task ReturnsCorrectCatalogItemsGivenPageIndex1() - { - - var pageSize = 10; - var pageIndex = 1; - - var client = ProgramTest.NewClient; - var response = await client.GetAsync($"/api/catalog-items"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); - var totalItem = model.CatalogItems.Count(); - - var response2 = await client.GetAsync($"/api/catalog-items?pageSize={pageSize}&pageIndex={pageIndex}"); - response.EnsureSuccessStatusCode(); - var stringResponse2 = await response2.Content.ReadAsStringAsync(); - var model2 = stringResponse2.FromJson(); - - var totalExpected = totalItem - (pageSize * pageIndex); - - Assert.AreEqual(totalExpected, model2.CatalogItems.Count()); - } - - [DataTestMethod] - [DataRow("catalog-items")] - [DataRow("catalog-brands")] - [DataRow("catalog-types")] - [DataRow("catalog-items/1")] - public async Task SuccessFullMutipleParallelCall(string endpointName) - { - var client = ProgramTest.NewClient; - var tasks = new List>(); - - for (int i = 0; i < 100; i++) - { - var task = client.GetAsync($"/api/{endpointName}"); - tasks.Add(task); - } - await Task.WhenAll(tasks.ToList()); - var totalKO = tasks.Count(t => t.Result.StatusCode != HttpStatusCode.OK); - - Assert.AreEqual(0, totalKO); - } + Assert.AreEqual(0, totalKO); } } diff --git a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CreateCatalogItemEndpointTest.cs b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CreateCatalogItemEndpointTest.cs index a85923d..6c5d79e 100644 --- a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CreateCatalogItemEndpointTest.cs +++ b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/CreateCatalogItemEndpointTest.cs @@ -8,62 +8,61 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -namespace PublicApiIntegrationTests.AuthEndpoints +namespace PublicApiIntegrationTests.AuthEndpoints; + +[TestClass] +public class CreateCatalogItemEndpointTest { - [TestClass] - public class CreateCatalogItemEndpointTest + private int _testBrandId = 1; + private int _testTypeId = 2; + private string _testDescription = "test description"; + private string _testName = "test name"; + private decimal _testPrice = 1.23m; + + + [TestMethod] + public async Task ReturnsNotAuthorizedGivenNormalUserToken() { - private int _testBrandId = 1; - private int _testTypeId = 2; - private string _testDescription = "test description"; - private string _testName = "test name"; - private decimal _testPrice = 1.23m; + var jsonContent = GetValidNewItemJson(); + var token = ApiTokenHelper.GetNormalUserToken(); + var client = ProgramTest.NewClient; + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + var response = await client.PostAsync("api/catalog-items", jsonContent); + Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode); + } - [TestMethod] - public async Task ReturnsNotAuthorizedGivenNormalUserToken() + [TestMethod] + public async Task ReturnsSuccessGivenValidNewItemAndAdminUserToken() + { + var jsonContent = GetValidNewItemJson(); + var adminToken = ApiTokenHelper.GetAdminUserToken(); + var client = ProgramTest.NewClient; + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); + var response = await client.PostAsync("api/catalog-items", jsonContent); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); + + Assert.AreEqual(_testBrandId, model!.CatalogItem.CatalogBrandId); + Assert.AreEqual(_testTypeId, model.CatalogItem.CatalogTypeId); + Assert.AreEqual(_testDescription, model.CatalogItem.Description); + Assert.AreEqual(_testName, model.CatalogItem.Name); + Assert.AreEqual(_testPrice, model.CatalogItem.Price); + } + + private StringContent GetValidNewItemJson() + { + var request = new CreateCatalogItemRequest() { - var jsonContent = GetValidNewItemJson(); - var token = ApiTokenHelper.GetNormalUserToken(); - var client = ProgramTest.NewClient; - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); - var response = await client.PostAsync("api/catalog-items", jsonContent); + CatalogBrandId = _testBrandId, + CatalogTypeId = _testTypeId, + Description = _testDescription, + Name = _testName, + Price = _testPrice + }; + var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); - Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode); - } - - [TestMethod] - public async Task ReturnsSuccessGivenValidNewItemAndAdminUserToken() - { - var jsonContent = GetValidNewItemJson(); - var adminToken = ApiTokenHelper.GetAdminUserToken(); - var client = ProgramTest.NewClient; - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); - var response = await client.PostAsync("api/catalog-items", jsonContent); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); - - Assert.AreEqual(_testBrandId, model.CatalogItem.CatalogBrandId); - Assert.AreEqual(_testTypeId, model.CatalogItem.CatalogTypeId); - Assert.AreEqual(_testDescription, model.CatalogItem.Description); - Assert.AreEqual(_testName, model.CatalogItem.Name); - Assert.AreEqual(_testPrice, model.CatalogItem.Price); - } - - private StringContent GetValidNewItemJson() - { - var request = new CreateCatalogItemRequest() - { - CatalogBrandId = _testBrandId, - CatalogTypeId = _testTypeId, - Description = _testDescription, - Name = _testName, - Price = _testPrice - }; - var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); - - return jsonContent; - } + return jsonContent; } } diff --git a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/DeleteCatalogItemEndpointTest.cs b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/DeleteCatalogItemEndpointTest.cs index f41976e..98c8212 100644 --- a/tests/PublicApiIntegrationTests/CatalogItemEndpoints/DeleteCatalogItemEndpointTest.cs +++ b/tests/PublicApiIntegrationTests/CatalogItemEndpoints/DeleteCatalogItemEndpointTest.cs @@ -5,34 +5,33 @@ using System.Net; using System.Net.Http.Headers; using System.Threading.Tasks; -namespace PublicApiIntegrationTests.CatalogItemEndpoints +namespace PublicApiIntegrationTests.CatalogItemEndpoints; + +[TestClass] +public class DeleteCatalogItemEndpointTest { - [TestClass] - public class DeleteCatalogItemEndpointTest + [TestMethod] + public async Task ReturnsSuccessGivenValidIdAndAdminUserToken() { - [TestMethod] - public async Task ReturnsSuccessGivenValidIdAndAdminUserToken() - { - var adminToken = ApiTokenHelper.GetAdminUserToken(); - var client = ProgramTest.NewClient; - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); - var response = await client.DeleteAsync("api/catalog-items/12"); - response.EnsureSuccessStatusCode(); - var stringResponse = await response.Content.ReadAsStringAsync(); - var model = stringResponse.FromJson(); + var adminToken = ApiTokenHelper.GetAdminUserToken(); + var client = ProgramTest.NewClient; + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); + var response = await client.DeleteAsync("api/catalog-items/12"); + response.EnsureSuccessStatusCode(); + var stringResponse = await response.Content.ReadAsStringAsync(); + var model = stringResponse.FromJson(); - Assert.AreEqual("Deleted", model.Status); - } + Assert.AreEqual("Deleted", model!.Status); + } - [TestMethod] - public async Task ReturnsNotFoundGivenInvalidIdAndAdminUserToken() - { - var adminToken = ApiTokenHelper.GetAdminUserToken(); - var client = ProgramTest.NewClient; - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); - var response = await client.DeleteAsync("api/catalog-items/0"); + [TestMethod] + public async Task ReturnsNotFoundGivenInvalidIdAndAdminUserToken() + { + var adminToken = ApiTokenHelper.GetAdminUserToken(); + var client = ProgramTest.NewClient; + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminToken); + var response = await client.DeleteAsync("api/catalog-items/0"); - Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); - } + Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode); } } diff --git a/tests/PublicApiIntegrationTests/ProgramTest.cs b/tests/PublicApiIntegrationTests/ProgramTest.cs index ca92234..3f13136 100644 --- a/tests/PublicApiIntegrationTests/ProgramTest.cs +++ b/tests/PublicApiIntegrationTests/ProgramTest.cs @@ -2,26 +2,25 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Net.Http; -namespace PublicApiIntegrationTests +namespace PublicApiIntegrationTests; + +[TestClass] +public class ProgramTest { - [TestClass] - public class ProgramTest + private static WebApplicationFactory _application = new(); + + public static HttpClient NewClient { - private static WebApplicationFactory _application; - - public static HttpClient NewClient + get { - get - { - return _application.CreateClient(); - } - } - - [AssemblyInitialize] - public static void AssemblyInitialize(TestContext _) - { - _application = new WebApplicationFactory(); - + return _application.CreateClient(); } } + + [AssemblyInitialize] + public static void AssemblyInitialize(TestContext _) + { + _application = new WebApplicationFactory(); + + } } From dbc19cf611e5effcdedb2a185bf03d88ddc9f280 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Mon, 20 Mar 2023 21:53:34 -0400 Subject: [PATCH 23/28] Update README.md Update .NET 6 reference to .NET 7 Note that the PDF will need to be created and published before it will have the latest .NET 7 changes in it. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f8fa72..0a5e5e8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ A list of Frequently Asked Questions about this repository can be found [here](h ## eBook -This reference application is meant to support the free .PDF download ebook: [Architecting Modern Web Applications with ASP.NET Core and Azure](https://aka.ms/webappebook), updated to **ASP.NET Core 6.0**. [Also available in ePub/mobi formats](https://dotnet.microsoft.com/learn/web/aspnet-architecture). +This reference application is meant to support the free .PDF download ebook: [Architecting Modern Web Applications with ASP.NET Core and Azure](https://aka.ms/webappebook), updated to **ASP.NET Core 7.0**. [Also available in ePub/mobi formats](https://dotnet.microsoft.com/learn/web/aspnet-architecture). You can also read the book in online pages at the .NET docs here: https://docs.microsoft.com/dotnet/architecture/modern-web-apps-azure/ From c116b4677dbdcbaede35313ae3ea68d16e053d81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:19:23 +0000 Subject: [PATCH 24/28] Bump Microsoft.VisualStudio.Azure.Containers.Tools.Targets Bumps Microsoft.VisualStudio.Azure.Containers.Tools.Targets from 1.17.0 to 1.18.1. --- updated-dependencies: - dependency-name: Microsoft.VisualStudio.Azure.Containers.Tools.Targets dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index a4eebe2..3a1c506 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -37,7 +37,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From 1b7e3b7bedc79954ed7ab863b53842d346b0808b Mon Sep 17 00:00:00 2001 From: Brigit Murtaugh Date: Wed, 5 Apr 2023 06:32:16 -0700 Subject: [PATCH 25/28] Update dev container config and guidance (#886) * Initial dev container changes * Update readme's * Clean up dev container * Cleanup * Use in-memory db * Indent * Update devcontainerreadme.md * Update appsettings.json * Update appsettings.json --------- Co-authored-by: bamurtaugh --- .devcontainer/Dockerfile | 82 ----------------------------- .devcontainer/devcontainer.json | 67 ++++++++--------------- .devcontainer/devcontainerreadme.md | 36 +++++++++++++ .gitattributes | 3 ++ README.md | 11 +++- src/Web/appsettings.json | 2 +- 6 files changed, 72 insertions(+), 129 deletions(-) delete mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainerreadme.md create mode 100644 .gitattributes diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 3fc7543..0000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,82 +0,0 @@ - -#------------------------------------------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. -#------------------------------------------------------------------------------------------------------------- -FROM mcr.microsoft.com/dotnet/sdk:7.0 - - -# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser" -# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs -# will be updated to match your local UID/GID (when using the dockerFile property). -# See https://aka.ms/vscode-remote/containers/non-root-user for details. -ARG USERNAME=vscode -ARG USER_UID=1000 -ARG USER_GID=$USER_UID - -# [Optional] Version of Node.js to install. -ARG INSTALL_NODE="false" -ARG NODE_VERSION="lts/*" -ENV NVM_DIR=/usr/local/share/nvm - -# [Optional] Install the Azure CLI -ARG INSTALL_AZURE_CLI="false" - -# Configure apt and install packages -RUN apt-get update \ - && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ - # - # Verify git, process tools, lsb-release (common in install instructions for CLIs) installed - && apt-get -y install git openssh-client less iproute2 procps apt-transport-https gnupg2 curl lsb-release \ - # - # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. - && groupadd --gid $USER_GID $USERNAME \ - && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ - # [Optional] Add sudo support for the non-root user - && apt-get install -y sudo \ - && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\ - && chmod 0440 /etc/sudoers.d/$USERNAME \ - # - # [Optional] Install Node.js for ASP.NET Core Web Applicationss - && if [ "$INSTALL_NODE" = "true" ]; then \ - # - # Install nvm and Node - mkdir -p ${NVM_DIR} \ - && curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash 2>&1 \ - && chown -R ${USER_UID}:${USER_GID} ${NVM_DIR} \ - && /bin/bash -c "source $NVM_DIR/nvm.sh \ - && nvm alias default ${NODE_VERSION}" 2>&1 \ - && echo '[ -s "$NVM_DIR/nvm.sh" ] && \\. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \\. "$NVM_DIR/bash_completion"' \ - | tee -a /home/${USERNAME}/.bashrc /home/${USERNAME}/.zshrc >> /root/.zshrc \ - && echo "if [ \"\$(stat -c '%U' ${NVM_DIR})\" != \"${USERNAME}\" ]; then sudo chown -R ${USER_UID}:root ${NVM_DIR}; fi" \ - | tee -a /root/.bashrc /root/.zshrc /home/${USERNAME}/.bashrc >> /home/${USERNAME}/.zshrc \ - && chown ${USER_UID}:${USER_GID} /home/${USERNAME}/.bashrc /home/${USERNAME}/.zshrc \ - && chown -R ${USER_UID}:root ${NVM_DIR} \ - # - # Install yarn - && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ - && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ - && apt-get update \ - && apt-get -y install --no-install-recommends yarn; \ - fi \ - # - # [Optional] Install the Azure CLI - && if [ "$INSTALL_AZURE_CLI" = "true" ]; then \ - echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" > /etc/apt/sources.list.d/azure-cli.list \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 2>/dev/null \ - && apt-get update \ - && apt-get install -y azure-cli; \ - fi \ - # - # Install EF Core dotnet tool - && dotnet tool install dotnet-ef --tool-path /home/$USERNAME/.dotnet/tools \ - && chown -R $USERNAME /home/$USERNAME/.dotnet \ - # - # Clean up - && apt-get autoremove -y \ - && apt-get clean -y \ - && rm -rf /var/lib/apt/lists/* - -# Set PATH for dotnet tools -ENV PATH "$PATH:/home/$USERNAME/.dotnet/tools" \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1448ea9..fcce1e8 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,46 +2,28 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/dotnetcore-3.1 { "name": "eShopOnWeb", - "build": { - "dockerfile": "Dockerfile", - "args": { - "USERNAME": "vscode", - "INSTALL_NODE": "false", - "NODE_VERSION": "lts/*", - "INSTALL_AZURE_CLI": "false" - } - }, + "image": "mcr.microsoft.com/devcontainers/dotnet:0-7.0", - // Comment out to connect as root user. See https://aka.ms/vscode-remote/containers/non-root. - // make sure this is the same as USERNAME above - "remoteUser": "vscode", - "runArgs": [ - "-v", - "/var/run/docker.sock:/var/run/docker.sock" - ], - // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.profiles.linux": { - "bash": { - "path": "bash", - "icon": "terminal-bash" - }, - }, + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-dotnettools.csharp", + "formulahendry.dotnet-test-explorer", + "ms-vscode.vscode-node-azure-pack", + "ms-kubernetes-tools.vscode-kubernetes-tools", + "redhat.vscode-yaml" + ] + } }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-dotnettools.csharp", - "formulahendry.dotnet-test-explorer", - "ms-vscode.vscode-node-azure-pack", - "ms-kubernetes-tools.vscode-kubernetes-tools", - "redhat.vscode-yaml" - ], - - // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [5000, 5001], + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "dotnet dev-certs https --trust" + // [Optional] To reuse of your local HTTPS dev cert, first export it locally using this command: // * Windows PowerShell: // dotnet dev-certs https --trust; dotnet dev-certs https -ep "$env:USERPROFILE/.aspnet/https/aspnetapp.pfx" -p "SecurePwdGoesHere" @@ -51,14 +33,11 @@ // Next, after running the command above, uncomment lines in the 'mounts' and 'remoteEnv' lines below, // and open / rebuild the container so the settings take effect. // - "mounts": [ - // "source=${env:HOME}${env:USERPROFILE}/.aspnet/https,target=/home/vscode/.aspnet/https,type=bind" - ], - "remoteEnv": { - // "ASPNETCORE_Kestrel__Certificates__Default__Password": "SecurePwdGoesHere", - // "ASPNETCORE_Kestrel__Certificates__Default__Path": "/home/vscode/.aspnet/https/aspnetapp.pfx", - } - - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "dotnet restore" + // "mounts": [ + // // "source=${env:HOME}${env:USERPROFILE}/.aspnet/https,target=/home/vscode/.aspnet/https,type=bind" + // ], + // "remoteEnv": { + // // "ASPNETCORE_Kestrel__Certificates__Default__Password": "SecurePwdGoesHere", + // // "ASPNETCORE_Kestrel__Certificates__Default__Path": "/home/vscode/.aspnet/https/aspnetapp.pfx", + // }, } diff --git a/.devcontainer/devcontainerreadme.md b/.devcontainer/devcontainerreadme.md new file mode 100644 index 0000000..ff6ee13 --- /dev/null +++ b/.devcontainer/devcontainerreadme.md @@ -0,0 +1,36 @@ +# Dev container + +This project includes a [dev container](https://containers.dev/), which lets you use a container as a full-featured dev environment. + +You can use the dev container configuration in this folder to build and run the app without needing to install any of its tools locally! You can use it in [GitHub Codespaces](https://github.com/features/codespaces) or the [VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). + +## GitHub Codespaces +Follow these steps to open this sample in a Codespace: +1. Click the **Code** drop-down menu at the top of https://github.com/dotnet-architecture/eShopOnWeb. +1. Click on the **Codespaces** tab. +1. Click **Create codespace on main** . + +For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace). + +## VS Code Dev Containers + +If you already have VS Code and Docker installed, you can click [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/dotnet-architecture/eShopOnWeb) to get started. This will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use. + +You can also follow these steps to open this sample in a container using the VS Code Dev Containers extension: + +1. If this is your first time using a development container, please ensure your system meets the pre-reqs (i.e. have Docker installed) in the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started). + +2. Open a locally cloned copy of the code: + + - Clone this repository to your local filesystem. + - Press F1 and select the **Dev Containers: Open Folder in Container...** command. + - Select the cloned copy of this folder, wait for the container to start, and try things out! + +You can learn more in the [Dev Containers documentation](https://code.visualstudio.com/docs/devcontainers/containers). + +## Tips and tricks + +* Since the dev container is Linux-based, you won't be able to use LocalDB. Add ` "UseOnlyInMemoryDatabase": true,` to the [appsettings.json](../src/Web/appsettings.json) file (there's additional context on this [in the app's readme](../README.md#configuring-the-sample-to-use-sql-server)). +* If you get a `502 bad gateway` error, you may need to set your port to the https protocol. You can do this by opening the Ports view in VS Code (**Ports: Focus on Ports View**), right-clicking on the port you're using, select **Change Port Protocol**, and set **https**. +* If you are working with the same repository folder in a container and Windows, you'll want consistent line endings (otherwise you may see hundreds of changes in the SCM view). The `.gitattributes` file in the root of this repo disables line ending conversion and should prevent this. See [tips and tricks](https://code.visualstudio.com/docs/devcontainers/tips-and-tricks#_resolving-git-line-ending-issues-in-containers-resulting-in-many-modified-files) for more info. +* If you'd like to review the contents of the image used in this dev container, you can check it out in the [devcontainers/images](https://github.com/devcontainers/images/tree/main/src/dotnet) repo. diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5dc46e6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto eol=lf +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf \ No newline at end of file diff --git a/README.md b/README.md index 0a5e5e8..831e0f5 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,12 @@ You can also run the samples in Docker (see below). ### Configuring the sample to use SQL Server -1. By default, the project uses a real database. If you want an in memory database, you can add in `appsettings.json` +1. By default, the project uses a real database. If you want an in memory database, you can add in the `appsettings.json` file in the Web folder ```json { "UseOnlyInMemoryDatabase": true } - ``` 1. Ensure your connection strings in `appsettings.json` point to a local SQL Server instance. @@ -98,6 +97,14 @@ You can also run the samples in Docker (see below). dotnet ef migrations add InitialIdentityModel --context appidentitydbcontext -p ../Infrastructure/Infrastructure.csproj -s Web.csproj -o Identity/Migrations ``` +## Running the sample in the dev container + +This project includes a `.devcontainer` folder with a [dev container configuration](https://containers.dev/), which lets you use a container as a full-featured dev environment. + +You can use the dev container to build and run the app without needing to install any of its tools locally! You can work in GitHub Codespaces or the VS Code Dev Containers extension. + +Learn more about using the dev container in its [readme](/.devcontainer/devcontainerreadme.md). + ## Running the sample using Docker You can run the Web sample by running these commands from the root folder (where the .sln file is located): diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 70989a6..c2bc659 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -17,4 +17,4 @@ }, "AllowedHosts": "*" } -} \ No newline at end of file +} From c794c867bbd9ccd8352ee1a733a18a32897bd55c Mon Sep 17 00:00:00 2001 From: Brigit Murtaugh Date: Wed, 5 Apr 2023 11:45:01 -0700 Subject: [PATCH 26/28] Minor dev container polish (#887) * Minor polish * Comment --- .devcontainer/devcontainer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fcce1e8..2f003b0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ -// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/dotnetcore-3.1 +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet { "name": "eShopOnWeb", "image": "mcr.microsoft.com/devcontainers/dotnet:0-7.0", @@ -11,9 +11,9 @@ "extensions": [ "ms-dotnettools.csharp", "formulahendry.dotnet-test-explorer", - "ms-vscode.vscode-node-azure-pack", - "ms-kubernetes-tools.vscode-kubernetes-tools", - "redhat.vscode-yaml" + "ms-vscode.vscode-node-azure-pack", + "ms-kubernetes-tools.vscode-kubernetes-tools", + "redhat.vscode-yaml" ] } }, From 8ec89a1c5fc097e9afa8de43a24639c3d1343114 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 15:48:39 -0400 Subject: [PATCH 27/28] Bump AutoMapper.Extensions.Microsoft.DependencyInjection (#891) Bumps [AutoMapper.Extensions.Microsoft.DependencyInjection](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection) from 12.0.0 to 12.0.1. - [Release notes](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/releases) - [Commits](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/compare/v12.0.0...v12.0.1) --- updated-dependencies: - dependency-name: AutoMapper.Extensions.Microsoft.DependencyInjection dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 67c8051..1ac4f59 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + From 896d75d55f6c7a6ea8d065245edb997c657f7645 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 10:02:57 -0400 Subject: [PATCH 28/28] Bump Microsoft.EntityFrameworkCore.InMemory from 7.0.4 to 7.0.5 (#892) Bumps [Microsoft.EntityFrameworkCore.InMemory](https://github.com/dotnet/efcore) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/dotnet/efcore/releases) - [Commits](https://github.com/dotnet/efcore/commits) --- updated-dependencies: - dependency-name: Microsoft.EntityFrameworkCore.InMemory dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 1ac4f59..aae2105 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,7 +31,7 @@ - + all