From 3aa41e32aee7f627f451cc5a22e985c83e0a056a Mon Sep 17 00:00:00 2001 From: Roger Date: Wed, 19 Apr 2017 10:54:16 -0400 Subject: [PATCH 1/2] Use markdown formatting for links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ac0f05a0..d99e49fa2 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # eShopOnWeb -Sample ASP.NET Core reference application, powered by Microsoft, demonstrating a monolithic application architecture and deployment model. This reference application is meant to support the [Architecting and Developing Modern Web Applications with ASP.NET Core and Azure eBook] +Sample ASP.NET Core reference application, powered by Microsoft, demonstrating a monolithic application architecture and deployment model. This reference application is meant to support the [Architecting and Developing Modern Web Applications with ASP.NET Core and Azure eBook](https://aka.ms/webappebook) -The **eShopOnWeb** is related to the eShopOnContainers sample application which, in that case, focuses on a microservices/containers based application architecture. However, **eShopOnWeb** is much simpler in regards its current functionality and focuses on traditional Web Application Development with a single monolithic deployment, no microservices/containers related. +The **eShopOnWeb** is related to the [eShopOnContainers](https://github.com/dotnet/eShopOnContainers) sample application which, in that case, focuses on a microservices/containers based application architecture. However, **eShopOnWeb** is much simpler in regards its current functionality and focuses on traditional Web Application Development with a single monolithic deployment, no microservices/containers related. > ### DISCLAIMER > **IMPORTANT:** The current state of this sample application is **ALPHA**, consider it a 0.1 foundational version. Therefore areas will change significantly while refactoring current code and implementing new features. **Feedback with improvements and pull requests from the community are highly appreciated and accepted.** From 408c5d97ec09ee5b3211532116cf65ce2e0e5401 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Thu, 20 Apr 2017 17:04:03 -0400 Subject: [PATCH 2/2] Working on wiring up identity and basket --- .../Identity/AppIdentityDbContext.cs | 27 +++++ src/Infrastructure/Infrastructure.csproj | 11 +++ src/Web/Controllers/AccountController.cs | 98 +++++++++++++++++++ src/Web/Infrastructure/CatalogContext.cs | 2 +- src/Web/Startup.cs | 15 ++- src/Web/ViewModels/LoginViewModel.cs | 22 +++++ src/Web/Views/Account/Signin.cshtml | 62 ++++++++++++ src/Web/Views/Shared/_Layout.cshtml | 3 +- src/Web/Views/Shared/_LoginPartial.cshtml | 57 +++++++++++ src/Web/Views/_ViewImports.cshtml | 1 + src/Web/Web.csproj | 2 + src/Web/appsettings.json | 5 +- 12 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 src/Infrastructure/Identity/AppIdentityDbContext.cs create mode 100644 src/Web/Controllers/AccountController.cs create mode 100644 src/Web/ViewModels/LoginViewModel.cs create mode 100644 src/Web/Views/Account/Signin.cshtml create mode 100644 src/Web/Views/Shared/_LoginPartial.cshtml diff --git a/src/Infrastructure/Identity/AppIdentityDbContext.cs b/src/Infrastructure/Identity/AppIdentityDbContext.cs new file mode 100644 index 000000000..22e6ed9e3 --- /dev/null +++ b/src/Infrastructure/Identity/AppIdentityDbContext.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + + +namespace Infrastructure.Identity +{ + public class AppIdentityDbContext : IdentityDbContext + { + public AppIdentityDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + // Customize the ASP.NET Identity model and override the defaults if needed. + // For example, you can rename the ASP.NET Identity table names and more. + // Add your customizations after calling base.OnModelCreating(builder); + } + } + + public class ApplicationUser : IdentityUser + { + } + +} diff --git a/src/Infrastructure/Infrastructure.csproj b/src/Infrastructure/Infrastructure.csproj index 9eca54729..b377567e2 100644 --- a/src/Infrastructure/Infrastructure.csproj +++ b/src/Infrastructure/Infrastructure.csproj @@ -3,5 +3,16 @@ netstandard1.4 + + + + + + + + + + + \ No newline at end of file diff --git a/src/Web/Controllers/AccountController.cs b/src/Web/Controllers/AccountController.cs new file mode 100644 index 000000000..7a9c89152 --- /dev/null +++ b/src/Web/Controllers/AccountController.cs @@ -0,0 +1,98 @@ +using Microsoft.eShopWeb.Services; +using Microsoft.eShopWeb.ViewModels; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Infrastructure.Identity; + +namespace Microsoft.eShopWeb.Controllers +{ + public class AccountController : Controller + { + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly string _externalCookieScheme; + + + public AccountController( + UserManager userManager, + SignInManager signInManager, + IOptions identityCookieOptions + +) + { + _userManager = userManager; + _signInManager = signInManager; + _externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme; + + } + + // + // GET: /Account/SignIn + [HttpGet] + [AllowAnonymous] + public async Task SignIn(string returnUrl = null) + { + // Clear the existing external cookie to ensure a clean login process + await HttpContext.Authentication.SignOutAsync(_externalCookieScheme); + + ViewData["ReturnUrl"] = returnUrl; + return View(); + } + + // + // POST: /Account/SignIn + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task SignIn(LoginViewModel model, string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + if (ModelState.IsValid) + { + // This doesn't count login failures towards account lockout + // To enable password failures to trigger account lockout, set lockoutOnFailure: true + var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); + if (result.Succeeded) + { + //_logger.LogInformation(1, "User logged in."); + return RedirectToLocal(returnUrl); + } + //if (result.RequiresTwoFactor) + //{ + // return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); + //} + if (result.IsLockedOut) + { + //_logger.LogWarning(2, "User account locked out."); + return View("Lockout"); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return View(model); + } + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + private IActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + else + { + return RedirectToAction(nameof(CatalogController.Index), "Home"); + } + } + + + } +} diff --git a/src/Web/Infrastructure/CatalogContext.cs b/src/Web/Infrastructure/CatalogContext.cs index e2439fd0a..576a9c23e 100644 --- a/src/Web/Infrastructure/CatalogContext.cs +++ b/src/Web/Infrastructure/CatalogContext.cs @@ -6,7 +6,7 @@ namespace Microsoft.eShopWeb.Infrastructure public class CatalogContext : DbContext { - public CatalogContext(DbContextOptions options) : base(options) + public CatalogContext(DbContextOptions options) : base(options) { } public DbSet CatalogItems { get; set; } diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index 08c314944..24d7dd2f4 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -7,6 +7,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Infrastructure.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; namespace Microsoft.eShopWeb { @@ -33,7 +35,7 @@ public void ConfigureServices(IServiceCollection services) { try { - c.UseSqlServer(Configuration["ConnectionString"]); + c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection")); c.ConfigureWarnings(wb => { //By default, in this application, we don't want to have client evaluations @@ -46,6 +48,15 @@ public void ConfigureServices(IServiceCollection services) } }); + // Add Identity DbContext + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection"))); + + services.AddIdentity() + .AddEntityFrameworkStores() + .AddDefaultTokenProviders(); + + services.AddTransient(); services.Configure(Configuration); services.AddMvc(); @@ -69,6 +80,8 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF app.UseStaticFiles(); + app.UseIdentity(); + app.UseMvc(routes => { routes.MapRoute( diff --git a/src/Web/ViewModels/LoginViewModel.cs b/src/Web/ViewModels/LoginViewModel.cs new file mode 100644 index 000000000..26e2f65d0 --- /dev/null +++ b/src/Web/ViewModels/LoginViewModel.cs @@ -0,0 +1,22 @@ +using Microsoft.eShopWeb.ApplicationCore.Entities; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace Microsoft.eShopWeb.ViewModels +{ + + public class LoginViewModel + { + [Required] + [EmailAddress] + public string Email { get; set; } + + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + + [Display(Name = "Remember me?")] + public bool RememberMe { get; set; } + } + +} diff --git a/src/Web/Views/Account/Signin.cshtml b/src/Web/Views/Account/Signin.cshtml new file mode 100644 index 000000000..09f8aee6f --- /dev/null +++ b/src/Web/Views/Account/Signin.cshtml @@ -0,0 +1,62 @@ +@using System.Collections.Generic +@using Microsoft.AspNetCore.Http +@using Microsoft.AspNetCore.Http.Authentication +@model LoginViewModel +@{ + ViewData["Title"] = "Log in"; +} +
+ +
+ + + @section Scripts { + @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } + } diff --git a/src/Web/Views/Shared/_Layout.cshtml b/src/Web/Views/Shared/_Layout.cshtml index 7eb654a67..cb6a1ada8 100644 --- a/src/Web/Views/Shared/_Layout.cshtml +++ b/src/Web/Views/Shared/_Layout.cshtml @@ -29,7 +29,8 @@ - + @await Html.PartialAsync("_LoginPartial") + diff --git a/src/Web/Views/Shared/_LoginPartial.cshtml b/src/Web/Views/Shared/_LoginPartial.cshtml new file mode 100644 index 000000000..eae827aff --- /dev/null +++ b/src/Web/Views/Shared/_LoginPartial.cshtml @@ -0,0 +1,57 @@ +@using Microsoft.AspNetCore.Identity +@*@inject IIdentityParser UserManager*@ + + @if (Context.User.Identity.IsAuthenticated) +{ +
+
+ +
+
+ +
+ @*@await Component.InvokeAsync("Cart", new { user = UserManager.Parse(User) })*@ +
+ +} +else +{ +
+
+
+ +
+
+
+ +
+} diff --git a/src/Web/Views/_ViewImports.cshtml b/src/Web/Views/_ViewImports.cshtml index b4d7baf3c..f3e172c27 100644 --- a/src/Web/Views/_ViewImports.cshtml +++ b/src/Web/Views/_ViewImports.cshtml @@ -1,2 +1,3 @@ @using Microsoft.eShopWeb +@using Microsoft.eShopWeb.ViewModels @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj index 564c309c8..22a20b327 100644 --- a/src/Web/Web.csproj +++ b/src/Web/Web.csproj @@ -30,11 +30,13 @@ + + diff --git a/src/Web/appsettings.json b/src/Web/appsettings.json index 6f5c42c75..c3ebcd8d4 100644 --- a/src/Web/appsettings.json +++ b/src/Web/appsettings.json @@ -1,5 +1,8 @@ { - "ConnectionString": "Server=(localdb)\\ProjectsV13;Integrated Security=true;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;", + "ConnectionStrings": { + "CatalogConnection": "Server=(localdb)\\ProjectsV13;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;", + "IdentityConnection": "Server=(localdb)\\ProjectsV13;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.Identity;" + }, "CatalogBaseUrl": "http://localhost:5106", "Logging": { "IncludeScopes": false,