Fix Null Warnings (#874)
* Fixing null warnings * Fix null warnings Fix other compiler warnings
This commit is contained in:
@@ -141,4 +141,10 @@ csharp_preserve_single_line_blocks = true
|
|||||||
###############################
|
###############################
|
||||||
[*.vb]
|
[*.vb]
|
||||||
# Modifier preferences
|
# 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
|
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
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
92
Everything.sln
Normal file
92
Everything.sln
Normal file
@@ -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
|
||||||
@@ -10,10 +10,10 @@ public static class Dependencies
|
|||||||
{
|
{
|
||||||
public static void ConfigureServices(IConfiguration configuration, IServiceCollection services)
|
public static void ConfigureServices(IConfiguration configuration, IServiceCollection services)
|
||||||
{
|
{
|
||||||
var useOnlyInMemoryDatabase = false;
|
bool useOnlyInMemoryDatabase = false;
|
||||||
if (configuration["UseOnlyInMemoryDatabase"] != null)
|
if (configuration["UseOnlyInMemoryDatabase"] != null)
|
||||||
{
|
{
|
||||||
useOnlyInMemoryDatabase = bool.Parse(configuration["UseOnlyInMemoryDatabase"]);
|
useOnlyInMemoryDatabase = bool.Parse(configuration["UseOnlyInMemoryDatabase"]!);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useOnlyInMemoryDatabase)
|
if (useOnlyInMemoryDatabase)
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ public class AppIdentityDbContextSeed
|
|||||||
var adminUser = new ApplicationUser { UserName = adminUserName, Email = adminUserName };
|
var adminUser = new ApplicationUser { UserName = adminUserName, Email = adminUserName };
|
||||||
await userManager.CreateAsync(adminUser, AuthorizationConstants.DEFAULT_PASSWORD);
|
await userManager.CreateAsync(adminUser, AuthorizationConstants.DEFAULT_PASSWORD);
|
||||||
adminUser = await userManager.FindByNameAsync(adminUserName);
|
adminUser = await userManager.FindByNameAsync(adminUserName);
|
||||||
|
if (adminUser != null)
|
||||||
|
{
|
||||||
await userManager.AddToRoleAsync(adminUser, BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS);
|
await userManager.AddToRoleAsync(adminUser, BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public class IdentityTokenClaimService : ITokenClaimsService
|
|||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
var key = Encoding.ASCII.GetBytes(AuthorizationConstants.JWT_SECRET_KEY);
|
var key = Encoding.ASCII.GetBytes(AuthorizationConstants.JWT_SECRET_KEY);
|
||||||
var user = await _userManager.FindByNameAsync(userName);
|
var user = await _userManager.FindByNameAsync(userName);
|
||||||
|
if (user == null) throw new UserNotFoundException(userName);
|
||||||
var roles = await _userManager.GetRolesAsync(user);
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
var claims = new List<Claim> { new Claim(ClaimTypes.Name, userName) };
|
var claims = new List<Claim> { new Claim(ClaimTypes.Name, userName) };
|
||||||
|
|
||||||
|
|||||||
10
src/Infrastructure/Identity/UserNotFoundException.cs
Normal file
10
src/Infrastructure/Identity/UserNotFoundException.cs
Normal file
@@ -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}")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
using System;
|
namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
|
||||||
|
|
||||||
public class ClaimValue
|
public class ClaimValue
|
||||||
{
|
{
|
||||||
@@ -17,6 +12,6 @@ public class ClaimValue
|
|||||||
Value = value;
|
Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Type { get; set; }
|
public string Type { get; set; } = string.Empty;
|
||||||
public string Value { get; set; }
|
public string Value { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
namespace Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
||||||
|
|
||||||
@@ -9,7 +6,7 @@ public class UserInfo
|
|||||||
{
|
{
|
||||||
public static readonly UserInfo Anonymous = new UserInfo();
|
public static readonly UserInfo Anonymous = new UserInfo();
|
||||||
public bool IsAuthenticated { get; set; }
|
public bool IsAuthenticated { get; set; }
|
||||||
public string NameClaimType { get; set; }
|
public string NameClaimType { get; set; } = string.Empty;
|
||||||
public string RoleClaimType { get; set; }
|
public string RoleClaimType { get; set; } = string.Empty;
|
||||||
public IEnumerable<ClaimValue> Claims { get; set; }
|
public IEnumerable<ClaimValue> Claims { get; set; } = new List<ClaimValue>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ public class AuthenticateEndpoint : EndpointBaseAsync
|
|||||||
OperationId = "auth.authenticate",
|
OperationId = "auth.authenticate",
|
||||||
Tags = new[] { "AuthEndpoints" })
|
Tags = new[] { "AuthEndpoints" })
|
||||||
]
|
]
|
||||||
public override async Task<ActionResult<AuthenticateResponse>> HandleAsync(AuthenticateRequest request, CancellationToken cancellationToken = default)
|
public override async Task<ActionResult<AuthenticateResponse>> HandleAsync(AuthenticateRequest request,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var response = new AuthenticateResponse(request.CorrelationId());
|
var response = new AuthenticateResponse(request.CorrelationId());
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
public class ListPagedCatalogItemRequest : BaseRequest
|
public class ListPagedCatalogItemRequest : BaseRequest
|
||||||
{
|
{
|
||||||
public int? PageSize { get; init; }
|
public int PageSize { get; init; }
|
||||||
public int? PageIndex { get; init; }
|
public int PageIndex { get; init; }
|
||||||
public int? CatalogBrandId { get; init; }
|
public int? CatalogBrandId { get; init; }
|
||||||
public int? CatalogTypeId { get; init; }
|
public int? CatalogTypeId { get; init; }
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogI
|
|||||||
int totalItems = await itemRepository.CountAsync(filterSpec);
|
int totalItems = await itemRepository.CountAsync(filterSpec);
|
||||||
|
|
||||||
var pagedSpec = new CatalogFilterPaginatedSpecification(
|
var pagedSpec = new CatalogFilterPaginatedSpecification(
|
||||||
skip: request.PageIndex.Value * request.PageSize.Value,
|
skip: request.PageIndex * request.PageSize,
|
||||||
take: request.PageSize.Value,
|
take: request.PageSize,
|
||||||
brandId: request.CatalogBrandId,
|
brandId: request.CatalogBrandId,
|
||||||
typeId: request.CatalogTypeId);
|
typeId: request.CatalogTypeId);
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public class CatalogItemListPagedEndpoint : IEndpoint<IResult, ListPagedCatalogI
|
|||||||
|
|
||||||
if (request.PageSize > 0)
|
if (request.PageSize > 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
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ public class UpdateCatalogItemEndpoint : IEndpoint<IResult, UpdateCatalogItemReq
|
|||||||
var response = new UpdateCatalogItemResponse(request.CorrelationId());
|
var response = new UpdateCatalogItemResponse(request.CorrelationId());
|
||||||
|
|
||||||
var existingItem = await itemRepository.GetByIdAsync(request.Id);
|
var existingItem = await itemRepository.GetByIdAsync(request.Id);
|
||||||
|
if (existingItem == null)
|
||||||
|
{
|
||||||
|
return Results.NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
CatalogItem.CatalogItemDetails details = new(request.Name, request.Description, request.Price);
|
CatalogItem.CatalogItemDetails details = new(request.Name, request.Description, request.Price);
|
||||||
existingItem.UpdateDetails(details);
|
existingItem.UpdateDetails(details);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using BlazorShared;
|
using BlazorShared;
|
||||||
using BlazorShared.Models;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@@ -41,7 +40,8 @@ builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
|
|||||||
builder.Services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
|
builder.Services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>));
|
||||||
builder.Services.AddScoped(typeof(IReadRepository<>), typeof(EfRepository<>));
|
builder.Services.AddScoped(typeof(IReadRepository<>), typeof(EfRepository<>));
|
||||||
builder.Services.Configure<CatalogSettings>(builder.Configuration);
|
builder.Services.Configure<CatalogSettings>(builder.Configuration);
|
||||||
builder.Services.AddSingleton<IUriComposer>(new UriComposer(builder.Configuration.Get<CatalogSettings>()));
|
var catalogSettings = builder.Configuration.Get<CatalogSettings>() ?? new CatalogSettings();
|
||||||
|
builder.Services.AddSingleton<IUriComposer>(new UriComposer(catalogSettings));
|
||||||
builder.Services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
builder.Services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||||
builder.Services.AddScoped<ITokenClaimsService, IdentityTokenClaimService>();
|
builder.Services.AddScoped<ITokenClaimsService, IdentityTokenClaimService>();
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ builder.Services.AddCors(options =>
|
|||||||
options.AddPolicy(name: CORS_POLICY,
|
options.AddPolicy(name: CORS_POLICY,
|
||||||
corsPolicyBuilder =>
|
corsPolicyBuilder =>
|
||||||
{
|
{
|
||||||
corsPolicyBuilder.WithOrigins(baseUrlConfig.WebBase.Replace("host.docker.internal", "localhost").TrimEnd('/'));
|
corsPolicyBuilder.WithOrigins(baseUrlConfig!.WebBase.Replace("host.docker.internal", "localhost").TrimEnd('/'));
|
||||||
corsPolicyBuilder.AllowAnyMethod();
|
corsPolicyBuilder.AllowAnyMethod();
|
||||||
corsPolicyBuilder.AllowAnyHeader();
|
corsPolicyBuilder.AllowAnyHeader();
|
||||||
});
|
});
|
||||||
@@ -172,12 +172,9 @@ app.UseSwaggerUI(c =>
|
|||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.MapControllers();
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.MapEndpoints();
|
app.MapEndpoints();
|
||||||
|
|
||||||
app.Logger.LogInformation("LAUNCHING PublicApi");
|
app.Logger.LogInformation("LAUNCHING PublicApi");
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class LoginModel : PageModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BindProperty]
|
[BindProperty]
|
||||||
public InputModel? Input { get; set; }
|
public required InputModel Input { get; set; }
|
||||||
|
|
||||||
public IList<AuthenticationScheme>? ExternalLogins { get; set; }
|
public IList<AuthenticationScheme>? ExternalLogins { get; set; }
|
||||||
|
|
||||||
@@ -74,7 +74,8 @@ public class LoginModel : PageModel
|
|||||||
// This doesn't count login failures towards account lockout
|
// This doesn't count login failures towards account lockout
|
||||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
// 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, 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)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class RegisterModel : PageModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BindProperty]
|
[BindProperty]
|
||||||
public InputModel? Input { get; set; }
|
public required InputModel Input { get; set; }
|
||||||
|
|
||||||
public string? ReturnUrl { get; set; }
|
public string? ReturnUrl { get; set; }
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ public class RegisterModel : PageModel
|
|||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var user = new ApplicationUser { UserName = Input?.Email, Email = Input?.Email };
|
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)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("User created a new account with password.");
|
_logger.LogInformation("User created a new account with password.");
|
||||||
@@ -82,7 +82,7 @@ public class RegisterModel : PageModel
|
|||||||
protocol: Request.Scheme);
|
protocol: Request.Scheme);
|
||||||
|
|
||||||
Guard.Against.Null(callbackUrl, nameof(callbackUrl));
|
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 <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
|
||||||
|
|
||||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ using Microsoft.eShopWeb.Infrastructure.Data;
|
|||||||
using Microsoft.eShopWeb.Infrastructure.Data.Queries;
|
using Microsoft.eShopWeb.Infrastructure.Data.Queries;
|
||||||
using Microsoft.eShopWeb.Infrastructure.Logging;
|
using Microsoft.eShopWeb.Infrastructure.Logging;
|
||||||
using Microsoft.eShopWeb.Infrastructure.Services;
|
using Microsoft.eShopWeb.Infrastructure.Services;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Web.Configuration;
|
namespace Microsoft.eShopWeb.Web.Configuration;
|
||||||
|
|
||||||
@@ -20,7 +18,10 @@ public static class ConfigureCoreServices
|
|||||||
services.AddScoped<IBasketService, BasketService>();
|
services.AddScoped<IBasketService, BasketService>();
|
||||||
services.AddScoped<IOrderService, OrderService>();
|
services.AddScoped<IOrderService, OrderService>();
|
||||||
services.AddScoped<IBasketQueryService, BasketQueryService>();
|
services.AddScoped<IBasketQueryService, BasketQueryService>();
|
||||||
services.AddSingleton<IUriComposer>(new UriComposer(configuration.Get<CatalogSettings>()));
|
|
||||||
|
var catalogSettings = configuration.Get<CatalogSettings>() ?? new CatalogSettings();
|
||||||
|
services.AddSingleton<IUriComposer>(new UriComposer(catalogSettings));
|
||||||
|
|
||||||
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||||
services.AddTransient<IEmailSender, EmailSender>();
|
services.AddTransient<IEmailSender, EmailSender>();
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ public class ManageController : Controller
|
|||||||
var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
|
var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
|
||||||
Guard.Against.Null(callbackUrl, nameof(callbackUrl));
|
Guard.Against.Null(callbackUrl, nameof(callbackUrl));
|
||||||
var email = user.Email;
|
var email = user.Email;
|
||||||
|
if (email == null)
|
||||||
|
{
|
||||||
|
throw new ApplicationException($"No email associated with user {user.UserName}'.");
|
||||||
|
}
|
||||||
|
|
||||||
await _emailSender.SendEmailConfirmationAsync(email, callbackUrl);
|
await _emailSender.SendEmailConfirmationAsync(email, callbackUrl);
|
||||||
|
|
||||||
StatusMessage = "Verification email sent. Please check your email.";
|
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)}'.");
|
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)
|
if (!changePasswordResult.Succeeded)
|
||||||
{
|
{
|
||||||
AddErrors(changePasswordResult);
|
AddErrors(changePasswordResult);
|
||||||
@@ -211,7 +217,7 @@ public class ManageController : Controller
|
|||||||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
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)
|
if (!addPasswordResult.Succeeded)
|
||||||
{
|
{
|
||||||
AddErrors(addPasswordResult);
|
AddErrors(addPasswordResult);
|
||||||
@@ -293,6 +299,10 @@ public class ManageController : Controller
|
|||||||
{
|
{
|
||||||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
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);
|
var result = await _userManager.RemoveLoginAsync(user, model.LoginProvider, model.ProviderKey);
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
@@ -407,7 +417,7 @@ public class ManageController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Strip spaces and hypens
|
// 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(
|
var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync(
|
||||||
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
|
user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);
|
||||||
@@ -421,7 +431,7 @@ public class ManageController : Controller
|
|||||||
|
|
||||||
await _userManager.SetTwoFactorEnabledAsync(user, true);
|
await _userManager.SetTwoFactorEnabledAsync(user, true);
|
||||||
_logger.LogInformation("User with ID {UserId} has enabled 2FA with an authenticator app.", user.Id);
|
_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<string>();
|
||||||
TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
|
TempData[RecoveryCodesKey] = recoveryCodes.ToArray();
|
||||||
|
|
||||||
return RedirectToAction(nameof(ShowRecoveryCodes));
|
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.");
|
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<string>();
|
||||||
_logger.LogInformation("User with ID {UserId} has generated new 2FA recovery codes.", user.Id);
|
_logger.LogInformation("User with ID {UserId} has generated new 2FA recovery codes.", user.Id);
|
||||||
|
|
||||||
var model = new ShowRecoveryCodesViewModel { RecoveryCodes = recoveryCodes.ToArray() };
|
var model = new ShowRecoveryCodesViewModel { RecoveryCodes = recoveryCodes.ToArray() };
|
||||||
@@ -533,8 +543,8 @@ public class ManageController : Controller
|
|||||||
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
model.SharedKey = FormatKey(unformattedKey);
|
model.SharedKey = FormatKey(unformattedKey!);
|
||||||
model.AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey);
|
model.AuthenticatorUri = GenerateQrCodeUri(user.Email!, unformattedKey!);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class IndexModel : PageModel
|
|||||||
_catalogViewModelService = catalogViewModelService;
|
_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)
|
public async Task OnGet(CatalogIndexViewModel catalogModel, int? pageId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ var baseUrlConfig = configSection.Get<BaseUrlConfiguration>();
|
|||||||
// Blazor Admin Required Services for Prerendering
|
// Blazor Admin Required Services for Prerendering
|
||||||
builder.Services.AddScoped<HttpClient>(s => new HttpClient
|
builder.Services.AddScoped<HttpClient>(s => new HttpClient
|
||||||
{
|
{
|
||||||
BaseAddress = new Uri(baseUrlConfig.WebBase)
|
BaseAddress = new Uri(baseUrlConfig!.WebBase)
|
||||||
});
|
});
|
||||||
|
|
||||||
// add blazor services
|
// add blazor services
|
||||||
@@ -171,15 +171,13 @@ app.UseCookiePolicy();
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
app.MapControllerRoute("default", "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
|
||||||
endpoints.MapControllerRoute("default", "{controller:slugify=Home}/{action:slugify=Index}/{id?}");
|
app.MapRazorPages();
|
||||||
endpoints.MapRazorPages();
|
app.MapHealthChecks("home_page_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("homePageHealthCheck") });
|
||||||
endpoints.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.MapHealthChecks("api_health_check", new HealthCheckOptions { Predicate = check => check.Tags.Contains("apiHealthCheck") });
|
//endpoints.MapBlazorHub("/admin");
|
||||||
//endpoints.MapBlazorHub("/admin");
|
app.MapFallbackToFile("index.html");
|
||||||
endpoints.MapFallbackToFile("index.html");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.Logger.LogInformation("LAUNCHING");
|
app.Logger.LogInformation("LAUNCHING");
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|||||||
@@ -21,30 +21,30 @@ public class CachedCatalogViewModelService : ICatalogViewModelService
|
|||||||
|
|
||||||
public async Task<IEnumerable<SelectListItem>> GetBrands()
|
public async Task<IEnumerable<SelectListItem>> GetBrands()
|
||||||
{
|
{
|
||||||
return await _cache.GetOrCreateAsync(CacheHelpers.GenerateBrandsCacheKey(), async entry =>
|
return (await _cache.GetOrCreateAsync(CacheHelpers.GenerateBrandsCacheKey(), async entry =>
|
||||||
{
|
{
|
||||||
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
|
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
|
||||||
return await _catalogViewModelService.GetBrands();
|
return await _catalogViewModelService.GetBrands();
|
||||||
});
|
})) ?? new List<SelectListItem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId)
|
public async Task<CatalogIndexViewModel> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId)
|
||||||
{
|
{
|
||||||
var cacheKey = CacheHelpers.GenerateCatalogItemCacheKey(pageIndex, Constants.ITEMS_PER_PAGE, brandId, 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;
|
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
|
||||||
return await _catalogViewModelService.GetCatalogItems(pageIndex, itemsPage, brandId, typeId);
|
return await _catalogViewModelService.GetCatalogItems(pageIndex, itemsPage, brandId, typeId);
|
||||||
});
|
})) ?? new CatalogIndexViewModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<SelectListItem>> GetTypes()
|
public async Task<IEnumerable<SelectListItem>> GetTypes()
|
||||||
{
|
{
|
||||||
return await _cache.GetOrCreateAsync(CacheHelpers.GenerateTypesCacheKey(), async entry =>
|
return (await _cache.GetOrCreateAsync(CacheHelpers.GenerateTypesCacheKey(), async entry =>
|
||||||
{
|
{
|
||||||
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
|
entry.SlidingExpiration = CacheHelpers.DefaultCacheDuration;
|
||||||
return await _catalogViewModelService.GetTypes();
|
return await _catalogViewModelService.GetTypes();
|
||||||
});
|
})) ?? new List<SelectListItem>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Web.ViewModels;
|
namespace Microsoft.eShopWeb.Web.ViewModels;
|
||||||
|
|
||||||
public class CatalogIndexViewModel
|
public class CatalogIndexViewModel
|
||||||
{
|
{
|
||||||
public List<CatalogItemViewModel>? CatalogItems { get; set; }
|
public List<CatalogItemViewModel> CatalogItems { get; set; } = new List<CatalogItemViewModel>();
|
||||||
public List<SelectListItem>? Brands { get; set; }
|
public List<SelectListItem>? Brands { get; set; } = new List<SelectListItem>();
|
||||||
public List<SelectListItem>? Types { get; set; }
|
public List<SelectListItem>? Types { get; set; } = new List<SelectListItem>();
|
||||||
public int? BrandFilterApplied { get; set; }
|
public int? BrandFilterApplied { get; set; }
|
||||||
public int? TypesFilterApplied { get; set; }
|
public int? TypesFilterApplied { get; set; }
|
||||||
public PaginationInfoViewModel? PaginationInfo { get; set; }
|
public PaginationInfoViewModel? PaginationInfo { get; set; }
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
namespace Microsoft.eShopWeb.Web.ViewModels.Manage;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopWeb.Web.ViewModels.Manage;
|
||||||
|
|
||||||
public class RemoveLoginViewModel
|
public class RemoveLoginViewModel
|
||||||
{
|
{
|
||||||
public string? LoginProvider { get; set; }
|
[Required]
|
||||||
public string? ProviderKey { get; set; }
|
public string LoginProvider { get; set; } = string.Empty;
|
||||||
|
[Required]
|
||||||
|
public string ProviderKey { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities.OrderAggregate;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Web.ViewModels;
|
namespace Microsoft.eShopWeb.Web.ViewModels;
|
||||||
|
|
||||||
@@ -13,5 +11,5 @@ public class OrderViewModel
|
|||||||
public decimal Total { get; set; }
|
public decimal Total { get; set; }
|
||||||
public string Status => DEFAULT_STATUS;
|
public string Status => DEFAULT_STATUS;
|
||||||
public Address? ShippingAddress { get; set; }
|
public Address? ShippingAddress { get; set; }
|
||||||
public List<OrderItemViewModel> OrderItems { get; set; } = new List<OrderItemViewModel>();
|
public List<OrderItemViewModel> OrderItems { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
@if (Model.RecoveryCodes != null)
|
||||||
|
{
|
||||||
@for (var row = 0; row < Model.RecoveryCodes.Length; row += 2)
|
@for (var row = 0; row < Model.RecoveryCodes.Length; row += 2)
|
||||||
{
|
{
|
||||||
<code>@Model.RecoveryCodes[row]</code><text> </text><code>@Model.RecoveryCodes[row + 1]</code><br />
|
<code>@Model.RecoveryCodes[row]</code><text> </text><code>@Model.RecoveryCodes[row + 1]</code><br />
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
© 2021 GitHub, Inc.
|
© 2023 GitHub, Inc.
|
||||||
@@ -30,15 +30,15 @@
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="esh-orders-detail-items row">
|
<article class="esh-orders-detail-items row">
|
||||||
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress.Street</section>
|
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress?.Street</section>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="esh-orders-detail-items row">
|
<article class="esh-orders-detail-items row">
|
||||||
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress.City</section>
|
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress?.City</section>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="esh-orders-detail-items row">
|
<article class="esh-orders-detail-items row">
|
||||||
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress.Country</section>
|
<section class="esh-orders-detail-item col-xs-12">@Model.ShippingAddress?.Country</section>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@if (Context.User.Identity.IsAuthenticated)
|
@if (Context!.User!.Identity!.IsAuthenticated)
|
||||||
{
|
{
|
||||||
<section class="col-lg-4 col-md-5 col-xs-12">
|
<section class="col-lg-4 col-md-5 col-xs-12">
|
||||||
<div class="esh-identity">
|
<div class="esh-identity">
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class OrderIndexOnGet : IClassFixture<TestApplication>
|
|||||||
public async Task ReturnsRedirectGivenAnonymousUser()
|
public async Task ReturnsRedirectGivenAnonymousUser()
|
||||||
{
|
{
|
||||||
var response = await Client.GetAsync("/order/my-orders");
|
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.Equal(HttpStatusCode.Redirect, response.StatusCode);
|
||||||
Assert.Contains("/Account/Login", redirectLocation);
|
Assert.Contains("/Account/Login", redirectLocation);
|
||||||
|
|||||||
@@ -45,6 +45,6 @@ public class BasketPageCheckout : IClassFixture<TestApplication>
|
|||||||
|
|
||||||
formContent = new FormUrlEncodedContent(keyValues);
|
formContent = new FormUrlEncodedContent(keyValues);
|
||||||
var postResponse2 = await Client.PostAsync("/Basket/Checkout", formContent);
|
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()!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class CheckoutTest : IClassFixture<TestApplication>
|
|||||||
var checkOutResponse = await Client.PostAsync("/basket/checkout", checkOutContent);
|
var checkOutResponse = await Client.PostAsync("/basket/checkout", checkOutContent);
|
||||||
var stringCheckOutResponse = await checkOutResponse.Content.ReadAsStringAsync();
|
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);
|
Assert.Contains("Thanks for your Order!", stringCheckOutResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class IndexTest : IClassFixture<TestApplication>
|
|||||||
|
|
||||||
var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync();
|
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;
|
decimal expectedTotalAmount = 416.50M;
|
||||||
Assert.Contains(expectedTotalAmount.ToString("N2"), stringUpdateResponse);
|
Assert.Contains(expectedTotalAmount.ToString("N2"), stringUpdateResponse);
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ public class IndexTest : IClassFixture<TestApplication>
|
|||||||
|
|
||||||
var stringUpdateResponse = await updateResponse.Content.ReadAsStringAsync();
|
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);
|
Assert.Contains("Basket is empty", stringUpdateResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,6 @@ public static class WebPageHelpers
|
|||||||
{
|
{
|
||||||
var regex = new Regex(regexpression);
|
var regex = new Regex(regexpression);
|
||||||
var match = regex.Match(input);
|
var match = regex.Match(input);
|
||||||
return match.Groups.Values.LastOrDefault().Value;
|
return match!.Groups!.Values!.LastOrDefault()!.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ using Microsoft.eShopWeb.ApplicationCore.Constants;
|
|||||||
using Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
using Microsoft.eShopWeb.PublicApi.AuthEndpoints;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests.AuthEndpoints
|
namespace PublicApiIntegrationTests.AuthEndpoints;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class AuthenticateEndpoint
|
||||||
{
|
{
|
||||||
[TestClass]
|
|
||||||
public class AuthenticateEndpoint
|
|
||||||
{
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
[DataRow("demouser@microsoft.com", AuthorizationConstants.DEFAULT_PASSWORD, true)]
|
[DataRow("demouser@microsoft.com", AuthorizationConstants.DEFAULT_PASSWORD, true)]
|
||||||
[DataRow("demouser@microsoft.com", "badpassword", false)]
|
[DataRow("demouser@microsoft.com", "badpassword", false)]
|
||||||
@@ -29,7 +29,6 @@ namespace PublicApiIntegrationTests.AuthEndpoints
|
|||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<AuthenticateResponse>();
|
var model = stringResponse.FromJson<AuthenticateResponse>();
|
||||||
|
|
||||||
Assert.AreEqual(expectedResult, model.Result);
|
Assert.AreEqual(expectedResult, model!.Result);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
namespace PublicApiIntegrationTests.CatalogItemEndpoints;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class CatalogItemGetByIdEndpointTest
|
||||||
{
|
{
|
||||||
[TestClass]
|
|
||||||
public class CatalogItemGetByIdEndpointTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task ReturnsItemGivenValidId()
|
public async Task ReturnsItemGivenValidId()
|
||||||
{
|
{
|
||||||
@@ -17,7 +17,7 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<GetByIdCatalogItemResponse>();
|
var model = stringResponse.FromJson<GetByIdCatalogItemResponse>();
|
||||||
|
|
||||||
Assert.AreEqual(5, model.CatalogItem.Id);
|
Assert.AreEqual(5, model!.CatalogItem.Id);
|
||||||
Assert.AreEqual("Roslyn Red Sheet", model.CatalogItem.Name);
|
Assert.AreEqual("Roslyn Red Sheet", model.CatalogItem.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,5 +28,4 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
|
|
||||||
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ using System.Net.Http;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
namespace PublicApiIntegrationTests.CatalogItemEndpoints;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class CatalogItemListPagedEndpoint
|
||||||
{
|
{
|
||||||
[TestClass]
|
|
||||||
public class CatalogItemListPagedEndpoint
|
|
||||||
{
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task ReturnsFirst10CatalogItems()
|
public async Task ReturnsFirst10CatalogItems()
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,7 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<CatalogIndexViewModel>();
|
var model = stringResponse.FromJson<CatalogIndexViewModel>();
|
||||||
|
|
||||||
Assert.AreEqual(10, model.CatalogItems.Count());
|
Assert.AreEqual(10, model!.CatalogItems.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -37,7 +37,7 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<ListPagedCatalogItemResponse>();
|
var model = stringResponse.FromJson<ListPagedCatalogItemResponse>();
|
||||||
var totalItem = model.CatalogItems.Count();
|
var totalItem = model!.CatalogItems.Count();
|
||||||
|
|
||||||
var response2 = await client.GetAsync($"/api/catalog-items?pageSize={pageSize}&pageIndex={pageIndex}");
|
var response2 = await client.GetAsync($"/api/catalog-items?pageSize={pageSize}&pageIndex={pageIndex}");
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
@@ -46,7 +46,7 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
|
|
||||||
var totalExpected = totalItem - (pageSize * pageIndex);
|
var totalExpected = totalItem - (pageSize * pageIndex);
|
||||||
|
|
||||||
Assert.AreEqual(totalExpected, model2.CatalogItems.Count());
|
Assert.AreEqual(totalExpected, model2!.CatalogItems.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataTestMethod]
|
[DataTestMethod]
|
||||||
@@ -69,5 +69,4 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
|
|
||||||
Assert.AreEqual(0, totalKO);
|
Assert.AreEqual(0, totalKO);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ using System.Text;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests.AuthEndpoints
|
namespace PublicApiIntegrationTests.AuthEndpoints;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class CreateCatalogItemEndpointTest
|
||||||
{
|
{
|
||||||
[TestClass]
|
|
||||||
public class CreateCatalogItemEndpointTest
|
|
||||||
{
|
|
||||||
private int _testBrandId = 1;
|
private int _testBrandId = 1;
|
||||||
private int _testTypeId = 2;
|
private int _testTypeId = 2;
|
||||||
private string _testDescription = "test description";
|
private string _testDescription = "test description";
|
||||||
@@ -44,7 +44,7 @@ namespace PublicApiIntegrationTests.AuthEndpoints
|
|||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<CreateCatalogItemResponse>();
|
var model = stringResponse.FromJson<CreateCatalogItemResponse>();
|
||||||
|
|
||||||
Assert.AreEqual(_testBrandId, model.CatalogItem.CatalogBrandId);
|
Assert.AreEqual(_testBrandId, model!.CatalogItem.CatalogBrandId);
|
||||||
Assert.AreEqual(_testTypeId, model.CatalogItem.CatalogTypeId);
|
Assert.AreEqual(_testTypeId, model.CatalogItem.CatalogTypeId);
|
||||||
Assert.AreEqual(_testDescription, model.CatalogItem.Description);
|
Assert.AreEqual(_testDescription, model.CatalogItem.Description);
|
||||||
Assert.AreEqual(_testName, model.CatalogItem.Name);
|
Assert.AreEqual(_testName, model.CatalogItem.Name);
|
||||||
@@ -65,5 +65,4 @@ namespace PublicApiIntegrationTests.AuthEndpoints
|
|||||||
|
|
||||||
return jsonContent;
|
return jsonContent;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ using System.Net;
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
namespace PublicApiIntegrationTests.CatalogItemEndpoints;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class DeleteCatalogItemEndpointTest
|
||||||
{
|
{
|
||||||
[TestClass]
|
|
||||||
public class DeleteCatalogItemEndpointTest
|
|
||||||
{
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task ReturnsSuccessGivenValidIdAndAdminUserToken()
|
public async Task ReturnsSuccessGivenValidIdAndAdminUserToken()
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,7 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||||
var model = stringResponse.FromJson<DeleteCatalogItemResponse>();
|
var model = stringResponse.FromJson<DeleteCatalogItemResponse>();
|
||||||
|
|
||||||
Assert.AreEqual("Deleted", model.Status);
|
Assert.AreEqual("Deleted", model!.Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -34,5 +34,4 @@ namespace PublicApiIntegrationTests.CatalogItemEndpoints
|
|||||||
|
|
||||||
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace PublicApiIntegrationTests
|
namespace PublicApiIntegrationTests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public class ProgramTest
|
||||||
{
|
{
|
||||||
[TestClass]
|
private static WebApplicationFactory<Program> _application = new();
|
||||||
public class ProgramTest
|
|
||||||
{
|
|
||||||
private static WebApplicationFactory<Program> _application;
|
|
||||||
|
|
||||||
public static HttpClient NewClient
|
public static HttpClient NewClient
|
||||||
{
|
{
|
||||||
@@ -23,5 +23,4 @@ namespace PublicApiIntegrationTests
|
|||||||
_application = new WebApplicationFactory<Program>();
|
_application = new WebApplicationFactory<Program>();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user