Advertisement
Guest User

Untitled

a guest
Jan 16th, 2017
510
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 81.00 KB | None | 0 0
  1. using System.Linq;
  2. using System.Security.Claims;
  3. using System.Threading.Tasks;
  4. using Microsoft.AspNetCore.Authorization;
  5. using Microsoft.AspNetCore.Identity;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.AspNetCore.Mvc.Rendering;
  8. using Microsoft.Extensions.Logging;
  9. using Beerhall.Models.ViewModels.AccountViewModels;
  10. using Beerhall.Services;
  11. using Beerhall.Models.Domain;
  12.  
  13. namespace Beerhall.Controllers
  14. {
  15.     [Authorize]
  16.     public class AccountController : Controller
  17.     {
  18.         private readonly UserManager<ApplicationUser> _userManager;
  19.         private readonly SignInManager<ApplicationUser> _signInManager;
  20.         private readonly IEmailSender _emailSender;
  21.         private readonly ISmsSender _smsSender;
  22.         private readonly ILogger _logger;
  23.         private readonly ICustomerRepository _customerRepository;
  24.         private readonly ILocationRepository _locationRepository;
  25.  
  26.         public AccountController(
  27.             UserManager<ApplicationUser> userManager,
  28.             SignInManager<ApplicationUser> signInManager,
  29.             IEmailSender emailSender,
  30.             ISmsSender smsSender,
  31.             ILoggerFactory loggerFactory,
  32.             ICustomerRepository customerRepository,
  33.             ILocationRepository locationRepository)
  34.         {
  35.             _userManager = userManager;
  36.             _signInManager = signInManager;
  37.             _emailSender = emailSender;
  38.             _smsSender = smsSender;
  39.             _logger = loggerFactory.CreateLogger<AccountController>();
  40.             _customerRepository = customerRepository;
  41.             _locationRepository = locationRepository;
  42.         }
  43.  
  44.         //
  45.         // GET: /Account/Login
  46.         [HttpGet]
  47.         [AllowAnonymous]
  48.         public IActionResult Login(string returnUrl = null)
  49.         {
  50.             ViewData["ReturnUrl"] = returnUrl;
  51.             return View();
  52.         }
  53.  
  54.         //
  55.         // POST: /Account/Login
  56.         [HttpPost]
  57.         [AllowAnonymous]
  58.         [ValidateAntiForgeryToken]
  59.         public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
  60.         {
  61.             ViewData["ReturnUrl"] = returnUrl;
  62.             if (ModelState.IsValid)
  63.             {
  64.                 // This doesn't count login failures towards account lockout
  65.                 // To enable password failures to trigger account lockout, set lockoutOnFailure: true
  66.                 var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
  67.                 if (result.Succeeded)
  68.                 {
  69.                     _logger.LogInformation(1, "User logged in.");
  70.                     return RedirectToLocal(returnUrl);
  71.                 }
  72.                 if (result.RequiresTwoFactor)
  73.                 {
  74.                     return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
  75.                 }
  76.                 if (result.IsLockedOut)
  77.                 {
  78.                     _logger.LogWarning(2, "User account locked out.");
  79.                     return View("Lockout");
  80.                 }
  81.                 else
  82.                 {
  83.                     ModelState.AddModelError(string.Empty, "Invalid login attempt.");
  84.                     return View(model);
  85.                 }
  86.             }
  87.  
  88.             // If we got this far, something failed, redisplay form
  89.             return View(model);
  90.         }
  91.  
  92.         //
  93.         // GET: /Account/Register
  94.         [HttpGet]
  95.         [AllowAnonymous]
  96.         public IActionResult Register(string returnUrl = null)
  97.         {
  98.             ViewData["ReturnUrl"] = returnUrl;
  99.             ViewData["Locations"] = new SelectList(
  100.               _locationRepository.GetAll().OrderBy(l => l.Name),
  101.               nameof(Location.PostalCode),
  102.               nameof(Location.Name),
  103.               null);
  104.             return View();
  105.         }
  106.  
  107.         //
  108.         // POST: /Account/Register
  109.         [HttpPost]
  110.         [AllowAnonymous]
  111.         [ValidateAntiForgeryToken]
  112.         public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
  113.         {
  114.             ViewData["ReturnUrl"] = returnUrl;
  115.             if (ModelState.IsValid)
  116.             {
  117.                 var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
  118.                 var result = await _userManager.CreateAsync(user, model.Password);
  119.                 if (result.Succeeded)
  120.                     result = await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Role, "customer"));
  121.                 if (result.Succeeded) {
  122.                     var customer = new Customer {
  123.                         Email = model.Email,
  124.                         Name = model.Name,
  125.                         FirstName = model.FirstName,
  126.                         Street = model.Street,
  127.                         Location = _locationRepository.GetBy(model.PostalCode)
  128.                     };
  129.                     _customerRepository.Add(customer);
  130.                     _customerRepository.SaveChanges();
  131.                     // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
  132.                     // Send an email with this link
  133.                     //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
  134.                     //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
  135.                     //await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
  136.                     //    $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");
  137.                     await _signInManager.SignInAsync(user, isPersistent: false);
  138.                     _logger.LogInformation(3, "User created a new account with password.");
  139.                     return RedirectToLocal(returnUrl);
  140.                 }
  141.                 AddErrors(result);
  142.             }
  143.  
  144.             // If we got this far, something failed, redisplay form
  145.             return View(model);
  146.         }
  147.  
  148.         //
  149.         // POST: /Account/LogOff
  150.         [HttpPost]
  151.         [ValidateAntiForgeryToken]
  152.         public async Task<IActionResult> LogOff()
  153.         {
  154.             await _signInManager.SignOutAsync();
  155.             _logger.LogInformation(4, "User logged out.");
  156.             return RedirectToAction(nameof(HomeController.Index), "Home");
  157.         }
  158.  
  159.         //
  160.         // POST: /Account/ExternalLogin
  161.         [HttpPost]
  162.         [AllowAnonymous]
  163.         [ValidateAntiForgeryToken]
  164.         public IActionResult ExternalLogin(string provider, string returnUrl = null)
  165.         {
  166.             // Request a redirect to the external login provider.
  167.             var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
  168.             var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
  169.             return Challenge(properties, provider);
  170.         }
  171.  
  172.         //
  173.         // GET: /Account/ExternalLoginCallback
  174.         [HttpGet]
  175.         [AllowAnonymous]
  176.         public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
  177.         {
  178.             if (remoteError != null)
  179.             {
  180.                 ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
  181.                 return View(nameof(Login));
  182.             }
  183.             var info = await _signInManager.GetExternalLoginInfoAsync();
  184.             if (info == null)
  185.             {
  186.                 return RedirectToAction(nameof(Login));
  187.             }
  188.  
  189.             // Sign in the user with this external login provider if the user already has a login.
  190.             var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
  191.             if (result.Succeeded)
  192.             {
  193.                 _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
  194.                 return RedirectToLocal(returnUrl);
  195.             }
  196.             if (result.RequiresTwoFactor)
  197.             {
  198.                 return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
  199.             }
  200.             if (result.IsLockedOut)
  201.             {
  202.                 return View("Lockout");
  203.             }
  204.             else
  205.             {
  206.                 // If the user does not have an account, then ask the user to create an account.
  207.                 ViewData["ReturnUrl"] = returnUrl;
  208.                 ViewData["LoginProvider"] = info.LoginProvider;
  209.                 var email = info.Principal.FindFirstValue(ClaimTypes.Email);
  210.                 return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
  211.             }
  212.         }
  213.  
  214.         //
  215.         // POST: /Account/ExternalLoginConfirmation
  216.         [HttpPost]
  217.         [AllowAnonymous]
  218.         [ValidateAntiForgeryToken]
  219.         public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null)
  220.         {
  221.             if (ModelState.IsValid)
  222.             {
  223.                 // Get the information about the user from the external login provider
  224.                 var info = await _signInManager.GetExternalLoginInfoAsync();
  225.                 if (info == null)
  226.                 {
  227.                     return View("ExternalLoginFailure");
  228.                 }
  229.                 var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
  230.                 var result = await _userManager.CreateAsync(user);
  231.                 if (result.Succeeded)
  232.                 {
  233.                     result = await _userManager.AddLoginAsync(user, info);
  234.                     if (result.Succeeded)
  235.                     {
  236.                         await _signInManager.SignInAsync(user, isPersistent: false);
  237.                         _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
  238.                         return RedirectToLocal(returnUrl);
  239.                     }
  240.                 }
  241.                 AddErrors(result);
  242.             }
  243.  
  244.             ViewData["ReturnUrl"] = returnUrl;
  245.             return View(model);
  246.         }
  247.  
  248.         // GET: /Account/ConfirmEmail
  249.         [HttpGet]
  250.         [AllowAnonymous]
  251.         public async Task<IActionResult> ConfirmEmail(string userId, string code)
  252.         {
  253.             if (userId == null || code == null)
  254.             {
  255.                 return View("Error");
  256.             }
  257.             var user = await _userManager.FindByIdAsync(userId);
  258.             if (user == null)
  259.             {
  260.                 return View("Error");
  261.             }
  262.             var result = await _userManager.ConfirmEmailAsync(user, code);
  263.             return View(result.Succeeded ? "ConfirmEmail" : "Error");
  264.         }
  265.  
  266.         //
  267.         // GET: /Account/ForgotPassword
  268.         [HttpGet]
  269.         [AllowAnonymous]
  270.         public IActionResult ForgotPassword()
  271.         {
  272.             return View();
  273.         }
  274.  
  275.         //
  276.         // POST: /Account/ForgotPassword
  277.         [HttpPost]
  278.         [AllowAnonymous]
  279.         [ValidateAntiForgeryToken]
  280.         public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
  281.         {
  282.             if (ModelState.IsValid)
  283.             {
  284.                 var user = await _userManager.FindByNameAsync(model.Email);
  285.                 if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
  286.                 {
  287.                     // Don't reveal that the user does not exist or is not confirmed
  288.                     return View("ForgotPasswordConfirmation");
  289.                 }
  290.  
  291.                 // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
  292.                 // Send an email with this link
  293.                 //var code = await _userManager.GeneratePasswordResetTokenAsync(user);
  294.                 //var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
  295.                 //await _emailSender.SendEmailAsync(model.Email, "Reset Password",
  296.                 //   $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
  297.                 //return View("ForgotPasswordConfirmation");
  298.             }
  299.  
  300.             // If we got this far, something failed, redisplay form
  301.             return View(model);
  302.         }
  303.  
  304.         //
  305.         // GET: /Account/ForgotPasswordConfirmation
  306.         [HttpGet]
  307.         [AllowAnonymous]
  308.         public IActionResult ForgotPasswordConfirmation()
  309.         {
  310.             return View();
  311.         }
  312.  
  313.         //
  314.         // GET: /Account/ResetPassword
  315.         [HttpGet]
  316.         [AllowAnonymous]
  317.         public IActionResult ResetPassword(string code = null)
  318.         {
  319.             return code == null ? View("Error") : View();
  320.         }
  321.  
  322.         //
  323.         // POST: /Account/ResetPassword
  324.         [HttpPost]
  325.         [AllowAnonymous]
  326.         [ValidateAntiForgeryToken]
  327.         public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
  328.         {
  329.             if (!ModelState.IsValid)
  330.             {
  331.                 return View(model);
  332.             }
  333.             var user = await _userManager.FindByNameAsync(model.Email);
  334.             if (user == null)
  335.             {
  336.                 // Don't reveal that the user does not exist
  337.                 return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
  338.             }
  339.             var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
  340.             if (result.Succeeded)
  341.             {
  342.                 return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account");
  343.             }
  344.             AddErrors(result);
  345.             return View();
  346.         }
  347.  
  348.         //
  349.         // GET: /Account/ResetPasswordConfirmation
  350.         [HttpGet]
  351.         [AllowAnonymous]
  352.         public IActionResult ResetPasswordConfirmation()
  353.         {
  354.             return View();
  355.         }
  356.  
  357.         //
  358.         // GET: /Account/SendCode
  359.         [HttpGet]
  360.         [AllowAnonymous]
  361.         public async Task<ActionResult> SendCode(string returnUrl = null, bool rememberMe = false)
  362.         {
  363.             var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
  364.             if (user == null)
  365.             {
  366.                 return View("Error");
  367.             }
  368.             var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
  369.             var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
  370.             return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
  371.         }
  372.  
  373.         //
  374.         // POST: /Account/SendCode
  375.         [HttpPost]
  376.         [AllowAnonymous]
  377.         [ValidateAntiForgeryToken]
  378.         public async Task<IActionResult> SendCode(SendCodeViewModel model)
  379.         {
  380.             if (!ModelState.IsValid)
  381.             {
  382.                 return View();
  383.             }
  384.  
  385.             var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
  386.             if (user == null)
  387.             {
  388.                 return View("Error");
  389.             }
  390.  
  391.             // Generate the token and send it
  392.             var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider);
  393.             if (string.IsNullOrWhiteSpace(code))
  394.             {
  395.                 return View("Error");
  396.             }
  397.  
  398.             var message = "Your security code is: " + code;
  399.             if (model.SelectedProvider == "Email")
  400.             {
  401.                 await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message);
  402.             }
  403.             else if (model.SelectedProvider == "Phone")
  404.             {
  405.                 await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message);
  406.             }
  407.  
  408.             return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
  409.         }
  410.  
  411.         //
  412.         // GET: /Account/VerifyCode
  413.         [HttpGet]
  414.         [AllowAnonymous]
  415.         public async Task<IActionResult> VerifyCode(string provider, bool rememberMe, string returnUrl = null)
  416.         {
  417.             // Require that the user has already logged in via username/password or external login
  418.             var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
  419.             if (user == null)
  420.             {
  421.                 return View("Error");
  422.             }
  423.             return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
  424.         }
  425.  
  426.         //
  427.         // POST: /Account/VerifyCode
  428.         [HttpPost]
  429.         [AllowAnonymous]
  430.         [ValidateAntiForgeryToken]
  431.         public async Task<IActionResult> VerifyCode(VerifyCodeViewModel model)
  432.         {
  433.             if (!ModelState.IsValid)
  434.             {
  435.                 return View(model);
  436.             }
  437.  
  438.             // The following code protects for brute force attacks against the two factor codes.
  439.             // If a user enters incorrect codes for a specified amount of time then the user account
  440.             // will be locked out for a specified amount of time.
  441.             var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
  442.             if (result.Succeeded)
  443.             {
  444.                 return RedirectToLocal(model.ReturnUrl);
  445.             }
  446.             if (result.IsLockedOut)
  447.             {
  448.                 _logger.LogWarning(7, "User account locked out.");
  449.                 return View("Lockout");
  450.             }
  451.             else
  452.             {
  453.                 ModelState.AddModelError(string.Empty, "Invalid code.");
  454.                 return View(model);
  455.             }
  456.         }
  457.  
  458.         #region Helpers
  459.  
  460.         private void AddErrors(IdentityResult result)
  461.         {
  462.             foreach (var error in result.Errors)
  463.             {
  464.                 ModelState.AddModelError(string.Empty, error.Description);
  465.             }
  466.         }
  467.  
  468.         private Task<ApplicationUser> GetCurrentUserAsync()
  469.         {
  470.             return _userManager.GetUserAsync(HttpContext.User);
  471.         }
  472.  
  473.         private IActionResult RedirectToLocal(string returnUrl)
  474.         {
  475.             if (Url.IsLocalUrl(returnUrl))
  476.             {
  477.                 return Redirect(returnUrl);
  478.             }
  479.             else
  480.             {
  481.                 return RedirectToAction(nameof(HomeController.Index), "Home");
  482.             }
  483.         }
  484.  
  485.         #endregion
  486.     }
  487. }
  488.  
  489.  
  490.  
  491. using System;
  492. using System.Collections.Generic;
  493. using Beerhall.Models.Domain;
  494. using Microsoft.AspNetCore.Mvc;
  495. using System.Linq;
  496. using Beerhall.Models.ViewModels.BrewerViewModels;
  497. using Microsoft.AspNetCore.Authorization;
  498. using Microsoft.AspNetCore.Mvc.Rendering;
  499.  
  500. namespace Beerhall.Controllers {
  501.     [Authorize(Policy = "AdminOnly")]
  502.     public class BrewerController : Controller {
  503.         private readonly IBrewerRepository _brewerRepository;
  504.         private readonly ILocationRepository _locationRepository;
  505.  
  506.         public BrewerController(IBrewerRepository brewerRepository, ILocationRepository locationRepository) {
  507.             _brewerRepository = brewerRepository;
  508.             _locationRepository = locationRepository;
  509.         }
  510.  
  511.         [AllowAnonymous]
  512.         public IActionResult Index() {
  513.             IEnumerable<Brewer> brewers = _brewerRepository.GetAll().OrderBy(b => b.Name).ToList();
  514.             ViewData["TotalTurnover"] = brewers.Sum(b => b.Turnover);
  515.             return View(brewers);
  516.         }
  517.  
  518.         public IActionResult Edit(int id) {
  519.             Brewer brewer = _brewerRepository.GetBy(id);
  520.             if (brewer == null)
  521.                 return NotFound();
  522.             ViewData["Locations"] = GetLocationsAsSelectList(brewer.Location?.PostalCode);
  523.             return View(new EditViewModel(brewer));
  524.         }
  525.  
  526.         [HttpPost]
  527.         [ValidateAntiForgeryToken]
  528.         public IActionResult Edit(EditViewModel brewerEditViewModel) {
  529.             if (ModelState.IsValid) {
  530.                 try {
  531.                     Brewer brewer = _brewerRepository.GetBy(brewerEditViewModel.BrewerId);
  532.                     MapBrewerEditViewModelToBrewer(brewerEditViewModel, brewer);
  533.                     _brewerRepository.SaveChanges();
  534.                     TempData["message"] = $"You successfully updated brewer {brewer.Name}.";
  535.                     return RedirectToAction(nameof(Index));
  536.                 }
  537.                 catch (Exception e) {
  538.                     ModelState.AddModelError("", e.Message);
  539.                 }
  540.             }
  541.             ViewData["Locations"] = GetLocationsAsSelectList(brewerEditViewModel?.PostalCode);
  542.             return View(brewerEditViewModel);
  543.         }
  544.  
  545.         public IActionResult Create() {
  546.             ViewData["Locations"] = GetLocationsAsSelectList(null);
  547.             return View(nameof(Edit), new EditViewModel(new Brewer()));
  548.         }
  549.  
  550.         [HttpPost]
  551.         [ValidateAntiForgeryToken]
  552.         public IActionResult Create(EditViewModel brewerEditViewModel) {
  553.             if (ModelState.IsValid) {
  554.                 try {
  555.                     Brewer brewer = new Brewer();
  556.                     MapBrewerEditViewModelToBrewer(brewerEditViewModel, brewer);
  557.                     _brewerRepository.Add(brewer);
  558.                     _brewerRepository.SaveChanges();
  559.                     TempData["message"] = $"You successfully added brewer {brewer.Name}.";
  560.                     return RedirectToAction(nameof(Index));
  561.                 }
  562.                 catch (Exception e) {
  563.                     ModelState.AddModelError("", e.Message);
  564.                 }
  565.             }
  566.             ViewData["Locations"] = GetLocationsAsSelectList(brewerEditViewModel?.PostalCode);
  567.             return View(nameof(Edit), brewerEditViewModel);
  568.         }
  569.  
  570.         public IActionResult Delete(int id) {
  571.             Brewer brewer = _brewerRepository.GetBy(id);
  572.             if (brewer == null)
  573.                 return NotFound();
  574.             ViewData[nameof(Brewer.Name)] = brewer.Name;
  575.             return View();
  576.         }
  577.  
  578.         [HttpPost, ActionName("Delete")]
  579.         [ValidateAntiForgeryToken]
  580.         public IActionResult DeleteConfirmed(int id) {
  581.             Brewer brewer = null;
  582.             try {
  583.                 brewer = _brewerRepository.GetBy(id);
  584.                 _brewerRepository.Delete(brewer);
  585.                 _brewerRepository.SaveChanges();
  586.                 TempData["message"] = $"You successfully deleted brewer {brewer.Name}.";
  587.             }
  588.             catch {
  589.                 TempData["error"] = $"Sorry, something went wrong, brewer {brewer?.Name} was not deleted...";
  590.             }
  591.             return RedirectToAction(nameof(Index));
  592.         }
  593.  
  594.         private SelectList GetLocationsAsSelectList(string postalCode) {
  595.             return new SelectList(
  596.                 _locationRepository.GetAll().OrderBy(l => l.Name),
  597.                 nameof(Location.PostalCode),
  598.                 nameof(Location.Name),
  599.                 postalCode);
  600.         }
  601.  
  602.         private void MapBrewerEditViewModelToBrewer(EditViewModel brewerEditViewModel, Brewer brewer) {
  603.             brewer.Name = brewerEditViewModel.Name;
  604.             brewer.Street = brewerEditViewModel.Street;
  605.             brewer.Location = brewerEditViewModel.PostalCode == null
  606.                 ? null
  607.                 : _locationRepository.GetBy(brewerEditViewModel.PostalCode);
  608.             brewer.ContactEmail = brewerEditViewModel.ContactEmail;
  609.             brewer.DateEstablished = brewerEditViewModel.DateEstablished;
  610.             brewer.Description = brewerEditViewModel.Description;
  611.             brewer.Turnover = brewerEditViewModel.Turnover;
  612.         }
  613.     }
  614. }
  615.  
  616.  
  617.  
  618. using System;
  619. using System.Collections.Generic;
  620. using System.Linq;
  621. using Beerhall.Filters;
  622. using Microsoft.AspNetCore.Mvc;
  623. using Beerhall.Models.Domain;
  624. using Beerhall.Models.ViewModels.CartViewModels;
  625. using Microsoft.AspNetCore.Authorization;
  626.  
  627. namespace Beerhall.Controllers {
  628.     [ServiceFilter(typeof(CartSessionFilter))]
  629.     public class CartController : Controller {
  630.         private readonly IBeerRepository _beerRepository;
  631.         private readonly ILocationRepository _locationRepository;
  632.         private readonly ICustomerRepository _customerRepository;
  633.  
  634.         public CartController(IBeerRepository beerRepository, ILocationRepository locationRepository, ICustomerRepository customerRepository) {
  635.             _beerRepository = beerRepository;
  636.             _locationRepository = locationRepository;
  637.             _customerRepository = customerRepository;
  638.         }
  639.  
  640.         public IActionResult Index(Cart cart) {
  641.             ViewData["Total"] = cart.TotalValue;
  642.             return View(cart.CartLines.Select(c => new IndexViewModel(c)).ToList());
  643.         }
  644.  
  645.         [HttpPost]
  646.         public IActionResult Add(Cart cart, int id, int quantity = 1) {
  647.             try {
  648.                 Beer product = _beerRepository.GetBy(id);
  649.                 if (product != null) {
  650.                     cart.AddLine(product, quantity);
  651.                     TempData["message"] = $"{quantity} x {product.Name} was added to your shopping basket";
  652.                 }
  653.             }
  654.             catch {
  655.                 TempData["error"] = "Sorry, something went wrong, the product could not be added to your shopping cart...";
  656.             }
  657.             return RedirectToAction("Index", "Store");
  658.         }
  659.  
  660.         [HttpPost]
  661.         public IActionResult Remove(Cart cart, int id) {
  662.             try {
  663.                 Beer product = _beerRepository.GetBy(id);
  664.                 cart.RemoveLine(product);
  665.                 TempData["message"] = $"{product.Name} was removed from you shopping basket";
  666.             }
  667.             catch {
  668.                 TempData["error"] = "Sorry, something went wrong, the product was not removed from your shopping cart...";
  669.             }
  670.             return RedirectToAction("Index");
  671.         }
  672.  
  673.         [Authorize(Policy = "Customer")]
  674.         public IActionResult Checkout(Cart cart) {
  675.             if (cart.NumberOfItems == 0)
  676.                 return RedirectToAction("Index", "Store");
  677.             IEnumerable<Location> locations = _locationRepository.GetAll().OrderBy(l => l.Name).ToList();
  678.             return View(new CheckOutViewModel(locations, new ShippingViewModel()));
  679.         }
  680.  
  681.         [HttpPost, Authorize(Policy = "Customer")]
  682.         [ServiceFilter(typeof(CustomerFilter))]
  683.         public IActionResult Checkout(Customer customer, Cart cart, [Bind(Prefix = "ShippingViewModel")]ShippingViewModel shippingVm) {
  684.             if (ModelState.IsValid) {
  685.                 try {
  686.                     if (cart.NumberOfItems == 0)
  687.                         return RedirectToAction("Index");
  688.                     Location location = _locationRepository.GetBy(shippingVm.PostalCode);
  689.                     customer.PlaceOrder(cart, shippingVm.DeliveryDate, shippingVm.Giftwrapping, shippingVm.Street, location);
  690.                     _customerRepository.SaveChanges();
  691.                     cart.Clear();
  692.                     TempData["message"] = "Thank you for your order!";
  693.                     return RedirectToAction("Index", "Store");
  694.                 }
  695.                 catch (Exception ex) {
  696.                     ModelState.AddModelError("", ex.Message);
  697.                 }
  698.             }
  699.             IEnumerable<Location> locations = _locationRepository.GetAll().OrderBy(l => l.Name);
  700.             return View(new CheckOutViewModel(locations, shippingVm));
  701.         }
  702.     }
  703. }
  704.  
  705.  
  706. using Microsoft.AspNetCore.Mvc;
  707.  
  708. namespace Beerhall.Controllers
  709. {
  710.     public class HomeController : Controller
  711.     {
  712.         public IActionResult Index()
  713.         {
  714.             return View();
  715.         }
  716.  
  717.         public IActionResult About()
  718.         {
  719.             ViewData["Message"] = "Your application description page.";
  720.  
  721.             return View();
  722.         }
  723.  
  724.         public IActionResult Contact()
  725.         {
  726.             ViewData["Message"] = "Your contact page.";
  727.  
  728.             return View();
  729.         }
  730.  
  731.         public IActionResult Error()
  732.         {
  733.             return View();
  734.         }
  735.     }
  736. }
  737.  
  738.  
  739.  
  740. using System.Linq;
  741. using System.Threading.Tasks;
  742. using Microsoft.AspNetCore.Authorization;
  743. using Microsoft.AspNetCore.Identity;
  744. using Microsoft.AspNetCore.Mvc;
  745. using Microsoft.Extensions.Logging;
  746. using Beerhall.Models.ViewModels.ManageViewModels;
  747. using Beerhall.Services;
  748. using Beerhall.Models.Domain;
  749.  
  750. namespace Beerhall.Controllers
  751. {
  752.     [Authorize]
  753.     public class ManageController : Controller
  754.     {
  755.         private readonly UserManager<ApplicationUser> _userManager;
  756.         private readonly SignInManager<ApplicationUser> _signInManager;
  757.         private readonly IEmailSender _emailSender;
  758.         private readonly ISmsSender _smsSender;
  759.         private readonly ILogger _logger;
  760.  
  761.         public ManageController(
  762.         UserManager<ApplicationUser> userManager,
  763.         SignInManager<ApplicationUser> signInManager,
  764.         IEmailSender emailSender,
  765.         ISmsSender smsSender,
  766.         ILoggerFactory loggerFactory)
  767.         {
  768.             _userManager = userManager;
  769.             _signInManager = signInManager;
  770.             _emailSender = emailSender;
  771.             _smsSender = smsSender;
  772.             _logger = loggerFactory.CreateLogger<ManageController>();
  773.         }
  774.  
  775.         //
  776.         // GET: /Manage/Index
  777.         [HttpGet]
  778.         public async Task<IActionResult> Index(ManageMessageId? message = null)
  779.         {
  780.             ViewData["StatusMessage"] =
  781.                 message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
  782.                 : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
  783.                 : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
  784.                 : message == ManageMessageId.Error ? "An error has occurred."
  785.                 : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
  786.                 : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
  787.                 : "";
  788.  
  789.             var user = await GetCurrentUserAsync();
  790.             if (user == null)
  791.             {
  792.                 return View("Error");
  793.             }
  794.             var model = new IndexViewModel
  795.             {
  796.                 HasPassword = await _userManager.HasPasswordAsync(user),
  797.                 PhoneNumber = await _userManager.GetPhoneNumberAsync(user),
  798.                 TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user),
  799.                 Logins = await _userManager.GetLoginsAsync(user),
  800.                 BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user)
  801.             };
  802.             return View(model);
  803.         }
  804.  
  805.         //
  806.         // POST: /Manage/RemoveLogin
  807.         [HttpPost]
  808.         [ValidateAntiForgeryToken]
  809.         public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
  810.         {
  811.             ManageMessageId? message = ManageMessageId.Error;
  812.             var user = await GetCurrentUserAsync();
  813.             if (user != null)
  814.             {
  815.                 var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey);
  816.                 if (result.Succeeded)
  817.                 {
  818.                     await _signInManager.SignInAsync(user, isPersistent: false);
  819.                     message = ManageMessageId.RemoveLoginSuccess;
  820.                 }
  821.             }
  822.             return RedirectToAction(nameof(ManageLogins), new { Message = message });
  823.         }
  824.  
  825.         //
  826.         // GET: /Manage/AddPhoneNumber
  827.         public IActionResult AddPhoneNumber()
  828.         {
  829.             return View();
  830.         }
  831.  
  832.         //
  833.         // POST: /Manage/AddPhoneNumber
  834.         [HttpPost]
  835.         [ValidateAntiForgeryToken]
  836.         public async Task<IActionResult> AddPhoneNumber(AddPhoneNumberViewModel model)
  837.         {
  838.             if (!ModelState.IsValid)
  839.             {
  840.                 return View(model);
  841.             }
  842.             // Generate the token and send it
  843.             var user = await GetCurrentUserAsync();
  844.             if (user == null)
  845.             {
  846.                 return View("Error");
  847.             }
  848.             var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber);
  849.             await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code);
  850.             return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber });
  851.         }
  852.  
  853.         //
  854.         // POST: /Manage/EnableTwoFactorAuthentication
  855.         [HttpPost]
  856.         [ValidateAntiForgeryToken]
  857.         public async Task<IActionResult> EnableTwoFactorAuthentication()
  858.         {
  859.             var user = await GetCurrentUserAsync();
  860.             if (user != null)
  861.             {
  862.                 await _userManager.SetTwoFactorEnabledAsync(user, true);
  863.                 await _signInManager.SignInAsync(user, isPersistent: false);
  864.                 _logger.LogInformation(1, "User enabled two-factor authentication.");
  865.             }
  866.             return RedirectToAction(nameof(Index), "Manage");
  867.         }
  868.  
  869.         //
  870.         // POST: /Manage/DisableTwoFactorAuthentication
  871.         [HttpPost]
  872.         [ValidateAntiForgeryToken]
  873.         public async Task<IActionResult> DisableTwoFactorAuthentication()
  874.         {
  875.             var user = await GetCurrentUserAsync();
  876.             if (user != null)
  877.             {
  878.                 await _userManager.SetTwoFactorEnabledAsync(user, false);
  879.                 await _signInManager.SignInAsync(user, isPersistent: false);
  880.                 _logger.LogInformation(2, "User disabled two-factor authentication.");
  881.             }
  882.             return RedirectToAction(nameof(Index), "Manage");
  883.         }
  884.  
  885.         //
  886.         // GET: /Manage/VerifyPhoneNumber
  887.         [HttpGet]
  888.         public async Task<IActionResult> VerifyPhoneNumber(string phoneNumber)
  889.         {
  890.             var user = await GetCurrentUserAsync();
  891.             if (user == null)
  892.             {
  893.                 return View("Error");
  894.             }
  895.             var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, phoneNumber);
  896.             // Send an SMS to verify the phone number
  897.             return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
  898.         }
  899.  
  900.         //
  901.         // POST: /Manage/VerifyPhoneNumber
  902.         [HttpPost]
  903.         [ValidateAntiForgeryToken]
  904.         public async Task<IActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
  905.         {
  906.             if (!ModelState.IsValid)
  907.             {
  908.                 return View(model);
  909.             }
  910.             var user = await GetCurrentUserAsync();
  911.             if (user != null)
  912.             {
  913.                 var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code);
  914.                 if (result.Succeeded)
  915.                 {
  916.                     await _signInManager.SignInAsync(user, isPersistent: false);
  917.                     return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess });
  918.                 }
  919.             }
  920.             // If we got this far, something failed, redisplay the form
  921.             ModelState.AddModelError(string.Empty, "Failed to verify phone number");
  922.             return View(model);
  923.         }
  924.  
  925.         //
  926.         // POST: /Manage/RemovePhoneNumber
  927.         [HttpPost]
  928.         [ValidateAntiForgeryToken]
  929.         public async Task<IActionResult> RemovePhoneNumber()
  930.         {
  931.             var user = await GetCurrentUserAsync();
  932.             if (user != null)
  933.             {
  934.                 var result = await _userManager.SetPhoneNumberAsync(user, null);
  935.                 if (result.Succeeded)
  936.                 {
  937.                     await _signInManager.SignInAsync(user, isPersistent: false);
  938.                     return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess });
  939.                 }
  940.             }
  941.             return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
  942.         }
  943.  
  944.         //
  945.         // GET: /Manage/ChangePassword
  946.         [HttpGet]
  947.         public IActionResult ChangePassword()
  948.         {
  949.             return View();
  950.         }
  951.  
  952.         //
  953.         // POST: /Manage/ChangePassword
  954.         [HttpPost]
  955.         [ValidateAntiForgeryToken]
  956.         public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model)
  957.         {
  958.             if (!ModelState.IsValid)
  959.             {
  960.                 return View(model);
  961.             }
  962.             var user = await GetCurrentUserAsync();
  963.             if (user != null)
  964.             {
  965.                 var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
  966.                 if (result.Succeeded)
  967.                 {
  968.                     await _signInManager.SignInAsync(user, isPersistent: false);
  969.                     _logger.LogInformation(3, "User changed their password successfully.");
  970.                     return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess });
  971.                 }
  972.                 AddErrors(result);
  973.                 return View(model);
  974.             }
  975.             return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
  976.         }
  977.  
  978.         //
  979.         // GET: /Manage/SetPassword
  980.         [HttpGet]
  981.         public IActionResult SetPassword()
  982.         {
  983.             return View();
  984.         }
  985.  
  986.         //
  987.         // POST: /Manage/SetPassword
  988.         [HttpPost]
  989.         [ValidateAntiForgeryToken]
  990.         public async Task<IActionResult> SetPassword(SetPasswordViewModel model)
  991.         {
  992.             if (!ModelState.IsValid)
  993.             {
  994.                 return View(model);
  995.             }
  996.  
  997.             var user = await GetCurrentUserAsync();
  998.             if (user != null)
  999.             {
  1000.                 var result = await _userManager.AddPasswordAsync(user, model.NewPassword);
  1001.                 if (result.Succeeded)
  1002.                 {
  1003.                     await _signInManager.SignInAsync(user, isPersistent: false);
  1004.                     return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess });
  1005.                 }
  1006.                 AddErrors(result);
  1007.                 return View(model);
  1008.             }
  1009.             return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
  1010.         }
  1011.  
  1012.         //GET: /Manage/ManageLogins
  1013.         [HttpGet]
  1014.         public async Task<IActionResult> ManageLogins(ManageMessageId? message = null)
  1015.         {
  1016.             ViewData["StatusMessage"] =
  1017.                 message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
  1018.                 : message == ManageMessageId.AddLoginSuccess ? "The external login was added."
  1019.                 : message == ManageMessageId.Error ? "An error has occurred."
  1020.                 : "";
  1021.             var user = await GetCurrentUserAsync();
  1022.             if (user == null)
  1023.             {
  1024.                 return View("Error");
  1025.             }
  1026.             var userLogins = await _userManager.GetLoginsAsync(user);
  1027.             var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();
  1028.             ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1;
  1029.             return View(new ManageLoginsViewModel
  1030.             {
  1031.                 CurrentLogins = userLogins,
  1032.                 OtherLogins = otherLogins
  1033.             });
  1034.         }
  1035.  
  1036.         //
  1037.         // POST: /Manage/LinkLogin
  1038.         [HttpPost]
  1039.         [ValidateAntiForgeryToken]
  1040.         public IActionResult LinkLogin(string provider)
  1041.         {
  1042.             // Request a redirect to the external login provider to link a login for the current user
  1043.             var redirectUrl = Url.Action("LinkLoginCallback", "Manage");
  1044.             var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
  1045.             return Challenge(properties, provider);
  1046.         }
  1047.  
  1048.         //
  1049.         // GET: /Manage/LinkLoginCallback
  1050.         [HttpGet]
  1051.         public async Task<ActionResult> LinkLoginCallback()
  1052.         {
  1053.             var user = await GetCurrentUserAsync();
  1054.             if (user == null)
  1055.             {
  1056.                 return View("Error");
  1057.             }
  1058.             var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
  1059.             if (info == null)
  1060.             {
  1061.                 return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error });
  1062.             }
  1063.             var result = await _userManager.AddLoginAsync(user, info);
  1064.             var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error;
  1065.             return RedirectToAction(nameof(ManageLogins), new { Message = message });
  1066.         }
  1067.  
  1068.         #region Helpers
  1069.  
  1070.         private void AddErrors(IdentityResult result)
  1071.         {
  1072.             foreach (var error in result.Errors)
  1073.             {
  1074.                 ModelState.AddModelError(string.Empty, error.Description);
  1075.             }
  1076.         }
  1077.  
  1078.         public enum ManageMessageId
  1079.         {
  1080.             AddPhoneSuccess,
  1081.             AddLoginSuccess,
  1082.             ChangePasswordSuccess,
  1083.             SetTwoFactorSuccess,
  1084.             SetPasswordSuccess,
  1085.             RemoveLoginSuccess,
  1086.             RemovePhoneSuccess,
  1087.             Error
  1088.         }
  1089.  
  1090.         private Task<ApplicationUser> GetCurrentUserAsync()
  1091.         {
  1092.             return _userManager.GetUserAsync(HttpContext.User);
  1093.         }
  1094.  
  1095.         #endregion
  1096.     }
  1097. }
  1098.  
  1099.  
  1100.  
  1101. using System.Linq;
  1102. using Beerhall.Models.Domain;
  1103. using Microsoft.AspNetCore.Mvc;
  1104.  
  1105. namespace Beerhall.Controllers {
  1106.     public class StoreController : Controller {
  1107.         private readonly IBeerRepository _beerRepository;
  1108.  
  1109.         public StoreController(IBeerRepository beerRepository) {
  1110.             _beerRepository = beerRepository;
  1111.         }
  1112.         [ResponseCache(Duration = 60)]
  1113.         public ActionResult Index() {
  1114.             return View(_beerRepository.GetAll().OrderBy(b => b.Name).ToList());
  1115.         }
  1116.     }
  1117. }
  1118.  
  1119.  
  1120. using System.Collections.Generic;
  1121. using System.Linq;
  1122. using Beerhall.Models.Domain;
  1123. using Microsoft.EntityFrameworkCore;
  1124.  
  1125. namespace Beerhall.Data.Repositories {
  1126.     public class BeerRepository : IBeerRepository {
  1127.         private readonly ApplicationDbContext _dbContext;
  1128.         private readonly DbSet<Beer> _beers;
  1129.  
  1130.         public BeerRepository(ApplicationDbContext dbContext) {
  1131.             _dbContext = dbContext;
  1132.             _beers = _dbContext.Beers;
  1133.         }
  1134.  
  1135.         public IEnumerable<Beer> GetAll() {
  1136.             return _beers.ToList();
  1137.         }
  1138.         public Beer GetBy(int beerId) {
  1139.             return _beers.SingleOrDefault(b => b.BeerId == beerId);
  1140.         }
  1141.     }
  1142. }
  1143.  
  1144.  
  1145.  
  1146. using System.Collections.Generic;
  1147. using System.Linq;
  1148. using Beerhall.Models.Domain;
  1149. using Microsoft.EntityFrameworkCore;
  1150.  
  1151. namespace Beerhall.Data.Repositories {
  1152.  
  1153.     public class BrewerRepository : IBrewerRepository {
  1154.         private readonly ApplicationDbContext _dbContext;
  1155.         private readonly DbSet<Brewer> _brewers;
  1156.  
  1157.         public BrewerRepository(ApplicationDbContext dbContext) {
  1158.             _dbContext = dbContext;
  1159.             _brewers = dbContext.Brewers;
  1160.         }
  1161.  
  1162.         public Brewer GetBy(int brewerId) {
  1163.             return _brewers.Include(b => b.Location).SingleOrDefault(b => b.BrewerId == brewerId);
  1164.         }
  1165.  
  1166.         public IEnumerable<Brewer> GetAll() {
  1167.             return _brewers.Include(b => b.Location).Include(b => b.Beers).ToList();
  1168.         }
  1169.  
  1170.         public void Add(Brewer brewer) {
  1171.             _brewers.Add(brewer);
  1172.         }
  1173.  
  1174.         public void Delete(Brewer brewer) {
  1175.             _brewers.Remove(brewer);
  1176.         }
  1177.  
  1178.         public void SaveChanges() {
  1179.             _dbContext.SaveChanges();
  1180.         }
  1181.     }
  1182. }
  1183.  
  1184.  
  1185.  
  1186. using System.Linq;
  1187. using Beerhall.Models.Domain;
  1188. using Microsoft.EntityFrameworkCore;
  1189.  
  1190. namespace Beerhall.Data.Repositories {
  1191.     public class CustomerRepository : ICustomerRepository {
  1192.         private DbSet<Customer> _customers;
  1193.         private ApplicationDbContext _dbContext;
  1194.  
  1195.         public CustomerRepository(ApplicationDbContext dbContext) {
  1196.             _dbContext = dbContext;
  1197.             _customers = _dbContext.Customers;
  1198.  
  1199.         }
  1200.         public Customer GetBy(string email) {
  1201.             return _customers.Include(c => c.Location).SingleOrDefault(c => c.Email == email);
  1202.         }
  1203.         public void Add(Customer customer) {
  1204.             _customers.Add(customer);
  1205.         }
  1206.  
  1207.         public void SaveChanges() {
  1208.             _dbContext.SaveChanges();
  1209.         }
  1210.     }
  1211. }
  1212.  
  1213.  
  1214.  
  1215. using System.Collections.Generic;
  1216. using System.Linq;
  1217. using Beerhall.Models.Domain;
  1218. using Microsoft.EntityFrameworkCore;
  1219.  
  1220. namespace Beerhall.Data.Repositories {
  1221.     public class LocationRepository : ILocationRepository {
  1222.         private readonly DbSet<Location> _locations;
  1223.  
  1224.         public LocationRepository(ApplicationDbContext dbContext) {
  1225.             _locations = dbContext.Locations;
  1226.         }
  1227.         public Location GetBy(string postalCode) {
  1228.             return _locations.SingleOrDefault(l => l.PostalCode == postalCode);
  1229.         }
  1230.  
  1231.         public IEnumerable<Location> GetAll() {
  1232.             return _locations.ToList();
  1233.         }
  1234.     }
  1235. }
  1236.  
  1237.  
  1238.  
  1239.  
  1240. using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
  1241. using Microsoft.EntityFrameworkCore;
  1242. using Beerhall.Models.Domain;
  1243. using Microsoft.EntityFrameworkCore.Metadata;
  1244. using Microsoft.EntityFrameworkCore.Metadata.Builders;
  1245.  
  1246. namespace Beerhall.Data {
  1247.     public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
  1248.     {
  1249.         public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
  1250.             : base(options)
  1251.         {
  1252.         }
  1253.  
  1254.         public DbSet<Brewer> Brewers { get; set; }
  1255.         public DbSet<Beer> Beers { get; set; }
  1256.         public DbSet<Location> Locations { get; set; }
  1257.         public DbSet<Customer> Customers { get; set; }
  1258.  
  1259.         protected override void OnModelCreating(ModelBuilder modelBuilder) {
  1260.             base.OnModelCreating(modelBuilder);
  1261.             modelBuilder.Entity<Brewer>(MapBrewer);
  1262.             modelBuilder.Entity<Beer>(MapBeer);
  1263.             modelBuilder.Entity<Location>(MapLocation);
  1264.             modelBuilder.Entity<Order>(MapOrder);
  1265.             modelBuilder.Entity<OrderLine>(MapOrderLine);
  1266.         }
  1267.  
  1268.         public static void MapOrder(EntityTypeBuilder<Order> o) {
  1269.             o.ToTable("Order");
  1270.             o.Property(t => t.Street).IsRequired().HasMaxLength(100);
  1271.             o.HasMany(t => t.OrderLines).WithOne().HasForeignKey(t => t.OrderId).IsRequired().OnDelete(DeleteBehavior.Cascade);
  1272.             o.HasOne(c => c.Location).WithMany().IsRequired().OnDelete(DeleteBehavior.Restrict);
  1273.         }
  1274.  
  1275.         public static void MapOrderLine(EntityTypeBuilder<OrderLine> ol) {
  1276.             ol.ToTable("OrderLine");
  1277.             ol.HasKey(t => new {
  1278.                 t.OrderId,
  1279.                 t.ProductId
  1280.             });
  1281.             ol.HasOne(o => o.Product).WithMany().IsRequired().HasForeignKey(o => o.ProductId).OnDelete(DeleteBehavior.Restrict);
  1282.         }
  1283.  
  1284.         private static void MapLocation(EntityTypeBuilder<Location> l) {
  1285.             //Table name
  1286.             l.ToTable("Location");
  1287.  
  1288.             //Primary Key
  1289.             l.HasKey(t => t.PostalCode);
  1290.  
  1291.             //Properties
  1292.             l.Property(t => t.Name)
  1293.                 .IsRequired()
  1294.                 .HasMaxLength(50);
  1295.         }
  1296.  
  1297.  
  1298.         private void MapBeer(EntityTypeBuilder<Beer> b) {
  1299.             //Table name
  1300.             b.ToTable("Beer");
  1301.             // Properties
  1302.             b.Property(t => t.Name).IsRequired().HasMaxLength(100);
  1303.         }
  1304.  
  1305.         private static void MapBrewer(EntityTypeBuilder<Brewer> b) {
  1306.             //Table name
  1307.             b.ToTable("Brewer");
  1308.  
  1309.             //Primary Key
  1310.             b.HasKey(t => t.BrewerId);
  1311.  
  1312.             //Properties
  1313.             b.Property(t => t.Name)
  1314.                 .HasColumnName("BrewerName")
  1315.                 .IsRequired()
  1316.                 .HasMaxLength(100);
  1317.  
  1318.             b.Property(t => t.ContactEmail)
  1319.                 .HasMaxLength(100);
  1320.  
  1321.             b.Property(t => t.Street)
  1322.                 .HasMaxLength(100);
  1323.  
  1324.             b.Property(t => t.BrewerId)
  1325.                 .ValueGeneratedOnAdd();
  1326.  
  1327.             //Associations
  1328.             b.HasMany(t => t.Beers)
  1329.                 .WithOne()
  1330.                 .IsRequired()
  1331.                 .OnDelete(DeleteBehavior.Cascade);
  1332.  
  1333.             b.HasOne(t => t.Location)
  1334.                .WithMany()
  1335.                .IsRequired(false)
  1336.                .OnDelete(DeleteBehavior.Restrict);
  1337.         }
  1338.     }
  1339. }
  1340.  
  1341.  
  1342.  
  1343. using System;
  1344. using System.Security.Claims;
  1345. using System.Threading.Tasks;
  1346. using Beerhall.Models.Domain;
  1347. using Microsoft.AspNetCore.Identity;
  1348. using System.Linq;
  1349.  
  1350. namespace Beerhall.Data {
  1351.     public class BeerhallDataInitializer {
  1352.         private readonly ApplicationDbContext _dbContext;
  1353.         private readonly UserManager<ApplicationUser> _userManager;
  1354.  
  1355.         public BeerhallDataInitializer(ApplicationDbContext dbContext, UserManager<ApplicationUser> userManager) {
  1356.             _dbContext = dbContext;
  1357.             _userManager = userManager;
  1358.         }
  1359.  
  1360.         public async Task InitializeData() {
  1361.             _dbContext.Database.EnsureDeleted();
  1362.             if (_dbContext.Database.EnsureCreated()) {
  1363.                 Location bavikhove = new Location { Name = "Bavikhove", PostalCode = "8531" };
  1364.                 Location roeselare = new Location { Name = "Roeselare", PostalCode = "8800" };
  1365.                 Location puurs = new Location { Name = "Puurs", PostalCode = "2870" };
  1366.                 Location leuven = new Location { Name = "Leuven", PostalCode = "3000" };
  1367.                 Location oudenaarde = new Location { Name = "Oudenaarde", PostalCode = "9700" };
  1368.                 Location affligem = new Location { Name = "Affligem", PostalCode = "1790" };
  1369.                 Location[] locations = { bavikhove, roeselare, puurs, leuven, oudenaarde, affligem };
  1370.                 _dbContext.Locations.AddRange(locations);
  1371.                 _dbContext.SaveChanges();
  1372.  
  1373.                 Brewer bavik = new Brewer("Bavik", bavikhove, "Rijksweg 33");
  1374.                 _dbContext.Brewers.Add(bavik);
  1375.                 bavik.AddBeer("Bavik Pils", 5.2, 0.80M,
  1376.                     "De Bavik Premium Pils wordt gebrouwen met de beste mout en hop en verdient koel geschonken te worden.");
  1377.                 bavik.AddBeer("Wittekerke", 5.0, 0.90M, "Wittekerke 1/4");
  1378.                 bavik.AddBeer("Wittekerke Speciale", 5.8, 2.35M);
  1379.                 bavik.AddBeer("Wittekerke Rosé", 4.3, 1.79M);
  1380.                 bavik.AddBeer("Ezel Wit", 5.8, 1.79M);
  1381.                 bavik.AddBeer("Ezel Bruin", 6.5, 1.69M);
  1382.                 bavik.Turnover = 20000000;
  1383.                 bavik.DateEstablished = new DateTime(1990, 12, 26);
  1384.                 bavik.ContactEmail = "info@bavik.be";
  1385.                 bavik.Description =
  1386.                     "Brouwerij De Brabandere kan terugblikken op een rijke geschiedenis, maar kijkt met evenveel vertrouwen naar de toekomst. De droom die stichter Adolphe De Brabandere op het eind van de negentiende eeuw koestert wanneer hij in Bavikhove de fundamenten legt van zijn brouwerij, is realiteit geworden in de succesvolle onderneming van vandaag.Met een rijk assortiment bieren dat gesmaakt wordt door kenners tot ver buiten onze landsgrenzen.Brouwen was, is, en blijft een kunst bij Brouwerij De Brabandere. Beschouw onze talrijke karaktervolle bieren gerust als erfgoed: gemaakt met traditioneel vakmanschap, met authentieke ingrediënten en… veel liefde. Het creëren van een unieke smaaksensatie om te delen met vrienden, dat drijft ons dag in dag uit.  Zonder compromissen.";
  1387.  
  1388.                 Brewer palm = new Brewer("Palm Breweries");
  1389.                 _dbContext.Brewers.Add(palm);
  1390.                 palm.AddBeer("Estimanet", 5.2, 1.39M);
  1391.                 palm.AddBeer("Steenbrugge Blond", 6.5, 1.80M);
  1392.                 palm.AddBeer("Palm", 5.4, 0.90M);
  1393.                 palm.AddBeer("Dobbel Palm", 6.0, 1.15M);
  1394.                 palm.Turnover = 500000;
  1395.  
  1396.                 Brewer duvelMoortgat = new Brewer("Duvel Moortgat", puurs, "Breendonkdorp 28");
  1397.                 _dbContext.Brewers.Add(duvelMoortgat);
  1398.                 duvelMoortgat.AddBeer("Duvel", 8.5, 1.78M);
  1399.                 duvelMoortgat.AddBeer("Vedett", price: 1.79M);
  1400.                 duvelMoortgat.AddBeer("Maredsous", price: 1.69M);
  1401.                 duvelMoortgat.AddBeer("Liefmans Kriekbier", price: 2.35M);
  1402.                 duvelMoortgat.AddBeer("La Chouffe", 8.0, 1.69M);
  1403.                 duvelMoortgat.AddBeer("De Koninck", 5.0, 0.79M);
  1404.  
  1405.                 Brewer inBev = new Brewer("InBev", leuven, "Brouwerijplein 1");
  1406.                 _dbContext.Brewers.Add(inBev);
  1407.                 inBev.AddBeer("Jupiler", price: 1.19M);
  1408.                 inBev.AddBeer("Stella Artois", price: 1.19M);
  1409.                 inBev.AddBeer("Leffe", price: 1.89M);
  1410.                 inBev.AddBeer("Belle-Vue", price: 1.25M);
  1411.                 inBev.AddBeer("Hoegaarden", price: 0.89M);
  1412.  
  1413.                 Brewer roman = new Brewer("Roman", oudenaarde, "Hauwaart 105");
  1414.                 _dbContext.Brewers.Add(roman);
  1415.                 roman.AddBeer("Sloeber", 7.5, 1.20M);
  1416.                 roman.AddBeer("Black Hole", 5.6, 1.68M);
  1417.                 roman.AddBeer("Ename", 6.5, 2.19M);
  1418.                 roman.AddBeer("Romy Pils", 5.1, 0.65M);
  1419.  
  1420.                 Brewer deGraal = new Brewer("De Graal");
  1421.                 _dbContext.Brewers.Add(deGraal);
  1422.  
  1423.                 Brewer deLeeuw = new Brewer("De Leeuw");
  1424.                 _dbContext.Brewers.Add(deLeeuw);
  1425.  
  1426.                 _dbContext.SaveChanges();
  1427.  
  1428.                 await InitializeUsersAndCustomers();
  1429.  
  1430.             }
  1431.         }
  1432.  
  1433.         private async Task InitializeUsersAndCustomers() {
  1434.             string eMailAddress = "beermaster@hogent.be";
  1435.             ApplicationUser user = new ApplicationUser { UserName = eMailAddress, Email = eMailAddress };
  1436.             await _userManager.CreateAsync(user, "P@ssword1");
  1437.             await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Role, "admin"));
  1438.  
  1439.             eMailAddress = "jan@hogent.be";
  1440.             user = new ApplicationUser { UserName = eMailAddress, Email = eMailAddress };
  1441.             await _userManager.CreateAsync(user, "P@ssword1");
  1442.             await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Role, "customer"));
  1443.  
  1444.             var customer = new Customer {
  1445.                 Email = eMailAddress,
  1446.                 FirstName = "Jan",
  1447.                 Name = "De man",
  1448.                 Location = _dbContext.Locations.SingleOrDefault(l => l.PostalCode == "9700"),
  1449.                 Street = "Nederstraat 5"
  1450.             };
  1451.  
  1452.             _dbContext.Customers.Add(customer);
  1453.             _dbContext.SaveChanges();
  1454.         }
  1455.     }
  1456. }
  1457.  
  1458.  
  1459.  
  1460.  
  1461. using Microsoft.AspNetCore.Http;
  1462. using Microsoft.AspNetCore.Mvc.Filters;
  1463. using Newtonsoft.Json;
  1464. using Beerhall.Models.Domain;
  1465.  
  1466. namespace Beerhall.Filters {
  1467.  
  1468.     public class CartSessionFilter : ActionFilterAttribute {
  1469.         private readonly IBeerRepository _beerRepository;
  1470.         private Cart _cart;
  1471.  
  1472.         public CartSessionFilter(IBeerRepository beerRepository) {
  1473.             _beerRepository = beerRepository;
  1474.         }
  1475.  
  1476.         public override void OnActionExecuting(ActionExecutingContext context) {
  1477.             _cart = ReadCartFromSession(context.HttpContext);
  1478.             context.ActionArguments["cart"] = _cart;
  1479.             base.OnActionExecuting(context);
  1480.         }
  1481.  
  1482.         public override void OnActionExecuted(ActionExecutedContext context) {
  1483.             WriteCartToSession(_cart, context.HttpContext);
  1484.             base.OnActionExecuted(context);
  1485.         }
  1486.  
  1487.         private Cart ReadCartFromSession(HttpContext context) {
  1488.             Cart cart = context.Session.GetString("cart") == null ?
  1489.                 new Cart() : JsonConvert.DeserializeObject<Cart>(context.Session.GetString("cart"));
  1490.             foreach (var l in cart.CartLines)
  1491.                 l.Product = _beerRepository.GetBy(l.Product.BeerId);
  1492.             return cart;
  1493.         }
  1494.  
  1495.         private void WriteCartToSession(Cart cart, HttpContext context) {
  1496.             context.Session.SetString("cart", JsonConvert.SerializeObject(cart));
  1497.         }
  1498.     }
  1499. }
  1500.  
  1501.  
  1502.  
  1503.  
  1504. using Beerhall.Models.Domain;
  1505. using Microsoft.AspNetCore.Mvc.Filters;
  1506.  
  1507. namespace Beerhall.Filters {
  1508.     public class CustomerFilter : ActionFilterAttribute {
  1509.         private readonly ICustomerRepository _customerRepository;
  1510.  
  1511.         public CustomerFilter(ICustomerRepository customerRespoitory) {
  1512.             _customerRepository = customerRespoitory;
  1513.         }
  1514.  
  1515.         public override void OnActionExecuting(ActionExecutingContext context) {
  1516.             context.ActionArguments["customer"] = context.HttpContext.User.Identity.IsAuthenticated ? _customerRepository.GetBy(context.HttpContext.User.Identity.Name) : null;
  1517.             base.OnActionExecuting(context);
  1518.         }
  1519.     }
  1520. }
  1521.  
  1522.  
  1523.  
  1524. using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
  1525.  
  1526. namespace Beerhall.Models.Domain {
  1527.     public class ApplicationUser : IdentityUser {
  1528.  
  1529.     }
  1530. }
  1531.  
  1532.  
  1533.  
  1534. using System;
  1535. using Newtonsoft.Json;
  1536.  
  1537. namespace Beerhall.Models.Domain {
  1538.     [JsonObject(MemberSerialization.OptIn)]
  1539.     public class Beer {
  1540.         #region Fields
  1541.         private string _name;
  1542.         #endregion
  1543.  
  1544.         #region Properties
  1545.         [JsonProperty]
  1546.         public int BeerId { get; set; }
  1547.         public string Name {
  1548.             get {
  1549.                 return _name;
  1550.             }
  1551.             private set {
  1552.                 if (string.IsNullOrWhiteSpace(value))
  1553.                     throw new ArgumentException("A beer must be given a name");
  1554.                 _name = value;
  1555.             }
  1556.         }
  1557.         public string Description { get; set; }
  1558.         public double? AlcoholByVolume { get; set; }
  1559.         public bool AlcoholKnown => AlcoholByVolume.HasValue;
  1560.         public decimal Price { get; set; }
  1561.         #endregion
  1562.  
  1563.         #region Constructors
  1564.         [JsonConstructor]
  1565.         protected Beer() {
  1566.  
  1567.         }
  1568.  
  1569.         public Beer(string name) : this() {
  1570.             Name = name;
  1571.         }
  1572.         #endregion
  1573.     }
  1574. }
  1575.  
  1576.  
  1577. using System;
  1578. using System.Collections.Generic;
  1579. using System.Linq;
  1580. using System.Text.RegularExpressions;
  1581.  
  1582. namespace Beerhall.Models.Domain {
  1583.     public class Brewer {
  1584.         #region Fields
  1585.         private string _name;
  1586.         private string _contactEmail;
  1587.         private int? _turnover;
  1588.         private DateTime? _dateEstablished;
  1589.         #endregion
  1590.  
  1591.         #region Properties
  1592.         public int BrewerId {
  1593.             get; set;
  1594.         }
  1595.         public string Name {
  1596.             get {
  1597.                 return _name;
  1598.             }
  1599.             set {
  1600.                 if (string.IsNullOrWhiteSpace(value))
  1601.                     throw new ArgumentException("A brewer must have a name");
  1602.                 if (value.Length > 50)
  1603.                     throw new ArgumentException("Name of brewer must not exceed 50 characters");
  1604.                 _name = value;
  1605.             }
  1606.         }
  1607.         public string Description {
  1608.             get; set;
  1609.         }
  1610.  
  1611.         public string ContactEmail {
  1612.             get { return _contactEmail; }
  1613.             set {
  1614.                 if (value != null) {
  1615.                     Regex regex = new Regex(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}");
  1616.                     Match match = regex.Match(value);
  1617.                     if (!match.Success)
  1618.                         throw new ArgumentException("Email address is not valid");
  1619.                     _contactEmail = value;
  1620.                 }
  1621.             }
  1622.         }
  1623.         public DateTime? DateEstablished {
  1624.             get { return _dateEstablished; }
  1625.             set {
  1626.                 if (value > DateTime.Today)
  1627.                     throw new ArgumentException("Date established must be in the past");
  1628.                 _dateEstablished = value;
  1629.  
  1630.             }
  1631.         }
  1632.         public string Street {
  1633.             get; set;
  1634.         }
  1635.         public Location Location {
  1636.             get; set;
  1637.         }
  1638.         public int? Turnover {
  1639.             get {
  1640.                 return _turnover;
  1641.             }
  1642.             set {
  1643.                 if (value.GetValueOrDefault() < 0)
  1644.                     throw new ArgumentException("Turnover must be positive");
  1645.                 _turnover = value;
  1646.             }
  1647.         }
  1648.  
  1649.         public ICollection<Beer> Beers {
  1650.             get;
  1651.         }
  1652.  
  1653.         public int NrOfBeers => Beers.Count;
  1654.  
  1655.         #endregion
  1656.  
  1657.         #region Constructors
  1658.         public Brewer() {
  1659.             Beers = new HashSet<Beer>();
  1660.             _turnover = null;
  1661.         }
  1662.  
  1663.         public Brewer(string name) : this() {
  1664.             Name = name;
  1665.         }
  1666.  
  1667.         public Brewer(string name, Location location, string street)
  1668.             : this(name) {
  1669.             Location = location;
  1670.             Street = street;
  1671.         }
  1672.         #endregion
  1673.  
  1674.         #region Methods
  1675.         public Beer AddBeer(string name, double? alcoholByVolume = null, decimal price = 0, string description = null) {
  1676.             if (name != null && Beers.FirstOrDefault(b => b.Name == name) != null)
  1677.                 throw new ArgumentException($"Brewer {Name} has already a beer by the name of {name}");
  1678.             Beer newBeer = new Beer(name) {
  1679.                 AlcoholByVolume = alcoholByVolume,
  1680.                 Description = description,
  1681.                 Price = price
  1682.             };
  1683.             Beers.Add(newBeer);
  1684.             return newBeer;
  1685.         }
  1686.  
  1687.         public void DeleteBeer(Beer beer) {
  1688.             if (!Beers.Contains(beer))
  1689.                 throw new ArgumentException($"{beer.Name} is not a {Name} beer");
  1690.             Beers.Remove(beer);
  1691.         }
  1692.  
  1693.         public Beer GetBy(int beerId) {
  1694.             return Beers.FirstOrDefault(b => b.BeerId == beerId);
  1695.         }
  1696.  
  1697.         public Beer GetBy(string name) {
  1698.             return Beers.FirstOrDefault(b => b.Name == name);
  1699.         }
  1700.         #endregion
  1701.     }
  1702. }
  1703.  
  1704.  
  1705. using System.Collections.Generic;
  1706. using System.Linq;
  1707. using Newtonsoft.Json;
  1708.  
  1709. namespace Beerhall.Models.Domain {
  1710.     [JsonObject(MemberSerialization.OptIn)]
  1711.     public class Cart {
  1712.         #region Properties
  1713.         [JsonProperty]
  1714.         private readonly IList<CartLine> _lines = new List<CartLine>();
  1715.         public IEnumerable<CartLine> CartLines => _lines.AsEnumerable();
  1716.         public int NumberOfItems => _lines.Count;
  1717.         public decimal TotalValue {
  1718.             get { return _lines.Sum(l => l.Product.Price * l.Quantity); }
  1719.         }
  1720.         #endregion
  1721.  
  1722.         #region Methods
  1723.         public void AddLine(Beer product, int quantity) {
  1724.             CartLine line = _lines.SingleOrDefault(l => l.Product.BeerId == product.BeerId);
  1725.             if (line == null)
  1726.                 _lines.Add(new CartLine { Product = product, Quantity = quantity });
  1727.             else
  1728.                 line.Quantity += quantity;
  1729.         }
  1730.  
  1731.         public void RemoveLine(Beer product) {
  1732.             CartLine line = _lines.SingleOrDefault(l => l.Product.BeerId == product.BeerId);
  1733.             if (line != null)
  1734.                 _lines.Remove(line);
  1735.         }
  1736.  
  1737.         public void Clear() {
  1738.             _lines.Clear();
  1739.         }
  1740.         #endregion
  1741.     }
  1742. }
  1743.  
  1744.  
  1745. using Newtonsoft.Json;
  1746.  
  1747. namespace Beerhall.Models.Domain {
  1748.     [JsonObject(MemberSerialization.OptIn)]
  1749.     public class CartLine {
  1750.         [JsonProperty]
  1751.         public int Quantity { get; set; }
  1752.         [JsonProperty]
  1753.         public Beer Product { get; set; }
  1754.         public decimal Total => Product.Price * Quantity;
  1755.     }
  1756. }
  1757.  
  1758.  
  1759. using System;
  1760. using System.Collections.Generic;
  1761.  
  1762. namespace Beerhall.Models.Domain {
  1763.     public class Customer {
  1764.         #region Properties
  1765.         public int CustomerId { get; set; }
  1766.         public string Email { get; set; }
  1767.         public string Name { get; set; }
  1768.         public string FirstName { get; set; }
  1769.         public string Street { get; set; }
  1770.         public Location Location { get; set; }
  1771.         public ICollection<Order> Orders { get; set; }
  1772.         #endregion
  1773.  
  1774.         #region Methods
  1775.         public Customer() {
  1776.             Orders = new List<Order>();
  1777.         }
  1778.  
  1779.         public void PlaceOrder(Cart cart, DateTime? deliveryDate, bool giftwrapping, string shippingStreet, Location shippingCity) {
  1780.             Orders.Add(new Order(cart, deliveryDate, giftwrapping, shippingStreet, shippingCity));
  1781.         }
  1782.         #endregion
  1783.     }
  1784. }
  1785.  
  1786.  
  1787.  
  1788. using System.Collections.Generic;
  1789.  
  1790. namespace Beerhall.Models.Domain {
  1791.     public interface IBeerRepository {
  1792.         IEnumerable<Beer> GetAll();
  1793.         Beer GetBy(int beerId);
  1794.     }
  1795. }
  1796.  
  1797.  
  1798. using System.Collections.Generic;
  1799.  
  1800. namespace Beerhall.Models.Domain {
  1801.     public interface IBrewerRepository {
  1802.         Brewer GetBy(int brewerId);
  1803.         IEnumerable<Brewer> GetAll();
  1804.         void Add(Brewer brewer);
  1805.         void Delete(Brewer brewer);
  1806.         void SaveChanges();
  1807.     }
  1808. }
  1809.  
  1810.  
  1811.  
  1812.  
  1813. namespace Beerhall.Models.Domain {
  1814.     public interface ICustomerRepository {
  1815.         Customer GetBy(string email);
  1816.         void Add(Customer customer);
  1817.         void SaveChanges();
  1818.     }
  1819. }
  1820.  
  1821.  
  1822.  
  1823. using System.Collections.Generic;
  1824.  
  1825. namespace Beerhall.Models.Domain {
  1826.     public interface ILocationRepository {
  1827.         Location GetBy(string postalCode);
  1828.         IEnumerable<Location> GetAll();
  1829.     }
  1830. }
  1831.  
  1832.  
  1833.  
  1834.  
  1835. namespace Beerhall.Models.Domain {
  1836.     public class Location {
  1837.         public string PostalCode { get; set; }
  1838.         public string Name { get; set; }
  1839.     }
  1840. }
  1841.  
  1842.  
  1843.  
  1844.  
  1845. using System;
  1846. using System.Collections.Generic;
  1847. using System.Linq;
  1848.  
  1849. namespace Beerhall.Models.Domain {
  1850.     public class Order {
  1851.         #region Fields
  1852.         private DateTime? _deliveryDate;
  1853.         private string _street;
  1854.         private Location _location;
  1855.         #endregion
  1856.  
  1857.         #region Properties
  1858.         public int OrderId { get; private set; } // required for EF
  1859.         public DateTime? DeliveryDate {
  1860.             get { return _deliveryDate; }
  1861.             private set {
  1862.                 if (value.HasValue) {
  1863.                     if (DateTime.Today.AddDays(3) > value.Value)
  1864.                         throw new ArgumentException("Date of delivery must at least be three days after placing order");
  1865.                     if (value.Value.DayOfWeek == DayOfWeek.Sunday)
  1866.                         throw new ArgumentException("Sundays are not valid delivery days");
  1867.                 }
  1868.                 _deliveryDate = value;
  1869.             }
  1870.         }
  1871.         public DateTime OrderDate { get; private set; }
  1872.         public bool Giftwrapping { get; private set; }
  1873.         public string Street {
  1874.             get { return _street; }
  1875.             private set {
  1876.                 if (string.IsNullOrWhiteSpace(value))
  1877.                     throw new ArgumentException("Street is required");
  1878.                 _street = value;
  1879.             }
  1880.         }
  1881.         public Location Location {
  1882.             get { return _location; }
  1883.             private set {
  1884.                 if (value == null)
  1885.                     throw new ArgumentException("Location is required");
  1886.                 _location = value;
  1887.             }
  1888.         }
  1889.         public ICollection<OrderLine> OrderLines { get; private set; }
  1890.         public decimal Total { get { return OrderLines.Sum(o => o.Price * o.Quantity); } }
  1891.  
  1892.         #endregion
  1893.  
  1894.         #region Constructors
  1895.         private Order() {
  1896.             OrderLines = new HashSet<OrderLine>();
  1897.             OrderDate = DateTime.Today;
  1898.         }
  1899.  
  1900.         public Order(Cart cart, DateTime? deliveryDate, bool giftwrapping, string street, Location location) : this() {
  1901.             if (cart.NumberOfItems == 0)
  1902.                 throw new ArgumentException("An order requires a non empty cart");
  1903.             foreach (CartLine line in cart.CartLines)
  1904.                 OrderLines.Add(new OrderLine {
  1905.                     Product = line.Product,
  1906.                     Price = line.Product.Price,
  1907.                     Quantity = line.Quantity
  1908.                 });
  1909.             DeliveryDate = deliveryDate;
  1910.             Giftwrapping = giftwrapping;
  1911.             Street = street;
  1912.             Location = location;
  1913.         }
  1914.         #endregion
  1915.     }
  1916. }
  1917.  
  1918.  
  1919.  
  1920. namespace Beerhall.Models.Domain {
  1921.     public class OrderLine : CartLine {
  1922.         public int OrderId { get; set; }
  1923.         public int ProductId { get; set; }
  1924.         public decimal Price { get; set; }
  1925.     }
  1926. }
  1927.  
  1928.  
  1929.  
  1930. using System.ComponentModel.DataAnnotations;
  1931.  
  1932. namespace Beerhall.Models.ViewModels.AccountViewModels
  1933. {
  1934.     public class ExternalLoginConfirmationViewModel
  1935.     {
  1936.         [Required]
  1937.         [EmailAddress]
  1938.         public string Email { get; set; }
  1939.     }
  1940. }
  1941.  
  1942.  
  1943.  
  1944. using System.ComponentModel.DataAnnotations;
  1945.  
  1946. namespace Beerhall.Models.ViewModels.AccountViewModels
  1947. {
  1948.     public class ForgotPasswordViewModel
  1949.     {
  1950.         [Required]
  1951.         [EmailAddress]
  1952.         public string Email { get; set; }
  1953.     }
  1954. }
  1955.  
  1956.  
  1957.  
  1958. using System.ComponentModel.DataAnnotations;
  1959.  
  1960. namespace Beerhall.Models.ViewModels.AccountViewModels
  1961. {
  1962.     public class LoginViewModel
  1963.     {
  1964.         [Required]
  1965.         [EmailAddress]
  1966.         public string Email { get; set; }
  1967.  
  1968.         [Required]
  1969.         [DataType(DataType.Password)]
  1970.         public string Password { get; set; }
  1971.  
  1972.         [Display(Name = "Remember me?")]
  1973.         public bool RememberMe { get; set; }
  1974.     }
  1975. }
  1976.  
  1977.  
  1978.  
  1979. using System.ComponentModel.DataAnnotations;
  1980.  
  1981. namespace Beerhall.Models.ViewModels.AccountViewModels
  1982. {
  1983.     public class RegisterViewModel
  1984.     {
  1985.         [Required]
  1986.         [EmailAddress]
  1987.         [Display(Name = "Email")]
  1988.         public string Email { get; set; }
  1989.  
  1990.         [Required]
  1991.         [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
  1992.         [DataType(DataType.Password)]
  1993.         [Display(Name = "Password")]
  1994.         public string Password { get; set; }
  1995.  
  1996.         [DataType(DataType.Password)]
  1997.         [Display(Name = "Confirm password")]
  1998.         [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
  1999.         public string ConfirmPassword { get; set; }
  2000.  
  2001.         [Required]
  2002.         [StringLength(100)]
  2003.         public string Name { get; set; }
  2004.  
  2005.         [Required]
  2006.         [Display(Name = "First name")]
  2007.         [StringLength(100)]
  2008.         public string FirstName { get; set; }
  2009.  
  2010.         [StringLength(100)]
  2011.         public string Street { get; set; }
  2012.  
  2013.         [Display(Name = "Location")]
  2014.         public string PostalCode { get; set; }
  2015.     }
  2016. }
  2017.  
  2018.  
  2019.  
  2020. using System.ComponentModel.DataAnnotations;
  2021.  
  2022. namespace Beerhall.Models.ViewModels.AccountViewModels
  2023. {
  2024.     public class ResetPasswordViewModel
  2025.     {
  2026.         [Required]
  2027.         [EmailAddress]
  2028.         public string Email { get; set; }
  2029.  
  2030.         [Required]
  2031.         [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
  2032.         [DataType(DataType.Password)]
  2033.         public string Password { get; set; }
  2034.  
  2035.         [DataType(DataType.Password)]
  2036.         [Display(Name = "Confirm password")]
  2037.         [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
  2038.         public string ConfirmPassword { get; set; }
  2039.  
  2040.         public string Code { get; set; }
  2041.     }
  2042. }
  2043.  
  2044.  
  2045.  
  2046. using System.Collections.Generic;
  2047. using Microsoft.AspNetCore.Mvc.Rendering;
  2048.  
  2049. namespace Beerhall.Models.ViewModels.AccountViewModels
  2050. {
  2051.     public class SendCodeViewModel
  2052.     {
  2053.         public string SelectedProvider { get; set; }
  2054.  
  2055.         public ICollection<SelectListItem> Providers { get; set; }
  2056.  
  2057.         public string ReturnUrl { get; set; }
  2058.  
  2059.         public bool RememberMe { get; set; }
  2060.     }
  2061. }
  2062.  
  2063.  
  2064.  
  2065. using System.ComponentModel.DataAnnotations;
  2066.  
  2067. namespace Beerhall.Models.ViewModels.AccountViewModels
  2068. {
  2069.     public class VerifyCodeViewModel
  2070.     {
  2071.         [Required]
  2072.         public string Provider { get; set; }
  2073.  
  2074.         [Required]
  2075.         public string Code { get; set; }
  2076.  
  2077.         public string ReturnUrl { get; set; }
  2078.  
  2079.         [Display(Name = "Remember this browser?")]
  2080.         public bool RememberBrowser { get; set; }
  2081.  
  2082.         [Display(Name = "Remember me?")]
  2083.         public bool RememberMe { get; set; }
  2084.     }
  2085. }
  2086.  
  2087.  
  2088.  
  2089. using System;
  2090. using System.ComponentModel.DataAnnotations;
  2091. using Beerhall.Models.Domain;
  2092. using Microsoft.AspNetCore.Mvc;
  2093.  
  2094. namespace Beerhall.Models.ViewModels.BrewerViewModels {
  2095.     public class EditViewModel {
  2096.         [HiddenInput]
  2097.         public int BrewerId {
  2098.             get; set;
  2099.         }
  2100.         [Required]
  2101.         [StringLength(50, ErrorMessage = "{0} may not contain more than 50 characters")]
  2102.         public string Name {
  2103.             get; set;
  2104.         }
  2105.         public string Street {
  2106.             get; set;
  2107.         }
  2108.         [Display(Name = "Postal code")]
  2109.         public string PostalCode {
  2110.             get; set;
  2111.         }
  2112.         [DataType(DataType.Currency)]
  2113.         [Range(0, int.MaxValue, ErrorMessage = "{0} may not be a negative value.")]
  2114.         public int? Turnover {
  2115.             get; set;
  2116.         }
  2117.         public string Description {
  2118.             get; set;
  2119.         }
  2120.         [Display(Name = "Email address")]
  2121.         [DataType(DataType.EmailAddress)]
  2122.         [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "Email address is not valid")]
  2123.         public string ContactEmail {
  2124.             get; set;
  2125.         }
  2126.         [Display(Name = "Date established")]
  2127.         [DataType(DataType.Date)]
  2128.         public DateTime? DateEstablished {
  2129.             get; set;
  2130.         }
  2131.  
  2132.         public EditViewModel() {
  2133.         }
  2134.  
  2135.         public EditViewModel(Brewer brewer) : this() {
  2136.             BrewerId = brewer.BrewerId;
  2137.             Name = brewer.Name;
  2138.             Street = brewer.Street;
  2139.             PostalCode = brewer.Location?.PostalCode;
  2140.             ContactEmail = brewer.ContactEmail;
  2141.             Description = brewer.Description;
  2142.             DateEstablished = brewer.DateEstablished;
  2143.             Turnover = brewer.Turnover;
  2144.         }
  2145.     }
  2146. }
  2147.  
  2148.  
  2149. using System;
  2150. using System.Collections.Generic;
  2151. using System.ComponentModel.DataAnnotations;
  2152. using Beerhall.Models.Domain;
  2153. using Microsoft.AspNetCore.Mvc.Rendering;
  2154.  
  2155. namespace Beerhall.Models.ViewModels.CartViewModels {
  2156.     public class CheckOutViewModel {
  2157.         public SelectList Locations { get; private set; }
  2158.         public ShippingViewModel ShippingViewModel { get; set; }
  2159.         public CheckOutViewModel(IEnumerable<Location> locations, ShippingViewModel shippingViewModel) {
  2160.             Locations = new SelectList(locations,
  2161.                 nameof(Location.PostalCode),
  2162.                 nameof(Location.Name),
  2163.                 shippingViewModel?.PostalCode);
  2164.             ShippingViewModel = shippingViewModel;
  2165.         }
  2166.     }
  2167.     public class ShippingViewModel {
  2168.         [DataType(DataType.Date)]
  2169.         [Display(Name = "Delivery date")]
  2170.         public DateTime? DeliveryDate { get; set; }
  2171.         [Display(Name = "Gift wrapping")]
  2172.         public bool Giftwrapping { get; set; }
  2173.         public string Street { get; set; }
  2174.         [Display(Name = "Location")]
  2175.         public string PostalCode { get; set; }
  2176.     }
  2177.  
  2178. }
  2179.  
  2180.  
  2181.  
  2182. using Beerhall.Models.Domain;
  2183. using Microsoft.AspNetCore.Mvc;
  2184.  
  2185. namespace Beerhall.Models.ViewModels.CartViewModels {
  2186.  
  2187.     public class IndexViewModel {
  2188.         [HiddenInput]
  2189.         public int BeerId { get; private set; }
  2190.  
  2191.         public int Quantity { get; private set; }
  2192.  
  2193.         public string Beer { get; private set; }
  2194.  
  2195.         public decimal Price { get; private set; }
  2196.  
  2197.         public decimal SubTotal { get; private set; }
  2198.  
  2199.         public IndexViewModel(CartLine cartLine) {
  2200.             BeerId = cartLine.Product.BeerId;
  2201.             Quantity = cartLine.Quantity;
  2202.             Beer = cartLine.Product.Name;
  2203.             Price = cartLine.Product.Price;
  2204.             SubTotal = cartLine.Total;
  2205.         }
  2206.     }
  2207. }
  2208.  
  2209.  
  2210.  
  2211. using System.ComponentModel.DataAnnotations;
  2212.  
  2213. namespace Beerhall.Models.ViewModels.ManageViewModels
  2214. {
  2215.     public class AddPhoneNumberViewModel
  2216.     {
  2217.         [Required]
  2218.         [Phone]
  2219.         [Display(Name = "Phone number")]
  2220.         public string PhoneNumber { get; set; }
  2221.     }
  2222. }
  2223.  
  2224.  
  2225.  
  2226. using System.ComponentModel.DataAnnotations;
  2227.  
  2228. namespace Beerhall.Models.ViewModels.ManageViewModels
  2229. {
  2230.     public class ChangePasswordViewModel
  2231.     {
  2232.         [Required]
  2233.         [DataType(DataType.Password)]
  2234.         [Display(Name = "Current password")]
  2235.         public string OldPassword { get; set; }
  2236.  
  2237.         [Required]
  2238.         [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
  2239.         [DataType(DataType.Password)]
  2240.         [Display(Name = "New password")]
  2241.         public string NewPassword { get; set; }
  2242.  
  2243.         [DataType(DataType.Password)]
  2244.         [Display(Name = "Confirm new password")]
  2245.         [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
  2246.         public string ConfirmPassword { get; set; }
  2247.     }
  2248. }
  2249.  
  2250.  
  2251.  
  2252. using System.Collections.Generic;
  2253. using Microsoft.AspNetCore.Mvc.Rendering;
  2254.  
  2255. namespace Beerhall.Models.ViewModels.ManageViewModels
  2256. {
  2257.     public class ConfigureTwoFactorViewModel
  2258.     {
  2259.         public string SelectedProvider { get; set; }
  2260.  
  2261.         public ICollection<SelectListItem> Providers { get; set; }
  2262.     }
  2263. }
  2264.  
  2265.  
  2266.  
  2267. namespace Beerhall.Models.ViewModels.ManageViewModels
  2268. {
  2269.     public class FactorViewModel
  2270.     {
  2271.         public string Purpose { get; set; }
  2272.     }
  2273. }
  2274.  
  2275.  
  2276.  
  2277. using System.Collections.Generic;
  2278. using Microsoft.AspNetCore.Identity;
  2279.  
  2280. namespace Beerhall.Models.ViewModels.ManageViewModels
  2281. {
  2282.     public class IndexViewModel
  2283.     {
  2284.         public bool HasPassword { get; set; }
  2285.  
  2286.         public IList<UserLoginInfo> Logins { get; set; }
  2287.  
  2288.         public string PhoneNumber { get; set; }
  2289.  
  2290.         public bool TwoFactor { get; set; }
  2291.  
  2292.         public bool BrowserRemembered { get; set; }
  2293.     }
  2294. }
  2295.  
  2296.  
  2297.  
  2298. using System.Collections.Generic;
  2299. using Microsoft.AspNetCore.Http.Authentication;
  2300. using Microsoft.AspNetCore.Identity;
  2301.  
  2302. namespace Beerhall.Models.ViewModels.ManageViewModels
  2303. {
  2304.     public class ManageLoginsViewModel
  2305.     {
  2306.         public IList<UserLoginInfo> CurrentLogins { get; set; }
  2307.  
  2308.         public IList<AuthenticationDescription> OtherLogins { get; set; }
  2309.     }
  2310. }
  2311.  
  2312.  
  2313.  
  2314. namespace Beerhall.Models.ViewModels.ManageViewModels
  2315. {
  2316.     public class RemoveLoginViewModel
  2317.     {
  2318.         public string LoginProvider { get; set; }
  2319.         public string ProviderKey { get; set; }
  2320.     }
  2321. }
  2322.  
  2323.  
  2324.  
  2325. using System.ComponentModel.DataAnnotations;
  2326.  
  2327. namespace Beerhall.Models.ViewModels.ManageViewModels
  2328. {
  2329.     public class SetPasswordViewModel
  2330.     {
  2331.         [Required]
  2332.         [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
  2333.         [DataType(DataType.Password)]
  2334.         [Display(Name = "New password")]
  2335.         public string NewPassword { get; set; }
  2336.  
  2337.         [DataType(DataType.Password)]
  2338.         [Display(Name = "Confirm new password")]
  2339.         [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
  2340.         public string ConfirmPassword { get; set; }
  2341.     }
  2342. }
  2343.  
  2344.  
  2345.  
  2346. using System.ComponentModel.DataAnnotations;
  2347.  
  2348. namespace Beerhall.Models.ViewModels.ManageViewModels
  2349. {
  2350.     public class VerifyPhoneNumberViewModel
  2351.     {
  2352.         [Required]
  2353.         public string Code { get; set; }
  2354.  
  2355.         [Required]
  2356.         [Phone]
  2357.         [Display(Name = "Phone number")]
  2358.         public string PhoneNumber { get; set; }
  2359.     }
  2360. }
  2361.  
  2362.  
  2363.  
  2364. using System.Threading.Tasks;
  2365.  
  2366. namespace Beerhall.Services
  2367. {
  2368.     public interface IEmailSender
  2369.     {
  2370.         Task SendEmailAsync(string email, string subject, string message);
  2371.     }
  2372. }
  2373.  
  2374.  
  2375.  
  2376. using System.Threading.Tasks;
  2377.  
  2378. namespace Beerhall.Services
  2379. {
  2380.     public interface ISmsSender
  2381.     {
  2382.         Task SendSmsAsync(string number, string message);
  2383.     }
  2384. }
  2385.  
  2386.  
  2387.  
  2388. using System.Threading.Tasks;
  2389.  
  2390. namespace Beerhall.Services
  2391. {
  2392.     // This class is used by the application to send Email and SMS
  2393.     // when you turn on two-factor authentication in ASP.NET Identity.
  2394.     // For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713
  2395.     public class AuthMessageSender : IEmailSender, ISmsSender
  2396.     {
  2397.         public Task SendEmailAsync(string email, string subject, string message)
  2398.         {
  2399.             // Plug in your email service here to send an email.
  2400.             return Task.FromResult(0);
  2401.         }
  2402.  
  2403.         public Task SendSmsAsync(string number, string message)
  2404.         {
  2405.             // Plug in your SMS service here to send a text message.
  2406.             return Task.FromResult(0);
  2407.         }
  2408.     }
  2409. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement