diff --git a/src/MusicStore/Controllers/AccountController.cs b/src/MusicStore/Controllers/AccountController.cs index cc53dd3074..3ab1822754 100644 --- a/src/MusicStore/Controllers/AccountController.cs +++ b/src/MusicStore/Controllers/AccountController.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using MusicStore.Models; namespace MusicStore.Controllers @@ -15,12 +16,16 @@ namespace MusicStore.Controllers [Authorize] public class AccountController : Controller { + private readonly ILogger _logger; + public AccountController( UserManager userManager, - SignInManager signInManager) + SignInManager signInManager, + ILogger logger) { UserManager = userManager; SignInManager = signInManager; + _logger = logger; } public UserManager UserManager { get; } @@ -53,6 +58,7 @@ namespace MusicStore.Controllers var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { + _logger.LogInformation("Logged in {userName}.", model.Email); return RedirectToLocal(returnUrl); } if (result.RequiresTwoFactor) @@ -65,6 +71,7 @@ namespace MusicStore.Controllers } else { + _logger.LogWarning("Failed to log in {userName}.", model.Email); ModelState.AddModelError("", "Invalid login attempt."); return View(model); } @@ -145,6 +152,7 @@ namespace MusicStore.Controllers var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { + _logger.LogInformation("User {userName} was created.", model.Email); //Bug: Remember browser option missing? //Uncomment this and comment the later part if account verification is not needed. //await SignInManager.SignInAsync(user, isPersistent: false); @@ -162,10 +170,10 @@ namespace MusicStore.Controllers ViewBag.Link = callbackUrl; return View("DemoLinkDisplay"); #endif + } AddErrors(result); } - // If we got this far, something failed, redisplay form return View(model); } @@ -443,6 +451,7 @@ namespace MusicStore.Controllers [ValidateAntiForgeryToken] public async Task LogOff() { + var userName = HttpContext.User.Identity.Name; // clear all items from the cart HttpContext.Session.Clear(); @@ -459,6 +468,7 @@ namespace MusicStore.Controllers }); } + _logger.LogInformation("{userName} logged out.", userName); return RedirectToAction("Index", "Home"); } @@ -477,6 +487,7 @@ namespace MusicStore.Controllers foreach (var error in result.Errors) { ModelState.AddModelError("", error.Description); + _logger.LogWarning("Error in creating user: {error}", error.Description); } } diff --git a/src/MusicStore/Controllers/CheckoutController.cs b/src/MusicStore/Controllers/CheckoutController.cs index 56ed9116ea..5f7a5e2ae8 100644 --- a/src/MusicStore/Controllers/CheckoutController.cs +++ b/src/MusicStore/Controllers/CheckoutController.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using MusicStore.Models; namespace MusicStore.Controllers @@ -15,6 +16,13 @@ namespace MusicStore.Controllers { private const string PromoCode = "FREE"; + private readonly ILogger _logger; + + public CheckoutController(ILogger logger) + { + _logger = logger; + } + // // GET: /Checkout/ public IActionResult AddressAndPayment() @@ -58,6 +66,8 @@ namespace MusicStore.Controllers var cart = ShoppingCart.GetCart(dbContext, HttpContext); await cart.CreateOrder(order); + _logger.LogInformation("User {userName} started checkout of {orderId}.", order.Username, order.OrderId); + // Save all changes await dbContext.SaveChangesAsync(requestAborted); @@ -78,17 +88,24 @@ namespace MusicStore.Controllers [FromServices] MusicStoreContext dbContext, int id) { + var userName = HttpContext.User.Identity.Name; + // Validate customer owns this order bool isValid = await dbContext.Orders.AnyAsync( o => o.OrderId == id && - o.Username == HttpContext.User.Identity.Name); + o.Username == userName); if (isValid) { + _logger.LogInformation("User {userName} completed checkout on order {orderId}.", userName, id); return View(id); } else { + _logger.LogError( + "User {userName} tried to checkout with an order ({orderId}) that doesn't belong to them.", + userName, + id); return View("Error"); } } diff --git a/src/MusicStore/Controllers/ShoppingCartController.cs b/src/MusicStore/Controllers/ShoppingCartController.cs index d2bfb401fb..637bce3a74 100644 --- a/src/MusicStore/Controllers/ShoppingCartController.cs +++ b/src/MusicStore/Controllers/ShoppingCartController.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using MusicStore.Models; using MusicStore.ViewModels; @@ -10,9 +11,12 @@ namespace MusicStore.Controllers { public class ShoppingCartController : Controller { - public ShoppingCartController(MusicStoreContext dbContext) + private readonly ILogger _logger; + + public ShoppingCartController(MusicStoreContext dbContext, ILogger logger) { DbContext = dbContext; + _logger = logger; } public MusicStoreContext DbContext { get; } @@ -49,6 +53,7 @@ namespace MusicStore.Controllers cart.AddToCart(addedAlbum); await DbContext.SaveChangesAsync(requestAborted); + _logger.LogInformation("Album {albumId} was added to the cart.", addedAlbum.AlbumId); // Go back to the main store page for more shopping return RedirectToAction("Index"); @@ -90,6 +95,8 @@ namespace MusicStore.Controllers DeleteId = id }; + _logger.LogInformation("Album {id} was removed from a cart.", id); + return Json(results); } } diff --git a/src/MusicStore/Startup.cs b/src/MusicStore/Startup.cs index 7be45a3eb9..14abc7ec7e 100644 --- a/src/MusicStore/Startup.cs +++ b/src/MusicStore/Startup.cs @@ -4,6 +4,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.PlatformAbstractions; using MusicStore.Components; using MusicStore.Models; @@ -34,7 +35,6 @@ namespace MusicStore public void ConfigureServices(IServiceCollection services) { services.Configure(Configuration.GetSection("AppSettings")); - var useInMemoryStore = !_platform.IsRunningOnWindows || _platform.IsRunningOnMono || _platform.IsRunningOnNanoServer; @@ -48,7 +48,7 @@ namespace MusicStore else { services.AddDbContext(options => - options.UseSqlServer(Configuration[StoreConfig.ConnectionStringKey.Replace("__",":")])); + options.UseSqlServer(Configuration[StoreConfig.ConnectionStringKey.Replace("__", ":")])); } // Add Identity services to the services container @@ -68,6 +68,8 @@ namespace MusicStore }); }); + services.AddLogging(); + // Add MVC services to the services container services.AddMvc(); @@ -86,7 +88,8 @@ namespace MusicStore { options.AddPolicy( "ManageStore", - authBuilder => { + authBuilder => + { authBuilder.RequireClaim("ManageStore", "Allowed"); }); }); diff --git a/src/MusicStore/project.json b/src/MusicStore/project.json index 43ab78588c..1b8ceb5647 100644 --- a/src/MusicStore/project.json +++ b/src/MusicStore/project.json @@ -13,6 +13,9 @@ ], "preserveCompilationContext": true }, + "commands": { + "web": "MusicStore" + }, "compile": [ "../../shared/**/*.cs" ], @@ -50,7 +53,7 @@ "Microsoft.NETCore.Platforms": "1.0.1-*", }, "frameworks": { - "net451": {}, + "net451": { }, "netstandardapp1.5": { "dependencies": { "NETStandard.Library": "1.5.0-*" diff --git a/test/E2ETests/project.json b/test/E2ETests/project.json index 2a7f144726..f690e0f0c7 100644 --- a/test/E2ETests/project.json +++ b/test/E2ETests/project.json @@ -6,12 +6,13 @@ "../../shared/**/*.cs" ], "dependencies": { - "Microsoft.AspNetCore.Identity": "1.0.0-*", "Microsoft.AspNetCore.Authentication.Cookies": "1.0.0-*", "Microsoft.AspNetCore.Authentication.OpenIdConnect": "0.1.0-*", + "Microsoft.AspNetCore.Identity": "1.0.0-*", "Microsoft.AspNetCore.Server.Testing": "1.0.0-*", "Microsoft.AspNetCore.WebUtilities": "1.0.0-*", "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-*", + "Microsoft.Extensions.Logging": "1.0.0-*", "Microsoft.Extensions.Logging.Console": "1.0.0-*", "xunit": "2.1.0" }, diff --git a/test/MusicStore.Test/CheckoutControllerTest.cs b/test/MusicStore.Test/CheckoutControllerTest.cs index 0a22d11a76..b2311abf1f 100644 --- a/test/MusicStore.Test/CheckoutControllerTest.cs +++ b/test/MusicStore.Test/CheckoutControllerTest.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using MusicStore.Models; using Xunit; @@ -33,7 +34,7 @@ namespace MusicStore.Controllers public void AddressAndPayment_ReturnsDefaultView() { // Arrange - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); // Act var result = controller.AddressAndPayment(); @@ -81,7 +82,7 @@ namespace MusicStore.Controllers dbContext.AddRange(cartItems); dbContext.SaveChanges(); - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -107,7 +108,7 @@ namespace MusicStore.Controllers context.Request.Form = new FormCollection(new Dictionary()); - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ControllerContext.HttpContext = context; // Do not need actual data for Order; the Order object will be checked for the reference equality. @@ -133,7 +134,7 @@ namespace MusicStore.Controllers new FormCollection(new Dictionary()); var dbContext = _serviceProvider.GetRequiredService(); - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ControllerContext.HttpContext = context; var order = new Order(); @@ -153,7 +154,7 @@ namespace MusicStore.Controllers public async Task AddressAndPayment_ReturnsOrderIfInvalidOrderModel() { // Arrange - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ModelState.AddModelError("a", "ModelErrorA"); var dbContext = _serviceProvider.GetRequiredService(); @@ -192,7 +193,7 @@ namespace MusicStore.Controllers }); dbContext.SaveChanges(); - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -214,7 +215,7 @@ namespace MusicStore.Controllers var dbContext = _serviceProvider.GetRequiredService(); - var controller = new CheckoutController(); + var controller = new CheckoutController(_serviceProvider.GetService>()); controller.ControllerContext.HttpContext = new DefaultHttpContext(); // Act diff --git a/test/MusicStore.Test/ShoppingCartControllerTest.cs b/test/MusicStore.Test/ShoppingCartControllerTest.cs index 699d421ef4..f24ee12b01 100644 --- a/test/MusicStore.Test/ShoppingCartControllerTest.cs +++ b/test/MusicStore.Test/ShoppingCartControllerTest.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.ObjectPool; using Microsoft.Extensions.Primitives; using MusicStore.Models; @@ -42,7 +43,9 @@ namespace MusicStore.Controllers var httpContext = new DefaultHttpContext(); httpContext.Session = new TestSession(); - var controller = new ShoppingCartController(_serviceProvider.GetRequiredService()); + var controller = new ShoppingCartController( + _serviceProvider.GetRequiredService(), + _serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -66,7 +69,9 @@ namespace MusicStore.Controllers httpContext.Session = new TestSession(); httpContext.Session.SetString("Session", "CartId_A"); - var controller = new ShoppingCartController(_serviceProvider.GetRequiredService()); + var controller = new ShoppingCartController( + _serviceProvider.GetRequiredService(), + _serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -100,7 +105,9 @@ namespace MusicStore.Controllers dbContext.AddRange(cartItems); dbContext.SaveChanges(); - var controller = new ShoppingCartController(dbContext); + var controller = new ShoppingCartController( + dbContext, + _serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -131,7 +138,9 @@ namespace MusicStore.Controllers dbContext.AddRange(albums); dbContext.SaveChanges(); - var controller = new ShoppingCartController(dbContext); + var controller = new ShoppingCartController( + dbContext, + _serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act @@ -184,7 +193,9 @@ namespace MusicStore.Controllers httpContext.Request.Headers.Add(headers); // Cotroller initialization - var controller = new ShoppingCartController(dbContext); + var controller = new ShoppingCartController( + dbContext, + _serviceProvider.GetService>()); controller.ControllerContext.HttpContext = httpContext; // Act