Browse Source

Merge branch 'EFCliAndSeeders' into dev

pull/335/head
Unai Zorrilla Castro 7 years ago
parent
commit
a7f51e7d65
71 changed files with 548 additions and 634 deletions
  1. +60
    -3
      eShopOnContainers.sln
  2. +11
    -0
      src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj
  3. +40
    -0
      src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs
  4. +1
    -0
      src/Services/Catalog/Catalog.API/Catalog.API.csproj
  5. +62
    -60
      src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs
  6. +18
    -2
      src/Services/Catalog/Catalog.API/Program.cs
  7. +7
    -42
      src/Services/Catalog/Catalog.API/Startup.cs
  8. +2
    -6
      src/Services/Identity/Identity.API/AppSettings.cs
  9. +2
    -5
      src/Services/Identity/Identity.API/Certificate/Certificate.cs
  10. +1
    -1
      src/Services/Identity/Identity.API/Configuration/Config.cs
  11. +6
    -9
      src/Services/Identity/Identity.API/Controllers/AccountController.cs
  12. +4
    -10
      src/Services/Identity/Identity.API/Controllers/ConsentController.cs
  13. +4
    -8
      src/Services/Identity/Identity.API/Controllers/HomeController.cs
  14. +3
    -3
      src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs
  15. +37
    -51
      src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs
  16. +56
    -0
      src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs
  17. +1
    -1
      src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs
  18. +1
    -0
      src/Services/Identity/Identity.API/Identity.API.csproj
  19. +1
    -3
      src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.Designer.cs
  20. +1
    -4
      src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs
  21. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs
  22. +2
    -4
      src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentViewModel.cs
  23. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs
  24. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs
  25. +1
    -5
      src/Services/Identity/Identity.API/Models/AccountViewModels/LoggedOutViewModel.cs
  26. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs
  27. +1
    -5
      src/Services/Identity/Identity.API/Models/AccountViewModels/LogoutViewModel.cs
  28. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs
  29. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs
  30. +2
    -5
      src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs
  31. +2
    -6
      src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs
  32. +0
    -20
      src/Services/Identity/Identity.API/Models/AccountViewModels/_LoginViewModel.cs
  33. +1
    -1
      src/Services/Identity/Identity.API/Models/ApplicationUser.cs
  34. +1
    -1
      src/Services/Identity/Identity.API/Models/ErrorViewModel.cs
  35. +2
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs
  36. +2
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs
  37. +2
    -5
      src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs
  38. +1
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/FactorViewModel.cs
  39. +2
    -5
      src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs
  40. +3
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/ManageLoginsViewModel.cs
  41. +1
    -7
      src/Services/Identity/Identity.API/Models/ManageViewModels/RemoveLoginViewModel.cs
  42. +2
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs
  43. +2
    -6
      src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs
  44. +27
    -4
      src/Services/Identity/Identity.API/Program.cs
  45. +3
    -6
      src/Services/Identity/Identity.API/Services/EFLoginService.cs
  46. +2
    -5
      src/Services/Identity/Identity.API/Services/IEmailSender.cs
  47. +2
    -5
      src/Services/Identity/Identity.API/Services/ILoginService.cs
  48. +1
    -6
      src/Services/Identity/Identity.API/Services/IRedirectService.cs
  49. +2
    -5
      src/Services/Identity/Identity.API/Services/ISmsSender.cs
  50. +2
    -5
      src/Services/Identity/Identity.API/Services/MessageServices.cs
  51. +7
    -7
      src/Services/Identity/Identity.API/Services/ProfileService.cs
  52. +2
    -6
      src/Services/Identity/Identity.API/Services/RedirectService.cs
  53. +5
    -71
      src/Services/Identity/Identity.API/Startup.cs
  54. +1
    -1
      src/Services/Identity/Identity.API/Views/Account/LoggedOut.cshtml
  55. +1
    -1
      src/Services/Identity/Identity.API/Views/Account/Login.cshtml
  56. +1
    -1
      src/Services/Identity/Identity.API/Views/Account/Logout.cshtml
  57. +1
    -2
      src/Services/Identity/Identity.API/Views/Account/Register.cshtml
  58. +1
    -1
      src/Services/Identity/Identity.API/Views/Consent/Index.cshtml
  59. +1
    -1
      src/Services/Identity/Identity.API/Views/Consent/_ScopeListItem.cshtml
  60. +1
    -1
      src/Services/Identity/Identity.API/Views/Shared/Error.cshtml
  61. +27
    -14
      src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs
  62. +3
    -0
      src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs
  63. +1
    -0
      src/Services/Marketing/Marketing.API/Marketing.API.csproj
  64. +12
    -1
      src/Services/Marketing/Marketing.API/Program.cs
  65. +1
    -30
      src/Services/Marketing/Marketing.API/Startup.cs
  66. +57
    -43
      src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs
  67. +0
    -29
      src/Services/Ordering/Ordering.API/Infrastructure/OrderingDbContextDesigner.cs
  68. +1
    -0
      src/Services/Ordering/Ordering.API/Ordering.API.csproj
  69. +18
    -1
      src/Services/Ordering/Ordering.API/Program.cs
  70. +9
    -36
      src/Services/Ordering/Ordering.API/Startup.cs
  71. +2
    -8
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs

+ 60
- 3
eShopOnContainers.sln View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.8
VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}"
ProjectSection(ProjectDependencies) = postProject
@ -60,7 +60,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSPA", "src\Web\WebSPA\We
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mobile Apps", "Mobile Apps", "{B7B1D395-4E06-4036-BE86-C216756B9367}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{F7B6A162-BC4D-4924-B16A-713F9B0344E7}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.UnitTests", "src\Mobile\eShopOnContainers\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj", "{F7B6A162-BC4D-4924-B16A-713F9B0344E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.TestRunner.Droid", "src\Mobile\eShopOnContainers\eShopOnContainers.TestRunner.Droid\eShopOnContainers.TestRunner.Droid.csproj", "{A289A7F0-ACD8-42AE-87B6-AB1AFD310BF1}"
EndProject
@ -76,7 +76,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "test\Se
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.UITests", "src\Mobile\eShopOnContainers\eShopOnContainers.UITests\eShopOnContainers.UITests.csproj", "{E3B18084-842C-4B80-8E4A-A7E588EC3137}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "eShopOnContainers.Core", "src\Mobile\eShopOnContainers\eShopOnContainers.Core\eShopOnContainers.Core.csproj", "{67F9D3A8-F71E-4428-913F-C37AE82CDB24}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
EndProject
@ -132,6 +132,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Payment", "Payment", "{D5D3
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payment.API", "src\Services\Payment\Payment.API\Payment.API.csproj", "{2A795FEA-2EB7-45F5-9B30-35E0810CB238}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebHost", "WebHost", "{3E51A82A-5DE1-482E-BA46-F4FF3138B41A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebHost.Customization", "src\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj", "{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@ -1877,6 +1881,54 @@ Global
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x64.Build.0 = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x86.ActiveCfg = Release|Any CPU
{2A795FEA-2EB7-45F5-9B30-35E0810CB238}.Release|x86.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|ARM.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|ARM.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhone.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x64.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x64.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x86.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.AppStore|x86.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|ARM.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|ARM.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhone.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x64.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x64.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x86.ActiveCfg = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Debug|x86.Build.0 = Debug|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|Any CPU.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|ARM.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|ARM.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhone.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhone.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x64.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x64.Build.0 = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x86.ActiveCfg = Release|Any CPU
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1937,5 +1989,10 @@ Global
{6C6A69FE-A484-4E75-AFEC-827EA354AF46} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}
{D5D3841D-F282-4E60-B9CB-267A1BF2D893} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8}
{2A795FEA-2EB7-45F5-9B30-35E0810CB238} = {D5D3841D-F282-4E60-B9CB-267A1BF2D893}
{3E51A82A-5DE1-482E-BA46-F4FF3138B41A} = {1EF3AC0F-F27C-46DD-AC53-D762D2C11C45}
{BF6AF4F9-684A-4EB3-8CF2-230AA2A03F98} = {3E51A82A-5DE1-482E-BA46-F4FF3138B41A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A6439048-F270-4A9E-A350-63C7BE2BB322}
EndGlobalSection
EndGlobal

+ 11
- 0
src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />
</ItemGroup>
</Project>

+ 40
- 0
src/BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHostExtensions.cs View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
namespace Microsoft.AspNetCore.Hosting
{
public static class IWebHostExtensions
{
public static IWebHost MigrateDbContext<TContext>(this IWebHost webHost, Action<TContext,IServiceProvider> seeder) where TContext : DbContext
{
using (var scope = webHost.Services.CreateScope())
{
var services = scope.ServiceProvider;
var logger = services.GetRequiredService<ILogger<TContext>>();
var context = services.GetService<TContext>();
try
{
logger.LogInformation($"Migrating database associated with context {typeof(TContext).Name}");
context.Database
.Migrate();
seeder(context,services);
logger.LogInformation($"Migrated database associated with context {typeof(TContext).Name}");
}
catch (Exception ex)
{
logger.LogError(ex, $"An error occurred while migrating the database used on context {typeof(TContext).Name}");
}
}
return webHost;
}
}
}

+ 1
- 0
src/Services/Catalog/Catalog.API/Catalog.API.csproj View File

@ -53,6 +53,7 @@
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup>
<ItemGroup>


+ 62
- 60
src/Services/Catalog/Catalog.API/Infrastructure/CatalogContextSeed.cs View File

@ -1,15 +1,14 @@
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure
{
using EntityFrameworkCore;
using Extensions.Logging;
using global::Catalog.API.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Model;
using Polly;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.IO.Compression;
@ -19,56 +18,48 @@
public class CatalogContextSeed
{
public static async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory, int? retry = 0)
public async Task SeedAsync(CatalogContext context,IHostingEnvironment env,IOptions<CatalogSettings> settings,ILogger<CatalogContextSeed> logger)
{
var log = loggerFactory.CreateLogger("catalog seed");
var policy = CreatePolicy(logger, nameof(CatalogContextSeed));
var context = (CatalogContext)applicationBuilder
.ApplicationServices.GetService(typeof(CatalogContext));
context.Database.Migrate();
var settings = (CatalogSettings)applicationBuilder
.ApplicationServices.GetRequiredService<IOptions<CatalogSettings>>().Value;
var useCustomizationData = settings.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
var picturePath = env.WebRootPath;
if (!context.CatalogBrands.Any())
await policy.ExecuteAsync(async () =>
{
context.CatalogBrands.AddRange(useCustomizationData
? GetCatalogBrandsFromFile(contentRootPath, log)
: GetPreconfiguredCatalogBrands()
);
var useCustomizationData = settings.Value.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
var picturePath = env.WebRootPath;
await context.SaveChangesAsync();
}
if (!context.CatalogBrands.Any())
{
context.CatalogBrands.AddRange(useCustomizationData
? GetCatalogBrandsFromFile(contentRootPath, logger)
: GetPreconfiguredCatalogBrands());
if (!context.CatalogTypes.Any())
{
context.CatalogTypes.AddRange(useCustomizationData
? GetCatalogTypesFromFile(contentRootPath, log)
: GetPreconfiguredCatalogTypes()
);
await context.SaveChangesAsync();
}
await context.SaveChangesAsync();
}
if (!context.CatalogTypes.Any())
{
context.CatalogTypes.AddRange(useCustomizationData
? GetCatalogTypesFromFile(contentRootPath, logger)
: GetPreconfiguredCatalogTypes());
if (!context.CatalogItems.Any())
{
context.CatalogItems.AddRange(useCustomizationData
? GetCatalogItemsFromFile(contentRootPath, context, log)
: GetPreconfiguredItems()
);
await context.SaveChangesAsync();
}
await context.SaveChangesAsync();
if (!context.CatalogItems.Any())
{
context.CatalogItems.AddRange(useCustomizationData
? GetCatalogItemsFromFile(contentRootPath, context, logger)
: GetPreconfiguredItems());
GetCatalogItemPictures(contentRootPath, picturePath);
}
await context.SaveChangesAsync();
GetCatalogItemPictures(contentRootPath, picturePath);
}
});
}
static IEnumerable<CatalogBrand> GetCatalogBrandsFromFile(string contentRootPath, ILogger log)
private IEnumerable<CatalogBrand> GetCatalogBrandsFromFile(string contentRootPath, ILogger<CatalogContextSeed> logger)
{
string csvFileCatalogBrands = Path.Combine(contentRootPath, "Setup", "CatalogBrands.csv");
@ -85,18 +76,18 @@
}
catch (Exception ex)
{
log.LogError(ex.Message);
logger.LogError(ex.Message);
return GetPreconfiguredCatalogBrands();
}
return File.ReadAllLines(csvFileCatalogBrands)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogBrand(x))
.OnCaughtException(ex => { log.LogError(ex.Message); return null; })
.OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
static CatalogBrand CreateCatalogBrand(string brand)
private CatalogBrand CreateCatalogBrand(string brand)
{
brand = brand.Trim('"').Trim();
@ -111,7 +102,7 @@
};
}
static IEnumerable<CatalogBrand> GetPreconfiguredCatalogBrands()
private IEnumerable<CatalogBrand> GetPreconfiguredCatalogBrands()
{
return new List<CatalogBrand>()
{
@ -123,7 +114,7 @@
};
}
static IEnumerable<CatalogType> GetCatalogTypesFromFile(string contentRootPath, ILogger log)
private IEnumerable<CatalogType> GetCatalogTypesFromFile(string contentRootPath, ILogger<CatalogContextSeed> logger)
{
string csvFileCatalogTypes = Path.Combine(contentRootPath, "Setup", "CatalogTypes.csv");
@ -140,18 +131,18 @@
}
catch (Exception ex)
{
log.LogError(ex.Message);
logger.LogError(ex.Message);
return GetPreconfiguredCatalogTypes();
}
return File.ReadAllLines(csvFileCatalogTypes)
.Skip(1) // skip header row
.SelectTry(x => CreateCatalogType(x))
.OnCaughtException(ex => { log.LogError(ex.Message); return null; })
.OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
static CatalogType CreateCatalogType(string type)
private CatalogType CreateCatalogType(string type)
{
type = type.Trim('"').Trim();
@ -166,7 +157,7 @@
};
}
static IEnumerable<CatalogType> GetPreconfiguredCatalogTypes()
private IEnumerable<CatalogType> GetPreconfiguredCatalogTypes()
{
return new List<CatalogType>()
{
@ -177,7 +168,7 @@
};
}
static IEnumerable<CatalogItem> GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger log)
private IEnumerable<CatalogItem> GetCatalogItemsFromFile(string contentRootPath, CatalogContext context, ILogger<CatalogContextSeed> logger)
{
string csvFileCatalogItems = Path.Combine(contentRootPath, "Setup", "CatalogItems.csv");
@ -195,7 +186,7 @@
}
catch (Exception ex)
{
log.LogError(ex.Message);
logger.LogError(ex.Message);
return GetPreconfiguredItems();
}
@ -206,11 +197,11 @@
.Skip(1) // skip header row
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateCatalogItem(column, csvheaders, catalogTypeIdLookup, catalogBrandIdLookup))
.OnCaughtException(ex => { log.LogError(ex.Message); return null; })
.OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null);
}
static CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary<String, int> catalogTypeIdLookup, Dictionary<String, int> catalogBrandIdLookup)
private CatalogItem CreateCatalogItem(string[] column, string[] headers, Dictionary<String, int> catalogTypeIdLookup, Dictionary<String, int> catalogBrandIdLookup)
{
if (column.Count() != headers.Count())
{
@ -316,7 +307,7 @@
return catalogItem;
}
static IEnumerable<CatalogItem> GetPreconfiguredItems()
private IEnumerable<CatalogItem> GetPreconfiguredItems()
{
return new List<CatalogItem>()
{
@ -335,7 +326,7 @@
};
}
static string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null)
private string[] GetHeaders(string csvfile, string[] requiredHeaders, string[] optionalHeaders = null)
{
string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(',');
@ -363,7 +354,7 @@
return csvheaders;
}
static void GetCatalogItemPictures(string contentRootPath, string picturePath)
private void GetCatalogItemPictures(string contentRootPath, string picturePath)
{
DirectoryInfo directory = new DirectoryInfo(picturePath);
foreach (FileInfo file in directory.GetFiles())
@ -374,7 +365,18 @@
string zipFileCatalogItemPictures = Path.Combine(contentRootPath, "Setup", "CatalogItems.zip");
ZipFile.ExtractToDirectory(zipFileCatalogItemPictures, picturePath);
}
}
private Policy CreatePolicy( ILogger<CatalogContextSeed> logger, string prefix,int retries = 3)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
}
}

+ 18
- 2
src/Services/Catalog/Catalog.API/Program.cs View File

@ -1,15 +1,31 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.IO;
namespace Microsoft.eShopOnContainers.Services.Catalog.API
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
BuildWebHost(args)
.MigrateDbContext<CatalogContext>((context,services)=>
{
var env = services.GetService<IHostingEnvironment>();
var settings = services.GetService<IOptions<CatalogSettings>>();
var logger = services.GetService<ILogger<CatalogContextSeed>>();
new CatalogContextSeed()
.SeedAsync(context,env,settings,logger)
.Wait();
})
.MigrateDbContext<IntegrationEventLogContext>((_,__)=> { })
.Run();
}
public static IWebHost BuildWebHost(string[] args) =>


+ 7
- 42
src/Services/Catalog/Catalog.API/Startup.cs View File

@ -9,7 +9,6 @@
using Microsoft.Azure.ServiceBus;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
@ -24,15 +23,10 @@
using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Polly;
using RabbitMQ.Client;
using System;
using System.Data.Common;
using System.Data.SqlClient;
using System.Reflection;
using System.Threading.Tasks;
public class Startup
{
@ -85,6 +79,13 @@
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
});
services.AddDbContext<IntegrationEventLogContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionString"], opts =>
opts.MigrationsAssembly("Catalog.API"));
});
services.Configure<CatalogSettings>(Configuration);
// Add framework services.
@ -184,43 +185,7 @@
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
var context = (CatalogContext)app
.ApplicationServices.GetService(typeof(CatalogContext));
WaitForSqlAvailabilityAsync(context, loggerFactory, app, env).Wait();
ConfigureEventBus(app);
var integrationEventLogContext = new IntegrationEventLogContext(
new DbContextOptionsBuilder<IntegrationEventLogContext>()
.UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API"))
.Options);
integrationEventLogContext.Database.Migrate();
}
private async Task WaitForSqlAvailabilityAsync(CatalogContext ctx, ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env, int retries = 0)
{
var logger = loggerFactory.CreateLogger(nameof(Startup));
var policy = CreatePolicy(retries, logger, nameof(WaitForSqlAvailabilityAsync));
await policy.ExecuteAsync(async () =>
{
await CatalogContextSeed.SeedAsync(app, env, loggerFactory);
});
}
private Policy CreatePolicy(int retries, ILogger logger, string prefix)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
private void RegisterEventBus(IServiceCollection services)


+ 2
- 6
src/Services/Identity/Identity.API/AppSettings.cs View File

@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace eShopOnContainers.Identity
namespace Microsoft.eShopOnContainers.Services.Identity.API
{
public class AppSettings
{
public string MvcClient { get; set; }
public bool UseCustomizationData { get; set; }
}
}

+ 2
- 5
src/Services/Identity/Identity.API/Certificate/Certificate.cs View File

@ -1,11 +1,8 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System.IO;
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace Identity.API.Certificate
namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates
{
static class Certificate
{


+ 1
- 1
src/Services/Identity/Identity.API/Configuration/Config.cs View File

@ -2,7 +2,7 @@
using IdentityServer4.Models;
using System.Collections.Generic;
namespace Identity.API.Configuration
namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
{
public class Config
{


+ 6
- 9
src/Services/Identity/Identity.API/Controllers/AccountController.cs View File

@ -1,11 +1,5 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using Identity.API.Models;
using Identity.API.Models.AccountViewModels;
using Identity.API.Services;
using IdentityModel;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
@ -13,6 +7,9 @@ using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels;
using Microsoft.eShopOnContainers.Services.Identity.API.Services;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
@ -20,7 +17,7 @@ using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
namespace IdentityServer4.Quickstart.UI.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
/// <summary>
/// This sample controller implements a typical login/logout/provision workflow for local and external accounts.


+ 4
- 10
src/Services/Identity/Identity.API/Controllers/ConsentController.cs View File

@ -1,19 +1,13 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using IdentityServer4.Quickstart.UI.Models;
using Identity.API.Models.AccountViewModels;
using Identity.API.Services;
namespace IdentityServer4.Quickstart.UI.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
/// <summary>
/// This controller implements the consent logic


+ 4
- 8
src/Services/Identity/Identity.API/Controllers/HomeController.cs View File

@ -1,16 +1,12 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using eShopOnContainers.Identity;
using Identity.API.Services;
using IdentityServer4.Quickstart.UI.Models;

using IdentityServer4.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using Microsoft.eShopOnContainers.Services.Identity.API.Services;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
namespace IdentityServer4.Quickstart.UI.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
public class HomeController : Controller
{


+ 3
- 3
src/Services/Identity/Identity.API/Data/ApplicationDbContext.cs View File

@ -1,8 +1,8 @@
using Identity.API.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
namespace Identity.API.Data
namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{


src/Services/Identity/Identity.API/Data/ApplicationContextSeed.cs → src/Services/Identity/Identity.API/Data/ApplicationDbContextSeed.cs View File

@ -1,56 +1,40 @@
namespace Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Extensions;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
using AspNetCore.Identity;
using EntityFrameworkCore;
using Extensions.Logging;
using global::eShopOnContainers.Identity;
using global::Identity.API.Data;
using global::Identity.API.Extensions;
using global::Identity.API.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
public class ApplicationContextSeed
{
private readonly IPasswordHasher<ApplicationUser> _passwordHasher;
public ApplicationContextSeed(IPasswordHasher<ApplicationUser> passwordHasher)
{
_passwordHasher = passwordHasher;
}
public async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory, int? retry = 0)
public class ApplicationDbContextSeed
{
private readonly IPasswordHasher<ApplicationUser> _passwordHasher = new PasswordHasher<ApplicationUser>();
public async Task SeedAsync(ApplicationDbContext context,IHostingEnvironment env,
ILogger<ApplicationDbContextSeed> logger, IOptions<AppSettings> settings,int? retry = 0)
{
int retryForAvaiability = retry.Value;
try
{
var log = loggerFactory.CreateLogger("application seed");
var context = (ApplicationDbContext)applicationBuilder
.ApplicationServices.GetService(typeof(ApplicationDbContext));
context.Database.Migrate();
var settings = (AppSettings)applicationBuilder
.ApplicationServices.GetRequiredService<IOptions<AppSettings>>().Value;
var useCustomizationData = settings.UseCustomizationData;
var useCustomizationData = settings.Value.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
var webroot = env.WebRootPath;
if (!context.Users.Any())
{
context.Users.AddRange(useCustomizationData
? GetUsersFromFile(contentRootPath, log)
? GetUsersFromFile(contentRootPath, logger)
: GetDefaultUser());
await context.SaveChangesAsync();
@ -58,7 +42,7 @@
if (useCustomizationData)
{
GetPreconfiguredImages(contentRootPath, webroot, log);
GetPreconfiguredImages(contentRootPath, webroot, logger);
}
}
catch (Exception ex)
@ -66,14 +50,15 @@
if (retryForAvaiability < 10)
{
retryForAvaiability++;
var log = loggerFactory.CreateLogger("catalog seed");
log.LogError(ex.Message);
await SeedAsync(applicationBuilder, env, loggerFactory, retryForAvaiability);
logger.LogError(ex.Message,$"There is an error migrating data for ApplicationDbContext");
await SeedAsync(context,env,logger,settings, retryForAvaiability);
}
}
}
private IEnumerable<ApplicationUser> GetUsersFromFile(string contentRootPath, ILogger log)
private IEnumerable<ApplicationUser> GetUsersFromFile(string contentRootPath, ILogger logger)
{
string csvFileUsers = Path.Combine(contentRootPath, "Setup", "Users.csv");
@ -95,7 +80,8 @@
}
catch (Exception ex)
{
log.LogError(ex.Message);
logger.LogError(ex.Message);
return GetDefaultUser();
}
@ -103,7 +89,7 @@
.Skip(1) // skip header column
.Select(row => Regex.Split(row, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)") )
.SelectTry(column => CreateApplicationUser(column, csvheaders))
.OnCaughtException(ex => { log.LogError(ex.Message); return null; })
.OnCaughtException(ex => { logger.LogError(ex.Message); return null; })
.Where(x => x != null)
.ToList();
@ -206,14 +192,14 @@
return csvheaders;
}
static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger log)
static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger logger)
{
try
{
string imagesZipFile = Path.Combine(contentRootPath, "Setup", "images.zip");
if (!File.Exists(imagesZipFile))
{
log.LogError($" zip file '{imagesZipFile}' does not exists.");
logger.LogError($" zip file '{imagesZipFile}' does not exists.");
return;
}
@ -235,14 +221,14 @@
}
else
{
log.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
logger.LogWarning($"Skip file '{entry.Name}' in zipfile '{imagesZipFile}'");
}
}
}
}
catch (Exception ex)
{
log.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
logger.LogError($"Exception in method GetPreconfiguredImages WebMVC. Exception Message={ex.Message}");
}
}
}

+ 56
- 0
src/Services/Identity/Identity.API/Data/ConfigurationDbContextSeed.cs View File

@ -0,0 +1,56 @@
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
public class ConfigurationDbContextSeed
{
public async Task SeedAsync(ConfigurationDbContext context,IConfiguration configuration)
{
//callbacks urls from config:
var clientUrls = new Dictionary<string, string>();
clientUrls.Add("Mvc", configuration.GetValue<string>("MvcClient"));
clientUrls.Add("Spa", configuration.GetValue<string>("SpaClient"));
clientUrls.Add("Xamarin", configuration.GetValue<string>("XamarinCallback"));
clientUrls.Add("LocationsApi", configuration.GetValue<string>("LocationApiClient"));
clientUrls.Add("MarketingApi", configuration.GetValue<string>("MarketingApiClient"));
clientUrls.Add("BasketApi", configuration.GetValue<string>("BasketApiClient"));
clientUrls.Add("OrderingApi", configuration.GetValue<string>("OrderingApiClient"));
if (!context.Clients.Any())
{
foreach (var client in Config.GetClients(clientUrls))
{
await context.Clients.AddAsync(client.ToEntity());
}
await context.SaveChangesAsync();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.GetResources())
{
await context.IdentityResources.AddAsync(resource.ToEntity());
}
await context.SaveChangesAsync();
}
if (!context.ApiResources.Any())
{
foreach (var api in Config.GetApis())
{
await context.ApiResources.AddAsync(api.ToEntity());
}
await context.SaveChangesAsync();
}
}
}
}

+ 1
- 1
src/Services/Identity/Identity.API/Extensions/LinqSelectExtensions.cs View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
namespace Identity.API.Extensions
namespace Microsoft.eShopOnContainers.Services.Identity.API.Extensions
{
public static class LinqSelectExtensions
{


+ 1
- 0
src/Services/Identity/Identity.API/Identity.API.csproj View File

@ -43,6 +43,7 @@
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup>
<ItemGroup>


+ 1
- 3
src/Services/Identity/Identity.API/Migrations/20170912114036_Initial.Designer.cs View File

@ -1,11 +1,9 @@
// <auto-generated />
using Identity.API.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using System;
namespace Identity.API.Migrations


+ 1
- 4
src/Services/Identity/Identity.API/Migrations/ApplicationDbContextModelSnapshot.cs View File

@ -1,11 +1,8 @@
// <auto-generated />
using Identity.API.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.Internal;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using System;
namespace Identity.API.Migrations


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentInputModel.cs View File

@ -1,10 +1,6 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System.Collections.Generic;
using System.Collections.Generic;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class ConsentInputModel
{


+ 2
- 4
src/Services/Identity/Identity.API/Models/AccountViewModels/ConsentViewModel.cs View File

@ -1,12 +1,10 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using IdentityServer4.Models;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class ConsentViewModel : ConsentInputModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class ExternalLoginConfirmationViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/ForgotPasswordViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class ForgotPasswordViewModel
{


+ 1
- 5
src/Services/Identity/Identity.API/Models/AccountViewModels/LoggedOutViewModel.cs View File

@ -1,8 +1,4 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class LoggedOutViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/LoginViewModel.cs View File

@ -1,10 +1,6 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class LoginViewModel
{


+ 1
- 5
src/Services/Identity/Identity.API/Models/AccountViewModels/LogoutViewModel.cs View File

@ -1,8 +1,4 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class LogoutViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/RegisterViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class RegisterViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/ResetPasswordViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class ResetPasswordViewModel
{


+ 2
- 5
src/Services/Identity/Identity.API/Models/AccountViewModels/SendCodeViewModel.cs View File

@ -1,10 +1,7 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class SendCodeViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/AccountViewModels/VerifyCodeViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public class VerifyCodeViewModel
{


+ 0
- 20
src/Services/Identity/Identity.API/Models/AccountViewModels/_LoginViewModel.cs View File

@ -1,20 +0,0 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System.Collections.Generic;
namespace Identity.API.Models.AccountViewModels
{
//public class _LoginViewModel : LoginViewModel
//{
// public bool EnableLocalLogin { get; set; }
// public IEnumerable<ExternalProvider> ExternalProviders { get; set; }
//}
//public class ExternalProvider
//{
// public string DisplayName { get; set; }
// public string AuthenticationScheme { get; set; }
//}
}

+ 1
- 1
src/Services/Identity/Identity.API/Models/ApplicationUser.cs View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser


+ 1
- 1
src/Services/Identity/Identity.API/Models/ErrorViewModel.cs View File

@ -4,7 +4,7 @@
using IdentityServer4.Models;
namespace IdentityServer4.Quickstart.UI.Models
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models
{
public class ErrorViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/AddPhoneNumberViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class AddPhoneNumberViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/ChangePasswordViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class ChangePasswordViewModel
{


+ 2
- 5
src/Services/Identity/Identity.API/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs View File

@ -1,10 +1,7 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class ConfigureTwoFactorViewModel
{


+ 1
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/FactorViewModel.cs View File

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class FactorViewModel
{


+ 2
- 5
src/Services/Identity/Identity.API/Models/ManageViewModels/IndexViewModel.cs View File

@ -1,10 +1,7 @@
using System;
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class IndexViewModel
{


+ 3
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/ManageLoginsViewModel.cs View File

@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class ManageLoginsViewModel
{


+ 1
- 7
src/Services/Identity/Identity.API/Models/ManageViewModels/RemoveLoginViewModel.cs View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class RemoveLoginViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/SetPasswordViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class SetPasswordViewModel
{


+ 2
- 6
src/Services/Identity/Identity.API/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public class VerifyPhoneNumberViewModel
{


+ 27
- 4
src/Services/Identity/Identity.API/Program.cs View File

@ -1,16 +1,39 @@
using Microsoft.AspNetCore;
using IdentityServer4.EntityFramework.DbContexts;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.eShopOnContainers.Services.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.IO;
namespace eShopOnContainers.Identity
namespace Microsoft.eShopOnContainers.Services.Identity.API
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
BuildWebHost(args)
.MigrateDbContext<PersistedGrantDbContext>((_, __) => { })
.MigrateDbContext<ApplicationDbContext>((context, services) =>
{
var env = services.GetService<IHostingEnvironment>();
var logger = services.GetService<ILogger<ApplicationDbContextSeed>>();
var settings = services.GetService<IOptions<AppSettings>>();
new ApplicationDbContextSeed()
.SeedAsync(context, env, logger, settings)
.Wait();
})
.MigrateDbContext<ConfigurationDbContext>((context,services)=>
{
var configuration = services.GetService<IConfiguration>();
new ConfigurationDbContextSeed()
.SeedAsync(context, configuration)
.Wait();
}).Run();
}
public static IWebHost BuildWebHost(string[] args) =>


+ 3
- 6
src/Services/Identity/Identity.API/Services/EFLoginService.cs View File

@ -1,11 +1,8 @@
using Identity.API.Models;
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class EFLoginService : ILoginService<ApplicationUser>
{


+ 2
- 5
src/Services/Identity/Identity.API/Services/IEmailSender.cs View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public interface IEmailSender
{


+ 2
- 5
src/Services/Identity/Identity.API/Services/ILoginService.cs View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public interface ILoginService<T>
{


+ 1
- 6
src/Services/Identity/Identity.API/Services/IRedirectService.cs View File

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public interface IRedirectService
{


+ 2
- 5
src/Services/Identity/Identity.API/Services/ISmsSender.cs View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public interface ISmsSender
{


+ 2
- 5
src/Services/Identity/Identity.API/Services/MessageServices.cs View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
// This class is used by the application to send Email and SMS
// when you turn on two-factor authentication in ASP.NET Identity.


+ 7
- 7
src/Services/Identity/Identity.API/Services/ProfileService.cs View File

@ -1,15 +1,15 @@
using IdentityServer4.Services;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using Microsoft.AspNetCore.Identity;
using Identity.API.Models;
using System.Security.Claims;
using IdentityModel;
using System.Threading.Tasks;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class ProfileService : IProfileService
{


+ 2
- 6
src/Services/Identity/Identity.API/Services/RedirectService.cs View File

@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class RedirectService : IRedirectService
{


+ 5
- 71
src/Services/Identity/Identity.API/Startup.cs View File

@ -1,31 +1,23 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using eShopOnContainers.Identity;
using Identity.API.Certificate;
using Identity.API.Configuration;
using Identity.API.Data;
using Identity.API.Models;
using Identity.API.Services;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.BuildingBlocks;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Identity.API.Certificates;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using Microsoft.eShopOnContainers.Services.Identity.API.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.HealthChecks;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity
namespace Microsoft.eShopOnContainers.Services.Identity.API
{
public class Startup
{
@ -39,7 +31,6 @@ namespace Microsoft.eShopOnContainers.Services.Identity
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
@ -146,63 +137,6 @@ namespace Microsoft.eShopOnContainers.Services.Identity
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
// Store idsrv grant config into db
InitializeGrantStoreAndConfiguration(app).Wait();
//Seed Data
var hasher = new PasswordHasher<ApplicationUser>();
new ApplicationContextSeed(hasher).SeedAsync(app, env, loggerFactory).Wait();
}
private async Task InitializeGrantStoreAndConfiguration(IApplicationBuilder app)
{
//callbacks urls from config:
Dictionary<string, string> clientUrls = new Dictionary<string, string>();
clientUrls.Add("Mvc", Configuration.GetValue<string>("MvcClient"));
clientUrls.Add("Spa", Configuration.GetValue<string>("SpaClient"));
clientUrls.Add("Xamarin", Configuration.GetValue<string>("XamarinCallback"));
clientUrls.Add("LocationsApi", Configuration.GetValue<string>("LocationApiClient"));
clientUrls.Add("MarketingApi", Configuration.GetValue<string>("MarketingApiClient"));
clientUrls.Add("BasketApi", Configuration.GetValue<string>("BasketApiClient"));
clientUrls.Add("OrderingApi", Configuration.GetValue<string>("OrderingApiClient"));
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>()
.Database
.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.GetClients(clientUrls))
{
await context.Clients.AddAsync(client.ToEntity());
}
await context.SaveChangesAsync();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.GetResources())
{
await context.IdentityResources.AddAsync(resource.ToEntity());
}
await context.SaveChangesAsync();
}
if (!context.ApiResources.Any())
{
foreach (var api in Config.GetApis())
{
await context.ApiResources.AddAsync(api.ToEntity());
}
await context.SaveChangesAsync();
}
}
}
}
}

+ 1
- 1
src/Services/Identity/Identity.API/Views/Account/LoggedOut.cshtml View File

@ -1,4 +1,4 @@
@model Identity.API.Models.AccountViewModels.LoggedOutViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LoggedOutViewModel
<div class="container page-header">
<h1>


+ 1
- 1
src/Services/Identity/Identity.API/Views/Account/Login.cshtml View File

@ -1,7 +1,7 @@
@using System.Collections.Generic
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Http.Authentication
@model Identity.API.Models.AccountViewModels.LoginViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LoginViewModel
@{


+ 1
- 1
src/Services/Identity/Identity.API/Views/Account/Logout.cshtml View File

@ -1,4 +1,4 @@
@model Identity.API.Models.AccountViewModels.LogoutViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.LogoutViewModel
<div class="container logout-page">
<div class="page-header">


+ 1
- 2
src/Services/Identity/Identity.API/Views/Account/Register.cshtml View File

@ -1,5 +1,4 @@
@using Identity.API.Models.AccountViewModels
@model RegisterViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.RegisterViewModel
@{
ViewData["Title"] = "Register";
}


+ 1
- 1
src/Services/Identity/Identity.API/Views/Consent/Index.cshtml View File

@ -1,4 +1,4 @@
@model Identity.API.Models.AccountViewModels.ConsentViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.ConsentViewModel
<div class="container page-consent">
<div class="row page-header">


+ 1
- 1
src/Services/Identity/Identity.API/Views/Consent/_ScopeListItem.cshtml View File

@ -1,4 +1,4 @@
@model Identity.API.Models.AccountViewModels.ScopeViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.ScopeViewModel
<li class="list-group-item">
<label>


+ 1
- 1
src/Services/Identity/Identity.API/Views/Shared/Error.cshtml View File

@ -1,4 +1,4 @@
@model IdentityServer4.Quickstart.UI.Models.ErrorViewModel
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.ErrorViewModel
@{
var error = Model?.Error?.Error;


+ 27
- 14
src/Services/Marketing/Marketing.API/Infrastructure/MarketingContextSeed.cs View File

@ -1,33 +1,33 @@
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure
{
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
using Microsoft.Extensions.Logging;
using Polly;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
public static class MarketingContextSeed
public class MarketingContextSeed
{
public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory, int? retry = 0)
public async Task SeedAsync(MarketingContext context,ILogger<MarketingContextSeed> logger,int retries = 3)
{
var context = (MarketingContext)applicationBuilder
.ApplicationServices.GetService(typeof(MarketingContext));
var policy = CreatePolicy(retries, logger, nameof(MarketingContextSeed));
context.Database.Migrate();
if (!context.Campaigns.Any())
await policy.ExecuteAsync(async () =>
{
context.Campaigns.AddRange(
GetPreconfiguredMarketings());
if (!context.Campaigns.Any())
{
context.Campaigns.AddRange(
GetPreconfiguredMarketings());
await context.SaveChangesAsync();
}
await context.SaveChangesAsync();
}
});
}
static List<Campaign> GetPreconfiguredMarketings()
private List<Campaign> GetPreconfiguredMarketings()
{
return new List<Campaign>
{
@ -67,5 +67,18 @@
}
};
}
private Policy CreatePolicy(int retries, ILogger<MarketingContextSeed> logger, string prefix)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
}
}

+ 3
- 0
src/Services/Marketing/Marketing.API/Infrastructure/MarketingReadDataContext.cs View File

@ -11,8 +11,11 @@
public MarketingReadDataContext(IOptions<MarketingSettings> settings)
{
var client = new MongoClient(settings.Value.MongoConnectionString);
if (client != null)
{
_database = client.GetDatabase(settings.Value.MongoDatabase);
}
}
public IMongoCollection<MarketingData> MarketingData


+ 1
- 0
src/Services/Marketing/Marketing.API/Marketing.API.csproj View File

@ -34,6 +34,7 @@
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.AzureStorage\Microsoft.Extensions.HealthChecks.AzureStorage.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
</ItemGroup>
<ItemGroup>


+ 12
- 1
src/Services/Marketing/Marketing.API/Program.cs View File

@ -2,6 +2,8 @@
{
using AspNetCore.Hosting;
using Microsoft.AspNetCore;
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.IO;
@ -9,7 +11,16 @@
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
BuildWebHost(args)
.MigrateDbContext<MarketingContext>((context, services) =>
{
var logger = services.GetService<ILogger<MarketingContextSeed>>();
new MarketingContextSeed()
.SeedAsync(context,logger)
.Wait();
}).Run();
}
public static IWebHost BuildWebHost(string[] args) =>


+ 1
- 30
src/Services/Marketing/Marketing.API/Startup.cs View File

@ -22,12 +22,10 @@
using IntegrationEvents.Events;
using Marketing.API.IntegrationEvents.Handlers;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Polly;
using RabbitMQ.Client;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Threading.Tasks;
@ -174,6 +172,7 @@
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
{
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
app.UsePathBase(pathBase);
@ -192,11 +191,6 @@
c.ConfigureOAuth2("marketingswaggerui", "", "", "Marketing Swagger UI");
});
var context = (MarketingContext)app
.ApplicationServices.GetService(typeof(MarketingContext));
WaitForSqlAvailabilityAsync(context, loggerFactory, app).Wait();
ConfigureEventBus(app);
}
@ -249,28 +243,5 @@
{
app.UseAuthentication();
}
private async Task WaitForSqlAvailabilityAsync(MarketingContext ctx, ILoggerFactory loggerFactory, IApplicationBuilder app, int retries = 0)
{
var logger = loggerFactory.CreateLogger(nameof(Startup));
var policy = CreatePolicy(retries, logger, nameof(WaitForSqlAvailabilityAsync));
await policy.ExecuteAsync(async () =>
{
await MarketingContextSeed.SeedAsync(app, loggerFactory);
});
}
private Policy CreatePolicy(int retries, ILogger logger, string prefix)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
}
}

+ 57
- 43
src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs View File

@ -1,63 +1,64 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure
{
using AspNetCore.Builder;
using global::Ordering.API.Extensions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Ordering.Domain;
using Ordering.Infrastructure;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using System.IO;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Ordering.Infrastructure;
using Polly;
using System;
using global::Ordering.API.Extensions;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
public class OrderingContextSeed
{
public static async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory)
public async Task SeedAsync(OrderingContext context, IHostingEnvironment env,IOptions<OrderingSettings> settings, ILogger<OrderingContextSeed> logger)
{
var log = loggerFactory.CreateLogger("ordering seed");
var policy = CreatePolicy(logger, nameof(OrderingContextSeed));
var context = (OrderingContext)applicationBuilder
.ApplicationServices.GetService(typeof(OrderingContext));
var settings = applicationBuilder
.ApplicationServices.GetRequiredService<IOptions<OrderingSettings>>().Value;
await policy.ExecuteAsync(async () =>
{
var useCustomizationData = settings.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
var useCustomizationData = settings.Value
.UseCustomizationData;
var contentRootPath = env.ContentRootPath;
using (context)
{
context.Database.Migrate();
if (!context.CardTypes.Any())
using (context)
{
context.CardTypes.AddRange(useCustomizationData
? GetCardTypesFromFile(contentRootPath, log)
: GetPredefinedCardTypes());
context.Database.Migrate();
await context.SaveChangesAsync();
}
if (!context.CardTypes.Any())
{
context.CardTypes.AddRange(useCustomizationData
? GetCardTypesFromFile(contentRootPath, logger)
: GetPredefinedCardTypes());
if (!context.OrderStatus.Any())
{
context.OrderStatus.AddRange(useCustomizationData
? GetOrderStatusFromFile(contentRootPath, log)
: GetPredefinedOrderStatus());
}
await context.SaveChangesAsync();
}
await context.SaveChangesAsync();
}
if (!context.OrderStatus.Any())
{
context.OrderStatus.AddRange(useCustomizationData
? GetOrderStatusFromFile(contentRootPath, logger)
: GetPredefinedOrderStatus());
}
await context.SaveChangesAsync();
}
});
}
static IEnumerable<CardType> GetCardTypesFromFile(string contentRootPath, ILogger log)
private IEnumerable<CardType> GetCardTypesFromFile(string contentRootPath, ILogger<OrderingContextSeed> log)
{
string csvFileCardTypes = Path.Combine(contentRootPath, "Setup", "CardTypes.csv");
@ -86,7 +87,7 @@
.Where(x => x != null);
}
static CardType CreateCardType(string value, ref int id)
private CardType CreateCardType(string value, ref int id)
{
if (String.IsNullOrEmpty(value))
{
@ -96,8 +97,7 @@
return new CardType(id++, value.Trim('"').Trim());
}
private static IEnumerable<CardType> GetPredefinedCardTypes()
private IEnumerable<CardType> GetPredefinedCardTypes()
{
return new List<CardType>()
{
@ -107,7 +107,7 @@
};
}
static IEnumerable<OrderStatus> GetOrderStatusFromFile(string contentRootPath, ILogger log)
private IEnumerable<OrderStatus> GetOrderStatusFromFile(string contentRootPath, ILogger<OrderingContextSeed> log)
{
string csvFileOrderStatus = Path.Combine(contentRootPath, "Setup", "OrderStatus.csv");
@ -136,7 +136,7 @@
.Where(x => x != null);
}
static OrderStatus CreateOrderStatus(string value, ref int id)
private OrderStatus CreateOrderStatus(string value, ref int id)
{
if (String.IsNullOrEmpty(value))
{
@ -146,7 +146,7 @@
return new OrderStatus(id++, value.Trim('"').Trim().ToLowerInvariant());
}
static IEnumerable<OrderStatus> GetPredefinedOrderStatus()
private IEnumerable<OrderStatus> GetPredefinedOrderStatus()
{
return new List<OrderStatus>()
{
@ -159,7 +159,7 @@
};
}
static string[] GetHeaders(string[] requiredHeaders, string csvfile)
private string[] GetHeaders(string[] requiredHeaders, string csvfile)
{
string[] csvheaders = File.ReadLines(csvfile).First().ToLowerInvariant().Split(',');
@ -178,5 +178,19 @@
return csvheaders;
}
private Policy CreatePolicy( ILogger<OrderingContextSeed> logger, string prefix, int retries =3)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
}
}

+ 0
- 29
src/Services/Ordering/Ordering.API/Infrastructure/OrderingDbContextDesigner.cs View File

@ -1,29 +0,0 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure
{
public class OrderingDbContextDesigner : IDesignTimeDbContextFactory<OrderingContext>
{
public OrderingContext CreateDbContext(string[] args)
{
var options = new DbContextOptionsBuilder<OrderingContext>();
options.UseSqlServer("Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;",
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
});
return OrderingContext.CreateForEFDesignTools(options.Options);
}
}
}

+ 1
- 0
src/Services/Ordering/Ordering.API/Ordering.API.csproj View File

@ -27,6 +27,7 @@
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.AspNetCore.HealthChecks\Microsoft.AspNetCore.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks.SqlServer\Microsoft.Extensions.HealthChecks.SqlServer.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\HealthChecks\src\Microsoft.Extensions.HealthChecks\Microsoft.Extensions.HealthChecks.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
<ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" />
<ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" />
</ItemGroup>


+ 18
- 1
src/Services/Ordering/Ordering.API/Program.cs View File

@ -1,6 +1,11 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.IO;
namespace Microsoft.eShopOnContainers.Services.Ordering.API
@ -9,7 +14,19 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
BuildWebHost(args)
.MigrateDbContext<OrderingContext>((context, services) =>
{
var env = services.GetService<IHostingEnvironment>();
var settings = services.GetService<IOptions<OrderingSettings>>();
var logger = services.GetService<ILogger<OrderingContextSeed>>();
new OrderingContextSeed()
.SeedAsync(context, env, settings, logger)
.Wait();
})
.MigrateDbContext<IntegrationEventLogContext>((_,__)=>{})
.Run();
}
public static IWebHost BuildWebHost(string[] args) =>


+ 9
- 36
src/Services/Ordering/Ordering.API/Startup.cs View File

@ -7,7 +7,6 @@
using global::Ordering.API.Application.IntegrationEvents.Events;
using global::Ordering.API.Infrastructure.Filters;
using global::Ordering.API.Infrastructure.HostedServices;
using Infrastructure;
using Infrastructure.AutofacModules;
using Infrastructure.Filters;
using Infrastructure.Services;
@ -28,16 +27,13 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Ordering.Infrastructure;
using Polly;
using RabbitMQ.Client;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.SqlClient;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Threading.Tasks;
public class Startup
{
@ -85,6 +81,15 @@
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
);
services.AddDbContext<IntegrationEventLogContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionString"], opts =>
{
opts.MigrationsAssembly("Ordering.API");
});
});
services.Configure<OrderingSettings>(Configuration);
services.AddSwaggerGen(options =>
@ -208,14 +213,6 @@
c.ConfigureOAuth2("orderingswaggerui", "", "", "Ordering Swagger UI");
});
WaitForSqlAvailabilityAsync(loggerFactory, app, env).Wait();
var integrationEventLogContext = new IntegrationEventLogContext(
new DbContextOptionsBuilder<IntegrationEventLogContext>()
.UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Ordering.API"))
.Options);
integrationEventLogContext.Database.Migrate();
ConfigureEventBus(app);
}
@ -279,29 +276,5 @@
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
}
private async Task WaitForSqlAvailabilityAsync(ILoggerFactory loggerFactory, IApplicationBuilder app, IHostingEnvironment env, int retries = 0)
{
var logger = loggerFactory.CreateLogger(nameof(Startup));
var policy = CreatePolicy(retries, logger, nameof(WaitForSqlAvailabilityAsync));
await policy.ExecuteAsync(async () =>
{
await OrderingContextSeed.SeedAsync(app, env, loggerFactory);
});
}
private Policy CreatePolicy(int retries, ILogger logger, string prefix)
{
return Policy.Handle<SqlException>().
WaitAndRetryAsync(
retryCount: retries,
sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
onRetry: (exception, timeSpan, retry, ctx) =>
{
logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
}
);
}
}
}

+ 2
- 8
src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs View File

@ -31,15 +31,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
private readonly IMediator _mediator;
public static OrderingContext CreateForEFDesignTools(DbContextOptions options)
{
return new OrderingContext(options);
}
private OrderingContext(DbContextOptions options) : base (options) { }
private OrderingContext(DbContextOptions<OrderingContext> options) : base (options) { }
public OrderingContext(DbContextOptions options, IMediator mediator) : base(options)
public OrderingContext(DbContextOptions<OrderingContext> options, IMediator mediator) : base(options)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));


Loading…
Cancel
Save