MVC App: Authentication against IdentityService and Order Api basic integration.
This commit is contained in:
parent
87186a8493
commit
a939fe7a51
@ -66,7 +66,10 @@ services:
|
||||
- ordering.data
|
||||
|
||||
ordering.data:
|
||||
image: eshop/ordering.data.sqlserver.linux
|
||||
image: microsoft/mssql-server-linux
|
||||
environment:
|
||||
- SA_PASSWORD=Pass@word
|
||||
- ACCEPT_EULA=Y
|
||||
ports:
|
||||
- "5432:1433"
|
||||
|
||||
|
@ -61,6 +61,55 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
"orders",
|
||||
"basket"
|
||||
}
|
||||
},
|
||||
new Client
|
||||
{
|
||||
ClientId = "xamarin",
|
||||
ClientName = "eShop Xamarin OpenId Client",
|
||||
AllowedGrantTypes = GrantTypes.Implicit,
|
||||
AllowAccessTokensViaBrowser = true,
|
||||
|
||||
RedirectUris = { "http://localhost:5003/callback.html" },
|
||||
PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
|
||||
AllowedCorsOrigins = { "http://localhost:5003" },
|
||||
|
||||
AllowedScopes =
|
||||
{
|
||||
StandardScopes.OpenId.Name,
|
||||
StandardScopes.Profile.Name,
|
||||
"orders",
|
||||
"basket"
|
||||
}
|
||||
},
|
||||
new Client
|
||||
{
|
||||
ClientId = "mvc",
|
||||
ClientName = "MVC Client",
|
||||
ClientSecrets = new List<Secret>
|
||||
{
|
||||
new Secret("secret".Sha256())
|
||||
},
|
||||
ClientUri = "http://localhost:2114",
|
||||
|
||||
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
|
||||
|
||||
RedirectUris = new List<string>
|
||||
{
|
||||
"http://localhost:2114/signin-oidc"
|
||||
},
|
||||
PostLogoutRedirectUris = new List<string>
|
||||
{
|
||||
"http://localhost:2114/"
|
||||
},
|
||||
LogoutUri = "http://localhost:2114/signout-oidc",
|
||||
AllowedScopes = new List<string>
|
||||
{
|
||||
StandardScopes.OpenId.Name,
|
||||
StandardScopes.Profile.Name,
|
||||
StandardScopes.OfflineAccess.Name,
|
||||
"orders",
|
||||
"basket",
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace eShopOnContainers.Identity.Extensions
|
||||
{
|
||||
//public static class PrincipalExtensions
|
||||
//{
|
||||
// public static string GetSubjectId(this IPrincipal principal)
|
||||
// {
|
||||
// return principal.Identity.GetSubjectId();
|
||||
// }
|
||||
//}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
using IdentityServer4.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using IdentityServer4.Models;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using eShopOnContainers.Identity.Models;
|
||||
using System.Security.Claims;
|
||||
using IdentityModel;
|
||||
|
||||
namespace eShopOnContainers.Identity.Services
|
||||
{
|
||||
public class ProfileService : IProfileService
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public ProfileService(UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
async public Task GetProfileDataAsync(ProfileDataRequestContext context)
|
||||
{
|
||||
var subject = context.Subject;
|
||||
if (subject == null) throw new ArgumentNullException(nameof(context.Subject));
|
||||
|
||||
var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
|
||||
|
||||
var user = await _userManager.FindByIdAsync(subjectId);
|
||||
if (user == null)
|
||||
throw new ArgumentException("Invalid subject identifier");
|
||||
|
||||
var claims = GetClaimsFromUser(user);
|
||||
context.IssuedClaims = claims.ToList();
|
||||
}
|
||||
|
||||
async public Task IsActiveAsync(IsActiveContext context)
|
||||
{
|
||||
var subject = context.Subject;
|
||||
if (subject == null) throw new ArgumentNullException(nameof(context.Subject));
|
||||
|
||||
var subjectId = subject.Claims.Where(x => x.Type == "sub").FirstOrDefault().Value;
|
||||
var user = await _userManager.FindByIdAsync(subjectId);
|
||||
|
||||
context.IsActive = false;
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
if (_userManager.SupportsUserSecurityStamp)
|
||||
{
|
||||
var security_stamp = subject.Claims.Where(c => c.Type == "security_stamp").Select(c => c.Value).SingleOrDefault();
|
||||
if (security_stamp != null)
|
||||
{
|
||||
var db_security_stamp = await _userManager.GetSecurityStampAsync(user);
|
||||
if (db_security_stamp != security_stamp)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context.IsActive =
|
||||
!user.LockoutEnabled ||
|
||||
!user.LockoutEnd.HasValue ||
|
||||
user.LockoutEnd <= DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Claim> GetClaimsFromUser(ApplicationUser user)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(JwtClaimTypes.Subject, user.Id),
|
||||
new Claim(JwtClaimTypes.PreferredUserName, user.UserName)
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.Name))
|
||||
claims.Add(new Claim("name", user.Name));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.Name))
|
||||
claims.Add(new Claim("last_name", user.LastName));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.CardNumber))
|
||||
claims.Add(new Claim("card_number", user.CardNumber));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.CardHolderName))
|
||||
claims.Add(new Claim("card_holder", user.CardHolderName));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.SecurityNumber))
|
||||
claims.Add(new Claim("card_security_number", user.SecurityNumber));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.City))
|
||||
claims.Add(new Claim("address_city", user.City));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.Country))
|
||||
claims.Add(new Claim("address_country", user.Country));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.State))
|
||||
claims.Add(new Claim("address_state", user.State));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.Street))
|
||||
claims.Add(new Claim("address_street", user.Street));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(user.ZipCode))
|
||||
claims.Add(new Claim("address_zip_code", user.ZipCode));
|
||||
|
||||
if (_userManager.SupportsUserEmail)
|
||||
{
|
||||
claims.AddRange(new[]
|
||||
{
|
||||
new Claim(JwtClaimTypes.Email, user.Email),
|
||||
new Claim(JwtClaimTypes.EmailVerified, user.EmailConfirmed ? "true" : "false", ClaimValueTypes.Boolean)
|
||||
});
|
||||
}
|
||||
|
||||
if (_userManager.SupportsUserPhoneNumber && !string.IsNullOrWhiteSpace(user.PhoneNumber))
|
||||
{
|
||||
claims.AddRange(new[]
|
||||
{
|
||||
new Claim(JwtClaimTypes.PhoneNumber, user.PhoneNumber),
|
||||
new Claim(JwtClaimTypes.PhoneNumberVerified, user.PhoneNumberConfirmed ? "true" : "false", ClaimValueTypes.Boolean)
|
||||
});
|
||||
}
|
||||
|
||||
return claims;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ using eShopOnContainers.Identity.Data;
|
||||
using eShopOnContainers.Identity.Models;
|
||||
using eShopOnContainers.Identity.Services;
|
||||
using eShopOnContainers.Identity.Configuration;
|
||||
using IdentityServer4.Services;
|
||||
|
||||
namespace eShopOnContainers.Identity
|
||||
{
|
||||
@ -47,6 +48,7 @@ namespace eShopOnContainers.Identity
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
@ -59,7 +61,8 @@ namespace eShopOnContainers.Identity
|
||||
.AddTemporarySigningCredential()
|
||||
.AddInMemoryScopes(Config.GetScopes())
|
||||
.AddInMemoryClients(Config.GetClients())
|
||||
.AddAspNetIdentity<ApplicationUser>();
|
||||
.AddAspNetIdentity<ApplicationUser>()
|
||||
.Services.AddTransient<IProfileService, ProfileService>();
|
||||
|
||||
//Configuration Settings:
|
||||
services.AddOptions();
|
||||
@ -89,6 +92,7 @@ namespace eShopOnContainers.Identity
|
||||
|
||||
// Adds IdentityServer
|
||||
app.UseIdentityServer();
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
//"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
//"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
},
|
||||
"ClientsCallBackUrls": {
|
||||
"Spa": "http://localhost:5003"
|
||||
|
@ -1,3 +1,4 @@
|
||||
{
|
||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
//"ConnectionString": "Server=tcp:ordering.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
"ConnectionString": "Server=tcp:127.0.0.1,5432;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
}
|
||||
|
@ -4,438 +4,497 @@ using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models.AccountViewModels;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Extensions;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class AccountController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public AccountController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
ILoggerFactory loggerFactory)
|
||||
private readonly IIdentityParser<ApplicationUser> _identityParser;
|
||||
public AccountController(IIdentityParser<ApplicationUser> identityParser)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||
_identityParser = identityParser;
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Login
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult Login(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Login
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Login(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);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Register
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult Register(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Register
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
UserName = model.Email,
|
||||
Email = model.Email,
|
||||
CardHolderName = model.User.CardHolderName,
|
||||
CardNumber = model.User.CardNumber,
|
||||
CardType = model.User.CardType,
|
||||
City = model.User.City,
|
||||
Country = model.User.Country,
|
||||
Expiration = model.User.Expiration,
|
||||
LastName = model.User.LastName,
|
||||
Name = model.User.Name,
|
||||
Street = model.User.Street,
|
||||
State = model.User.State,
|
||||
ZipCode = model.User.ZipCode,
|
||||
PhoneNumber = model.User.PhoneNumber,
|
||||
SecurityNumber = model.User.SecurityNumber
|
||||
};
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// Send an email with this link
|
||||
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
|
||||
// $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
_logger.LogInformation(3, "User created a new account with password.");
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/LogOff
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> LogOff()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
_logger.LogInformation(4, "User logged out.");
|
||||
return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLogin
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult ExternalLogin(string provider, string returnUrl = null)
|
||||
{
|
||||
// Request a redirect to the external login provider.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
return Challenge(properties, provider);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ExternalLoginCallback
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
|
||||
{
|
||||
if (remoteError != null)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
|
||||
return View(nameof(Login));
|
||||
}
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
if (info == null)
|
||||
{
|
||||
return RedirectToAction(nameof(Login));
|
||||
}
|
||||
|
||||
// Sign in the user with this external login provider if the user already has a login.
|
||||
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the user does not have an account, then ask the user to create an account.
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
ViewData["LoginProvider"] = info.LoginProvider;
|
||||
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
|
||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLoginConfirmation
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// Get the information about the user from the external login provider
|
||||
var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
if (info == null)
|
||||
{
|
||||
return View("ExternalLoginFailure");
|
||||
}
|
||||
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
|
||||
var result = await _userManager.CreateAsync(user);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
result = await _userManager.AddLoginAsync(user, info);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
_logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
}
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// GET: /Account/ConfirmEmail
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> ConfirmEmail(string userId, string code)
|
||||
{
|
||||
if (userId == null || code == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var user = await _userManager.FindByIdAsync(userId);
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var result = await _userManager.ConfirmEmailAsync(user, code);
|
||||
return View(result.Succeeded ? "ConfirmEmail" : "Error");
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ForgotPassword
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ForgotPassword()
|
||||
public ActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ForgotPassword
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
|
||||
[Authorize]
|
||||
public IActionResult SignIn(string returnUrl)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
var user = User as ClaimsPrincipal;
|
||||
|
||||
//TODO - Not retrieving AccessToken yet
|
||||
var token = user.FindFirst("access_token");
|
||||
if (token != null)
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(model.Email);
|
||||
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
|
||||
{
|
||||
// Don't reveal that the user does not exist or is not confirmed
|
||||
return View("ForgotPasswordConfirmation");
|
||||
}
|
||||
|
||||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// Send an email with this link
|
||||
//var code = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
//var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
//await _emailSender.SendEmailAsync(model.Email, "Reset Password",
|
||||
// $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
|
||||
//return View("ForgotPasswordConfirmation");
|
||||
ViewData["access_token"] = token.Value;
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
return Redirect("/");
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ForgotPasswordConfirmation
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ForgotPasswordConfirmation()
|
||||
[Authorize]
|
||||
public async Task<ActionResult> CallApi()
|
||||
{
|
||||
var token = (User as ClaimsPrincipal).FindFirst("access_token").Value;
|
||||
|
||||
var client = new HttpClient();
|
||||
client.SetBearerToken(token);
|
||||
|
||||
var result = await client.GetStringAsync("apiuri");
|
||||
ViewBag.Json = JArray.Parse(result.ToString());
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ResetPassword
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ResetPassword(string code = null)
|
||||
|
||||
public async Task<ActionResult> Signout()
|
||||
{
|
||||
return code == null ? View("Error") : View();
|
||||
await Request.HttpContext.Authentication.SignOutAsync("oidc");
|
||||
return Redirect("/");
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ResetPassword
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
|
||||
public async Task SignoutCleanup(string sid)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
var cp = (ClaimsPrincipal)User;
|
||||
var sidClaim = cp.FindFirst("sid");
|
||||
if (sidClaim != null && sidClaim.Value == sid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
var user = await _userManager.FindByNameAsync(model.Email);
|
||||
if (user == null)
|
||||
{
|
||||
// Don't reveal that the user does not exist
|
||||
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
|
||||
}
|
||||
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
|
||||
}
|
||||
AddErrors(result);
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ResetPasswordConfirmation
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult ResetPasswordConfirmation()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/SendCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public async Task<ActionResult> SendCode(string returnUrl = null, bool rememberMe = false)
|
||||
{
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
|
||||
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
|
||||
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/VerifyCode
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> VerifyCode(string provider, bool rememberMe, string returnUrl = null)
|
||||
{
|
||||
// Require that the user has already logged in via username/password or external login
|
||||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
if (user == null)
|
||||
{
|
||||
return View("Error");
|
||||
}
|
||||
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/VerifyCode
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> VerifyCode(VerifyCodeViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// The following code protects for brute force attacks against the two factor codes.
|
||||
// If a user enters incorrect codes for a specified amount of time then the user account
|
||||
// will be locked out for a specified amount of time.
|
||||
var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(7, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
return View(model);
|
||||
await Request.HttpContext.Authentication.SignOutAsync("Cookies");
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
//private readonly UserManager<ApplicationUser> _userManager;
|
||||
//private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
//private readonly ILogger _logger;
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
}
|
||||
//public AccountController(
|
||||
// UserManager<ApplicationUser> userManager,
|
||||
// SignInManager<ApplicationUser> signInManager,
|
||||
// ILoggerFactory loggerFactory)
|
||||
//{
|
||||
// _userManager = userManager;
|
||||
// _signInManager = signInManager;
|
||||
// _logger = loggerFactory.CreateLogger<AccountController>();
|
||||
//}
|
||||
|
||||
private Task<ApplicationUser> GetCurrentUserAsync()
|
||||
{
|
||||
return _userManager.GetUserAsync(HttpContext.User);
|
||||
}
|
||||
////
|
||||
//// GET: /Account/Login
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult Login(string returnUrl = null)
|
||||
//{
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// return View();
|
||||
//}
|
||||
|
||||
private IActionResult RedirectToLocal(string returnUrl)
|
||||
{
|
||||
if (Url.IsLocalUrl(returnUrl))
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
}
|
||||
}
|
||||
////
|
||||
//// POST: /Account/Login
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> Login(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);
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
// // If we got this far, something failed, redisplay form
|
||||
// return View(model);
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/Register
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult Register(string returnUrl = null)
|
||||
//{
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// return View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/Register
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
|
||||
//{
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// if (ModelState.IsValid)
|
||||
// {
|
||||
// var user = new ApplicationUser
|
||||
// {
|
||||
// UserName = model.Email,
|
||||
// Email = model.Email,
|
||||
// CardHolderName = model.User.CardHolderName,
|
||||
// CardNumber = model.User.CardNumber,
|
||||
// CardType = model.User.CardType,
|
||||
// City = model.User.City,
|
||||
// Country = model.User.Country,
|
||||
// Expiration = model.User.Expiration,
|
||||
// LastName = model.User.LastName,
|
||||
// Name = model.User.Name,
|
||||
// Street = model.User.Street,
|
||||
// State = model.User.State,
|
||||
// ZipCode = model.User.ZipCode,
|
||||
// PhoneNumber = model.User.PhoneNumber,
|
||||
// SecurityNumber = model.User.SecurityNumber
|
||||
// };
|
||||
// var result = await _userManager.CreateAsync(user, model.Password);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// // Send an email with this link
|
||||
// //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
// //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
// //await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
|
||||
// // $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
|
||||
// await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
// _logger.LogInformation(3, "User created a new account with password.");
|
||||
// return RedirectToLocal(returnUrl);
|
||||
// }
|
||||
// AddErrors(result);
|
||||
// }
|
||||
|
||||
// // If we got this far, something failed, redisplay form
|
||||
// return View(model);
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/LogOff
|
||||
//[HttpPost]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> LogOff()
|
||||
//{
|
||||
// await _signInManager.SignOutAsync();
|
||||
// _logger.LogInformation(4, "User logged out.");
|
||||
// return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/ExternalLogin
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public IActionResult ExternalLogin(string provider, string returnUrl = null)
|
||||
//{
|
||||
// // Request a redirect to the external login provider.
|
||||
// var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||
// var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
// return Challenge(properties, provider);
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ExternalLoginCallback
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
|
||||
//{
|
||||
// if (remoteError != null)
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
|
||||
// return View(nameof(Login));
|
||||
// }
|
||||
// var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
// if (info == null)
|
||||
// {
|
||||
// return RedirectToAction(nameof(Login));
|
||||
// }
|
||||
|
||||
// // Sign in the user with this external login provider if the user already has a login.
|
||||
// var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
|
||||
// return RedirectToLocal(returnUrl);
|
||||
// }
|
||||
// if (result.RequiresTwoFactor)
|
||||
// {
|
||||
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
|
||||
// }
|
||||
// if (result.IsLockedOut)
|
||||
// {
|
||||
// return View("Lockout");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // If the user does not have an account, then ask the user to create an account.
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// ViewData["LoginProvider"] = info.LoginProvider;
|
||||
// var email = info.Principal.FindFirstValue(ClaimTypes.Email);
|
||||
// return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
|
||||
// }
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/ExternalLoginConfirmation
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
|
||||
//{
|
||||
// if (ModelState.IsValid)
|
||||
// {
|
||||
// // Get the information about the user from the external login provider
|
||||
// var info = await _signInManager.GetExternalLoginInfoAsync();
|
||||
// if (info == null)
|
||||
// {
|
||||
// return View("ExternalLoginFailure");
|
||||
// }
|
||||
// var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
|
||||
// var result = await _userManager.CreateAsync(user);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// result = await _userManager.AddLoginAsync(user, info);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// await _signInManager.SignInAsync(user, isPersistent: false);
|
||||
// _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
|
||||
// return RedirectToLocal(returnUrl);
|
||||
// }
|
||||
// }
|
||||
// AddErrors(result);
|
||||
// }
|
||||
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// return View(model);
|
||||
//}
|
||||
|
||||
//// GET: /Account/ConfirmEmail
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public async Task<IActionResult> ConfirmEmail(string userId, string code)
|
||||
//{
|
||||
// if (userId == null || code == null)
|
||||
// {
|
||||
// return View("Error");
|
||||
// }
|
||||
// var user = await _userManager.FindByIdAsync(userId);
|
||||
// if (user == null)
|
||||
// {
|
||||
// return View("Error");
|
||||
// }
|
||||
// var result = await _userManager.ConfirmEmailAsync(user, code);
|
||||
// return View(result.Succeeded ? "ConfirmEmail" : "Error");
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ForgotPassword
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult ForgotPassword()
|
||||
//{
|
||||
// return View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/ForgotPassword
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
|
||||
//{
|
||||
// if (ModelState.IsValid)
|
||||
// {
|
||||
// var user = await _userManager.FindByNameAsync(model.Email);
|
||||
// if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
|
||||
// {
|
||||
// // Don't reveal that the user does not exist or is not confirmed
|
||||
// return View("ForgotPasswordConfirmation");
|
||||
// }
|
||||
|
||||
// // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
||||
// // Send an email with this link
|
||||
// //var code = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
// //var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
|
||||
// //await _emailSender.SendEmailAsync(model.Email, "Reset Password",
|
||||
// // $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
|
||||
// //return View("ForgotPasswordConfirmation");
|
||||
// }
|
||||
|
||||
// // If we got this far, something failed, redisplay form
|
||||
// return View(model);
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ForgotPasswordConfirmation
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult ForgotPasswordConfirmation()
|
||||
//{
|
||||
// return View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ResetPassword
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult ResetPassword(string code = null)
|
||||
//{
|
||||
// return code == null ? View("Error") : View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/ResetPassword
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
|
||||
//{
|
||||
// if (!ModelState.IsValid)
|
||||
// {
|
||||
// return View(model);
|
||||
// }
|
||||
// var user = await _userManager.FindByNameAsync(model.Email);
|
||||
// if (user == null)
|
||||
// {
|
||||
// // Don't reveal that the user does not exist
|
||||
// return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
|
||||
// }
|
||||
// var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
|
||||
// }
|
||||
// AddErrors(result);
|
||||
// return View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ResetPasswordConfirmation
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public IActionResult ResetPasswordConfirmation()
|
||||
//{
|
||||
// return View();
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/SendCode
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public async Task<ActionResult> SendCode(string returnUrl = null, bool rememberMe = false)
|
||||
//{
|
||||
// var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
// if (user == null)
|
||||
// {
|
||||
// return View("Error");
|
||||
// }
|
||||
// var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
|
||||
// var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
|
||||
// return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/VerifyCode
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public async Task<IActionResult> VerifyCode(string provider, bool rememberMe, string returnUrl = null)
|
||||
//{
|
||||
// // Require that the user has already logged in via username/password or external login
|
||||
// var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
|
||||
// if (user == null)
|
||||
// {
|
||||
// return View("Error");
|
||||
// }
|
||||
// return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/VerifyCode
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public async Task<IActionResult> VerifyCode(VerifyCodeViewModel model)
|
||||
//{
|
||||
// if (!ModelState.IsValid)
|
||||
// {
|
||||
// return View(model);
|
||||
// }
|
||||
|
||||
// // The following code protects for brute force attacks against the two factor codes.
|
||||
// // If a user enters incorrect codes for a specified amount of time then the user account
|
||||
// // will be locked out for a specified amount of time.
|
||||
// var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
|
||||
// if (result.Succeeded)
|
||||
// {
|
||||
// return RedirectToLocal(model.ReturnUrl);
|
||||
// }
|
||||
// if (result.IsLockedOut)
|
||||
// {
|
||||
// _logger.LogWarning(7, "User account locked out.");
|
||||
// return View("Lockout");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
// return View(model);
|
||||
// }
|
||||
//}
|
||||
|
||||
//#region Helpers
|
||||
|
||||
//private void AddErrors(IdentityResult result)
|
||||
//{
|
||||
// foreach (var error in result.Errors)
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, error.Description);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private Task<ApplicationUser> GetCurrentUserAsync()
|
||||
//{
|
||||
// return _userManager.GetUserAsync(HttpContext.User);
|
||||
//}
|
||||
|
||||
//private IActionResult RedirectToLocal(string returnUrl)
|
||||
//{
|
||||
// if (Url.IsLocalUrl(returnUrl))
|
||||
// {
|
||||
// return Redirect(returnUrl);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
// }
|
||||
//}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@ -13,21 +12,22 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
[Authorize]
|
||||
public class CartController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly IBasketService _basketSvc;
|
||||
private readonly ICatalogService _catalogSvc;
|
||||
private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
||||
|
||||
public CartController(IBasketService basketSvc, ICatalogService catalogSvc, UserManager<ApplicationUser> userManager)
|
||||
public CartController(IBasketService basketSvc, ICatalogService catalogSvc, IIdentityParser<ApplicationUser> appUserParser)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_basketSvc = basketSvc;
|
||||
_catalogSvc = catalogSvc;
|
||||
_appUserParser = appUserParser;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var vm = await _basketSvc.GetBasket(user);
|
||||
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
@ -36,7 +36,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Index(Dictionary<string, int> quantities, string action)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var basket = await _basketSvc.SetQuantities(user, quantities);
|
||||
var vm = await _basketSvc.UpdateBasket(basket);
|
||||
|
||||
@ -51,8 +51,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
|
||||
public async Task<IActionResult> AddToCart(CatalogItem productDetails)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
//var productDetails = _catalogSvc.GetCatalogItem(productId);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var product = new BasketItem()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
@ -66,4 +65,4 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
return RedirectToAction("Index", "Catalog");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models.OrderViewModels;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
@ -16,10 +15,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
{
|
||||
private IOrderingService _orderSvc;
|
||||
private IBasketService _basketSvc;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
public OrderController(IOrderingService orderSvc, IBasketService basketSvc, UserManager<ApplicationUser> userManager)
|
||||
private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
||||
public OrderController(IOrderingService orderSvc, IBasketService basketSvc, IIdentityParser<ApplicationUser> appUserParser)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_appUserParser = appUserParser;
|
||||
_orderSvc = orderSvc;
|
||||
_basketSvc = basketSvc;
|
||||
}
|
||||
@ -27,7 +26,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
public async Task<IActionResult> Create()
|
||||
{
|
||||
var vm = new CreateOrderViewModel();
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var basket = await _basketSvc.GetBasket(user);
|
||||
var order = _basketSvc.MapBasketToOrder(basket);
|
||||
vm.Order = _orderSvc.MapUserInfoIntoOrder(user, order);
|
||||
@ -38,7 +37,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create(CreateOrderViewModel model, Dictionary<string, int> quantities, string action)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var basket = await _basketSvc.SetQuantities(user, quantities);
|
||||
basket = await _basketSvc.UpdateBasket(basket);
|
||||
var order = _basketSvc.MapBasketToOrder(basket);
|
||||
@ -48,10 +47,18 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
|
||||
if (action == "[ Place Order ]")
|
||||
{
|
||||
_orderSvc.CreateOrder(user, order);
|
||||
try
|
||||
{
|
||||
await _orderSvc.CreateOrder(user, order);
|
||||
|
||||
//Empty basket for current user.
|
||||
await _basketSvc.CleanBasket(user);
|
||||
//Empty basket for current user.
|
||||
await _basketSvc.CleanBasket(user);
|
||||
|
||||
}
|
||||
catch (Exception) {
|
||||
//redirect to some error page if the operation fails.
|
||||
return Redirect("http://www.google.com");
|
||||
}
|
||||
|
||||
//Redirect to historic list.
|
||||
return RedirectToAction("Index");
|
||||
@ -60,17 +67,17 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
return View(model);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Detail(string orderId)
|
||||
public IActionResult Detail(string orderId)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var order = _orderSvc.GetOrder(user, orderId);
|
||||
|
||||
return View(order);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Index(Order item)
|
||||
public IActionResult Index(Order item)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(HttpContext.User);
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
return View(_orderSvc.GetMyOrders(user));
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Data
|
||||
{
|
||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
{
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> 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);
|
||||
}
|
||||
}
|
||||
}
|
44
src/Web/WebMVC/Extensions/HttpClientExtensions.cs
Normal file
44
src/Web/WebMVC/Extensions/HttpClientExtensions.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Extensions
|
||||
{
|
||||
public static class HttpClientExtensions
|
||||
{
|
||||
public static void SetBasicAuthentication(this HttpClient client, string userName, string password)
|
||||
{
|
||||
client.DefaultRequestHeaders.Authorization = new BasicAuthenticationHeaderValue(userName, password);
|
||||
}
|
||||
|
||||
public static void SetToken(this HttpClient client, string scheme, string token)
|
||||
{
|
||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(scheme, token);
|
||||
}
|
||||
|
||||
public static void SetBearerToken(this HttpClient client, string token)
|
||||
{
|
||||
client.SetToken(JwtConstants.TokenType, token);
|
||||
}
|
||||
}
|
||||
|
||||
public class BasicAuthenticationHeaderValue : AuthenticationHeaderValue
|
||||
{
|
||||
public BasicAuthenticationHeaderValue(string userName, string password)
|
||||
: base("Basic", EncodeCredential(userName, password))
|
||||
{ }
|
||||
|
||||
private static string EncodeCredential(string userName, string password)
|
||||
{
|
||||
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
|
||||
string credential = String.Format("{0}:{1}", userName, password);
|
||||
|
||||
return Convert.ToBase64String(encoding.GetBytes(credential));
|
||||
}
|
||||
}
|
||||
}
|
@ -2,8 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Models
|
||||
{
|
||||
|
36
src/Web/WebMVC/Models/OrderRequest.cs
Normal file
36
src/Web/WebMVC/Models/OrderRequest.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Models
|
||||
{
|
||||
public class OrderRequest
|
||||
{
|
||||
public OrderRequest() {
|
||||
|
||||
}
|
||||
|
||||
public string City { get; set; }
|
||||
|
||||
public string Street { get; set; }
|
||||
|
||||
public string State { get; set; }
|
||||
|
||||
public string Country { get; set; }
|
||||
|
||||
public string ZipCode { get; set; }
|
||||
|
||||
public string CardNumber { get; set; }
|
||||
|
||||
public string CardHolderName { get; set; }
|
||||
|
||||
public DateTime CardExpiration { get; set; }
|
||||
|
||||
public string CardSecurityNumber { get; set; }
|
||||
|
||||
public int CardTypeId { get; set; }
|
||||
|
||||
public string Buyer { get; set; }
|
||||
}
|
||||
}
|
13
src/Web/WebMVC/Services/IIdentityParser.cs
Normal file
13
src/Web/WebMVC/Services/IIdentityParser.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
{
|
||||
public interface IIdentityParser<T>
|
||||
{
|
||||
T Parse(IPrincipal principal);
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
{
|
||||
public interface IOrderingService
|
||||
{
|
||||
List<Order> GetMyOrders(ApplicationUser user);
|
||||
Order GetOrder(ApplicationUser user, string orderId);
|
||||
void CreateOrder(ApplicationUser user, Order order);
|
||||
Task<List<Order>> GetMyOrders(ApplicationUser user);
|
||||
Task<Order> GetOrder(ApplicationUser user, string orderId);
|
||||
Task CreateOrder(ApplicationUser user, Order order);
|
||||
Order MapUserInfoIntoOrder(ApplicationUser user, Order order);
|
||||
void OverrideUserInfoIntoOrder(Order original, Order destination);
|
||||
}
|
||||
|
38
src/Web/WebMVC/Services/IdentityParser.cs
Normal file
38
src/Web/WebMVC/Services/IdentityParser.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
{
|
||||
public class IdentityParser:IIdentityParser<ApplicationUser>
|
||||
{
|
||||
public ApplicationUser Parse(IPrincipal principal)
|
||||
{
|
||||
var user = new ApplicationUser();
|
||||
var claims = (ClaimsPrincipal)principal;
|
||||
|
||||
user.CardHolderName = (claims.Claims.Where(x => x.Type == "card_holder").Count() > 0) ? claims.Claims.First(x => x.Type == "card_holder").Value : "";
|
||||
user.CardNumber = (claims.Claims.Where(x => x.Type == "card_number").Count() > 0) ? claims.Claims.First(x => x.Type == "card_number").Value : "";
|
||||
user.CardType = (claims.Claims.Where(x => x.Type == "missing").Count() > 0) ? int.Parse(claims.Claims.First(x => x.Type == "missing").Value) : 0;
|
||||
user.City = (claims.Claims.Where(x => x.Type == "address_city").Count() > 0) ? claims.Claims.First(x => x.Type == "address_city").Value : "";
|
||||
user.Country = (claims.Claims.Where(x => x.Type == "address_country").Count() > 0) ? claims.Claims.First(x => x.Type == "address_country").Value : "";
|
||||
user.Email = (claims.Claims.Where(x => x.Type == "email").Count() > 0) ? claims.Claims.First(x => x.Type == "email").Value : "";
|
||||
user.Id = (claims.Claims.Where(x => x.Type == "sub").Count() > 0) ? claims.Claims.First(x => x.Type == "sub").Value : "";
|
||||
user.LastName = (claims.Claims.Where(x => x.Type == "last_name").Count() > 0) ? claims.Claims.First(x => x.Type == "last_name").Value : "";
|
||||
user.Name = (claims.Claims.Where(x => x.Type == "name").Count() > 0) ? claims.Claims.First(x => x.Type == "name").Value : "";
|
||||
user.PhoneNumber = (claims.Claims.Where(x => x.Type == "phone_number").Count() > 0) ? claims.Claims.First(x => x.Type == "phone_number").Value : "";
|
||||
user.SecurityNumber = (claims.Claims.Where(x => x.Type == "card_security_number").Count() > 0) ? claims.Claims.First(x => x.Type == "card_security_number").Value : "";
|
||||
user.State = (claims.Claims.Where(x => x.Type == "address_state").Count() > 0) ? claims.Claims.First(x => x.Type == "address_state").Value : "";
|
||||
user.Street = (claims.Claims.Where(x => x.Type == "address_street").Count() > 0) ? claims.Claims.First(x => x.Type == "address_street").Value : "";
|
||||
user.ZipCode = (claims.Claims.Where(x => x.Type == "address_zip_code").Count() > 0) ? claims.Claims.First(x => x.Type == "address_zip_code").Value : "";
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,65 +4,80 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
{
|
||||
public class OrderingService : IOrderingService
|
||||
{
|
||||
private List<Order> _orders;
|
||||
|
||||
//var ordersUrl = _settings.OrderingUrl + "/api/ordering/orders";
|
||||
//var dataString = await _http.GetStringAsync(ordersUrl);
|
||||
//var items = JsonConvert.DeserializeObject<List<Order>>(dataString);
|
||||
private HttpClient _apiClient;
|
||||
private readonly string _remoteServiceBaseUrl;
|
||||
private readonly IOptions<AppSettings> _settings;
|
||||
|
||||
public OrderingService(IHttpContextAccessor httpContextAccessor)
|
||||
public OrderingService(IOptions<AppSettings> settings)
|
||||
{
|
||||
_orders = new List<Order>()
|
||||
{
|
||||
new Order()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
OrderDate = DateTime.Now,
|
||||
State = OrderState.InProcess,
|
||||
OrderItems = new List<OrderItem>()
|
||||
{
|
||||
new OrderItem() { UnitPrice = 12.40m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
}
|
||||
},
|
||||
new Order()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
OrderDate = DateTime.Now,
|
||||
State = OrderState.InProcess,
|
||||
OrderItems = new List<OrderItem>()
|
||||
{
|
||||
new OrderItem() { UnitPrice = 12.00m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
}
|
||||
},
|
||||
new Order()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
OrderDate = DateTime.Now,
|
||||
State = OrderState.Delivered,
|
||||
OrderItems = new List<OrderItem>()
|
||||
{
|
||||
new OrderItem() { UnitPrice = 12.05m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
}
|
||||
}
|
||||
};
|
||||
_remoteServiceBaseUrl = $"{settings.Value.OrderingUrl}/api/v1/orders";
|
||||
_settings = settings;
|
||||
#region fake items
|
||||
//_orders = new List<Order>()
|
||||
//{
|
||||
// new Order()
|
||||
// {
|
||||
// Id = Guid.NewGuid().ToString(),
|
||||
// BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
// OrderDate = DateTime.Now,
|
||||
// State = OrderState.InProcess,
|
||||
// OrderItems = new List<OrderItem>()
|
||||
// {
|
||||
// new OrderItem() { UnitPrice = 12.40m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
// }
|
||||
// },
|
||||
// new Order()
|
||||
// {
|
||||
// Id = Guid.NewGuid().ToString(),
|
||||
// BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
// OrderDate = DateTime.Now,
|
||||
// State = OrderState.InProcess,
|
||||
// OrderItems = new List<OrderItem>()
|
||||
// {
|
||||
// new OrderItem() { UnitPrice = 12.00m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
// }
|
||||
// },
|
||||
// new Order()
|
||||
// {
|
||||
// Id = Guid.NewGuid().ToString(),
|
||||
// BuyerId = new Guid("ebcbcb4c-b032-4baa-834b-7fd66d37bc95").ToString(),
|
||||
// OrderDate = DateTime.Now,
|
||||
// State = OrderState.Delivered,
|
||||
// OrderItems = new List<OrderItem>()
|
||||
// {
|
||||
// new OrderItem() { UnitPrice = 12.05m, PictureUrl = "https://fakeimg.pl/370x240/EEEEEE/000/?text=RoslynRedT-Shirt", Quantity = 1, ProductName="Roslyn Red T-Shirt" }
|
||||
// }
|
||||
// }
|
||||
//};
|
||||
#endregion
|
||||
}
|
||||
|
||||
public Order GetOrder(ApplicationUser user, string Id)
|
||||
async public Task<Order> GetOrder(ApplicationUser user, string Id)
|
||||
{
|
||||
return _orders.Where(x => x.BuyerId.Equals(user.Id) && x.Id.Equals(Id)).FirstOrDefault();
|
||||
_apiClient = new HttpClient();
|
||||
var ordersUrl = $"{_remoteServiceBaseUrl}/{Id}";
|
||||
var dataString = await _apiClient.GetStringAsync(ordersUrl);
|
||||
var response = JsonConvert.DeserializeObject<Order>(dataString);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public List<Order> GetMyOrders(ApplicationUser user)
|
||||
async public Task<List<Order>> GetMyOrders(ApplicationUser user)
|
||||
{
|
||||
return _orders.Where(x => x.BuyerId.Equals(user.Id)).ToList();
|
||||
_apiClient = new HttpClient();
|
||||
var ordersUrl = _remoteServiceBaseUrl;
|
||||
var dataString = await _apiClient.GetStringAsync(ordersUrl);
|
||||
var response = JsonConvert.DeserializeObject<List<Order>>(dataString);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public Order MapUserInfoIntoOrder(ApplicationUser user, Order order)
|
||||
@ -80,15 +95,34 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
return order;
|
||||
}
|
||||
|
||||
public void CreateOrder(ApplicationUser user, Order order)
|
||||
public OrderRequest MapOrderIntoOrderRequest(Order order)
|
||||
{
|
||||
order.OrderDate = DateTime.Now;
|
||||
order.Id = Guid.NewGuid().ToString();
|
||||
order.BuyerId = user.Id;
|
||||
order.SequenceNumber = new Random(100).Next();
|
||||
order.State = OrderState.InProcess;
|
||||
return new OrderRequest()
|
||||
{
|
||||
CardHolderName = order.PaymentInfo.CardHolderName,
|
||||
CardNumber = order.PaymentInfo.CardNumber,
|
||||
CardSecurityNumber = order.PaymentInfo.SecurityNumber,
|
||||
CardTypeId = (int)order.PaymentInfo.CardType,
|
||||
City = order.ShippingAddress.City,
|
||||
Country = order.ShippingAddress.Country,
|
||||
State = order.ShippingAddress.State,
|
||||
Street = order.ShippingAddress.Street,
|
||||
ZipCode = order.ShippingAddress.ZipCode
|
||||
};
|
||||
}
|
||||
|
||||
_orders.Add(order);
|
||||
async public Task CreateOrder(ApplicationUser user, Order order)
|
||||
{
|
||||
_apiClient = new HttpClient();
|
||||
var ordersUrl = $"{_remoteServiceBaseUrl}/new";
|
||||
order.PaymentInfo.CardType = CardType.AMEX;
|
||||
OrderRequest request = MapOrderIntoOrderRequest(order);
|
||||
StringContent content = new StringContent(JsonConvert.SerializeObject(request), System.Text.Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _apiClient.PostAsync(ordersUrl, content);
|
||||
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
|
||||
throw new Exception("Error creating order, try later");
|
||||
}
|
||||
|
||||
public void OverrideUserInfoIntoOrder(Order original, Order destination)
|
||||
|
@ -4,14 +4,13 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Data;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC
|
||||
{
|
||||
@ -40,12 +39,12 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Add framework services.
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
||||
//services.AddDbContext<ApplicationDbContext>(options =>
|
||||
// options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
//services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
// .AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
// .AddDefaultTokenProviders();
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
@ -53,6 +52,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
services.AddTransient<ICatalogService, CatalogService>();
|
||||
services.AddSingleton<IOrderingService, OrderingService>(); //CCE: Once services are integrated, a singleton is not needed we can left transient.
|
||||
services.AddTransient<IBasketService, BasketService>();
|
||||
services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
|
||||
|
||||
services.Configure<AppSettings>(Configuration);
|
||||
}
|
||||
@ -60,13 +60,14 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
// 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)
|
||||
{
|
||||
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
||||
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseDatabaseErrorPage();
|
||||
app.UseBrowserLink();
|
||||
}
|
||||
else
|
||||
@ -76,7 +77,46 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseIdentity();
|
||||
app.UseCookieAuthentication(new CookieAuthenticationOptions
|
||||
{
|
||||
AuthenticationScheme = "cookies",
|
||||
AutomaticAuthenticate = true,
|
||||
});
|
||||
|
||||
//app.UseIdentity();
|
||||
|
||||
var oidcOptions = new OpenIdConnectOptions
|
||||
{
|
||||
AuthenticationScheme = "oidc",
|
||||
SignInScheme = "cookies",
|
||||
|
||||
Authority = "http://localhost:5000",
|
||||
ClientId = "mvc",
|
||||
ClientSecret = "secret",
|
||||
ResponseType = "code id_token",
|
||||
SaveTokens = true,
|
||||
GetClaimsFromUserInfoEndpoint = true,
|
||||
RequireHttpsMetadata = false,
|
||||
|
||||
//TokenValidationParameters = new TokenValidationParameters
|
||||
//{
|
||||
// NameClaimType = "name",
|
||||
// RoleClaimType = "role"
|
||||
//}
|
||||
};
|
||||
|
||||
oidcOptions.Scope.Clear();
|
||||
oidcOptions.Scope.Add("openid");
|
||||
oidcOptions.Scope.Add("profile");
|
||||
oidcOptions.Scope.Add("orders");
|
||||
|
||||
app.UseOpenIdConnectAuthentication(oidcOptions);
|
||||
app.UseJwtBearerAuthentication(new JwtBearerOptions
|
||||
{
|
||||
Authority = "http://localhost:5000/", // base address of your OIDC server.
|
||||
Audience = "http://localhost:5000/", // base address of your API.
|
||||
RequireHttpsMetadata = false
|
||||
});
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
@using Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
@model Microsoft.eShopOnContainers.WebMVC.Models.Basket
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject IIdentityParser<ApplicationUser> UserManager
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "My Cart";
|
||||
@ -14,7 +16,7 @@
|
||||
<form method="post" id="cartForm">
|
||||
<div class="container cart-index-container">
|
||||
<div class="row">
|
||||
@await Component.InvokeAsync("CartList", new { user = await UserManager.GetUserAsync(User) })
|
||||
@await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) })
|
||||
<div class="col-md-offset-8 col-md-4">
|
||||
<input type="submit"
|
||||
class="btn btn-default btn-brand btn-cart"
|
||||
|
@ -1,5 +1,6 @@
|
||||
@using Microsoft.eShopOnContainers.WebMVC.Services
|
||||
@model Microsoft.eShopOnContainers.WebMVC.Models.OrderViewModels.CreateOrderViewModel
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject IIdentityParser<ApplicationUser> UserManager
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "New Order";
|
||||
@ -65,7 +66,7 @@
|
||||
<br /><br />
|
||||
<div class="col-md-12 order-create-section-items">
|
||||
<section>
|
||||
@await Component.InvokeAsync("CartList", new { user = await UserManager.GetUserAsync(User) })
|
||||
@await Component.InvokeAsync("CartList", new { user = UserManager.Parse(User) })
|
||||
</section>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -27,6 +27,9 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-header col-sm-6 col-xs-4 text-center">
|
||||
@*@Html.ActionLink("Claims", "Claims", "Account")
|
||||
@Html.ActionLink("Call Api", "Claims", "Account")
|
||||
@Html.ActionLink("Log Out", "Signout", "Account")*@
|
||||
@await Html.PartialAsync("_LoginPartial")
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,16 +1,16 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
@using Microsoft.eShopOnContainers.WebMVC.Models
|
||||
@using Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
@inject SignInManager<ApplicationUser> SignInManager
|
||||
@inject UserManager<ApplicationUser> UserManager
|
||||
@inject IIdentityParser<ApplicationUser> UserManager
|
||||
|
||||
@if (SignInManager.IsSignedIn(User))
|
||||
@if(Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
<form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right">
|
||||
<div class="nav navbar-nav navbar-right mt-15">
|
||||
@await Component.InvokeAsync("Cart", new { user = await UserManager.GetUserAsync(User) })
|
||||
@await Component.InvokeAsync("Cart", new { user = UserManager.Parse(User) })
|
||||
<div class="fr login-user">
|
||||
<span class="hidden-xs">@UserManager.GetUserName(User)</span>
|
||||
<span class="hidden-xs">@User.FindFirst(x => x.Type == "preferred_username").Value</span>
|
||||
<i class="down-arrow"></i>
|
||||
<div class="login-user-dropdown-content">
|
||||
<a asp-controller="Order" asp-action="Index">MY ORDERS<i class="myorders-icon"></i></a>
|
||||
@ -23,6 +23,6 @@
|
||||
else
|
||||
{
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a asp-area="" asp-controller="Account" class="btn-login" asp-action="Login"> Log In </a></li>
|
||||
<li><a asp-area="" asp-controller="Account" class="btn-login" asp-action="SignIn"> Log In </a></li>
|
||||
</ul>
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
//"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
//"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
},
|
||||
"CatalogUrl": "http://localhost:5101",
|
||||
"OrderingUrl": "http://localhost:5102/",
|
||||
"OrderingUrl": "http://localhost:2446",
|
||||
"BasketUrl": "http://localhost:5103",
|
||||
"IdentityUrl": "http://localhost:5104",
|
||||
"IdentityUrl": "http://localhost:5000",
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"LogLevel": {
|
||||
|
@ -7,10 +7,7 @@
|
||||
},
|
||||
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0",
|
||||
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
|
||||
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0",
|
||||
"Microsoft.AspNetCore.Mvc": "1.0.0",
|
||||
"Microsoft.AspNetCore.Session": "1.0.0",
|
||||
"Microsoft.AspNetCore.Razor.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
@ -18,15 +15,6 @@
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
|
||||
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
|
||||
"Microsoft.EntityFrameworkCore.SqlServer.Design": {
|
||||
"version": "1.0.0",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.EntityFrameworkCore.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
|
||||
@ -43,13 +31,16 @@
|
||||
"version": "1.0.0-preview2-final",
|
||||
"type": "build"
|
||||
},
|
||||
"Newtonsoft.Json": "9.0.1"
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"System.IdentityModel.Tokens.Jwt": "5.0.0",
|
||||
"Microsoft.AspNetCore.Authentication.OpenIdConnect": "1.0.0",
|
||||
"Microsoft.AspNetCore.Authentication.JwtBearer": "1.0.0",
|
||||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0"
|
||||
},
|
||||
"tools": {
|
||||
"BundlerMinifier.Core": "2.0.238",
|
||||
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview2-final",
|
||||
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
|
||||
"version": "1.0.0-preview2-final",
|
||||
|
Loading…
x
Reference in New Issue
Block a user