From 13cfe4337870575914d043e09117f3d61e7893ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Tom=C3=A1s?= Date: Thu, 1 Jun 2017 20:16:19 +0200 Subject: [PATCH] Created UserLocationModel Map Position to Locations APi Update current user location --- .../Identity.API/Configuration/Config.cs | 6 +- .../Controllers/LocationsController.cs | 35 +++++++++ .../Controllers/ValuesController.cs | 44 ------------ .../Infrastructure/LocationsContext.cs | 23 +++++- .../Infrastructure/LocationsContextSeed.cs | 72 +++++++++---------- ....cs => 20170601140634_Initial.Designer.cs} | 41 +++++++++-- ...4_Initial.cs => 20170601140634_Initial.cs} | 67 +++++++++++------ .../LocationsContextModelSnapshot.cs | 39 ++++++++-- .../Repositories/ILocationsRepository.cs | 17 +++++ .../Repositories/IRepository.cs | 12 ++++ .../Repositories/IUnitOfWork.cs | 13 ++++ .../Repositories/LocationsRepository.cs | 60 ++++++++++++++++ .../Services/IIdentityService.cs | 12 ++++ .../Services/ILocationsService.cs | 10 +++ .../Services/IdentityService.cs | 23 ++++++ .../Services/LocationsService.cs | 62 ++++++++++++++++ .../Locations.API/Locations.API.csproj | 1 + .../Locations.API/Model/FrontierPoints.cs | 16 ++++- .../Location/Locations.API/Model/Locations.cs | 46 ++++++++++-- .../Locations.API/Model/UserLocation.cs | 24 +++++++ .../Location/Locations.API/Startup.cs | 8 +++ .../ViewModel/LocationRequest.cs | 13 ++++ .../IntegrationTests/IntegrationTests.csproj | 5 ++ .../Locations/LocationsScenarioBase.cs | 36 ++++++++++ .../Services/Locations/LocationsScenarios.cs | 37 ++++++++++ .../Locations/LocationsTestsStartup.cs | 26 +++++++ .../Services/Locations/appsettings.json | 7 ++ 27 files changed, 627 insertions(+), 128 deletions(-) create mode 100644 src/Services/Location/Locations.API/Controllers/LocationsController.cs delete mode 100644 src/Services/Location/Locations.API/Controllers/ValuesController.cs rename src/Services/Location/Locations.API/Infrastructure/Migrations/{20170529174524_Initial.Designer.cs => 20170601140634_Initial.Designer.cs} (66%) rename src/Services/Location/Locations.API/Infrastructure/Migrations/{20170529174524_Initial.cs => 20170601140634_Initial.cs} (72%) create mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/IRepository.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/IUnitOfWork.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs create mode 100644 src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs create mode 100644 src/Services/Location/Locations.API/Model/UserLocation.cs create mode 100644 src/Services/Location/Locations.API/ViewModel/LocationRequest.cs create mode 100644 test/Services/IntegrationTests/Services/Locations/LocationsScenarioBase.cs create mode 100644 test/Services/IntegrationTests/Services/Locations/LocationsScenarios.cs create mode 100644 test/Services/IntegrationTests/Services/Locations/LocationsTestsStartup.cs create mode 100644 test/Services/IntegrationTests/Services/Locations/appsettings.json diff --git a/src/Services/Identity/Identity.API/Configuration/Config.cs b/src/Services/Identity/Identity.API/Configuration/Config.cs index a07f5d01d..2b78737a9 100644 --- a/src/Services/Identity/Identity.API/Configuration/Config.cs +++ b/src/Services/Identity/Identity.API/Configuration/Config.cs @@ -72,7 +72,8 @@ namespace Identity.API.Configuration IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OfflineAccess, "orders", - "basket" + "basket", + "locations" }, //Allow requesting refresh tokens for long lived API access AllowOfflineAccess = true @@ -103,7 +104,8 @@ namespace Identity.API.Configuration IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.OfflineAccess, "orders", - "basket" + "basket", + "locations" }, } }; diff --git a/src/Services/Location/Locations.API/Controllers/LocationsController.cs b/src/Services/Location/Locations.API/Controllers/LocationsController.cs new file mode 100644 index 000000000..dc2940b73 --- /dev/null +++ b/src/Services/Location/Locations.API/Controllers/LocationsController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; +using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; +using System; +using System.Threading.Tasks; + +namespace Locations.API.Controllers +{ + [Route("api/v1/[controller]")] + [Authorize] + public class LocationsController : ControllerBase + { + private readonly ILocationsService _locationsService; + private readonly IIdentityService _identityService; + + public LocationsController(ILocationsService locationsService, IIdentityService identityService) + { + _locationsService = locationsService ?? throw new ArgumentNullException(nameof(locationsService)); + _identityService = identityService ?? throw new ArgumentNullException(nameof(identityService)); + } + + //POST api/v1/[controller]/ + [Route("")] + [HttpPost] + public async Task UpdateUserLocation([FromBody]LocationRequest newLocReq) + { + var userId = _identityService.GetUserIdentity(); + var result = await _locationsService.AddOrUpdateUserLocation(userId, newLocReq); + return result ? + (IActionResult)Ok() : + (IActionResult)BadRequest(); + } + } +} diff --git a/src/Services/Location/Locations.API/Controllers/ValuesController.cs b/src/Services/Location/Locations.API/Controllers/ValuesController.cs deleted file mode 100644 index e711e221d..000000000 --- a/src/Services/Location/Locations.API/Controllers/ValuesController.cs +++ /dev/null @@ -1,44 +0,0 @@ -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/Infrastructure/LocationsContext.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs index 42c3f7900..5767694df 100644 --- a/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs +++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContext.cs @@ -2,20 +2,26 @@ { using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; + using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using System.Threading; + using System.Threading.Tasks; - public class LocationsContext : DbContext + public class LocationsContext : DbContext, IUnitOfWork { public LocationsContext(DbContextOptions options) : base(options) { } public DbSet Locations { get; set; } + public DbSet FrontierPoints { get; set; } + public DbSet UserLocation { get; set; } protected override void OnModelCreating(ModelBuilder builder) { builder.Entity(ConfigureLocations); builder.Entity(ConfigureFrontierPoints); + builder.Entity(ConfigureUserLocation); } void ConfigureLocations(EntityTypeBuilder builder) @@ -25,7 +31,7 @@ builder.HasKey(cl => cl.Id); builder.Property(cl => cl.Id) - .ForSqlServerUseSequenceHiLo("locations_hilo") + .ForSqlServerUseSequenceHiLo("locations_seq") .IsRequired(); builder.Property(cb => cb.Code) @@ -48,8 +54,19 @@ builder.HasKey(fp => fp.Id); builder.Property(fp => fp.Id) - .ForSqlServerUseSequenceHiLo("frontier_hilo") + .ForSqlServerUseSequenceHiLo("frontier_seq") .IsRequired(); + } + + void ConfigureUserLocation(EntityTypeBuilder builder) + { + builder.ToTable("UserLocation"); + + builder.Property(ul => ul.Id) + .ForSqlServerUseSequenceHiLo("UserLocation_seq") + .IsRequired(); + + builder.HasIndex(ul => ul.UserId).IsUnique(); } } } diff --git a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs index 67673719b..63404f49d 100644 --- a/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs +++ b/src/Services/Location/Locations.API/Infrastructure/LocationsContextSeed.cs @@ -29,21 +29,21 @@ static Locations GetPreconfiguredLocations() { - var ww = new Locations() { Code = "WW", Description = "WorldWide", Latitude = -1, Longitude = -1 }; + var ww = new Locations("WW", "WorldWide", -1, -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() }; + var us = new Locations("US", "United States", 41.650455, -101.357386, 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() }; + var wht = new Locations("WHT", "Washington", 47.223652, -119.542781, GetWashingtonPoligon()); wht.ChildLocations.Add(GetSeattleLocations()); wht.ChildLocations.Add(GetRedmondLocations()); return wht; @@ -51,80 +51,80 @@ 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() }); + var bcn = new Locations("SEAT", "Seattle", 47.603111, -122.330747, GetSeattlePoligon()); + bcn.ChildLocations.Add(new Locations("SEAT-PioneerSqr", "Seattle Pioneer Square Shop", 47.602053, -122.333884, 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() }); + var bcn = new Locations("REDM", "Redmond", 47.674961, -122.122887, GetRedmondPoligon()); + bcn.ChildLocations.Add(new Locations("REDM-DWNTWP", "Redmond Downtown Central Park Shop", 47.674433, -122.125006, 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 }); + poligon.Add(new FrontierPoints(48.7985, -62.88205)); + poligon.Add(new FrontierPoints(48.76513, -129.3132)); + poligon.Add(new FrontierPoints(30.12256, -120.9496)); + poligon.Add(new FrontierPoints(30.87114, -111.3944)); + poligon.Add(new FrontierPoints(24.24979, -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 }); + poligon.Add(new FrontierPoints(48.8943, -124.68633)); + poligon.Add(new FrontierPoints(45.66613, -124.32962)); + poligon.Add(new FrontierPoints(45.93384, -116.73824)); + poligon.Add(new FrontierPoints(49.04282, -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 }); + poligon.Add(new FrontierPoints(47.82929, -122.36238)); + poligon.Add(new FrontierPoints(47.6337, -122.42091)); + poligon.Add(new FrontierPoints(47.45224, -122.37371)); + poligon.Add(new FrontierPoints(47.50259, -122.20788)); + poligon.Add(new FrontierPoints(47.73644, -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 }); + poligon.Add(new FrontierPoints(47.73148, -122.15432)); + poligon.Add(new FrontierPoints(47.72559, -122.17673)); + poligon.Add(new FrontierPoints(47.67851, -122.16904)); + poligon.Add(new FrontierPoints(47.65036, -122.16136)); + poligon.Add(new FrontierPoints(47.62746, -122.15604)); + poligon.Add(new FrontierPoints(47.63463, -122.01562)); + poligon.Add(new FrontierPoints(47.74244, -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 }); + poligon.Add(new FrontierPoints(47.60338, -122.3327)); + poligon.Add(new FrontierPoints(47.60192, -122.33665)); + poligon.Add(new FrontierPoints(47.60096, -122.33456)); + poligon.Add(new FrontierPoints(47.60136, -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 }); + poligon.Add(new FrontierPoints(47.67595, -122.12467)); + poligon.Add(new FrontierPoints(47.67449, -122.12862)); + poligon.Add(new FrontierPoints(47.67353, -122.12653)); + poligon.Add(new FrontierPoints(47.67368, -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/20170601140634_Initial.Designer.cs similarity index 66% rename from src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs rename to src/Services/Location/Locations.API/Infrastructure/Migrations/20170601140634_Initial.Designer.cs index 0623edc4e..441ec1d82 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.Designer.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170601140634_Initial.Designer.cs @@ -8,22 +8,23 @@ using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure; namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migrations { [DbContext(typeof(LocationsContext))] - [Migration("20170529174524_Initial")] + [Migration("20170601140634_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:Sequence:.frontier_seq", "'frontier_seq', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.locations_seq", "'locations_seq', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.UserLocation_seq", "'UserLocation_seq', '', '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:HiLoSequenceName", "frontier_seq") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); b.Property("Latitude"); @@ -44,7 +45,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr { b.Property("Id") .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo") + .HasAnnotation("SqlServer:HiLoSequenceName", "locations_seq") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); b.Property("Code") @@ -68,10 +69,31 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr b.ToTable("Locations"); }); + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.UserLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "UserLocation_seq") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("LocationId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("UserLocation"); + }); + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => { b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") - .WithMany("FrontierPoints") + .WithMany("Polygon") .HasForeignKey("LocationId") .OnDelete(DeleteBehavior.Cascade); }); @@ -82,6 +104,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr .WithMany("ChildLocations") .HasForeignKey("ParentId"); }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.UserLocation", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") + .WithMany() + .HasForeignKey("LocationId"); + }); } } } diff --git a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170601140634_Initial.cs similarity index 72% rename from src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs rename to src/Services/Location/Locations.API/Infrastructure/Migrations/20170601140634_Initial.cs index d2352312f..3073ca8ce 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Migrations/20170529174524_Initial.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/20170601140634_Initial.cs @@ -10,11 +10,15 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.CreateSequence( - name: "frontier_hilo", + name: "frontier_seq", incrementBy: 10); migrationBuilder.CreateSequence( - name: "locations_hilo", + name: "locations_seq", + incrementBy: 10); + + migrationBuilder.CreateSequence( + name: "UserLocation_seq", incrementBy: 10); migrationBuilder.CreateTable( @@ -59,6 +63,25 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "UserLocation", + columns: table => new + { + Id = table.Column(nullable: false), + LocationId = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLocation", x => x.Id); + table.ForeignKey( + name: "FK_UserLocation_Locations_LocationId", + column: x => x.LocationId, + principalTable: "Locations", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateIndex( name: "IX_FrontierPoints_LocationId", table: "FrontierPoints", @@ -69,8 +92,18 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr table: "Locations", column: "ParentId"); + migrationBuilder.CreateIndex( + name: "IX_UserLocation_LocationId", + table: "UserLocation", + column: "LocationId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLocation_UserId", + table: "UserLocation", + column: "UserId", + unique: true); + migrationBuilder.Sql(CreateGetDistanceFunction()); - migrationBuilder.Sql(CreateLocationsNearSP()); } protected override void Down(MigrationBuilder migrationBuilder) @@ -78,33 +111,22 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr migrationBuilder.DropTable( name: "FrontierPoints"); + migrationBuilder.DropTable( + name: "UserLocation"); + migrationBuilder.DropTable( name: "Locations"); migrationBuilder.DropSequence( - name: "frontier_hilo"); + name: "frontier_seq"); migrationBuilder.DropSequence( - name: "locations_hilo"); + name: "locations_seq"); - migrationBuilder.Sql(@"DROP PROCEDURE IF EXISTS pLocationsNear"); - migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS dbo.GetDistanceFromLocation"); - } + migrationBuilder.DropSequence( + name: "UserLocation_seq"); - 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(); + migrationBuilder.Sql(@"DROP FUNCTION IF EXISTS dbo.GetDistanceFromLocation"); } private string CreateGetDistanceFunction() @@ -125,5 +147,6 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr 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 index 02f77cdd0..c01237ab2 100644 --- a/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs +++ b/src/Services/Location/Locations.API/Infrastructure/Migrations/LocationsContextModelSnapshot.cs @@ -14,15 +14,16 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr { 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:Sequence:.frontier_seq", "'frontier_seq', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.locations_seq", "'locations_seq', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:.UserLocation_seq", "'UserLocation_seq', '', '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:HiLoSequenceName", "frontier_seq") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); b.Property("Latitude"); @@ -43,7 +44,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr { b.Property("Id") .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:HiLoSequenceName", "locations_hilo") + .HasAnnotation("SqlServer:HiLoSequenceName", "locations_seq") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); b.Property("Code") @@ -67,10 +68,31 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr b.ToTable("Locations"); }); + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.UserLocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "UserLocation_seq") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("LocationId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("LocationId"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("UserLocation"); + }); + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.FrontierPoints", b => { b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") - .WithMany("FrontierPoints") + .WithMany("Polygon") .HasForeignKey("LocationId") .OnDelete(DeleteBehavior.Cascade); }); @@ -81,6 +103,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Migr .WithMany("ChildLocations") .HasForeignKey("ParentId"); }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Locations.API.Model.UserLocation", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Locations.API.Model.Locations", "Location") + .WithMany() + .HasForeignKey("LocationId"); + }); } } } diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs new file mode 100644 index 000000000..bd3b58cb2 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Repositories/ILocationsRepository.cs @@ -0,0 +1,17 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories +{ + using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using System.Collections.Generic; + using System.Threading.Tasks; + + public interface ILocationsRepository : IRepository + { + UserLocation Add(UserLocation order); + + void Update(UserLocation order); + + Task GetAsync(int userId); + + Task> GetNearestLocationListAsync(double lat, double lon); + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/IRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/IRepository.cs new file mode 100644 index 000000000..946cf489c --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Repositories/IRepository.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories +{ + public interface IRepository + { + IUnitOfWork UnitOfWork { get; } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/IUnitOfWork.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/IUnitOfWork.cs new file mode 100644 index 000000000..a81ac95e1 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Repositories/IUnitOfWork.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories +{ + public interface IUnitOfWork : IDisposable + { + Task SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs b/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs new file mode 100644 index 000000000..98cb501b9 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Repositories/LocationsRepository.cs @@ -0,0 +1,60 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories +{ + using System; + using System.Threading.Tasks; + using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using Microsoft.EntityFrameworkCore; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + + public class LocationsRepository + : ILocationsRepository + { + private readonly LocationsContext _context; + + public IUnitOfWork UnitOfWork + { + get + { + return _context; + } + } + + public LocationsRepository(LocationsContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public UserLocation Add(UserLocation location) + { + return _context.UserLocation.Add(location).Entity; + + } + + public async Task GetAsync(int userId) + { + return await _context.UserLocation + .Where(ul => ul.UserId == userId) + .SingleOrDefaultAsync(); + } + + public async Task> GetNearestLocationListAsync(double lat, double lon) + { + var query = $"SELECT TOP(100) location.* " + + $"FROM[dbo].[Locations] AS location " + + $"ORDER BY [dbo].[GetDistanceFromLocation](location.Latitude, location.Longitude, " + + $"{lat.ToString(CultureInfo.InvariantCulture)}, " + + $"{lon.ToString(CultureInfo.InvariantCulture)})"; + + return await _context.Locations.FromSql(query) + .Include(f => f.Polygon) + .ToListAsync(); + } + + public void Update(UserLocation location) + { + _context.Entry(location).State = EntityState.Modified; + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs new file mode 100644 index 000000000..d49abe111 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Services/IIdentityService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +{ + public interface IIdentityService + { + string GetUserIdentity(); + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs new file mode 100644 index 000000000..672dd2703 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Services/ILocationsService.cs @@ -0,0 +1,10 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +{ + using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; + using System.Threading.Tasks; + + public interface ILocationsService + { + Task AddOrUpdateUserLocation(string userId, LocationRequest locRequest); + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs new file mode 100644 index 000000000..bcb7a84f8 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Services/IdentityService.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +{ + public class IdentityService : IIdentityService + { + private IHttpContextAccessor _context; + + public IdentityService(IHttpContextAccessor context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public string GetUserIdentity() + { + return _context.HttpContext.User.FindFirst("sub").Value; + } + } +} diff --git a/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs new file mode 100644 index 000000000..d2b721399 --- /dev/null +++ b/src/Services/Location/Locations.API/Infrastructure/Services/LocationsService.cs @@ -0,0 +1,62 @@ +namespace Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services +{ + using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; + using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; + using Microsoft.eShopOnContainers.Services.Locations.API.Model; + using System; + using System.Threading.Tasks; + + public class LocationsService : ILocationsService + { + private ILocationsRepository _locationsRepository; + + public LocationsService(ILocationsRepository locationsRepository) + { + _locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository)); + } + + public async Task AddOrUpdateUserLocation(string id, LocationRequest currentPosition) + { + int.TryParse(id, out int userId); + var currentUserLocation = await _locationsRepository.GetAsync(userId); + + // Get the nearest locations ordered by proximity + var nearestLocationList = await _locationsRepository.GetNearestLocationListAsync(currentPosition.Latitude, currentPosition.Longitude); + + // Check out in which region we currently are + foreach(var locCandidate in nearestLocationList) + { + // Check location's tree and retrive user most specific area + var findNewLocationResult = locCandidate.GetUserMostSpecificLocation(currentPosition.Latitude, currentPosition.Longitude); + if (findNewLocationResult.isSuccess) + { + CreateUserLocation(currentUserLocation, findNewLocationResult.location, userId); + UpdateUserLocation(currentUserLocation, findNewLocationResult.location); + break; + } + } + + var result = await _locationsRepository.UnitOfWork.SaveChangesAsync(); + return result > 0; + } + + private void CreateUserLocation(UserLocation currentUserLocation, Locations newLocation, int userId) + { + if (currentUserLocation is null) + { + currentUserLocation = currentUserLocation ?? new UserLocation(userId); + currentUserLocation.Location = newLocation; + _locationsRepository.Add(currentUserLocation); + } + } + + private void UpdateUserLocation(UserLocation currentUserLocation, Locations newLocation) + { + if (currentUserLocation != null) + { + currentUserLocation.Location = newLocation; + _locationsRepository.Update(currentUserLocation); + } + } + } +} diff --git a/src/Services/Location/Locations.API/Locations.API.csproj b/src/Services/Location/Locations.API/Locations.API.csproj index b00054921..34808c5e0 100644 --- a/src/Services/Location/Locations.API/Locations.API.csproj +++ b/src/Services/Location/Locations.API/Locations.API.csproj @@ -7,6 +7,7 @@ aspnet-Locations.API-20161122013619 + diff --git a/src/Services/Location/Locations.API/Model/FrontierPoints.cs b/src/Services/Location/Locations.API/Model/FrontierPoints.cs index 4a9112e5e..e9061a88f 100644 --- a/src/Services/Location/Locations.API/Model/FrontierPoints.cs +++ b/src/Services/Location/Locations.API/Model/FrontierPoints.cs @@ -3,9 +3,19 @@ public class FrontierPoints { public int Id { get; set; } - public double Latitude { get; set; } - public double Longitude { get; set; } + public double Latitude { get; private set; } + public double Longitude { get; private set; } - public Locations Location { get; set; } + public FrontierPoints() + { + } + + public FrontierPoints(double latitude, double longitude) + { + Latitude = latitude; + Longitude = longitude; + } + + public Locations Location { get; private 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 index ec21ac34f..71ffb603e 100644 --- a/src/Services/Location/Locations.API/Model/Locations.cs +++ b/src/Services/Location/Locations.API/Model/Locations.cs @@ -7,27 +7,59 @@ 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 int Id { get; private set; } + public string Code { get; private set; } + public int? ParentId { get; private set; } + public string Description { get; private set; } + public double Latitude { get; private set; } + public double Longitude { get; private set; } + public (Locations location, bool isSuccess) GetUserMostSpecificLocation(double userLatitude, double userLongitude) + => CheckUserMostSpecificLocation(userLatitude, userLongitude); public Locations() { ChildLocations = new List(); } + public Locations(string code, string description, double latitude, double longitude, List polygon = null) : this() + { + Code = code; + Description = description; + Latitude = latitude; + Longitude = longitude; + Polygon = polygon ?? new List(); + } + public virtual List Polygon { get; set; } [ForeignKey("ParentId")] public virtual List ChildLocations { get; set; } + private (Locations location, bool isSuccess) CheckUserMostSpecificLocation(double userLatitude, double userLongitude, Locations location = null) + { + Locations result = this; + var childLocations = location != null ? location.ChildLocations : ChildLocations; + + // Check if user is in location's area, if not then returns false + if (!CheckIsPointInPolygon(userLatitude, userLongitude)) + { + return (this, false); + } + + foreach (var childLocation in childLocations) + { + result = childLocation; + + if (childLocation.ChildLocations.Count == 0){ break; } + + CheckUserMostSpecificLocation(userLatitude, userLongitude, childLocation); + } + return (result, true); + } private bool CheckIsPointInPolygon(double lat, double lon) { + if(Polygon.Count == 0) { return false; }; double minX = Polygon[0].Latitude; double maxX = Polygon[0].Latitude; double minY = Polygon[0].Longitude; diff --git a/src/Services/Location/Locations.API/Model/UserLocation.cs b/src/Services/Location/Locations.API/Model/UserLocation.cs new file mode 100644 index 000000000..f26196ace --- /dev/null +++ b/src/Services/Location/Locations.API/Model/UserLocation.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.Model +{ + public class UserLocation + { + public int Id { get; set; } + public int UserId { get; set; } + + public UserLocation() + { + } + + public UserLocation(int userId) : this() + { + UserId = userId; + } + + public Locations Location { get; set; } + } +} diff --git a/src/Services/Location/Locations.API/Startup.cs b/src/Services/Location/Locations.API/Startup.cs index 1a42679a6..c13117b87 100644 --- a/src/Services/Location/Locations.API/Startup.cs +++ b/src/Services/Location/Locations.API/Startup.cs @@ -8,6 +8,9 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System.Reflection; using System; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services; +using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories; +using Microsoft.AspNetCore.Http; namespace Microsoft.eShopOnContainers.Services.Locations.API { @@ -75,6 +78,11 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API .AllowAnyHeader() .AllowCredentials()); }); + + services.AddSingleton(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs b/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs new file mode 100644 index 000000000..8619bfc0f --- /dev/null +++ b/src/Services/Location/Locations.API/ViewModel/LocationRequest.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Services.Locations.API.ViewModel +{ + public class LocationRequest + { + public double Longitude { get; set; } + public double Latitude { get; set; } + } +} diff --git a/test/Services/IntegrationTests/IntegrationTests.csproj b/test/Services/IntegrationTests/IntegrationTests.csproj index 60911dd4d..0306f2005 100644 --- a/test/Services/IntegrationTests/IntegrationTests.csproj +++ b/test/Services/IntegrationTests/IntegrationTests.csproj @@ -13,6 +13,7 @@ + @@ -20,6 +21,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -28,6 +32,7 @@ + diff --git a/test/Services/IntegrationTests/Services/Locations/LocationsScenarioBase.cs b/test/Services/IntegrationTests/Services/Locations/LocationsScenarioBase.cs new file mode 100644 index 000000000..b9d3af44c --- /dev/null +++ b/test/Services/IntegrationTests/Services/Locations/LocationsScenarioBase.cs @@ -0,0 +1,36 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace IntegrationTests.Services.Locations +{ + public class LocationsScenarioBase + { + public TestServer CreateServer() + { + var webHostBuilder = new WebHostBuilder(); + webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Locations"); + webHostBuilder.UseStartup(); + + return new TestServer(webHostBuilder); + } + + public static class Get + { + public static string Locations = "api/v1/locations"; + + public static string LocationBy(int id) + { + return $"api/v1/locations/{id}"; + } + } + + public static class Post + { + public static string AddNewLocation = "api/v1/locations/"; + } + } +} diff --git a/test/Services/IntegrationTests/Services/Locations/LocationsScenarios.cs b/test/Services/IntegrationTests/Services/Locations/LocationsScenarios.cs new file mode 100644 index 000000000..0c177d6f4 --- /dev/null +++ b/test/Services/IntegrationTests/Services/Locations/LocationsScenarios.cs @@ -0,0 +1,37 @@ +using Microsoft.eShopOnContainers.Services.Locations.API.ViewModel; +using Newtonsoft.Json; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace IntegrationTests.Services.Locations +{ + public class LocationsScenarios + : LocationsScenarioBase + { + [Fact] + public async Task Set_new_user_location_response_ok_status_code() + { + using (var server = CreateServer()) + { + var content = new StringContent(BuildLocationsRequest(), UTF8Encoding.UTF8, "application/json"); + + var response = await server.CreateClient() + .PostAsync(Post.AddNewLocation, content); + + response.EnsureSuccessStatusCode(); + } + } + + string BuildLocationsRequest() + { + var location = new LocationRequest() + { + Longitude = -122.333875, + Latitude = 47.602050 + }; + return JsonConvert.SerializeObject(location); + } + } +} diff --git a/test/Services/IntegrationTests/Services/Locations/LocationsTestsStartup.cs b/test/Services/IntegrationTests/Services/Locations/LocationsTestsStartup.cs new file mode 100644 index 000000000..0e622d854 --- /dev/null +++ b/test/Services/IntegrationTests/Services/Locations/LocationsTestsStartup.cs @@ -0,0 +1,26 @@ +namespace IntegrationTests.Services.Locations +{ + using IntegrationTests.Middleware; + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.eShopOnContainers.Services.Locations.API; + + public class LocationsTestsStartup : Startup + { + public LocationsTestsStartup(IHostingEnvironment env) : base(env) + { + } + + protected override void ConfigureAuth(IApplicationBuilder app) + { + if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant()) + { + app.UseMiddleware(); + } + else + { + base.ConfigureAuth(app); + } + } + } +} diff --git a/test/Services/IntegrationTests/Services/Locations/appsettings.json b/test/Services/IntegrationTests/Services/Locations/appsettings.json new file mode 100644 index 000000000..c31d6c9f1 --- /dev/null +++ b/test/Services/IntegrationTests/Services/Locations/appsettings.json @@ -0,0 +1,7 @@ +{ + "ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.LocationsDb;User Id=sa;Password=Pass@word;", + "ExternalCatalogBaseUrl": "http://localhost:5101", + "IdentityUrl": "http://localhost:5105", + "isTest": "true", + "EventBusConnection": "localhost" +}