Merge branch 'EFCliAndSeeders' into dev
This commit is contained in:
commit
a7f51e7d65
@ -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
|
||||
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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}");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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) =>
|
||||
|
@ -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)
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
public class ApplicationDbContextSeed
|
||||
{
|
||||
private readonly IPasswordHasher<ApplicationUser> _passwordHasher;
|
||||
private readonly IPasswordHasher<ApplicationUser> _passwordHasher = new PasswordHasher<ApplicationUser>();
|
||||
|
||||
public ApplicationContextSeed(IPasswordHasher<ApplicationUser> passwordHasher)
|
||||
{
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task SeedAsync(IApplicationBuilder applicationBuilder, IHostingEnvironment env, ILoggerFactory loggerFactory, int? retry = 0)
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -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,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,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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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
|
||||
{
|
||||
|
@ -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,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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models
|
||||
{
|
||||
public class ErrorViewModel
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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) =>
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,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,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,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,5 +1,4 @@
|
||||
@using Identity.API.Models.AccountViewModels
|
||||
@model RegisterViewModel
|
||||
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels.RegisterViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Register";
|
||||
}
|
||||
|
@ -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,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,4 +1,4 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.ErrorViewModel
|
||||
@model Microsoft.eShopOnContainers.Services.Identity.API.Models.ErrorViewModel
|
||||
|
||||
@{
|
||||
var error = Model?.Error?.Error;
|
||||
|
@ -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}");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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) =>
|
||||
|
@ -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}");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
var useCustomizationData = settings.UseCustomizationData;
|
||||
var contentRootPath = env.ContentRootPath;
|
||||
|
||||
|
||||
using (context)
|
||||
await policy.ExecuteAsync(async () =>
|
||||
{
|
||||
context.Database.Migrate();
|
||||
|
||||
if (!context.CardTypes.Any())
|
||||
var useCustomizationData = settings.Value
|
||||
.UseCustomizationData;
|
||||
|
||||
var contentRootPath = env.ContentRootPath;
|
||||
|
||||
|
||||
using (context)
|
||||
{
|
||||
context.CardTypes.AddRange(useCustomizationData
|
||||
? GetCardTypesFromFile(contentRootPath, log)
|
||||
: GetPredefinedCardTypes());
|
||||
context.Database.Migrate();
|
||||
|
||||
if (!context.CardTypes.Any())
|
||||
{
|
||||
context.CardTypes.AddRange(useCustomizationData
|
||||
? GetCardTypesFromFile(contentRootPath, logger)
|
||||
: GetPredefinedCardTypes());
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (!context.OrderStatus.Any())
|
||||
{
|
||||
context.OrderStatus.AddRange(useCustomizationData
|
||||
? GetOrderStatusFromFile(contentRootPath, logger)
|
||||
: GetPredefinedOrderStatus());
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (!context.OrderStatus.Any())
|
||||
{
|
||||
context.OrderStatus.AddRange(useCustomizationData
|
||||
? GetOrderStatusFromFile(contentRootPath, log)
|
||||
: 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}");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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) =>
|
||||
|
@ -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}");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<OrderingContext> options) : base (options) { }
|
||||
|
||||
private OrderingContext(DbContextOptions 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…
x
Reference in New Issue
Block a user