Updates basket-api to .NET 6 (#1742)

* Use global usings

* Use file-scoped namespaces

* Updates docker images to preview 7

* Created a new migration plan

* Included global usings for identity project

* Updated docker file to preview version to 7

* Updated dockerfiles

* Merged conent from Startup.cs to Program.cs

* Removed Starup.cs

* Removed unnecessary files

* Revert "Removed unnecessary files"

This reverts commit 536bddcd96b54673401cedbe802520dce12b3472.

* Revert "Removed Starup.cs"

This reverts commit 46175d7aa97475d88ec46bce39ed498c7037d924.

* Revert "Merged conent from Startup.cs to Program.cs"

This reverts commit 2766ea86dfef9220fe3f0c27a37a9a6c18153078.

* Removed extra spaces

* Updated basket-api project file

* Update src/Services/Basket/Basket.API/Grpc/BasketService.cs

Co-authored-by: David Pine <david.pine@microsoft.com>

* Apply suggestions from code review

Co-authored-by: David Pine <david.pine@microsoft.com>

* Moved the fully qualified namespace on top

* Updated relevant packages in basket.api project

* Updated relevant packages in identity.api project

Co-authored-by: David Pine <david.pine@microsoft.com>
This commit is contained in:
Sumit Ghosh 2021-10-04 19:39:36 +05:30 committed by GitHub
parent 8be1c9cd3e
commit ab1d9cc897
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 2547 additions and 2142 deletions

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,33 +1,25 @@
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Auth.Server
public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
operation.Parameters ??= new List<OpenApiParameter>();
if (isAuthorized && !allowAnonymous)
operation.Parameters.Add(new OpenApiParameter
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "Authorization",
In = ParameterLocation.Header,
Description = "access token",
Required = true
});
}
Name = "Authorization",
In = ParameterLocation.Header,
Description = "access token",
Required = true
});
}
}
}

View File

@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
@ -16,30 +15,36 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="5.0.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.12.2" />
<PackageReference Include="Azure.Identity" Version="1.5.0-beta.3" />
<PackageReference Include="AspNetCore.HealthChecks.AzureServiceBus" Version="5.1.1" />
<PackageReference Include="AspNetCore.HealthChecks.Rabbitmq" Version="5.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="5.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="5.0.2" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="5.0.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0-preview.1" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageReference Include="Azure.Identity" Version="1.4.0" />
<PackageReference Include="Google.Protobuf" Version="3.14.0" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.34.0" />
<PackageReference Include="Grpc.Tools" Version="2.34.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.2" />
<PackageReference Include="Google.Protobuf" Version="3.14.0" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.34.0" />
<PackageReference Include="Grpc.Tools" Version="2.34.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.18.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.18.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="2.0.2-beta2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.2" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00216" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Serilog.Sinks.Http" Version="7.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.18" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.11.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.1-dev-00229" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.1-dev-00787" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0-dev-00291" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1-dev-00876" />
<PackageReference Include="Serilog.Sinks.Http" Version="8.0.0-beta.9" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.1.0-dev-00166" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.2.1" />
</ItemGroup>
<ItemGroup>
@ -53,5 +58,4 @@
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
</ItemGroup>
</Project>

View File

@ -1,7 +1,7 @@
namespace Microsoft.eShopOnContainers.Services.Basket.API
namespace Microsoft.eShopOnContainers.Services.Basket.API;
public class BasketSettings
{
public class BasketSettings
{
public string ConnectionString { get; set; }
}
public string ConnectionString { get; set; }
}

View File

@ -1,103 +1,89 @@
using Basket.API.IntegrationEvents.Events;
using Basket.API.Model;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
[Route("api/v1/[controller]")]
[Authorize]
[ApiController]
public class BasketController : ControllerBase
{
[Route("api/v1/[controller]")]
[Authorize]
[ApiController]
public class BasketController : ControllerBase
private readonly IBasketRepository _repository;
private readonly IIdentityService _identityService;
private readonly IEventBus _eventBus;
private readonly ILogger<BasketController> _logger;
public BasketController(
ILogger<BasketController> logger,
IBasketRepository repository,
IIdentityService identityService,
IEventBus eventBus)
{
private readonly IBasketRepository _repository;
private readonly IIdentityService _identityService;
private readonly IEventBus _eventBus;
private readonly ILogger<BasketController> _logger;
_logger = logger;
_repository = repository;
_identityService = identityService;
_eventBus = eventBus;
}
public BasketController(
ILogger<BasketController> logger,
IBasketRepository repository,
IIdentityService identityService,
IEventBus eventBus)
[HttpGet("{id}")]
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
public async Task<ActionResult<CustomerBasket>> GetBasketByIdAsync(string id)
{
var basket = await _repository.GetBasketAsync(id);
return Ok(basket ?? new CustomerBasket(id));
}
[HttpPost]
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
public async Task<ActionResult<CustomerBasket>> UpdateBasketAsync([FromBody] CustomerBasket value)
{
return Ok(await _repository.UpdateBasketAsync(value));
}
[Route("checkout")]
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.Accepted)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<ActionResult> CheckoutAsync([FromBody] BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
{
var userId = _identityService.GetUserIdentity();
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
guid : basketCheckout.RequestId;
var basket = await _repository.GetBasketAsync(userId);
if (basket == null)
{
_logger = logger;
_repository = repository;
_identityService = identityService;
_eventBus = eventBus;
return BadRequest();
}
[HttpGet("{id}")]
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
public async Task<ActionResult<CustomerBasket>> GetBasketByIdAsync(string id)
{
var basket = await _repository.GetBasketAsync(id);
var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value;
return Ok(basket ?? new CustomerBasket(id));
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street,
basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName,
basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket);
// Once basket is checkout, sends an integration event to
// ordering.api to convert basket to order and proceeds with
// order creation process
try
{
_eventBus.Publish(eventMessage);
}
catch (Exception ex)
{
_logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName);
throw;
}
[HttpPost]
[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)]
public async Task<ActionResult<CustomerBasket>> UpdateBasketAsync([FromBody] CustomerBasket value)
{
return Ok(await _repository.UpdateBasketAsync(value));
}
return Accepted();
}
[Route("checkout")]
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.Accepted)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
public async Task<ActionResult> CheckoutAsync([FromBody] BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
{
var userId = _identityService.GetUserIdentity();
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
guid : basketCheckout.RequestId;
var basket = await _repository.GetBasketAsync(userId);
if (basket == null)
{
return BadRequest();
}
var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value;
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street,
basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName,
basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket);
// Once basket is checkout, sends an integration event to
// ordering.api to convert basket to order and proceeds with
// order creation process
try
{
_eventBus.Publish(eventMessage);
}
catch (Exception ex)
{
_logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, Program.AppName);
throw;
}
return Accepted();
}
// DELETE api/values/5
[HttpDelete("{id}")]
[ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)]
public async Task DeleteBasketByIdAsync(string id)
{
await _repository.DeleteBasketAsync(id);
}
// DELETE api/values/5
[HttpDelete("{id}")]
[ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)]
public async Task DeleteBasketByIdAsync(string id)
{
await _repository.DeleteBasketAsync(id);
}
}

View File

@ -1,13 +1,11 @@
using Microsoft.AspNetCore.Mvc;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
public class HomeController : Controller
{
public class HomeController : Controller
// GET: /<controller>/
public IActionResult Index()
{
// GET: /<controller>/
public IActionResult Index()
{
return new RedirectResult("~/swagger");
}
return new RedirectResult("~/swagger");
}
}

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -0,0 +1,61 @@
global using Autofac.Extensions.DependencyInjection;
global using Autofac;
global using Azure.Core;
global using Azure.Identity;
global using Basket.API.Infrastructure.ActionResults;
global using Basket.API.Infrastructure.Exceptions;
global using Basket.API.Infrastructure.Filters;
global using Basket.API.Infrastructure.Middlewares;
global using Basket.API.IntegrationEvents.EventHandling;
global using Basket.API.IntegrationEvents.Events;
global using Basket.API.Model;
global using Grpc.Core;
global using GrpcBasket;
global using HealthChecks.UI.Client;
global using Microsoft.AspNetCore.Authentication.JwtBearer;
global using Microsoft.AspNetCore.Authorization;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Diagnostics.HealthChecks;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.AspNetCore.Http.Features;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Mvc.Authorization;
global using Microsoft.AspNetCore.Mvc.Filters;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.AspNetCore.Server.Kestrel.Core;
global using Microsoft.AspNetCore;
global using Microsoft.Azure.ServiceBus;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
global using Microsoft.eShopOnContainers.Services.Basket.API.Controllers;
global using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories;
global using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling;
global using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
global using Microsoft.eShopOnContainers.Services.Basket.API.Model;
global using Microsoft.eShopOnContainers.Services.Basket.API.Services;
global using Microsoft.eShopOnContainers.Services.Basket.API;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Diagnostics.HealthChecks;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Options;
global using Microsoft.OpenApi.Models;
global using RabbitMQ.Client;
global using Serilog.Context;
global using Serilog;
global using StackExchange.Redis;
global using Swashbuckle.AspNetCore.SwaggerGen;
global using System.Collections.Generic;
global using System.ComponentModel.DataAnnotations;
global using System.IdentityModel.Tokens.Jwt;
global using System.IO;
global using System.Linq;
global using System.Net;
global using System.Security.Claims;
global using System.Text.Json;
global using System.Threading.Tasks;
global using System;

View File

@ -1,102 +1,94 @@
using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.Extensions.Logging;
using System.Linq;
using System.Threading.Tasks;
namespace GrpcBasket;
namespace GrpcBasket
public class BasketService : Basket.BasketBase
{
public class BasketService : Basket.BasketBase
private readonly IBasketRepository _repository;
private readonly ILogger<BasketService> _logger;
public BasketService(IBasketRepository repository, ILogger<BasketService> logger)
{
private readonly IBasketRepository _repository;
private readonly ILogger<BasketService> _logger;
_repository = repository;
_logger = logger;
}
public BasketService(IBasketRepository repository, ILogger<BasketService> logger)
[AllowAnonymous]
public override async Task<CustomerBasketResponse> GetBasketById(BasketRequest request, ServerCallContext context)
{
_logger.LogInformation("Begin grpc call from method {Method} for basket id {Id}", context.Method, request.Id);
var data = await _repository.GetBasketAsync(request.Id);
if (data != null)
{
_repository = repository;
_logger = logger;
context.Status = new Status(StatusCode.OK, $"Basket with id {request.Id} do exist");
return MapToCustomerBasketResponse(data);
}
else
{
context.Status = new Status(StatusCode.NotFound, $"Basket with id {request.Id} do not exist");
}
[AllowAnonymous]
public override async Task<CustomerBasketResponse> GetBasketById(BasketRequest request, ServerCallContext context)
return new CustomerBasketResponse();
}
public override async Task<CustomerBasketResponse> UpdateBasket(CustomerBasketRequest request, ServerCallContext context)
{
_logger.LogInformation("Begin grpc call BasketService.UpdateBasketAsync for buyer id {Buyerid}", request.Buyerid);
var customerBasket = MapToCustomerBasket(request);
var response = await _repository.UpdateBasketAsync(customerBasket);
if (response != null)
{
_logger.LogInformation("Begin grpc call from method {Method} for basket id {Id}", context.Method, request.Id);
var data = await _repository.GetBasketAsync(request.Id);
if (data != null)
{
context.Status = new Status(StatusCode.OK, $"Basket with id {request.Id} do exist");
return MapToCustomerBasketResponse(data);
}
else
{
context.Status = new Status(StatusCode.NotFound, $"Basket with id {request.Id} do not exist");
}
return new CustomerBasketResponse();
return MapToCustomerBasketResponse(response);
}
public override async Task<CustomerBasketResponse> UpdateBasket(CustomerBasketRequest request, ServerCallContext context)
context.Status = new Status(StatusCode.NotFound, $"Basket with buyer id {request.Buyerid} do not exist");
return null;
}
private CustomerBasketResponse MapToCustomerBasketResponse(CustomerBasket customerBasket)
{
var response = new CustomerBasketResponse
{
_logger.LogInformation("Begin grpc call BasketService.UpdateBasketAsync for buyer id {Buyerid}", request.Buyerid);
Buyerid = customerBasket.BuyerId
};
var customerBasket = MapToCustomerBasket(request);
var response = await _repository.UpdateBasketAsync(customerBasket);
if (response != null)
{
return MapToCustomerBasketResponse(response);
}
context.Status = new Status(StatusCode.NotFound, $"Basket with buyer id {request.Buyerid} do not exist");
return null;
}
private CustomerBasketResponse MapToCustomerBasketResponse(CustomerBasket customerBasket)
customerBasket.Items.ForEach(item => response.Items.Add(new BasketItemResponse
{
var response = new CustomerBasketResponse
{
Buyerid = customerBasket.BuyerId
};
Id = item.Id,
Oldunitprice = (double)item.OldUnitPrice,
Pictureurl = item.PictureUrl,
Productid = item.ProductId,
Productname = item.ProductName,
Quantity = item.Quantity,
Unitprice = (double)item.UnitPrice
}));
customerBasket.Items.ForEach(item => response.Items.Add(new BasketItemResponse
{
Id = item.Id,
Oldunitprice = (double)item.OldUnitPrice,
Pictureurl = item.PictureUrl,
Productid = item.ProductId,
Productname = item.ProductName,
Quantity = item.Quantity,
Unitprice = (double)item.UnitPrice
}));
return response;
}
return response;
}
private CustomerBasket MapToCustomerBasket(CustomerBasketRequest customerBasketRequest)
private CustomerBasket MapToCustomerBasket(CustomerBasketRequest customerBasketRequest)
{
var response = new CustomerBasket
{
var response = new CustomerBasket
{
BuyerId = customerBasketRequest.Buyerid
};
BuyerId = customerBasketRequest.Buyerid
};
customerBasketRequest.Items.ToList().ForEach(item => response.Items.Add(new BasketItem
{
Id = item.Id,
OldUnitPrice = (decimal)item.Oldunitprice,
PictureUrl = item.Pictureurl,
ProductId = item.Productid,
ProductName = item.Productname,
Quantity = item.Quantity,
UnitPrice = (decimal)item.Unitprice
}));
customerBasketRequest.Items.ToList().ForEach(item => response.Items.Add(new BasketItem
{
Id = item.Id,
OldUnitPrice = (decimal)item.Oldunitprice,
PictureUrl = item.Pictureurl,
ProductId = item.Productid,
ProductName = item.Productname,
Quantity = item.Quantity,
UnitPrice = (decimal)item.Unitprice
}));
return response;
}
return response;
}
}

View File

@ -1,14 +1,11 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Basket.API.Infrastructure.ActionResults;
namespace Basket.API.Infrastructure.ActionResults
public class InternalServerErrorObjectResult : ObjectResult
{
public class InternalServerErrorObjectResult : ObjectResult
public InternalServerErrorObjectResult(object error)
: base(error)
{
public InternalServerErrorObjectResult(object error)
: base(error)
{
StatusCode = StatusCodes.Status500InternalServerError;
}
StatusCode = StatusCodes.Status500InternalServerError;
}
}

View File

@ -1,21 +1,16 @@
using System;
namespace Basket.API.Infrastructure.Exceptions;
namespace Basket.API.Infrastructure.Exceptions
public class BasketDomainException : Exception
{
/// <summary>
/// Exception type for app exceptions
/// </summary>
public class BasketDomainException : Exception
{
public BasketDomainException()
{ }
public BasketDomainException()
{ }
public BasketDomainException(string message)
: base(message)
{ }
public BasketDomainException(string message)
: base(message)
{ }
public BasketDomainException(string message, Exception innerException)
: base(message, innerException)
{ }
}
public BasketDomainException(string message, Exception innerException)
: base(message, innerException)
{ }
}

View File

@ -1,20 +1,18 @@
using Microsoft.AspNetCore.Builder;
using System;
namespace Basket.API.Infrastructure.Middlewares;
namespace Basket.API.Infrastructure.Middlewares
public static class FailingMiddlewareAppBuilderExtensions
{
public static class FailingMiddlewareAppBuilderExtensions
public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder)
{
public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder)
{
return UseFailingMiddleware(builder, null);
}
public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder, Action<FailingOptions> action)
{
var options = new FailingOptions();
action?.Invoke(options);
builder.UseMiddleware<FailingMiddleware>(options);
return builder;
}
return UseFailingMiddleware(builder, null);
}
public static IApplicationBuilder UseFailingMiddleware(this IApplicationBuilder builder, Action<FailingOptions> action)
{
var options = new FailingOptions();
action?.Invoke(options);
builder.UseMiddleware<FailingMiddleware>(options);
return builder;
}
}

View File

@ -1,58 +1,47 @@
using Basket.API.Infrastructure.ActionResults;
using Basket.API.Infrastructure.Exceptions;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Net;
namespace Basket.API.Infrastructure.Filters;
namespace Basket.API.Infrastructure.Filters
public partial class HttpGlobalExceptionFilter : IExceptionFilter
{
public partial class HttpGlobalExceptionFilter : IExceptionFilter
private readonly IWebHostEnvironment env;
private readonly ILogger<HttpGlobalExceptionFilter> logger;
public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
{
private readonly IWebHostEnvironment env;
private readonly ILogger<HttpGlobalExceptionFilter> logger;
this.env = env;
this.logger = logger;
}
public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger<HttpGlobalExceptionFilter> logger)
public void OnException(ExceptionContext context)
{
logger.LogError(new EventId(context.Exception.HResult),
context.Exception,
context.Exception.Message);
if (context.Exception.GetType() == typeof(BasketDomainException))
{
this.env = env;
this.logger = logger;
}
var json = new JsonErrorResponse
{
Messages = new[] { context.Exception.Message }
};
public void OnException(ExceptionContext context)
context.Result = new BadRequestObjectResult(json);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
else
{
logger.LogError(new EventId(context.Exception.HResult),
context.Exception,
context.Exception.Message);
if (context.Exception.GetType() == typeof(BasketDomainException))
var json = new JsonErrorResponse
{
var json = new JsonErrorResponse
{
Messages = new[] { context.Exception.Message }
};
Messages = new[] { "An error occurred. Try it again." }
};
context.Result = new BadRequestObjectResult(json);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
else
if (env.IsDevelopment())
{
var json = new JsonErrorResponse
{
Messages = new[] { "An error occurred. Try it again." }
};
if (env.IsDevelopment())
{
json.DeveloperMessage = context.Exception;
}
context.Result = new InternalServerErrorObjectResult(json);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
json.DeveloperMessage = context.Exception;
}
context.ExceptionHandled = true;
context.Result = new InternalServerErrorObjectResult(json);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
context.ExceptionHandled = true;
}
}

View File

@ -1,9 +1,9 @@
namespace Basket.API.Infrastructure.Filters
{
public class JsonErrorResponse
{
public string[] Messages { get; set; }
namespace Basket.API.Infrastructure.Filters;
public object DeveloperMessage { get; set; }
}
public class JsonErrorResponse
{
public string[] Messages { get; set; }
public object DeveloperMessage { get; set; }
}

View File

@ -1,30 +1,26 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Linq;
namespace Basket.API.Infrastructure.Filters;
namespace Basket.API.Infrastructure.Filters
public class ValidateModelStateFilter : ActionFilterAttribute
{
public class ValidateModelStateFilter : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext context)
{
public override void OnActionExecuting(ActionExecutingContext context)
if (context.ModelState.IsValid)
{
if (context.ModelState.IsValid)
{
return;
}
var validationErrors = context.ModelState
.Keys
.SelectMany(k => context.ModelState[k].Errors)
.Select(e => e.ErrorMessage)
.ToArray();
var json = new JsonErrorResponse
{
Messages = validationErrors
};
context.Result = new BadRequestObjectResult(json);
return;
}
var validationErrors = context.ModelState
.Keys
.SelectMany(k => context.ModelState[k].Errors)
.Select(e => e.ErrorMessage)
.ToArray();
var json = new JsonErrorResponse
{
Messages = validationErrors
};
context.Result = new BadRequestObjectResult(json);
}
}

View File

@ -1,36 +1,29 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
using System.Linq;
namespace Basket.API.Infrastructure.Filters;
namespace Basket.API.Infrastructure.Filters
public class AuthorizeCheckOperationFilter : IOperationFilter
{
public class AuthorizeCheckOperationFilter : IOperationFilter
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
// Check for authorize attribute
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
if (!hasAuthorize) return;
operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" });
operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" });
var oAuthScheme = new OpenApiSecurityScheme
{
// Check for authorize attribute
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
};
if (!hasAuthorize) return;
operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" });
operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" });
var oAuthScheme = new OpenApiSecurityScheme
operation.Security = new List<OpenApiSecurityRequirement>
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
};
operation.Security = new List<OpenApiSecurityRequirement>
new OpenApiSecurityRequirement
{
new OpenApiSecurityRequirement
{
[ oAuthScheme ] = new [] { "basketapi" }
}
};
}
[ oAuthScheme ] = new [] { "basketapi" }
}
};
}
}

View File

@ -1,95 +1,88 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Basket.API.Infrastructure.Middlewares;
namespace Basket.API.Infrastructure.Middlewares
public class FailingMiddleware
{
public class FailingMiddleware
private readonly RequestDelegate _next;
private bool _mustFail;
private readonly FailingOptions _options;
private readonly Microsoft.Extensions.Logging.ILogger _logger;
public FailingMiddleware(RequestDelegate next, Microsoft.Extensions.Logging.ILogger<FailingMiddleware> logger, FailingOptions options)
{
private readonly RequestDelegate _next;
private bool _mustFail;
private readonly FailingOptions _options;
private readonly ILogger _logger;
_next = next;
_options = options;
_mustFail = false;
_logger = logger;
}
public FailingMiddleware(RequestDelegate next, ILogger<FailingMiddleware> logger, FailingOptions options)
public async Task Invoke(HttpContext context)
{
var path = context.Request.Path;
if (path.Equals(_options.ConfigPath, StringComparison.OrdinalIgnoreCase))
{
_next = next;
_options = options;
_mustFail = false;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
var path = context.Request.Path;
if (path.Equals(_options.ConfigPath, StringComparison.OrdinalIgnoreCase))
{
await ProcessConfigRequest(context);
return;
}
if (MustFail(context))
{
_logger.LogInformation("Response for path {Path} will fail.", path);
context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Failed due to FailingMiddleware enabled.");
}
else
{
await _next.Invoke(context);
}
}
private async Task ProcessConfigRequest(HttpContext context)
{
var enable = context.Request.Query.Keys.Any(k => k == "enable");
var disable = context.Request.Query.Keys.Any(k => k == "disable");
if (enable && disable)
{
throw new ArgumentException("Must use enable or disable querystring values, but not both");
}
if (disable)
{
_mustFail = false;
await SendOkResponse(context, "FailingMiddleware disabled. Further requests will be processed.");
return;
}
if (enable)
{
_mustFail = true;
await SendOkResponse(context, "FailingMiddleware enabled. Further requests will return HTTP 500");
return;
}
// If reach here, that means that no valid parameter has been passed. Just output status
await SendOkResponse(context, string.Format("FailingMiddleware is {0}", _mustFail ? "enabled" : "disabled"));
await ProcessConfigRequest(context);
return;
}
private async Task SendOkResponse(HttpContext context, string message)
if (MustFail(context))
{
context.Response.StatusCode = (int)System.Net.HttpStatusCode.OK;
_logger.LogInformation("Response for path {Path} will fail.", path);
context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(message);
await context.Response.WriteAsync("Failed due to FailingMiddleware enabled.");
}
private bool MustFail(HttpContext context)
else
{
var rpath = context.Request.Path.Value;
if (_options.NotFilteredPaths.Any(p => p.Equals(rpath, StringComparison.InvariantCultureIgnoreCase)))
{
return false;
}
return _mustFail &&
(_options.EndpointPaths.Any(x => x == rpath)
|| _options.EndpointPaths.Count == 0);
await _next.Invoke(context);
}
}
private async Task ProcessConfigRequest(HttpContext context)
{
var enable = context.Request.Query.Keys.Any(k => k == "enable");
var disable = context.Request.Query.Keys.Any(k => k == "disable");
if (enable && disable)
{
throw new ArgumentException("Must use enable or disable querystring values, but not both");
}
if (disable)
{
_mustFail = false;
await SendOkResponse(context, "FailingMiddleware disabled. Further requests will be processed.");
return;
}
if (enable)
{
_mustFail = true;
await SendOkResponse(context, "FailingMiddleware enabled. Further requests will return HTTP 500");
return;
}
// If reach here, that means that no valid parameter has been passed. Just output status
await SendOkResponse(context, string.Format("FailingMiddleware is {0}", _mustFail ? "enabled" : "disabled"));
return;
}
private async Task SendOkResponse(HttpContext context, string message)
{
context.Response.StatusCode = (int)System.Net.HttpStatusCode.OK;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync(message);
}
private bool MustFail(HttpContext context)
{
var rpath = context.Request.Path.Value;
if (_options.NotFilteredPaths.Any(p => p.Equals(rpath, StringComparison.InvariantCultureIgnoreCase)))
{
return false;
}
return _mustFail &&
(_options.EndpointPaths.Any(x => x == rpath)
|| _options.EndpointPaths.Count == 0);
}
}

View File

@ -1,12 +1,10 @@
using System.Collections.Generic;
namespace Basket.API.Infrastructure.Middlewares;
namespace Basket.API.Infrastructure.Middlewares
public class FailingOptions
{
public class FailingOptions
{
public string ConfigPath = "/Failing";
public List<string> EndpointPaths { get; set; } = new List<string>();
public string ConfigPath = "/Failing";
public List<string> EndpointPaths { get; set; } = new List<string>();
public List<string> NotFilteredPaths { get; set; } = new List<string>();
}
public List<string> NotFilteredPaths { get; set; } = new List<string>();
}

View File

@ -1,24 +1,20 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System;
namespace Basket.API.Infrastructure.Middlewares;
namespace Basket.API.Infrastructure.Middlewares
public class FailingStartupFilter : IStartupFilter
{
public class FailingStartupFilter : IStartupFilter
private readonly Action<FailingOptions> _options;
public FailingStartupFilter(Action<FailingOptions> optionsAction)
{
private readonly Action<FailingOptions> _options;
public FailingStartupFilter(Action<FailingOptions> optionsAction)
{
_options = optionsAction;
}
_options = optionsAction;
}
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return app =>
{
return app =>
{
app.UseFailingMiddleware(_options);
next(app);
};
}
app.UseFailingMiddleware(_options);
next(app);
};
}
}

View File

@ -1,18 +1,14 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Basket.API.Infrastructure.Middlewares;
namespace Basket.API.Infrastructure.Middlewares
public static class WebHostBuildertExtensions
{
public static class WebHostBuildertExtensions
public static IWebHostBuilder UseFailing(this IWebHostBuilder builder, Action<FailingOptions> options)
{
public static IWebHostBuilder UseFailing(this IWebHostBuilder builder, Action<FailingOptions> options)
builder.ConfigureServices(services =>
{
builder.ConfigureServices(services =>
{
services.AddSingleton<IStartupFilter>(new FailingStartupFilter(options));
});
return builder;
}
services.AddSingleton<IStartupFilter>(new FailingStartupFilter(options));
});
return builder;
}
}

View File

@ -1,73 +1,64 @@
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories
public class RedisBasketRepository : IBasketRepository
{
public class RedisBasketRepository : IBasketRepository
private readonly ILogger<RedisBasketRepository> _logger;
private readonly ConnectionMultiplexer _redis;
private readonly IDatabase _database;
public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis)
{
private readonly ILogger<RedisBasketRepository> _logger;
private readonly ConnectionMultiplexer _redis;
private readonly IDatabase _database;
_logger = loggerFactory.CreateLogger<RedisBasketRepository>();
_redis = redis;
_database = redis.GetDatabase();
}
public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis)
public async Task<bool> DeleteBasketAsync(string id)
{
return await _database.KeyDeleteAsync(id);
}
public IEnumerable<string> GetUsers()
{
var server = GetServer();
var data = server.Keys();
return data?.Select(k => k.ToString());
}
public async Task<CustomerBasket> GetBasketAsync(string customerId)
{
var data = await _database.StringGetAsync(customerId);
if (data.IsNullOrEmpty)
{
_logger = loggerFactory.CreateLogger<RedisBasketRepository>();
_redis = redis;
_database = redis.GetDatabase();
return null;
}
public async Task<bool> DeleteBasketAsync(string id)
return JsonSerializer.Deserialize<CustomerBasket>(data, new JsonSerializerOptions
{
return await _database.KeyDeleteAsync(id);
PropertyNameCaseInsensitive = true
});
}
public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket)
{
var created = await _database.StringSetAsync(basket.BuyerId, JsonSerializer.Serialize(basket));
if (!created)
{
_logger.LogInformation("Problem occur persisting the item.");
return null;
}
public IEnumerable<string> GetUsers()
{
var server = GetServer();
var data = server.Keys();
_logger.LogInformation("Basket item persisted succesfully.");
return data?.Select(k => k.ToString());
}
return await GetBasketAsync(basket.BuyerId);
}
public async Task<CustomerBasket> GetBasketAsync(string customerId)
{
var data = await _database.StringGetAsync(customerId);
if (data.IsNullOrEmpty)
{
return null;
}
return JsonSerializer.Deserialize<CustomerBasket>(data, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
public async Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket)
{
var created = await _database.StringSetAsync(basket.BuyerId, JsonSerializer.Serialize(basket));
if (!created)
{
_logger.LogInformation("Problem occur persisting the item.");
return null;
}
_logger.LogInformation("Basket item persisted succesfully.");
return await GetBasketAsync(basket.BuyerId);
}
private IServer GetServer()
{
var endpoint = _redis.GetEndPoints();
return _redis.GetServer(endpoint.First());
}
private IServer GetServer()
{
var endpoint = _redis.GetEndPoints();
return _redis.GetServer(endpoint.First());
}
}

View File

@ -1,37 +1,29 @@
using Basket.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using System;
using System.Threading.Tasks;
namespace Basket.API.IntegrationEvents.EventHandling;
namespace Basket.API.IntegrationEvents.EventHandling
public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler<OrderStartedIntegrationEvent>
{
public class OrderStartedIntegrationEventHandler : IIntegrationEventHandler<OrderStartedIntegrationEvent>
private readonly IBasketRepository _repository;
private readonly ILogger<OrderStartedIntegrationEventHandler> _logger;
public OrderStartedIntegrationEventHandler(
IBasketRepository repository,
ILogger<OrderStartedIntegrationEventHandler> logger)
{
private readonly IBasketRepository _repository;
private readonly ILogger<OrderStartedIntegrationEventHandler> _logger;
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public OrderStartedIntegrationEventHandler(
IBasketRepository repository,
ILogger<OrderStartedIntegrationEventHandler> logger)
public async Task Handle(OrderStartedIntegrationEvent @event)
{
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
public async Task Handle(OrderStartedIntegrationEvent @event)
{
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
await _repository.DeleteBasketAsync(@event.UserId.ToString());
}
await _repository.DeleteBasketAsync(@event.UserId.ToString());
}
}
}

View File

@ -1,64 +1,53 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.Extensions.Logging;
using Serilog.Context;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling;
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling
public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>
{
public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>
private readonly ILogger<ProductPriceChangedIntegrationEventHandler> _logger;
private readonly IBasketRepository _repository;
public ProductPriceChangedIntegrationEventHandler(
ILogger<ProductPriceChangedIntegrationEventHandler> logger,
IBasketRepository repository)
{
private readonly ILogger<ProductPriceChangedIntegrationEventHandler> _logger;
private readonly IBasketRepository _repository;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
public ProductPriceChangedIntegrationEventHandler(
ILogger<ProductPriceChangedIntegrationEventHandler> logger,
IBasketRepository repository)
public async Task Handle(ProductPriceChangedIntegrationEvent @event)
{
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
public async Task Handle(ProductPriceChangedIntegrationEvent @event)
{
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}"))
var userIds = _repository.GetUsers();
foreach (var id in userIds)
{
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event);
var basket = await _repository.GetBasketAsync(id);
var userIds = _repository.GetUsers();
foreach (var id in userIds)
{
var basket = await _repository.GetBasketAsync(id);
await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket);
}
}
}
private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket)
{
var itemsToUpdate = basket?.Items?.Where(x => x.ProductId == productId).ToList();
if (itemsToUpdate != null)
{
_logger.LogInformation("----- ProductPriceChangedIntegrationEventHandler - Updating items in basket for user: {BuyerId} ({@Items})", basket.BuyerId, itemsToUpdate);
foreach (var item in itemsToUpdate)
{
if (item.UnitPrice == oldPrice)
{
var originalPrice = item.UnitPrice;
item.UnitPrice = newPrice;
item.OldUnitPrice = originalPrice;
}
}
await _repository.UpdateBasketAsync(basket);
await UpdatePriceInBasketItems(@event.ProductId, @event.NewPrice, @event.OldPrice, basket);
}
}
}
}
private async Task UpdatePriceInBasketItems(int productId, decimal newPrice, decimal oldPrice, CustomerBasket basket)
{
var itemsToUpdate = basket?.Items?.Where(x => x.ProductId == productId).ToList();
if (itemsToUpdate != null)
{
_logger.LogInformation("----- ProductPriceChangedIntegrationEventHandler - Updating items in basket for user: {BuyerId} ({@Items})", basket.BuyerId, itemsToUpdate);
foreach (var item in itemsToUpdate)
{
if (item.UnitPrice == oldPrice)
{
var originalPrice = item.UnitPrice;
item.UnitPrice = newPrice;
item.OldUnitPrice = originalPrice;
}
}
await _repository.UpdateBasketAsync(basket);
}
}
}

View File

@ -1,15 +1,13 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
namespace Basket.API.IntegrationEvents.Events;
namespace Basket.API.IntegrationEvents.Events
// Integration Events notes:
// An Event is "something that has happened in the past", therefore its name has to be
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
public record OrderStartedIntegrationEvent : IntegrationEvent
{
// Integration Events notes:
// An Event is “something that has happened in the past”, therefore its name has to be
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
public record OrderStartedIntegrationEvent : IntegrationEvent
{
public string UserId { get; init; }
public string UserId { get; init; }
public OrderStartedIntegrationEvent(string userId)
=> UserId = userId;
}
public OrderStartedIntegrationEvent(string userId)
=> UserId = userId;
}

View File

@ -1,23 +1,21 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
namespace Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events
// Integration Events notes:
// An Event is "something that has happened in the past", therefore its name has to be
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
public record ProductPriceChangedIntegrationEvent : IntegrationEvent
{
// Integration Events notes:
// An Event is “something that has happened in the past”, therefore its name has to be
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
public record ProductPriceChangedIntegrationEvent : IntegrationEvent
public int ProductId { get; private init; }
public decimal NewPrice { get; private init; }
public decimal OldPrice { get; private init; }
public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice)
{
public int ProductId { get; private init; }
public decimal NewPrice { get; private init; }
public decimal OldPrice { get; private init; }
public ProductPriceChangedIntegrationEvent(int productId, decimal newPrice, decimal oldPrice)
{
ProductId = productId;
NewPrice = newPrice;
OldPrice = oldPrice;
}
ProductId = productId;
NewPrice = newPrice;
OldPrice = oldPrice;
}
}

View File

@ -1,64 +1,59 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using System;
namespace Basket.API.IntegrationEvents.Events;
namespace Basket.API.IntegrationEvents.Events
public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent
{
public record UserCheckoutAcceptedIntegrationEvent : IntegrationEvent
public string UserId { get; }
public string UserName { get; }
public int OrderNumber { get; init; }
public string City { get; init; }
public string Street { get; init; }
public string State { get; init; }
public string Country { get; init; }
public string ZipCode { get; init; }
public string CardNumber { get; init; }
public string CardHolderName { get; init; }
public DateTime CardExpiration { get; init; }
public string CardSecurityNumber { get; init; }
public int CardTypeId { get; init; }
public string Buyer { get; init; }
public Guid RequestId { get; init; }
public CustomerBasket Basket { get; }
public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street,
string state, string country, string zipCode, string cardNumber, string cardHolderName,
DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId,
CustomerBasket basket)
{
public string UserId { get; }
public string UserName { get; }
public int OrderNumber { get; init; }
public string City { get; init; }
public string Street { get; init; }
public string State { get; init; }
public string Country { get; init; }
public string ZipCode { get; init; }
public string CardNumber { get; init; }
public string CardHolderName { get; init; }
public DateTime CardExpiration { get; init; }
public string CardSecurityNumber { get; init; }
public int CardTypeId { get; init; }
public string Buyer { get; init; }
public Guid RequestId { get; init; }
public CustomerBasket Basket { get; }
public UserCheckoutAcceptedIntegrationEvent(string userId, string userName, string city, string street,
string state, string country, string zipCode, string cardNumber, string cardHolderName,
DateTime cardExpiration, string cardSecurityNumber, int cardTypeId, string buyer, Guid requestId,
CustomerBasket basket)
{
UserId = userId;
UserName = userName;
City = city;
Street = street;
State = state;
Country = country;
ZipCode = zipCode;
CardNumber = cardNumber;
CardHolderName = cardHolderName;
CardExpiration = cardExpiration;
CardSecurityNumber = cardSecurityNumber;
CardTypeId = cardTypeId;
Buyer = buyer;
Basket = basket;
RequestId = requestId;
}
UserId = userId;
UserName = userName;
City = city;
Street = street;
State = state;
Country = country;
ZipCode = zipCode;
CardNumber = cardNumber;
CardHolderName = cardHolderName;
CardExpiration = cardExpiration;
CardSecurityNumber = cardSecurityNumber;
CardTypeId = cardTypeId;
Buyer = buyer;
Basket = basket;
RequestId = requestId;
}
}

View File

@ -1,32 +1,28 @@
using System;
namespace Basket.API.Model;
namespace Basket.API.Model
public class BasketCheckout
{
public class BasketCheckout
{
public string City { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string Street { get; set; }
public string State { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string Country { get; set; }
public string ZipCode { get; set; }
public string ZipCode { get; set; }
public string CardNumber { get; set; }
public string CardNumber { get; set; }
public string CardHolderName { get; set; }
public string CardHolderName { get; set; }
public DateTime CardExpiration { get; set; }
public DateTime CardExpiration { get; set; }
public string CardSecurityNumber { get; set; }
public string CardSecurityNumber { get; set; }
public int CardTypeId { get; set; }
public int CardTypeId { get; set; }
public string Buyer { get; set; }
public string Buyer { get; set; }
public Guid RequestId { get; set; }
}
public Guid RequestId { get; set; }
}

View File

@ -1,27 +1,24 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
public class BasketItem : IValidatableObject
{
public class BasketItem : IValidatableObject
public string Id { get; set; }
public int ProductId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public decimal OldUnitPrice { get; set; }
public int Quantity { get; set; }
public string PictureUrl { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
public string Id { get; set; }
public int ProductId { get; set; }
public string ProductName { get; set; }
public decimal UnitPrice { get; set; }
public decimal OldUnitPrice { get; set; }
public int Quantity { get; set; }
public string PictureUrl { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
var results = new List<ValidationResult>();
if (Quantity < 1)
{
var results = new List<ValidationResult>();
if (Quantity < 1)
{
results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" }));
}
return results;
results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" }));
}
return results;
}
}

View File

@ -1,21 +1,19 @@
using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
public class CustomerBasket
{
public class CustomerBasket
public string BuyerId { get; set; }
public List<BasketItem> Items { get; set; } = new();
public CustomerBasket()
{
public string BuyerId { get; set; }
public List<BasketItem> Items { get; set; } = new List<BasketItem>();
}
public CustomerBasket()
{
}
public CustomerBasket(string customerId)
{
BuyerId = customerId;
}
public CustomerBasket(string customerId)
{
BuyerId = customerId;
}
}

View File

@ -1,13 +1,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Model
public interface IBasketRepository
{
public interface IBasketRepository
{
Task<CustomerBasket> GetBasketAsync(string customerId);
IEnumerable<string> GetUsers();
Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket);
Task<bool> DeleteBasketAsync(string id);
}
Task<CustomerBasket> GetBasketAsync(string customerId);
IEnumerable<string> GetUsers();
Task<CustomerBasket> UpdateBasketAsync(CustomerBasket basket);
Task<bool> DeleteBasketAsync(string id);
}

View File

@ -1,18 +1,4 @@
using Basket.API.Infrastructure.Middlewares;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.eShopOnContainers.Services.Basket.API;
using Microsoft.Extensions.Configuration;
using Azure.Identity;
using Serilog;
using System;
using System.IO;
using System.Net;
using Azure.Core;
var configuration = GetConfiguration();
var configuration = GetConfiguration();
Log.Logger = CreateSerilogLogger(configuration);

View File

@ -1,7 +1,7 @@
namespace Microsoft.eShopOnContainers.Services.Basket.API.Services
namespace Microsoft.eShopOnContainers.Services.Basket.API.Services;
public interface IIdentityService
{
public interface IIdentityService
{
string GetUserIdentity();
}
string GetUserIdentity();
}

View File

@ -1,21 +1,17 @@

using Microsoft.AspNetCore.Http;
using System;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Services;
namespace Microsoft.eShopOnContainers.Services.Basket.API.Services
public class IdentityService : IIdentityService
{
public class IdentityService : IIdentityService
private IHttpContextAccessor _context;
public IdentityService(IHttpContextAccessor context)
{
private IHttpContextAccessor _context;
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public IdentityService(IHttpContextAccessor context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public string GetUserIdentity()
{
return _context.HttpContext.User.FindFirst("sub").Value;
}
public string GetUserIdentity()
{
return _context.HttpContext.User.FindFirst("sub").Value;
}
}

View File

@ -1,363 +1,325 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Basket.API.Infrastructure.Filters;
using Basket.API.IntegrationEvents.EventHandling;
using Basket.API.IntegrationEvents.Events;
using GrpcBasket;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.ServiceBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
using Microsoft.eShopOnContainers.Services.Basket.API.Controllers;
using Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Repositories;
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.EventHandling;
using Microsoft.eShopOnContainers.Services.Basket.API.IntegrationEvents.Events;
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
using Microsoft.eShopOnContainers.Services.Basket.API.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using RabbitMQ.Client;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
namespace Microsoft.eShopOnContainers.Services.Basket.API;
namespace Microsoft.eShopOnContainers.Services.Basket.API
public class Startup
{
public class Startup
public Startup(IConfiguration configuration)
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddGrpc(options =>
{
options.EnableDetailedErrors = true;
});
RegisterAppInsights(services);
services.AddControllers(options =>
{
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
options.Filters.Add(typeof(ValidateModelStateFilter));
}) // Added for functional tests
.AddApplicationPart(typeof(BasketController).Assembly)
.AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "eShopOnContainers - Basket HTTP API",
Version = "v1",
Description = "The Basket Service HTTP API"
});
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows()
{
Implicit = new OpenApiOAuthFlow()
{
AuthorizationUrl = new Uri($"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
TokenUrl = new Uri($"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
Scopes = new Dictionary<string, string>()
{
{ "basket", "Basket API" }
}
}
}
});
options.OperationFilter<AuthorizeCheckOperationFilter>();
});
ConfigureAuthService(services);
services.AddCustomHealthCheck(Configuration);
services.Configure<BasketSettings>(Configuration);
//By connecting here we are making sure that our service
//cannot start until redis is ready. This might slow down startup,
//but given that there is a delay on resolving the ip address
//and then creating the connection it seems reasonable to move
//that cost to startup instead of having the first request pay the
//penalty.
services.AddSingleton<ConnectionMultiplexer>(sp =>
{
var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;
var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);
configuration.ResolveDns = true;
return ConnectionMultiplexer.Connect(configuration);
});
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{
var serviceBusConnectionString = Configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
var subscriptionClientName = Configuration["SubscriptionClientName"];
return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName);
});
}
else
{
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory()
{
HostName = Configuration["EventBusConnection"],
DispatchConsumersAsync = true
};
if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
{
factory.UserName = Configuration["EventBusUserName"];
}
if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
{
factory.Password = Configuration["EventBusPassword"];
}
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
RegisterEventBus(services);
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IBasketRepository, RedisBasketRepository>();
services.AddTransient<IIdentityService, IdentityService>();
services.AddOptions();
var container = new ContainerBuilder();
container.Populate(services);
return new AutofacServiceProvider(container.Build());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
//loggerFactory.AddAzureWebAppDiagnostics();
//loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
app.UsePathBase(pathBase);
}
app.UseSwagger()
.UseSwaggerUI(setup =>
{
setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1");
setup.OAuthClientId("basketswaggerui");
setup.OAuthAppName("Basket Swagger UI");
});
app.UseRouting();
app.UseCors("CorsPolicy");
ConfigureAuth(app);
app.UseStaticFiles();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<BasketService>();
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers();
endpoints.MapGet("/_proto/", async ctx =>
{
ctx.Response.ContentType = "text/plain";
using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs);
while (!sr.EndOfStream)
{
var line = await sr.ReadLineAsync();
if (line != "/* >>" || line != "<< */")
{
await ctx.Response.WriteAsync(line);
}
}
});
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions
{
Predicate = r => r.Name.Contains("self")
});
});
ConfigureEventBus(app);
}
private void RegisterAppInsights(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.AddApplicationInsightsKubernetesEnricher();
}
private void ConfigureAuthService(IServiceCollection services)
{
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "basket";
});
}
protected virtual void ConfigureAuth(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseAuthorization();
}
private void RegisterEventBus(IServiceCollection services)
{
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, iLifetimeScope);
});
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var subscriptionClientName = Configuration["SubscriptionClientName"];
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
services.AddTransient<ProductPriceChangedIntegrationEventHandler>();
services.AddTransient<OrderStartedIntegrationEventHandler>();
}
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
}
Configuration = configuration;
}
public static class CustomExtensionMethods
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
services.AddGrpc(options =>
{
var hcBuilder = services.AddHealthChecks();
options.EnableDetailedErrors = true;
});
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy());
RegisterAppInsights(services);
hcBuilder
.AddRedis(
configuration["ConnectionString"],
name: "redis-check",
tags: new string[] { "redis" });
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
services.AddControllers(options =>
{
hcBuilder
.AddAzureServiceBusTopic(
configuration["EventBusConnection"],
topicName: "eshop_event_bus",
name: "basket-servicebus-check",
tags: new string[] { "servicebus" });
}
else
{
hcBuilder
.AddRabbitMQ(
$"amqp://{configuration["EventBusConnection"]}",
name: "basket-rabbitmqbus-check",
tags: new string[] { "rabbitmqbus" });
}
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
options.Filters.Add(typeof(ValidateModelStateFilter));
return services;
}) // Added for functional tests
.AddApplicationPart(typeof(BasketController).Assembly)
.AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "eShopOnContainers - Basket HTTP API",
Version = "v1",
Description = "The Basket Service HTTP API"
});
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows()
{
Implicit = new OpenApiOAuthFlow()
{
AuthorizationUrl = new Uri($"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
TokenUrl = new Uri($"{Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
Scopes = new Dictionary<string, string>()
{
{ "basket", "Basket API" }
}
}
}
});
options.OperationFilter<AuthorizeCheckOperationFilter>();
});
ConfigureAuthService(services);
services.AddCustomHealthCheck(Configuration);
services.Configure<BasketSettings>(Configuration);
//By connecting here we are making sure that our service
//cannot start until redis is ready. This might slow down startup,
//but given that there is a delay on resolving the ip address
//and then creating the connection it seems reasonable to move
//that cost to startup instead of having the first request pay the
//penalty.
services.AddSingleton<ConnectionMultiplexer>(sp =>
{
var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value;
var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true);
configuration.ResolveDns = true;
return ConnectionMultiplexer.Connect(configuration);
});
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{
var serviceBusConnectionString = Configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
var subscriptionClientName = Configuration["SubscriptionClientName"];
return new DefaultServiceBusPersisterConnection(serviceBusConnection, subscriptionClientName);
});
}
else
{
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory()
{
HostName = Configuration["EventBusConnection"],
DispatchConsumersAsync = true
};
if (!string.IsNullOrEmpty(Configuration["EventBusUserName"]))
{
factory.UserName = Configuration["EventBusUserName"];
}
if (!string.IsNullOrEmpty(Configuration["EventBusPassword"]))
{
factory.Password = Configuration["EventBusPassword"];
}
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
RegisterEventBus(services);
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IBasketRepository, RedisBasketRepository>();
services.AddTransient<IIdentityService, IdentityService>();
services.AddOptions();
var container = new ContainerBuilder();
container.Populate(services);
return new AutofacServiceProvider(container.Build());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
//loggerFactory.AddAzureWebAppDiagnostics();
//loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
app.UsePathBase(pathBase);
}
app.UseSwagger()
.UseSwaggerUI(setup =>
{
setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1");
setup.OAuthClientId("basketswaggerui");
setup.OAuthAppName("Basket Swagger UI");
});
app.UseRouting();
app.UseCors("CorsPolicy");
ConfigureAuth(app);
app.UseStaticFiles();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<BasketService>();
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers();
endpoints.MapGet("/_proto/", async ctx =>
{
ctx.Response.ContentType = "text/plain";
using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read);
using var sr = new StreamReader(fs);
while (!sr.EndOfStream)
{
var line = await sr.ReadLineAsync();
if (line != "/* >>" || line != "<< */")
{
await ctx.Response.WriteAsync(line);
}
}
});
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions
{
Predicate = r => r.Name.Contains("self")
});
});
ConfigureEventBus(app);
}
private void RegisterAppInsights(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
services.AddApplicationInsightsKubernetesEnricher();
}
private void ConfigureAuthService(IServiceCollection services)
{
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.Audience = "basket";
});
}
protected virtual void ConfigureAuth(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseAuthorization();
}
private void RegisterEventBus(IServiceCollection services)
{
if (Configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, iLifetimeScope);
});
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{
var subscriptionClientName = Configuration["SubscriptionClientName"];
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5;
if (!string.IsNullOrEmpty(Configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(Configuration["EventBusRetryCount"]);
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
});
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
services.AddTransient<ProductPriceChangedIntegrationEventHandler>();
services.AddTransient<OrderStartedIntegrationEventHandler>();
}
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>();
}
}
public static class CustomExtensionMethods
{
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
{
var hcBuilder = services.AddHealthChecks();
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy());
hcBuilder
.AddRedis(
configuration["ConnectionString"],
name: "redis-check",
tags: new string[] { "redis" });
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
hcBuilder
.AddAzureServiceBusTopic(
configuration["EventBusConnection"],
topicName: "eshop_event_bus",
name: "basket-servicebus-check",
tags: new string[] { "servicebus" });
}
else
{
hcBuilder
.AddRabbitMQ(
$"amqp://{configuration["EventBusConnection"]}",
name: "basket-rabbitmqbus-check",
tags: new string[] { "rabbitmqbus" });
}
return services;
}
}

View File

@ -1,10 +1,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
namespace Microsoft.eShopOnContainers.Services.Basket.API;
namespace Microsoft.eShopOnContainers.Services.Basket.API
internal class TestHttpResponseTrailersFeature : IHttpResponseTrailersFeature
{
internal class TestHttpResponseTrailersFeature : IHttpResponseTrailersFeature
{
public IHeaderDictionary Trailers { get; set; }
}
public IHeaderDictionary Trailers { get; set; }
}

View File

@ -1,9 +1,9 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,4 @@
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates
namespace Microsoft.eShopOnContainers.Services.Identity.API.Certificates
{
static class Certificate
{

View File

@ -1,6 +1,4 @@
using IdentityServer4;
using IdentityServer4.Models;
using System.Collections.Generic;
using IdentityServer4.Models;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
{
@ -93,6 +91,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Configuration
ClientName = "MVC Client",
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
ClientUri = $"{clientsUrl["Mvc"]}", // public uri of the client

View File

@ -1,23 +1,4 @@
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
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.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
/// <summary>
/// This sample controller implements a typical login/logout/provision workflow for local accounts.

View File

@ -1,13 +1,4 @@
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;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
/// <summary>
/// This controller implements the consent logic

View File

@ -1,12 +1,4 @@

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 Microsoft.eShopOnContainers.Services.Identity.API.Controllers
namespace Microsoft.eShopOnContainers.Services.Identity.API.Controllers
{
public class HomeController : Controller
{

View File

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

View File

@ -1,18 +1,4 @@
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
namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{
@ -58,7 +44,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
}
}
private IEnumerable<ApplicationUser> GetUsersFromFile(string contentRootPath, ILogger logger)
private IEnumerable<ApplicationUser> GetUsersFromFile(string contentRootPath, Microsoft.Extensions.Logging.ILogger logger)
{
string csvFileUsers = Path.Combine(contentRootPath, "Setup", "Users.csv");
@ -192,7 +178,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
return csvheaders;
}
static void GetPreconfiguredImages(string contentRootPath, string webroot, ILogger logger)
static void GetPreconfiguredImages(string contentRootPath, string webroot, Microsoft.Extensions.Logging.ILogger logger)
{
try
{

View File

@ -1,12 +1,4 @@
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Entities;
using IdentityServer4.EntityFramework.Mappers;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.EntityFramework.Entities;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Data
{

View File

@ -1,27 +1,21 @@
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces
{
public class DevspacesRedirectUriValidator : IRedirectUriValidator
{
private readonly ILogger _logger;
private readonly Microsoft.Extensions.Logging.ILogger _logger;
public DevspacesRedirectUriValidator(ILogger<DevspacesRedirectUriValidator> logger)
{
_logger = logger;
}
public Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client)
public Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, IdentityServer4.Models.Client client)
{
_logger.LogInformation("Client {ClientName} used post logout uri {RequestedUri}.", client.ClientName, requestedUri);
return Task.FromResult(true);
}
public Task<bool> IsRedirectUriValidAsync(string requestedUri, Client client)
public Task<bool> IsRedirectUriValidAsync(string requestedUri, IdentityServer4.Models.Client client)
{
_logger.LogInformation("Client {ClientName} used post logout uri {RequestedUri}.", client.ClientName, requestedUri);
return Task.FromResult(true);

View File

@ -1,6 +1,4 @@
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces
namespace Microsoft.eShopOnContainers.Services.Identity.API.Devspaces
{
static class IdentityDevspacesBuilderExtensions
{

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

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

View File

@ -1,10 +1,4 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace Identity.API.Factories
namespace Identity.API.Factories
{
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{

View File

@ -1,11 +1,4 @@
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Options;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace Identity.API.Factories
namespace Identity.API.Factories
{
public class ConfigurationDbContextFactory : IDesignTimeDbContextFactory<ConfigurationDbContext>
{

View File

@ -1,11 +1,4 @@
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Options;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace Identity.API.Factories
namespace Identity.API.Factories
{
public class PersistedGrantDbContextFactory : IDesignTimeDbContextFactory<PersistedGrantDbContext>
{

View File

@ -0,0 +1,183 @@
global using Microsoft.eShopOnContainers.Services.Identity.API.Extensions;
global using System.IO.Compression;
global using Autofac.Extensions.DependencyInjection;
global using Autofac;
global using Azure.Core;
global using Azure.Identity;
global using HealthChecks.UI.Client;
global using IdentityModel;
global using IdentityServer4.EntityFramework.DbContexts;
global using IdentityServer4.EntityFramework.Mappers;
global using IdentityServer4.EntityFramework.Options;
global using IdentityServer4.Models;
global using IdentityServer4.Services;
global using IdentityServer4.Stores;
global using IdentityServer4.Validation;
global using IdentityServer4;
global using Microsoft.AspNetCore.Authentication;
global using Microsoft.AspNetCore.Authorization;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Diagnostics.HealthChecks;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
global using Microsoft.AspNetCore.Identity;
global using Microsoft.AspNetCore.Mvc.Rendering;
global using Microsoft.AspNetCore.Mvc;
global using Microsoft.AspNetCore;
global using Microsoft.EntityFrameworkCore.Design;
global using Microsoft.EntityFrameworkCore.Infrastructure;
global using Microsoft.EntityFrameworkCore.Metadata;
global using Microsoft.EntityFrameworkCore.Migrations;
global using Microsoft.EntityFrameworkCore;
global using Microsoft.eShopOnContainers.Services.Identity.API.Certificates;
global using Microsoft.eShopOnContainers.Services.Identity.API.Configuration;
global using Microsoft.eShopOnContainers.Services.Identity.API.Data;
global using Microsoft.eShopOnContainers.Services.Identity.API.Devspaces;
global using Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels;
global using Microsoft.eShopOnContainers.Services.Identity.API.Models;
global using Microsoft.eShopOnContainers.Services.Identity.API.Services;
global using Microsoft.eShopOnContainers.Services.Identity.API;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Diagnostics.HealthChecks;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Options;
global using Polly;
global using Serilog;
global using StackExchange.Redis;
global using System.Collections.Generic;
global using System.ComponentModel.DataAnnotations;
global using System.Data.SqlClient;
global using System.IdentityModel.Tokens.Jwt;
global using System.IO;
global using System.Linq;
global using System.Reflection;
global using System.Security.Claims;
global using System.Security.Cryptography.X509Certificates;
global using System.Text.RegularExpressions;
global using System.Threading.Tasks;
global using System;

View File

@ -1,11 +1,3 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Polly;
using System;
using System.Data.SqlClient;
namespace Microsoft.AspNetCore.Hosting
{
public static class IWebHostExtensions

View File

@ -16,41 +16,44 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="5.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="5.0.3" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="5.0.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.1.0" />
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageReference Include="Azure.Identity" Version="1.4.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="7.2.0-preview.1" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="3.1.4" />
<PackageReference Include="IdentityServer4.EntityFramework.Storage" Version="3.1.4" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="3.1.4" />
<PackageReference Include="IdentityServer4.Storage" Version="3.1.4" />
<PackageReference Include="IdentityServer4" Version="3.1.4" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.16.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.3" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="5.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.18.0" />
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.18.0" />
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="2.0.2-beta2" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.HealthChecks" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.2">
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0-preview.7.21378.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.0-preview.7.21378.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0-preview.7.21378.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.18" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.0-preview.7.21378.6" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.11.1" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.113" />
<PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.3" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.1-dev-00216" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0-dev-00834" />
<PackageReference Include="Serilog.Sinks.Http" Version="7.2.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.1.0-dev-00166" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
<PackageReference Include="Polly" Version="7.2.2" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.1-dev-00229" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.1-dev-00787" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0-dev-00291" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1-dev-00876" />
<PackageReference Include="Serilog.Sinks.Http" Version="8.0.0-beta.9" />
<PackageReference Include="Serilog.Sinks.Seq" Version="5.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.2.1" />
<PackageReference Include="System.Data.SqlClient" version="4.8.2"/>
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.2.1" />
<PackageReference Include="Azure.Identity" Version="1.4.0" />
</ItemGroup>
<ItemGroup>

View File

@ -10,209 +10,258 @@ using Microsoft.eShopOnContainers.Services.Identity.API.Data;
namespace Identity.API.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20190729091724_InitialMigration")]
[Migration("20210813072445_InitialMigration")]
partial class InitialMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id");
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Identity.API.Models.ApplicationUser", b =>
{
b.Property<string>("Id");
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("CardHolderName")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("CardNumber")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("CardType");
b.Property<int>("CardType")
.HasColumnType("int");
b.Property<string>("City")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Country")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("Expiration")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityNumber")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SecurityStamp");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<string>("State")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Street")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ZipCode")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex")
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>

View File

@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Identity.API.Migrations
{
@ -12,10 +11,10 @@ namespace Identity.API.Migrations
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
@ -26,33 +25,33 @@ namespace Identity.API.Migrations
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false),
CardNumber = table.Column<string>(nullable: false),
SecurityNumber = table.Column<string>(nullable: false),
Expiration = table.Column<string>(nullable: false),
CardHolderName = table.Column<string>(nullable: false),
CardType = table.Column<int>(nullable: false),
Street = table.Column<string>(nullable: false),
City = table.Column<string>(nullable: false),
State = table.Column<string>(nullable: false),
Country = table.Column<string>(nullable: false),
ZipCode = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false),
LastName = table.Column<string>(nullable: false)
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
CardNumber = table.Column<string>(type: "nvarchar(max)", nullable: false),
SecurityNumber = table.Column<string>(type: "nvarchar(max)", nullable: false),
Expiration = table.Column<string>(type: "nvarchar(max)", nullable: false),
CardHolderName = table.Column<string>(type: "nvarchar(max)", nullable: false),
CardType = table.Column<int>(type: "int", nullable: false),
Street = table.Column<string>(type: "nvarchar(max)", nullable: false),
City = table.Column<string>(type: "nvarchar(max)", nullable: false),
State = table.Column<string>(type: "nvarchar(max)", nullable: false),
Country = table.Column<string>(type: "nvarchar(max)", nullable: false),
ZipCode = table.Column<string>(type: "nvarchar(max)", nullable: false),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
LastName = table.Column<string>(type: "nvarchar(max)", nullable: false),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -63,11 +62,11 @@ namespace Identity.API.Migrations
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
@ -84,11 +83,11 @@ namespace Identity.API.Migrations
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
@ -105,10 +104,10 @@ namespace Identity.API.Migrations
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(nullable: false),
ProviderKey = table.Column<string>(nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderKey = table.Column<string>(type: "nvarchar(450)", nullable: false),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
@ -125,8 +124,8 @@ namespace Identity.API.Migrations
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
@ -149,10 +148,10 @@ namespace Identity.API.Migrations
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false),
Value = table.Column<string>(nullable: true)
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
LoginProvider = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(450)", nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{

View File

@ -15,202 +15,251 @@ namespace Identity.API.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id");
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex")
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");
b.ToTable("AspNetRoles");
b.ToTable("AspNetRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("RoleId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
b.ToTable("AspNetRoleClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("ClaimType");
b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");
b.Property<string>("ClaimValue");
b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
b.ToTable("AspNetUserClaims", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderKey")
.HasColumnType("nvarchar(450)");
b.Property<string>("ProviderDisplayName");
b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("UserId")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(450)");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
b.ToTable("AspNetUserLogins", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("RoleId");
b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
b.ToTable("AspNetUserRoles", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("LoginProvider");
b.Property<string>("LoginProvider")
.HasColumnType("nvarchar(450)");
b.Property<string>("Name");
b.Property<string>("Name")
.HasColumnType("nvarchar(450)");
b.Property<string>("Value");
b.Property<string>("Value")
.HasColumnType("nvarchar(max)");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
b.ToTable("AspNetUserTokens", (string)null);
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Identity.API.Models.ApplicationUser", b =>
{
b.Property<string>("Id");
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");
b.Property<int>("AccessFailedCount");
b.Property<int>("AccessFailedCount")
.HasColumnType("int");
b.Property<string>("CardHolderName")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("CardNumber")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("CardType");
b.Property<int>("CardType")
.HasColumnType("int");
b.Property<string>("City")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");
b.Property<string>("Country")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Email")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<bool>("EmailConfirmed");
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("Expiration")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("LockoutEnabled");
b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");
b.Property<string>("Name")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("PasswordHash");
b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");
b.Property<string>("PhoneNumber");
b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");
b.Property<string>("SecurityNumber")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("SecurityStamp");
b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");
b.Property<string>("State")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Street")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("TwoFactorEnabled");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");
b.Property<string>("UserName")
.HasMaxLength(256);
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("ZipCode")
.IsRequired();
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
.HasDatabaseName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex")
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");
b.ToTable("AspNetUsers");
b.ToTable("AspNetUsers", (string)null);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>

View File

@ -10,116 +10,140 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Identity.API.Migrations.ConfigurationDb
{
[DbContext(typeof(ConfigurationDbContext))]
[Migration("20190729092011_InitialConfigurationMigration")]
partial class InitialConfigurationMigration
[Migration("20210813072543_InitialMigration")]
partial class InitialMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<DateTime?>("LastAccessed");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("ApiResources");
b.ToTable("ApiResources", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiClaims");
b.ToTable("ApiClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiProperties");
b.ToTable("ApiProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Emphasize");
b.Property<bool>("Emphasize")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Required");
b.Property<bool>("Required")
.HasColumnType("bit");
b.Property<bool>("ShowInDiscoveryDocument");
b.Property<bool>("ShowInDiscoveryDocument")
.HasColumnType("bit");
b.HasKey("Id");
@ -128,435 +152,538 @@ namespace Identity.API.Migrations.ConfigurationDb
b.HasIndex("Name")
.IsUnique();
b.ToTable("ApiScopes");
b.ToTable("ApiScopes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiScopeId");
b.Property<int>("ApiScopeId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ApiScopeId");
b.ToTable("ApiScopeClaims");
b.ToTable("ApiScopeClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(4000);
.HasMaxLength(4000)
.HasColumnType("nvarchar(4000)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiSecrets");
b.ToTable("ApiSecrets", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("AbsoluteRefreshTokenLifetime");
b.Property<int>("AbsoluteRefreshTokenLifetime")
.HasColumnType("int");
b.Property<int>("AccessTokenLifetime");
b.Property<int>("AccessTokenLifetime")
.HasColumnType("int");
b.Property<int>("AccessTokenType");
b.Property<int>("AccessTokenType")
.HasColumnType("int");
b.Property<bool>("AllowAccessTokensViaBrowser");
b.Property<bool>("AllowAccessTokensViaBrowser")
.HasColumnType("bit");
b.Property<bool>("AllowOfflineAccess");
b.Property<bool>("AllowOfflineAccess")
.HasColumnType("bit");
b.Property<bool>("AllowPlainTextPkce");
b.Property<bool>("AllowPlainTextPkce")
.HasColumnType("bit");
b.Property<bool>("AllowRememberConsent");
b.Property<bool>("AllowRememberConsent")
.HasColumnType("bit");
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken");
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken")
.HasColumnType("bit");
b.Property<bool>("AlwaysSendClientClaims");
b.Property<bool>("AlwaysSendClientClaims")
.HasColumnType("bit");
b.Property<int>("AuthorizationCodeLifetime");
b.Property<int>("AuthorizationCodeLifetime")
.HasColumnType("int");
b.Property<bool>("BackChannelLogoutSessionRequired");
b.Property<bool>("BackChannelLogoutSessionRequired")
.HasColumnType("bit");
b.Property<string>("BackChannelLogoutUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("ClientClaimsPrefix")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<int?>("ConsentLifetime");
b.Property<int?>("ConsentLifetime")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<int>("DeviceCodeLifetime");
b.Property<int>("DeviceCodeLifetime")
.HasColumnType("int");
b.Property<bool>("EnableLocalLogin");
b.Property<bool>("EnableLocalLogin")
.HasColumnType("bit");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<bool>("FrontChannelLogoutSessionRequired");
b.Property<bool>("FrontChannelLogoutSessionRequired")
.HasColumnType("bit");
b.Property<string>("FrontChannelLogoutUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<int>("IdentityTokenLifetime");
b.Property<int>("IdentityTokenLifetime")
.HasColumnType("int");
b.Property<bool>("IncludeJwtId");
b.Property<bool>("IncludeJwtId")
.HasColumnType("bit");
b.Property<DateTime?>("LastAccessed");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("LogoUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<string>("PairWiseSubjectSalt")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ProtocolType")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("RefreshTokenExpiration");
b.Property<int>("RefreshTokenExpiration")
.HasColumnType("int");
b.Property<int>("RefreshTokenUsage");
b.Property<int>("RefreshTokenUsage")
.HasColumnType("int");
b.Property<bool>("RequireClientSecret");
b.Property<bool>("RequireClientSecret")
.HasColumnType("bit");
b.Property<bool>("RequireConsent");
b.Property<bool>("RequireConsent")
.HasColumnType("bit");
b.Property<bool>("RequirePkce");
b.Property<bool>("RequirePkce")
.HasColumnType("bit");
b.Property<int>("SlidingRefreshTokenLifetime");
b.Property<int>("SlidingRefreshTokenLifetime")
.HasColumnType("int");
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh");
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.Property<string>("UserCodeType")
.HasMaxLength(100);
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int?>("UserSsoLifetime");
b.Property<int?>("UserSsoLifetime")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique();
b.ToTable("Clients");
b.ToTable("Clients", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientClaims");
b.ToTable("ClientClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Origin")
.IsRequired()
.HasMaxLength(150);
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientCorsOrigins");
b.ToTable("ClientCorsOrigins", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("GrantType")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientGrantTypes");
b.ToTable("ClientGrantTypes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Provider")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientIdPRestrictions");
b.ToTable("ClientIdPRestrictions", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("PostLogoutRedirectUri")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientPostLogoutRedirectUris");
b.ToTable("ClientPostLogoutRedirectUris", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientProperties");
b.ToTable("ClientProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("RedirectUri")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientRedirectUris");
b.ToTable("ClientRedirectUris", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Scope")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientScopes");
b.ToTable("ClientScopes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(4000);
.HasMaxLength(4000)
.HasColumnType("nvarchar(4000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientSecrets");
b.ToTable("ClientSecrets", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("IdentityResourceId");
b.Property<int>("IdentityResourceId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("IdentityResourceId");
b.ToTable("IdentityClaims");
b.ToTable("IdentityClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Emphasize");
b.Property<bool>("Emphasize")
.HasColumnType("bit");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<bool>("Required");
b.Property<bool>("Required")
.HasColumnType("bit");
b.Property<bool>("ShowInDiscoveryDocument");
b.Property<bool>("ShowInDiscoveryDocument")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("IdentityResources");
b.ToTable("IdentityResources", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("IdentityResourceId");
b.Property<int>("IdentityResourceId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("IdentityResourceId");
b.ToTable("IdentityProperties");
b.ToTable("IdentityProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
@ -566,6 +693,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b =>
@ -575,6 +704,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
@ -584,6 +715,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
@ -593,6 +726,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiScopeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiScope");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
@ -602,6 +737,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
@ -611,6 +748,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
@ -620,6 +759,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
@ -629,6 +770,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
@ -638,6 +781,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
@ -647,6 +792,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b =>
@ -656,6 +803,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
@ -665,6 +814,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
@ -674,6 +825,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
@ -683,6 +836,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
@ -692,6 +847,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("IdentityResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("IdentityResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b =>
@ -701,6 +858,52 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("IdentityResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("IdentityResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
{
b.Navigation("Properties");
b.Navigation("Scopes");
b.Navigation("Secrets");
b.Navigation("UserClaims");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
{
b.Navigation("UserClaims");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
{
b.Navigation("AllowedCorsOrigins");
b.Navigation("AllowedGrantTypes");
b.Navigation("AllowedScopes");
b.Navigation("Claims");
b.Navigation("ClientSecrets");
b.Navigation("IdentityProviderRestrictions");
b.Navigation("PostLogoutRedirectUris");
b.Navigation("Properties");
b.Navigation("RedirectUris");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
{
b.Navigation("Properties");
b.Navigation("UserClaims");
});
#pragma warning restore 612, 618
}

View File

@ -1,10 +1,9 @@
using Microsoft.EntityFrameworkCore.Metadata;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Identity.API.Migrations.ConfigurationDb
{
public partial class InitialConfigurationMigration : Migration
public partial class InitialMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
@ -12,16 +11,16 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiResources",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Enabled = table.Column<bool>(nullable: false),
Name = table.Column<string>(maxLength: 200, nullable: false),
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
Description = table.Column<string>(maxLength: 1000, nullable: true),
Created = table.Column<DateTime>(nullable: false),
Updated = table.Column<DateTime>(nullable: true),
LastAccessed = table.Column<DateTime>(nullable: true),
NonEditable = table.Column<bool>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
Updated = table.Column<DateTime>(type: "datetime2", nullable: true),
LastAccessed = table.Column<DateTime>(type: "datetime2", nullable: true),
NonEditable = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
@ -32,49 +31,49 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "Clients",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Enabled = table.Column<bool>(nullable: false),
ClientId = table.Column<string>(maxLength: 200, nullable: false),
ProtocolType = table.Column<string>(maxLength: 200, nullable: false),
RequireClientSecret = table.Column<bool>(nullable: false),
ClientName = table.Column<string>(maxLength: 200, nullable: true),
Description = table.Column<string>(maxLength: 1000, nullable: true),
ClientUri = table.Column<string>(maxLength: 2000, nullable: true),
LogoUri = table.Column<string>(maxLength: 2000, nullable: true),
RequireConsent = table.Column<bool>(nullable: false),
AllowRememberConsent = table.Column<bool>(nullable: false),
AlwaysIncludeUserClaimsInIdToken = table.Column<bool>(nullable: false),
RequirePkce = table.Column<bool>(nullable: false),
AllowPlainTextPkce = table.Column<bool>(nullable: false),
AllowAccessTokensViaBrowser = table.Column<bool>(nullable: false),
FrontChannelLogoutUri = table.Column<string>(maxLength: 2000, nullable: true),
FrontChannelLogoutSessionRequired = table.Column<bool>(nullable: false),
BackChannelLogoutUri = table.Column<string>(maxLength: 2000, nullable: true),
BackChannelLogoutSessionRequired = table.Column<bool>(nullable: false),
AllowOfflineAccess = table.Column<bool>(nullable: false),
IdentityTokenLifetime = table.Column<int>(nullable: false),
AccessTokenLifetime = table.Column<int>(nullable: false),
AuthorizationCodeLifetime = table.Column<int>(nullable: false),
ConsentLifetime = table.Column<int>(nullable: true),
AbsoluteRefreshTokenLifetime = table.Column<int>(nullable: false),
SlidingRefreshTokenLifetime = table.Column<int>(nullable: false),
RefreshTokenUsage = table.Column<int>(nullable: false),
UpdateAccessTokenClaimsOnRefresh = table.Column<bool>(nullable: false),
RefreshTokenExpiration = table.Column<int>(nullable: false),
AccessTokenType = table.Column<int>(nullable: false),
EnableLocalLogin = table.Column<bool>(nullable: false),
IncludeJwtId = table.Column<bool>(nullable: false),
AlwaysSendClientClaims = table.Column<bool>(nullable: false),
ClientClaimsPrefix = table.Column<string>(maxLength: 200, nullable: true),
PairWiseSubjectSalt = table.Column<string>(maxLength: 200, nullable: true),
Created = table.Column<DateTime>(nullable: false),
Updated = table.Column<DateTime>(nullable: true),
LastAccessed = table.Column<DateTime>(nullable: true),
UserSsoLifetime = table.Column<int>(nullable: true),
UserCodeType = table.Column<string>(maxLength: 100, nullable: true),
DeviceCodeLifetime = table.Column<int>(nullable: false),
NonEditable = table.Column<bool>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Enabled = table.Column<bool>(type: "bit", nullable: false),
ClientId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
ProtocolType = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
RequireClientSecret = table.Column<bool>(type: "bit", nullable: false),
ClientName = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
ClientUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
LogoUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
RequireConsent = table.Column<bool>(type: "bit", nullable: false),
AllowRememberConsent = table.Column<bool>(type: "bit", nullable: false),
AlwaysIncludeUserClaimsInIdToken = table.Column<bool>(type: "bit", nullable: false),
RequirePkce = table.Column<bool>(type: "bit", nullable: false),
AllowPlainTextPkce = table.Column<bool>(type: "bit", nullable: false),
AllowAccessTokensViaBrowser = table.Column<bool>(type: "bit", nullable: false),
FrontChannelLogoutUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
FrontChannelLogoutSessionRequired = table.Column<bool>(type: "bit", nullable: false),
BackChannelLogoutUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
BackChannelLogoutSessionRequired = table.Column<bool>(type: "bit", nullable: false),
AllowOfflineAccess = table.Column<bool>(type: "bit", nullable: false),
IdentityTokenLifetime = table.Column<int>(type: "int", nullable: false),
AccessTokenLifetime = table.Column<int>(type: "int", nullable: false),
AuthorizationCodeLifetime = table.Column<int>(type: "int", nullable: false),
ConsentLifetime = table.Column<int>(type: "int", nullable: true),
AbsoluteRefreshTokenLifetime = table.Column<int>(type: "int", nullable: false),
SlidingRefreshTokenLifetime = table.Column<int>(type: "int", nullable: false),
RefreshTokenUsage = table.Column<int>(type: "int", nullable: false),
UpdateAccessTokenClaimsOnRefresh = table.Column<bool>(type: "bit", nullable: false),
RefreshTokenExpiration = table.Column<int>(type: "int", nullable: false),
AccessTokenType = table.Column<int>(type: "int", nullable: false),
EnableLocalLogin = table.Column<bool>(type: "bit", nullable: false),
IncludeJwtId = table.Column<bool>(type: "bit", nullable: false),
AlwaysSendClientClaims = table.Column<bool>(type: "bit", nullable: false),
ClientClaimsPrefix = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
PairWiseSubjectSalt = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
Updated = table.Column<DateTime>(type: "datetime2", nullable: true),
LastAccessed = table.Column<DateTime>(type: "datetime2", nullable: true),
UserSsoLifetime = table.Column<int>(type: "int", nullable: true),
UserCodeType = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
DeviceCodeLifetime = table.Column<int>(type: "int", nullable: false),
NonEditable = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
@ -85,18 +84,18 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "IdentityResources",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Enabled = table.Column<bool>(nullable: false),
Name = table.Column<string>(maxLength: 200, nullable: false),
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
Description = table.Column<string>(maxLength: 1000, nullable: true),
Required = table.Column<bool>(nullable: false),
Emphasize = table.Column<bool>(nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(nullable: false),
Created = table.Column<DateTime>(nullable: false),
Updated = table.Column<DateTime>(nullable: true),
NonEditable = table.Column<bool>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Required = table.Column<bool>(type: "bit", nullable: false),
Emphasize = table.Column<bool>(type: "bit", nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(type: "bit", nullable: false),
Created = table.Column<DateTime>(type: "datetime2", nullable: false),
Updated = table.Column<DateTime>(type: "datetime2", nullable: true),
NonEditable = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
@ -107,10 +106,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Type = table.Column<string>(maxLength: 200, nullable: false),
ApiResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ApiResourceId = table.Column<int>(type: "int", nullable: false),
Type = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{
@ -127,11 +126,11 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiProperties",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Key = table.Column<string>(maxLength: 250, nullable: false),
Value = table.Column<string>(maxLength: 2000, nullable: false),
ApiResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ApiResourceId = table.Column<int>(type: "int", nullable: false),
Key = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
@ -148,15 +147,15 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiScopes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(maxLength: 200, nullable: false),
DisplayName = table.Column<string>(maxLength: 200, nullable: true),
Description = table.Column<string>(maxLength: 1000, nullable: true),
Required = table.Column<bool>(nullable: false),
Emphasize = table.Column<bool>(nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(nullable: false),
ApiResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Required = table.Column<bool>(type: "bit", nullable: false),
Emphasize = table.Column<bool>(type: "bit", nullable: false),
ShowInDiscoveryDocument = table.Column<bool>(type: "bit", nullable: false),
ApiResourceId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -173,14 +172,14 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiSecrets",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Description = table.Column<string>(maxLength: 1000, nullable: true),
Value = table.Column<string>(maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(nullable: true),
Type = table.Column<string>(maxLength: 250, nullable: false),
Created = table.Column<DateTime>(nullable: false),
ApiResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ApiResourceId = table.Column<int>(type: "int", nullable: false),
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
Value = table.Column<string>(type: "nvarchar(4000)", maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(type: "datetime2", nullable: true),
Type = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Created = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
@ -197,11 +196,11 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Type = table.Column<string>(maxLength: 250, nullable: false),
Value = table.Column<string>(maxLength: 250, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Type = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -218,10 +217,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientCorsOrigins",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Origin = table.Column<string>(maxLength: 150, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Origin = table.Column<string>(type: "nvarchar(150)", maxLength: 150, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -238,10 +237,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientGrantTypes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
GrantType = table.Column<string>(maxLength: 250, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
GrantType = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -258,10 +257,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientIdPRestrictions",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Provider = table.Column<string>(maxLength: 200, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Provider = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -278,10 +277,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientPostLogoutRedirectUris",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
PostLogoutRedirectUri = table.Column<string>(maxLength: 2000, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
PostLogoutRedirectUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -298,11 +297,11 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientProperties",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Key = table.Column<string>(maxLength: 250, nullable: false),
Value = table.Column<string>(maxLength: 2000, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ClientId = table.Column<int>(type: "int", nullable: false),
Key = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
@ -319,10 +318,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientRedirectUris",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
RedirectUri = table.Column<string>(maxLength: 2000, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RedirectUri = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -339,10 +338,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientScopes",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Scope = table.Column<string>(maxLength: 200, nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Scope = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
ClientId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
@ -359,14 +358,14 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ClientSecrets",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Description = table.Column<string>(maxLength: 2000, nullable: true),
Value = table.Column<string>(maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(nullable: true),
Type = table.Column<string>(maxLength: 250, nullable: false),
Created = table.Column<DateTime>(nullable: false),
ClientId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ClientId = table.Column<int>(type: "int", nullable: false),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
Value = table.Column<string>(type: "nvarchar(4000)", maxLength: 4000, nullable: false),
Expiration = table.Column<DateTime>(type: "datetime2", nullable: true),
Type = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Created = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
@ -383,10 +382,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "IdentityClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Type = table.Column<string>(maxLength: 200, nullable: false),
IdentityResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
IdentityResourceId = table.Column<int>(type: "int", nullable: false),
Type = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{
@ -403,11 +402,11 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "IdentityProperties",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Key = table.Column<string>(maxLength: 250, nullable: false),
Value = table.Column<string>(maxLength: 2000, nullable: false),
IdentityResourceId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
IdentityResourceId = table.Column<int>(type: "int", nullable: false),
Key = table.Column<string>(type: "nvarchar(250)", maxLength: 250, nullable: false),
Value = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false)
},
constraints: table =>
{
@ -424,10 +423,10 @@ namespace Identity.API.Migrations.ConfigurationDb
name: "ApiScopeClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Type = table.Column<string>(maxLength: 200, nullable: false),
ApiScopeId = table.Column<int>(nullable: false)
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ApiScopeId = table.Column<int>(type: "int", nullable: false),
Type = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false)
},
constraints: table =>
{

View File

@ -15,109 +15,133 @@ namespace Identity.API.Migrations.ConfigurationDb
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<DateTime?>("LastAccessed");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("ApiResources");
b.ToTable("ApiResources", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiClaims");
b.ToTable("ApiClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiProperties");
b.ToTable("ApiProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Emphasize");
b.Property<bool>("Emphasize")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Required");
b.Property<bool>("Required")
.HasColumnType("bit");
b.Property<bool>("ShowInDiscoveryDocument");
b.Property<bool>("ShowInDiscoveryDocument")
.HasColumnType("bit");
b.HasKey("Id");
@ -126,435 +150,538 @@ namespace Identity.API.Migrations.ConfigurationDb
b.HasIndex("Name")
.IsUnique();
b.ToTable("ApiScopes");
b.ToTable("ApiScopes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiScopeId");
b.Property<int>("ApiScopeId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ApiScopeId");
b.ToTable("ApiScopeClaims");
b.ToTable("ApiScopeClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ApiResourceId");
b.Property<int>("ApiResourceId")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(4000);
.HasMaxLength(4000)
.HasColumnType("nvarchar(4000)");
b.HasKey("Id");
b.HasIndex("ApiResourceId");
b.ToTable("ApiSecrets");
b.ToTable("ApiSecrets", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("AbsoluteRefreshTokenLifetime");
b.Property<int>("AbsoluteRefreshTokenLifetime")
.HasColumnType("int");
b.Property<int>("AccessTokenLifetime");
b.Property<int>("AccessTokenLifetime")
.HasColumnType("int");
b.Property<int>("AccessTokenType");
b.Property<int>("AccessTokenType")
.HasColumnType("int");
b.Property<bool>("AllowAccessTokensViaBrowser");
b.Property<bool>("AllowAccessTokensViaBrowser")
.HasColumnType("bit");
b.Property<bool>("AllowOfflineAccess");
b.Property<bool>("AllowOfflineAccess")
.HasColumnType("bit");
b.Property<bool>("AllowPlainTextPkce");
b.Property<bool>("AllowPlainTextPkce")
.HasColumnType("bit");
b.Property<bool>("AllowRememberConsent");
b.Property<bool>("AllowRememberConsent")
.HasColumnType("bit");
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken");
b.Property<bool>("AlwaysIncludeUserClaimsInIdToken")
.HasColumnType("bit");
b.Property<bool>("AlwaysSendClientClaims");
b.Property<bool>("AlwaysSendClientClaims")
.HasColumnType("bit");
b.Property<int>("AuthorizationCodeLifetime");
b.Property<int>("AuthorizationCodeLifetime")
.HasColumnType("int");
b.Property<bool>("BackChannelLogoutSessionRequired");
b.Property<bool>("BackChannelLogoutSessionRequired")
.HasColumnType("bit");
b.Property<string>("BackChannelLogoutUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<string>("ClientClaimsPrefix")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<int?>("ConsentLifetime");
b.Property<int?>("ConsentLifetime")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<int>("DeviceCodeLifetime");
b.Property<int>("DeviceCodeLifetime")
.HasColumnType("int");
b.Property<bool>("EnableLocalLogin");
b.Property<bool>("EnableLocalLogin")
.HasColumnType("bit");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<bool>("FrontChannelLogoutSessionRequired");
b.Property<bool>("FrontChannelLogoutSessionRequired")
.HasColumnType("bit");
b.Property<string>("FrontChannelLogoutUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<int>("IdentityTokenLifetime");
b.Property<int>("IdentityTokenLifetime")
.HasColumnType("int");
b.Property<bool>("IncludeJwtId");
b.Property<bool>("IncludeJwtId")
.HasColumnType("bit");
b.Property<DateTime?>("LastAccessed");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("LogoUri")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<string>("PairWiseSubjectSalt")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ProtocolType")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("RefreshTokenExpiration");
b.Property<int>("RefreshTokenExpiration")
.HasColumnType("int");
b.Property<int>("RefreshTokenUsage");
b.Property<int>("RefreshTokenUsage")
.HasColumnType("int");
b.Property<bool>("RequireClientSecret");
b.Property<bool>("RequireClientSecret")
.HasColumnType("bit");
b.Property<bool>("RequireConsent");
b.Property<bool>("RequireConsent")
.HasColumnType("bit");
b.Property<bool>("RequirePkce");
b.Property<bool>("RequirePkce")
.HasColumnType("bit");
b.Property<int>("SlidingRefreshTokenLifetime");
b.Property<int>("SlidingRefreshTokenLifetime")
.HasColumnType("int");
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh");
b.Property<bool>("UpdateAccessTokenClaimsOnRefresh")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.Property<string>("UserCodeType")
.HasMaxLength(100);
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int?>("UserSsoLifetime");
b.Property<int?>("UserSsoLifetime")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique();
b.ToTable("Clients");
b.ToTable("Clients", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientClaims");
b.ToTable("ClientClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Origin")
.IsRequired()
.HasMaxLength(150);
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientCorsOrigins");
b.ToTable("ClientCorsOrigins", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("GrantType")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientGrantTypes");
b.ToTable("ClientGrantTypes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Provider")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientIdPRestrictions");
b.ToTable("ClientIdPRestrictions", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("PostLogoutRedirectUri")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientPostLogoutRedirectUris");
b.ToTable("ClientPostLogoutRedirectUris", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientProperties");
b.ToTable("ClientProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("RedirectUri")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientRedirectUris");
b.ToTable("ClientRedirectUris", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<string>("Scope")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientScopes");
b.ToTable("ClientScopes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("ClientId");
b.Property<int>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(4000);
.HasMaxLength(4000)
.HasColumnType("nvarchar(4000)");
b.HasKey("Id");
b.HasIndex("ClientId");
b.ToTable("ClientSecrets");
b.ToTable("ClientSecrets", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("IdentityResourceId");
b.Property<int>("IdentityResourceId")
.HasColumnType("int");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("IdentityResourceId");
b.ToTable("IdentityClaims");
b.ToTable("IdentityClaims", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<DateTime>("Created");
b.Property<DateTime>("Created")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000);
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("DisplayName")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("Emphasize");
b.Property<bool>("Emphasize")
.HasColumnType("bit");
b.Property<bool>("Enabled");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<bool>("NonEditable");
b.Property<bool>("NonEditable")
.HasColumnType("bit");
b.Property<bool>("Required");
b.Property<bool>("Required")
.HasColumnType("bit");
b.Property<bool>("ShowInDiscoveryDocument");
b.Property<bool>("ShowInDiscoveryDocument")
.HasColumnType("bit");
b.Property<DateTime?>("Updated");
b.Property<DateTime?>("Updated")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("IdentityResources");
b.ToTable("IdentityResources", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int>("IdentityResourceId");
b.Property<int>("IdentityResourceId")
.HasColumnType("int");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(250);
.HasMaxLength(250)
.HasColumnType("nvarchar(250)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(2000);
.HasMaxLength(2000)
.HasColumnType("nvarchar(2000)");
b.HasKey("Id");
b.HasIndex("IdentityResourceId");
b.ToTable("IdentityProperties");
b.ToTable("IdentityProperties", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceClaim", b =>
@ -564,6 +691,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResourceProperty", b =>
@ -573,6 +702,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
@ -582,6 +713,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScopeClaim", b =>
@ -591,6 +724,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiScopeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiScope");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiSecret", b =>
@ -600,6 +735,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ApiResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ApiResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientClaim", b =>
@ -609,6 +746,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientCorsOrigin", b =>
@ -618,6 +757,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientGrantType", b =>
@ -627,6 +768,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientIdPRestriction", b =>
@ -636,6 +779,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientPostLogoutRedirectUri", b =>
@ -645,6 +790,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientProperty", b =>
@ -654,6 +801,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientRedirectUri", b =>
@ -663,6 +812,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientScope", b =>
@ -672,6 +823,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ClientSecret", b =>
@ -681,6 +834,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Client");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityClaim", b =>
@ -690,6 +845,8 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("IdentityResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("IdentityResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResourceProperty", b =>
@ -699,6 +856,52 @@ namespace Identity.API.Migrations.ConfigurationDb
.HasForeignKey("IdentityResourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("IdentityResource");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiResource", b =>
{
b.Navigation("Properties");
b.Navigation("Scopes");
b.Navigation("Secrets");
b.Navigation("UserClaims");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.ApiScope", b =>
{
b.Navigation("UserClaims");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.Client", b =>
{
b.Navigation("AllowedCorsOrigins");
b.Navigation("AllowedGrantTypes");
b.Navigation("AllowedScopes");
b.Navigation("Claims");
b.Navigation("ClientSecrets");
b.Navigation("IdentityProviderRestrictions");
b.Navigation("PostLogoutRedirectUris");
b.Navigation("Properties");
b.Navigation("RedirectUris");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.IdentityResource", b =>
{
b.Navigation("Properties");
b.Navigation("UserClaims");
});
#pragma warning restore 612, 618
}

View File

@ -1,65 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
namespace Identity.API.Migrations.PersistedGrantDb
{
public partial class InitialPersistedGrantMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "DeviceCodes",
columns: table => new
{
UserCode = table.Column<string>(maxLength: 200, nullable: false),
DeviceCode = table.Column<string>(maxLength: 200, nullable: false),
SubjectId = table.Column<string>(maxLength: 200, nullable: true),
ClientId = table.Column<string>(maxLength: 200, nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
Expiration = table.Column<DateTime>(nullable: false),
Data = table.Column<string>(maxLength: 50000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DeviceCodes", x => x.UserCode);
});
migrationBuilder.CreateTable(
name: "PersistedGrants",
columns: table => new
{
Key = table.Column<string>(maxLength: 200, nullable: false),
Type = table.Column<string>(maxLength: 50, nullable: false),
SubjectId = table.Column<string>(maxLength: 200, nullable: true),
ClientId = table.Column<string>(maxLength: 200, nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
Expiration = table.Column<DateTime>(nullable: true),
Data = table.Column<string>(maxLength: 50000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PersistedGrants", x => x.Key);
});
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_DeviceCode",
table: "DeviceCodes",
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",
columns: new[] { "SubjectId", "ClientId", "Type" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DeviceCodes");
migrationBuilder.DropTable(
name: "PersistedGrants");
}
}
}

View File

@ -10,79 +10,97 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Identity.API.Migrations.PersistedGrantDb
{
[DbContext(typeof(PersistedGrantDbContext))]
[Migration("20190729092100_InitialPersistedGrantMigration")]
partial class InitialPersistedGrantMigration
[Migration("20210813072513_InitialMigration")]
partial class InitialMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("CreationTime");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
.HasMaxLength(50000)
.HasColumnType("nvarchar(max)");
b.Property<string>("DeviceCode")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("Expiration")
.IsRequired();
.IsRequired()
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("UserCode");
b.HasIndex("DeviceCode")
.IsUnique();
b.ToTable("DeviceCodes");
b.HasIndex("Expiration");
b.ToTable("DeviceCodes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("CreationTime");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
.HasMaxLength(50000)
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50);
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Key");
b.HasIndex("Expiration");
b.HasIndex("SubjectId", "ClientId", "Type");
b.ToTable("PersistedGrants");
b.ToTable("PersistedGrants", (string)null);
});
#pragma warning restore 612, 618
}

View File

@ -0,0 +1,75 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Identity.API.Migrations.PersistedGrantDb
{
public partial class InitialMigration : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "DeviceCodes",
columns: table => new
{
UserCode = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DeviceCode = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
SubjectId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
ClientId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
Expiration = table.Column<DateTime>(type: "datetime2", nullable: false),
Data = table.Column<string>(type: "nvarchar(max)", maxLength: 50000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DeviceCodes", x => x.UserCode);
});
migrationBuilder.CreateTable(
name: "PersistedGrants",
columns: table => new
{
Key = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
SubjectId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
ClientId = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
Expiration = table.Column<DateTime>(type: "datetime2", nullable: true),
Data = table.Column<string>(type: "nvarchar(max)", maxLength: 50000, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PersistedGrants", x => x.Key);
});
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_DeviceCode",
table: "DeviceCodes",
column: "DeviceCode",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeviceCodes_Expiration",
table: "DeviceCodes",
column: "Expiration");
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_Expiration",
table: "PersistedGrants",
column: "Expiration");
migrationBuilder.CreateIndex(
name: "IX_PersistedGrants_SubjectId_ClientId_Type",
table: "PersistedGrants",
columns: new[] { "SubjectId", "ClientId", "Type" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "DeviceCodes");
migrationBuilder.DropTable(
name: "PersistedGrants");
}
}
}

View File

@ -15,72 +15,90 @@ namespace Identity.API.Migrations.PersistedGrantDb
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.0-preview7.19362.6")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "6.0.0-preview.7.21378.4")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("CreationTime");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
.HasMaxLength(50000)
.HasColumnType("nvarchar(max)");
b.Property<string>("DeviceCode")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("Expiration")
.IsRequired();
.IsRequired()
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("UserCode");
b.HasIndex("DeviceCode")
.IsUnique();
b.ToTable("DeviceCodes");
b.HasIndex("Expiration");
b.ToTable("DeviceCodes", (string)null);
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("ClientId")
.IsRequired()
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime>("CreationTime");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasMaxLength(50000);
.HasMaxLength(50000)
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("Expiration");
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasMaxLength(200);
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50);
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Key");
b.HasIndex("Expiration");
b.HasIndex("SubjectId", "ClientId", "Type");
b.ToTable("PersistedGrants");
b.ToTable("PersistedGrants", (string)null);
});
#pragma warning restore 612, 618
}

View File

@ -1,6 +1,4 @@
using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record ConsentInputModel
{

View File

@ -1,6 +1,4 @@
using IdentityServer4.Models;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record ForgotPasswordViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record LoginViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record RegisterViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record ResetPasswordViewModel
{

View File

@ -1,7 +1,4 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record SendCodeViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.AccountViewModels
{
public record VerifyCodeViewModel
{

View File

@ -1,7 +1,4 @@
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.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

View File

@ -1,9 +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 IdentityServer4.Models;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models
{
public record ErrorViewModel

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record AddPhoneNumberViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record ChangePasswordViewModel
{

View File

@ -1,7 +1,4 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record ConfigureTwoFactorViewModel
{

View File

@ -1,7 +1,4 @@
using Microsoft.AspNetCore.Identity;
using System.Collections.Generic;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record IndexViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record SetPasswordViewModel
{

View File

@ -1,6 +1,4 @@
using System.ComponentModel.DataAnnotations;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
namespace Microsoft.eShopOnContainers.Services.Identity.API.Models.ManageViewModels
{
public record VerifyPhoneNumberViewModel
{

View File

@ -1,20 +1,4 @@
using IdentityServer4.EntityFramework.DbContexts;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.eShopOnContainers.Services.Identity.API;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using System;
using System.IO;
using Azure.Identity;
using Azure.Core;
string Namespace = typeof(Startup).Namespace;
string Namespace = typeof(Startup).Namespace;
string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
var configuration = GetConfiguration();

View File

@ -1,9 +1,4 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.eShopOnContainers.Services.Identity.API.Models;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class EFLoginService : ILoginService<ApplicationUser>
{

View File

@ -1,7 +1,4 @@
using Microsoft.AspNetCore.Authentication;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public interface ILoginService<T>
{

View File

@ -1,16 +1,4 @@
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.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class ProfileService : IProfileService
{

View File

@ -1,6 +1,4 @@
using System.Text.RegularExpressions;
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
namespace Microsoft.eShopOnContainers.Services.Identity.API.Services
{
public class RedirectService : IRedirectService
{

View File

@ -1,26 +1,4 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using HealthChecks.UI.Client;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.Services.Identity.API.Certificates;
using Microsoft.eShopOnContainers.Services.Identity.API.Data;
using Microsoft.eShopOnContainers.Services.Identity.API.Devspaces;
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.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using System;
using System.Reflection;
using Microsoft.AspNetCore.DataProtection;
namespace Microsoft.eShopOnContainers.Services.Identity.API
{
@ -137,7 +115,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase))
{
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
//loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
@ -159,6 +137,7 @@ namespace Microsoft.eShopOnContainers.Services.Identity.API
// To avoid this problem, the policy of cookies shold be in Lax mode.
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = AspNetCore.Http.SameSiteMode.Lax });
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles

View File

@ -1,7 +1,7 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
ARG NODE_IMAGE=node:12.0
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
@ -14,7 +14,7 @@ RUN npm install
COPY Web/WebSPA/Client .
RUN npm run build:prod
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# Create this "restore-solution" section by running ./Create-DockerfileSolutionRestore.ps1, to optimize build cache reuse

View File

@ -1,9 +1,9 @@
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.6 AS base
FROM mcr.microsoft.com/dotnet/nightly/aspnet:6.0.0-preview.7 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.6 AS build
FROM mcr.microsoft.com/dotnet/nightly/sdk:6.0.100-preview.7 AS build
WORKDIR /src
# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles