From 9d5cde205727311bd8898530cbf86c4b3914ef5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Tue, 30 May 2017 15:01:58 +0200 Subject: [PATCH] #2412-Create Location Microservice --- ...irewall-rules-for-sts-auth-thru-docker.ps1 | 4 +- docker-compose.override.yml | 10 ++ docker-compose.vs.debug.yml | 15 ++ docker-compose.vs.release.yml | 10 ++ docker-compose.yml | 9 +- eShopOnContainers-ServicesAndWebApps.sln | 56 +++++++- .../Catalog/Catalog.API/Catalog.API.csproj | 1 + .../Identity.API/Configuration/Config.cs | 3 +- .../Location/Locations.API/.dockerignore | 3 + .../Controllers/HomeController.cs | 19 +++ .../Controllers/ValuesController.cs | 44 ++++++ .../Location/Locations.API/Dockerfile | 6 + .../Infrastructure/LocationsContext.cs | 55 ++++++++ .../Infrastructure/LocationsContextSeed.cs | 131 ++++++++++++++++++ .../20170529174524_Initial.Designer.cs | 87 ++++++++++++ .../Migrations/20170529174524_Initial.cs | 129 +++++++++++++++++ .../LocationsContextModelSnapshot.cs | 86 ++++++++++++ .../Locations.API/Locations.API.csproj | 39 ++++++ .../Locations.API/Model/FrontierPoints.cs | 11 ++ .../Location/Locations.API/Model/Locations.cs | 62 +++++++++ .../Location/Locations.API/Program.cs | 25 ++++ .../Properties/launchSettings.json | 29 ++++ .../Location/Locations.API/Startup.cs | 115 +++++++++++++++ .../appsettings.Development.json | 10 ++ .../Location/Locations.API/appsettings.json | 12 ++ .../FunctionalTests/FunctionalTests.csproj | 4 + .../IntegrationTests/IntegrationTests.csproj | 4 + test/Services/UnitTest/UnitTest.csproj | 4 + 28 files changed, 978 insertions(+), 5 deletions(-) create mode 100644 src/Services/Location/Locations.API/.dockerignore create mode 100644 src/Services/Location/Locations.API/Controllers/HomeController.cs create mode 100644 src/Services/Location/Locations.API/Controllers/ValuesController.cs create mode 100644 src/Services/Location/Locations.API/Dockerfile create mode 100644 src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs create mode 100644 src/Services/Location/Locations.API/Locations.API.csproj create mode 100644 src/Services/Location/Locations.API/Model/FrontierPoints.cs create mode 100644 src/Services/Location/Locations.API/Model/Locations.cs create mode 100644 src/Services/Location/Locations.API/Program.cs create mode 100644 src/Services/Location/Locations.API/Properties/launchSettings.json create mode 100644 src/Services/Location/Locations.API/Startup.cs create mode 100644 src/Services/Location/Locations.API/appsettings.Development.json create mode 100644 src/Services/Location/Locations.API/appsettings.json diff --git a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 index be63d8a25..865f24067 100644 --- a/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 +++ b/cli-windows/add-firewall-rules-for-sts-auth-thru-docker.ps1 @@ -21,6 +21,6 @@ try { Write-Host "Rule found" } catch [Exception] { - New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound - New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5105 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound + New-NetFirewallRule -DisplayName eShopOnContainers-Inbound -Confirm -Description "eShopOnContainers Inbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Inbound + New-NetFirewallRule -DisplayName eShopOnContainers-Outbound -Confirm -Description "eShopOnContainers Outbound Rule for port range 5100-5105" -LocalAddress Any -LocalPort 5100-5110 -Protocol tcp -RemoteAddress Any -RemotePort Any -Direction Outbound } \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 04d1c4d9c..a96720ba5 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -95,3 +95,13 @@ services: - spa=http://webspa/hc ports: - "5107:80" + + locations.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=http://0.0.0.0:80 + - ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.LocationsDb;User Id=sa;Password=Pass@word + - identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. + - EventBusConnection=rabbitmq + ports: + - "5109:80" \ No newline at end of file diff --git a/docker-compose.vs.debug.yml b/docker-compose.vs.debug.yml index 2e7145637..50ba68a69 100644 --- a/docker-compose.vs.debug.yml +++ b/docker-compose.vs.debug.yml @@ -105,3 +105,18 @@ services: entrypoint: tail -f /dev/null labels: - "com.microsoft.visualstudio.targetoperatingsystem=linux" + + locations.api: + image: eshop/locations.api:dev + build: + args: + source: ${DOCKER_BUILD_SOURCE} + environment: + - DOTNET_USE_POLLING_FILE_WATCHER=1 + volumes: + - ./src/Services/Location/Locations.API:/app + - ~/.nuget/packages:/root/.nuget/packages:ro + - ~/clrdbg:/clrdbg:ro + entrypoint: tail -f /dev/null + labels: + - "com.microsoft.visualstudio.targetoperatingsystem=linux" diff --git a/docker-compose.vs.release.yml b/docker-compose.vs.release.yml index d1ca5b2c6..58c9ffb81 100644 --- a/docker-compose.vs.release.yml +++ b/docker-compose.vs.release.yml @@ -70,3 +70,13 @@ services: entrypoint: tail -f /dev/null labels: - "com.microsoft.visualstudio.targetoperatingsystem=linux" + + locations.api: + build: + args: + source: ${DOCKER_BUILD_SOURCE} + volumes: + - ~/clrdbg:/clrdbg:ro + entrypoint: tail -f /dev/null + labels: + - "com.microsoft.visualstudio.targetoperatingsystem=linux" diff --git a/docker-compose.yml b/docker-compose.yml index 21f3972f2..e698992b2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,4 +74,11 @@ services: build: context: ./src/Web/WebStatus dockerfile: Dockerfile - \ No newline at end of file + + locations.api: + image: locations.api + build: + context: ./src/Services/Location/Locations.API + dockerfile: Dockerfile + depends_on: + - sql.data \ No newline at end of file diff --git a/eShopOnContainers-ServicesAndWebApps.sln b/eShopOnContainers-ServicesAndWebApps.sln index eb0e83e02..699185133 100644 --- a/eShopOnContainers-ServicesAndWebApps.sln +++ b/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26403.3 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}" EndProject @@ -76,6 +76,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Health EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventBus.Tests", "src\BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{41139F64-4046-4F16-96B7-D941D96FA9C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Locations.API", "src\Services\Location\Locations.API\Locations.API.csproj", "{E7581357-FC34-474C-B8F5-307EE3CE05EF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1002,6 +1006,54 @@ Global {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x64.Build.0 = Release|Any CPU {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.ActiveCfg = Release|Any CPU {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D}.Release|x86.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x64.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Ad-Hoc|x86.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|ARM.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhone.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x64.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.AppStore|x86.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|ARM.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhone.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x64.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.ActiveCfg = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Debug|x86.Build.0 = Debug|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|Any CPU.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|ARM.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhone.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x64.Build.0 = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.ActiveCfg = Release|Any CPU + {E7581357-FC34-474C-B8F5-307EE3CE05EF}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1038,5 +1090,7 @@ Global {22A0F9C1-2D4A-4107-95B7-8459E6688BC5} = {A81ECBC2-6B00-4DCD-8388-469174033379} {4BD76717-3102-4969-8C2C-BAAA3F0263B6} = {A81ECBC2-6B00-4DCD-8388-469174033379} {89D80DF1-32E1-4AAF-970F-DA0AA6881F9D} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} + {41139F64-4046-4F16-96B7-D941D96FA9C6} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} + {E7581357-FC34-474C-B8F5-307EE3CE05EF} = {41139F64-4046-4F16-96B7-D941D96FA9C6} EndGlobalSection EndGlobal diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index 10fe25945..5bea2f22d 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -30,6 +30,7 @@ + diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs index 260989da4..a07f5d01d 100644 --- a/src/Services/Identity/Identity.API/Configuration/Config.cs +++ b/src/Services/Identity/Identity.API/Configuration/Config.cs @@ -12,7 +12,8 @@ namespace Identity.API.Configuration return new List { new ApiResource("orders", "Orders Service"), - new ApiResource("basket", "Basket Service") + new ApiResource("basket", "Basket Service"), + new ApiResource("locations", "Locations Service") }; } diff --git a/src/Services/Location/Locations.API/.dockerignore b/src/Services/Location/Locations.API/.dockerignore new file mode 100644 index 000000000..d8f8175f6 --- /dev/null +++ b/src/Services/Location/Locations.API/.dockerignore @@ -0,0 +1,3 @@ +* +!obj/Docker/publish/* +!obj/Docker/empty/ diff --git a/src/Services/Location/Locations.API/Controllers/HomeController.cs b/src/Services/Location/Locations.API/Controllers/HomeController.cs new file mode 100644 index 000000000..e7cea3cca --- /dev/null +++ b/src/Services/Location/Locations.API/Controllers/HomeController.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Controllers +{ + public class HomeController : Controller + { + // GET: // + public IActionResult Index() + { + return new RedirectResult("~/swagger"); + } + } +} diff --git a/src/Services/Location/Locations.API/Controllers/ValuesController.cs b/src/Services/Location/Locations.API/Controllers/ValuesController.cs new file mode 100644 index 000000000..e711e221d --- /dev/null +++ b/src/Services/Location/Locations.API/Controllers/ValuesController.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace Locations.API.Controllers +{ + [Route("api/[controller]")] + public class ValuesController : Controller + { + // GET api/values + [HttpGet] + public IEnumerable Get() + { + return new string[] { "value1", "value2" }; + } + + // GET api/values/5 + [HttpGet("{id}")] + public string Get(int id) + { + return "value"; + } + + // POST api/values + [HttpPost] + public void Post([FromBody]string value) + { + } + + // PUT api/values/5 + [HttpPut("{id}")] + public void Put(int id, [FromBody]string value) + { + } + + // DELETE api/values/5 + [HttpDelete("{id}")] + public void Delete(int id) + { + } + } +} diff --git a/src/Services/Location/Locations.API/Dockerfile b/src/Services/Location/Locations.API/Dockerfile new file mode 100644 index 000000000..3d00f01a9 --- /dev/null +++ b/src/Services/Location/Locations.API/Dockerfile @@ -0,0 +1,6 @@ +FROM microsoft/aspnetcore:1.1 +ARG source +WORKDIR /app +EXPOSE 80 +COPY ${source:-obj/Docker/publish} . +ENTRYPOINT ["dotnet", "Locations.API.dll"] diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs new file mode 100644 index 000000000..42c3f7900 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs @@ -0,0 +1,55 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure +{ + using Microsoft.EntityFrameworkCore; + using Microsoft.EntityFrameworkCore.Metadata.Builders; + using Microsoft.eShopOnContainers.Services.Locations.API.Model; + + public class LocationsContext : DbContext + { + public LocationsContext(DbContextOptions options) : base(options) + { + } + + public DbSet Locations { get; set; } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.Entity(ConfigureLocations); + builder.Entity(ConfigureFrontierPoints); + } + + void ConfigureLocations(EntityTypeBuilder builder) + { + builder.ToTable("Locations"); + + builder.HasKey(cl => cl.Id); + + builder.Property(cl => cl.Id) + .ForSqlServerUseSequenceHiLo("locations_hilo") + .IsRequired(); + + builder.Property(cb => cb.Code) + .IsRequired() + .HasColumnName("LocationCode") + .HasMaxLength(15); + + builder.HasMany(f => f.Polygon) + .WithOne(l => l.Location) + .IsRequired(); + + builder.Property(cb => cb.Description) + .HasMaxLength(100); + } + + void ConfigureFrontierPoints(EntityTypeBuilder builder) + { + builder.ToTable("FrontierPoints"); + + builder.HasKey(fp => fp.Id); + + builder.Property(fp => fp.Id) + .ForSqlServerUseSequenceHiLo("frontier_hilo") + .IsRequired(); + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs new file mode 100644 index 000000000..67673719b --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs @@ -0,0 +1,131 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure +{ + using Microsoft.AspNetCore.Builder; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.Logging; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using System.Text; + + public class LocationsContextSeed + { + public static async Task SeedAsync(IApplicationBuilder applicationBuilder, ILoggerFactory loggerFactory) + { + var context = (LocationsContext)applicationBuilder + .ApplicationServices.GetService(typeof(LocationsContext)); + + context.Database.Migrate(); + + if (!context.Locations.Any()) + { + context.Locations.AddRange( + GetPreconfiguredLocations()); + + await context.SaveChangesAsync(); + } + } + + static Locations GetPreconfiguredLocations() + { + var ww = new Locations() { Code = "WW", Description = "WorldWide", Latitude = -1, Longitude = -1 }; + ww.ChildLocations.Add(GetUSLocations()); + return ww; + } + + static Locations GetUSLocations() + { + var us = new Locations() { Code = "US", Description = "United States", Latitude = 41.650455, Longitude = -101.357386, Polygon = GetUSPoligon() }; + us.ChildLocations.Add(GetWashingtonLocations()); + return us; + } + + static Locations GetWashingtonLocations() + { + var wht = new Locations() { Code = "WHT", Description = "Washington", Latitude = 47.223652, Longitude = -119.542781, Polygon = GetWashingtonPoligon() }; + wht.ChildLocations.Add(GetSeattleLocations()); + wht.ChildLocations.Add(GetRedmondLocations()); + return wht; + } + + static Locations GetSeattleLocations() + { + var bcn = new Locations() { Code = "SEAT", Description = "Seattle", Latitude = 47.603111, Longitude = -122.330747, Polygon = GetSeattlePoligon() }; + bcn.ChildLocations.Add(new Locations() { Code = "SEAT-PioneerSqr", Description = "Seattle Pioneer Square Shop" , Latitude = 47.602053, Longitude= -122.333884, Polygon = GetSeattlePioneerSqrPoligon() }); + return bcn; + } + + static Locations GetRedmondLocations() + { + var bcn = new Locations() { Code = "REDM", Description = "Redmond", Latitude = 47.674961, Longitude = -122.122887, Polygon = GetRedmondPoligon() }; + bcn.ChildLocations.Add(new Locations() { Code = "REDM-DWNTWP", Description = "Redmond Downtown Central Park Shop", Latitude = 47.674433, Longitude = -122.125006, Polygon = GetRedmondDowntownParkPoligon() }); + return bcn; + } + + static List GetUSPoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 48.7985, Longitude = -62.88205 }); + poligon.Add(new FrontierPoints() { Latitude = 48.76513, Longitude = -129.31329 }); + poligon.Add(new FrontierPoints() { Latitude = 30.12256, Longitude = -120.9496 }); + poligon.Add(new FrontierPoints() { Latitude = 30.87114, Longitude = -111.39442 }); + poligon.Add(new FrontierPoints() { Latitude = 24.24979, Longitude = -78.11975 }); + return poligon; + } + + static List GetWashingtonPoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 48.8943, Longitude = -124.68633 }); + poligon.Add(new FrontierPoints() { Latitude = 45.66613, Longitude = -124.32962 }); + poligon.Add(new FrontierPoints() { Latitude = 45.93384, Longitude = -116.73824 }); + poligon.Add(new FrontierPoints() { Latitude = 49.04282, Longitude = -116.96912 }); + return poligon; + } + + static List GetSeattlePoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 47.82929, Longitude = -122.36238 }); + poligon.Add(new FrontierPoints() { Latitude = 47.6337, Longitude = -122.42091 }); + poligon.Add(new FrontierPoints() { Latitude = 47.45224, Longitude = -122.37371 }); + poligon.Add(new FrontierPoints() { Latitude = 47.50259, Longitude = -122.20788 }); + poligon.Add(new FrontierPoints() { Latitude = 47.73644, Longitude = -122.26934 }); + return poligon; + } + + static List GetRedmondPoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 47.73148, Longitude = -122.15432 }); + poligon.Add(new FrontierPoints() { Latitude = 47.72559, Longitude = -122.17673 }); + poligon.Add(new FrontierPoints() { Latitude = 47.67851, Longitude = -122.16904 }); + poligon.Add(new FrontierPoints() { Latitude = 47.65036, Longitude = -122.16136 }); + poligon.Add(new FrontierPoints() { Latitude = 47.62746, Longitude = -122.15604 }); + poligon.Add(new FrontierPoints() { Latitude = 47.63463, Longitude = -122.01562 }); + poligon.Add(new FrontierPoints() { Latitude = 47.74244, Longitude = -122.04961 }); + return poligon; + } + + static List GetSeattlePioneerSqrPoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 47.60338, Longitude = -122.3327 }); + poligon.Add(new FrontierPoints() { Latitude = 47.60192, Longitude = -122.33665 }); + poligon.Add(new FrontierPoints() { Latitude = 47.60096, Longitude = -122.33456 }); + poligon.Add(new FrontierPoints() { Latitude = 47.60136, Longitude = -122.33186 }); + return poligon; + } + + static List GetRedmondDowntownParkPoligon() + { + var poligon = new List(); + poligon.Add(new FrontierPoints() { Latitude = 47.67595, Longitude = -122.12467 }); + poligon.Add(new FrontierPoints() { Latitude = 47.67449, Longitude = -122.12862 }); + poligon.Add(new FrontierPoints() { Latitude = 47.67353, Longitude = -122.12653 }); + poligon.Add(new FrontierPoints() { Latitude = 47.67368, Longitude = -122.12197 }); + return poligon; + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs new file mode 100644 index 000000000..0623edc4e --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs @@ -0,0 +1,87 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations +{ + [DbContext(typeof(LocationsContext))] + [Migration("20170529174524_Initial")] + partial class Initial + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.2") + .HasAnnotation("SqlServer:Sequence:.frontier_hilo", "'frontier_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.locations_hilo", "'locations_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "frontier_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Latitude"); + + b.Property("LocationId") + .IsRequired(); + + b.Property("Longitude"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.ToTable("FrontierPoints"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Code") + .IsRequired() + .HasColumnName("LocationCode") + .HasMaxLength(15); + + b.Property("Description") + .HasMaxLength(100); + + b.Property("Latitude"); + + b.Property("Longitude"); + + b.Property("ParentId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") + .WithMany("FrontierPoints") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations") + .WithMany("ChildLocations") + .HasForeignKey("ParentId"); + }); + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs new file mode 100644 index 000000000..d2352312f --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; +using System.Text; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateSequence( + name: "frontier_hilo", + incrementBy: 10); + + migrationBuilder.CreateSequence( + name: "locations_hilo", + incrementBy: 10); + + migrationBuilder.CreateTable( + name: "Locations", + columns: table => new + { + Id = table.Column(nullable: false), + LocationCode = table.Column(maxLength: 15, nullable: false), + Description = table.Column(maxLength: 100, nullable: true), + Latitude = table.Column(nullable: false), + Longitude = table.Column(nullable: false), + ParentId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Locations", x => x.Id); + table.ForeignKey( + name: "FK_Locations_Locations_ParentId", + column: x => x.ParentId, + principalTable: "Locations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "FrontierPoints", + columns: table => new + { + Id = table.Column(nullable: false), + Latitude = table.Column(nullable: false), + LocationId = table.Column(nullable: false), + Longitude = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_FrontierPoints", x => x.Id); + table.ForeignKey( + name: "FK_FrontierPoints_Locations_LocationId", + column: x => x.LocationId, + principalTable: "Locations", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_FrontierPoints_LocationId", + table: "FrontierPoints", + column: "LocationId"); + + migrationBuilder.CreateIndex( + name: "IX_Locations_ParentId", + table: "Locations", + column: "ParentId"); + + migrationBuilder.Sql(CreateGetDistanceFunction()); + migrationBuilder.Sql(CreateLocationsNearSP()); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "FrontierPoints"); + + migrationBuilder.DropTable( + name: "Locations"); + + migrationBuilder.DropSequence( + name: "frontier_hilo"); + + migrationBuilder.DropSequence( + name: "locations_hilo"); + + migrationBuilder.Sql(@"DROP PROCEDURE IF EXISTS pLocationsNear"); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS dbo.GetDistanceFromLocation"); + } + + private string CreateLocationsNearSP() + { + var sb = new StringBuilder(); + sb.AppendLine(@"CREATE PROCEDURE [dbo].[pLocationsNear]"); + sb.AppendLine(@"@latitude float,"); + sb.AppendLine(@"@longitude float,"); + sb.AppendLine(@"@size int = 500"); + sb.AppendLine(@"AS"); + sb.AppendLine(@"BEGIN"); + sb.AppendLine(@"SELECT TOP( @size) location.*"); + sb.AppendLine(@"FROM [dbo].[Locations] AS location"); + sb.AppendLine(@"ORDER BY dbo.[GetDistanceFromLocation](location.Latitude, location.Longitude, @latitude, @longitude)"); + sb.AppendLine(@"END"); + return sb.ToString(); + } + + private string CreateGetDistanceFunction() + { + var sb = new StringBuilder(); + sb.AppendLine(@"CREATE FUNCTION [dbo].[GetDistanceFromLocation]("); + sb.AppendLine(@"@CurrentLatitude float,"); + sb.AppendLine(@"@CurrentLongitude float,"); + sb.AppendLine(@"@latitude float,"); + sb.AppendLine(@"@longitude float)"); + sb.AppendLine(@"RETURNS int"); + sb.AppendLine(@"AS"); + sb.AppendLine(@"BEGIN"); + sb.AppendLine(@"DECLARE @geo1 geography = geography::Point(@CurrentLatitude, @CurrentLongitude, 4268),@geo2 geography = geography::Point(@latitude, @longitude, 4268)"); + sb.AppendLine(@"DECLARE @distance int"); + sb.AppendLine(@"SELECT @distance = @geo1.STDistance(@geo2)"); + sb.AppendLine(@"RETURN @distance"); + sb.AppendLine(@"END"); + return sb.ToString(); + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs new file mode 100644 index 000000000..02f77cdd0 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs @@ -0,0 +1,86 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations +{ + [DbContext(typeof(LocationsContext))] + partial class LocationsContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.2") + .HasAnnotation("SqlServer:Sequence:.frontier_hilo", "'frontier_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.locations_hilo", "'locations_hilo', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "frontier_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Latitude"); + + b.Property("LocationId") + .IsRequired(); + + b.Property("Longitude"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.ToTable("FrontierPoints"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Code") + .IsRequired() + .HasColumnName("LocationCode") + .HasMaxLength(15); + + b.Property("Description") + .HasMaxLength(100); + + b.Property("Latitude"); + + b.Property("Longitude"); + + b.Property("ParentId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("Locations"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") + .WithMany("FrontierPoints") + .HasForeignKey("LocationId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations") + .WithMany("ChildLocations") + .HasForeignKey("ParentId"); + }); + } + } +} diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj new file mode 100644 index 000000000..b00054921 --- /dev/null +++ b/src/Services/Location/Locations.API/Locations.API.csproj @@ -0,0 +1,39 @@ + + + + netcoreapp1.1 + ..\..\..\..\docker-compose.dcproj + Microsoft.eShopOnContainers.Services.Locations.API + aspnet-Locations.API-20161122013619 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Location/Locations.API/Model/FrontierPoints.cs b/src/Services/Location/Locations.API/Model/FrontierPoints.cs new file mode 100644 index 000000000..4a9112e5e --- /dev/null +++ b/src/Services/Location/Locations.API/Model/FrontierPoints.cs @@ -0,0 +1,11 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Model +{ + public class FrontierPoints + { + public int Id { get; set; } + public double Latitude { get; set; } + public double Longitude { get; set; } + + public Locations Location { get; set; } + } +} \ No newline at end of file diff --git a/src/Services/Location/Locations.API/Model/Locations.cs b/src/Services/Location/Locations.API/Model/Locations.cs new file mode 100644 index 000000000..ec21ac34f --- /dev/null +++ b/src/Services/Location/Locations.API/Model/Locations.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Model +{ + public class Locations + { + public int Id { get; set; } + public string Code { get; set; } + public int? ParentId { get; set; } + public string Description { get; set; } + public double Latitude { get; set; } + public double Longitude { get; set; } + public bool IsPointInPolygon(double lat, double lon) => CheckIsPointInPolygon(lat, lon); + + public Locations() + { + ChildLocations = new List(); + } + + public virtual List Polygon { get; set; } + + [ForeignKey("ParentId")] + public virtual List ChildLocations { get; set; } + + + private bool CheckIsPointInPolygon(double lat, double lon) + { + double minX = Polygon[0].Latitude; + double maxX = Polygon[0].Latitude; + double minY = Polygon[0].Longitude; + double maxY = Polygon[0].Longitude; + for (int i = 1; i < Polygon.Count; i++) + { + FrontierPoints q = Polygon[i]; + minX = Math.Min(q.Latitude, minX); + maxX = Math.Max(q.Latitude, maxX); + minY = Math.Min(q.Longitude, minY); + maxY = Math.Max(q.Longitude, maxY); + } + + if (lat < minX || lat > maxX || lon < minY || lon > maxY) + { + return false; + } + + bool inside = false; + for (int i = 0, j = Polygon.Count - 1; i < Polygon.Count; j = i++) + { + if ((Polygon[i].Longitude > lon) != (Polygon[j].Latitude > lat) && + lat < (Polygon[j].Longitude - Polygon[i].Latitude) * (lon - Polygon[i].Longitude) / (Polygon[j].Longitude - Polygon[i].Longitude) + Polygon[i].Latitude) + { + inside = !inside; + } + } + + return inside; + } + } +} diff --git a/src/Services/Location/Locations.API/Program.cs b/src/Services/Location/Locations.API/Program.cs new file mode 100644 index 000000000..345956401 --- /dev/null +++ b/src/Services/Location/Locations.API/Program.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; + +namespace Microsoft.eShopOnContainers.Services.Locations.API +{ + public class Program + { + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup() + .UseApplicationInsights() + .Build(); + + host.Run(); + } + } +} diff --git a/src/Services/Location/Locations.API/Properties/launchSettings.json b/src/Services/Location/Locations.API/Properties/launchSettings.json new file mode 100644 index 000000000..45b637914 --- /dev/null +++ b/src/Services/Location/Locations.API/Properties/launchSettings.json @@ -0,0 +1,29 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:3278/", + "sslPort": 0 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Locations.API": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:3279" + } + } +} diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs new file mode 100644 index 000000000..1a42679a6 --- /dev/null +++ b/src/Services/Location/Locations.API/Startup.cs @@ -0,0 +1,115 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using System.Reflection; +using System; + +namespace Microsoft.eShopOnContainers.Services.Locations.API +{ + public class Startup + { + public IConfigurationRoot Configuration { get; } + + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); + + if (env.IsDevelopment()) + { + builder.AddUserSecrets(typeof(Startup).GetTypeInfo().Assembly); + } + + builder.AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + // Add framework services. + services.AddMvc(); + + services.AddDbContext(options => + { + options.UseSqlServer(Configuration["ConnectionString"], + sqlServerOptionsAction: sqlOptions => + { + sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency + sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); + }); + + // Changing default behavior when client evaluation occurs to throw. + // Default in EF Core would be to log a warning when client evaluation is performed. + options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); + //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval + }); + + // Add framework services. + services.AddSwaggerGen(options => + { + options.DescribeAllEnumsAsStrings(); + options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info + { + Title = "eShopOnContainers - Location HTTP API", + Version = "v1", + Description = "The Location Microservice HTTP API. This is a Data-Driven/CRUD microservice sample", + TermsOfService = "Terms Of Service" + }); + }); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + //Configure logs + + loggerFactory.AddConsole(Configuration.GetSection("Logging")); + loggerFactory.AddDebug(); + + app.UseCors("CorsPolicy"); + + ConfigureAuth(app); + + app.UseMvcWithDefaultRoute(); + + app.UseSwagger() + .UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + }); + + LocationsContextSeed.SeedAsync(app, loggerFactory) + .Wait(); + } + + protected virtual void ConfigureAuth(IApplicationBuilder app) + { + var identityUrl = Configuration.GetValue("IdentityUrl"); + app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions + { + Authority = identityUrl.ToString(), + ApiName = "locations", + RequireHttpsMetadata = false + }); + } + } +} diff --git a/src/Services/Location/Locations.API/appsettings.Development.json b/src/Services/Location/Locations.API/appsettings.Development.json new file mode 100644 index 000000000..fa8ce71a9 --- /dev/null +++ b/src/Services/Location/Locations.API/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/src/Services/Location/Locations.API/appsettings.json b/src/Services/Location/Locations.API/appsettings.json new file mode 100644 index 000000000..812cce207 --- /dev/null +++ b/src/Services/Location/Locations.API/appsettings.json @@ -0,0 +1,12 @@ +{ + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.LocationsDb;User Id=sa;Password=Pass@word;", + "IdentityUrl": "http://localhost:5105", + "Logging": { + "IncludeScopes": false, + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} \ No newline at end of file diff --git a/test/Services/FunctionalTests/FunctionalTests.csproj b/test/Services/FunctionalTests/FunctionalTests.csproj index 2b8ee1f44..54a74beda 100644 --- a/test/Services/FunctionalTests/FunctionalTests.csproj +++ b/test/Services/FunctionalTests/FunctionalTests.csproj @@ -38,4 +38,8 @@ + + + + \ No newline at end of file diff --git a/test/Services/IntegrationTests/IntegrationTests.csproj b/test/Services/IntegrationTests/IntegrationTests.csproj index b71e1d4c4..60911dd4d 100644 --- a/test/Services/IntegrationTests/IntegrationTests.csproj +++ b/test/Services/IntegrationTests/IntegrationTests.csproj @@ -46,4 +46,8 @@ + + + + diff --git a/test/Services/UnitTest/UnitTest.csproj b/test/Services/UnitTest/UnitTest.csproj index 3a80e594b..8955e4a45 100644 --- a/test/Services/UnitTest/UnitTest.csproj +++ b/test/Services/UnitTest/UnitTest.csproj @@ -28,4 +28,8 @@ + + + +