Exercise Files

This commit is contained in:
Jess Chadwick
2018-06-06 23:57:58 -04:00
commit 20458e435e
4436 changed files with 1359080 additions and 0 deletions

View File

@ -0,0 +1,485 @@
using System;
using System.Globalization;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using HPlusSports.Models;
namespace HPlusSports.Controllers
{
[Authorize]
public class AccountController : Controller
{
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
{
UserManager = userManager;
SignInManager = signInManager;
}
public ApplicationSignInManager SignInManager
{
get
{
return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
private set
{
_signInManager = value;
}
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
//
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
//
// GET: /Account/VerifyCode
[AllowAnonymous]
public async Task<ActionResult> VerifyCode(string provider, string returnUrl, bool rememberMe)
{
// Require that the user has already logged in via username/password or external login
if (!await SignInManager.HasBeenVerifiedAsync())
{
return View("Error");
}
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe });
}
//
// POST: /Account/VerifyCode
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> VerifyCode(VerifyCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// The following code protects for brute force attacks against the two factor codes.
// If a user enters incorrect codes for a specified amount of time then the user account
// will be locked out for a specified amount of time.
// You can configure the account lockout settings in IdentityConfig
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(model.ReturnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid code.");
return View(model);
}
}
//
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
return View();
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return View("Error");
}
var result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
//
// GET: /Account/ForgotPassword
[AllowAnonymous]
public ActionResult ForgotPassword()
{
return View();
}
//
// POST: /Account/ForgotPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
// var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Reset Password", "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>");
// return RedirectToAction("ForgotPasswordConfirmation", "Account");
}
// If we got this far, something failed, redisplay form
return View(model);
}
//
// GET: /Account/ForgotPasswordConfirmation
[AllowAnonymous]
public ActionResult ForgotPasswordConfirmation()
{
return View();
}
//
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
return code == null ? View("Error") : View();
}
//
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
AddErrors(result);
return View();
}
//
// GET: /Account/ResetPasswordConfirmation
[AllowAnonymous]
public ActionResult ResetPasswordConfirmation()
{
return View();
}
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
//
// GET: /Account/SendCode
[AllowAnonymous]
public async Task<ActionResult> SendCode(string returnUrl, bool rememberMe)
{
var userId = await SignInManager.GetVerifiedUserIdAsync();
if (userId == null)
{
return View("Error");
}
var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(userId);
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe });
}
//
// POST: /Account/SendCode
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SendCode(SendCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View();
}
// Generate the token and send it
if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
{
return View("Error");
}
return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
}
//
// GET: /Account/ExternalLoginCallback
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
case SignInStatus.Failure:
default:
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
}
}
//
// POST: /Account/ExternalLoginConfirmation
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Manage");
}
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await AuthenticationManager.GetExternalLoginInfoAsync();
if (info == null)
{
return View("ExternalLoginFailure");
}
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user);
if (result.Succeeded)
{
result = await UserManager.AddLoginAsync(user.Id, info.Login);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
return RedirectToAction("Index", "Home");
}
//
// GET: /Account/ExternalLoginFailure
[AllowAnonymous]
public ActionResult ExternalLoginFailure()
{
return View();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_userManager != null)
{
_userManager.Dispose();
_userManager = null;
}
if (_signInManager != null)
{
_signInManager.Dispose();
_signInManager = null;
}
}
base.Dispose(disposing);
}
#region Helpers
// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");
}
internal class ChallengeResult : HttpUnauthorizedResult
{
public ChallengeResult(string provider, string redirectUri)
: this(provider, redirectUri, null)
{
}
public ChallengeResult(string provider, string redirectUri, string userId)
{
LoginProvider = provider;
RedirectUri = redirectUri;
UserId = userId;
}
public string LoginProvider { get; set; }
public string RedirectUri { get; set; }
public string UserId { get; set; }
public override void ExecuteResult(ControllerContext context)
{
var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = UserId;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}
#endregion
}
}

View File

@ -0,0 +1,132 @@
using HPlusSports.Models;
using System;
using System.Data.Entity.Validation;
using System.Linq;
using System.Web.Mvc;
namespace HPlusSports.Controllers
{
public class CartController : Controller
{
private readonly HPlusSportsDbContext _context;
public CartController()
: this(new HPlusSportsDbContext())
{
}
public CartController(HPlusSportsDbContext context)
{
_context = context;
}
public ActionResult Index()
{
var cart = GetCart();
if (cart.Items.Any())
return View("Cart", cart);
return View("EmptyCart");
}
public ActionResult Add(string sku, int quantity = 1)
{
var product = _context.Products.FirstOrDefault(x => x.SKU == sku);
var cart = GetCart();
var item = cart.Items.FirstOrDefault(x => x.SKU == sku);
if (item == null)
{
item = new ShoppingCartItem
{
SKU = product?.SKU,
Name = product?.Name,
MSRP = (product?.MSRP).GetValueOrDefault(),
Price = (product?.Price).GetValueOrDefault(),
Quantity = quantity,
};
cart.Items.Add(item);
}
else
{
item.Quantity += quantity;
}
if (item.Quantity <= 0)
{
cart.Items.Remove(item);
}
try
{
_context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
var errors = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors);
foreach (var error in errors)
{
ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
}
if (!ModelState.IsValid)
{
return View();
}
TempData["SuccessMessage"] = $"Successfully added {item.Name} to the cart";
return RedirectToAction("Index", "Cart");
}
public ActionResult Remove(long id)
{
var cart = GetCart();
var item = cart.Items.FirstOrDefault(x => x.Id == id);
if (item == null)
{
ModelState.AddModelError("", "Missing or invalid cart item");
return View();
}
cart.Items.Remove(item);
_context.SaveChanges();
return RedirectToAction("Index", "Cart");
}
private ShoppingCart GetCart()
{
var userId = GetUserId(this);
var cart =
_context.ShoppingCarts
.Include("Items")
.FirstOrDefault(x => x.UserId == userId);
if (cart == null)
{
cart = new ShoppingCart { UserId = userId };
_context.ShoppingCarts.Add(cart);
_context.SaveChanges();
}
cart.Recalculate();
return cart;
}
// Overwriteable function for unit testing
internal Func<Controller, string> GetUserId =
(controller) => controller.User.Identity.Name;
}
}

View File

@ -0,0 +1,57 @@
using HPlusSports.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace HPlusSports.Controllers
{
[RoutePrefix("home/{name}")]
public class HomeController : Controller
{
private readonly HPlusSportsDbContext _context;
public HomeController()
: this(new HPlusSportsDbContext())
{
}
public HomeController(HPlusSportsDbContext context)
{
_context = context;
}
public ActionResult Index()
{
var categories =
(
from category in _context.Categories
let count = _context.Products.Count(x => x.CategoryId == category.Id)
select new { category, count }
).ToDictionary(x => x.category, x => x.count);
return View(categories);
}
[Route("about")]
public ActionResult About(string name)
{
ViewBag.Message = "Your application description page, " + name;
return View();
}
public ActionResult Broken(string error)
{
throw new Exception(error);
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}

View File

@ -0,0 +1,82 @@
using System.Linq;
using System.Web.Mvc;
using HPlusSports.Models;
namespace HPlusSports.Controllers
{
public class ImagesController : Controller
{
private readonly HPlusSportsDbContext _context;
public ImagesController()
: this(new HPlusSportsDbContext())
{
}
public ImagesController(HPlusSportsDbContext context)
{
_context = context;
}
// /images/category/{SKU}
// Redirects to the main image for a category
public ActionResult Category(string id)
{
var imageId =
_context.Categories
.Where(x => x.Key == id)
.Select(x => x.ImageId)
.FirstOrDefault();
return Image(imageId);
}
// /images/product/{SKU}
// Redirects to the main image for a product
public ActionResult Product(string id)
{
var imageId =
_context.Products
.Where(x => x.SKU == id)
.SelectMany(x => x.Images.Select(img => img.Id))
.FirstOrDefault();
return Image(imageId);
}
public ActionResult Image(long? id)
{
var image = _context.Images.FirstOrDefault(x => x.Id == id);
if (!string.IsNullOrWhiteSpace(image.Url))
{
return RedirectPermanent(image.Url);
}
if (image?.Content == null)
{
image = GetPlaceholderImage();
}
return File(image.Content, image.ContentType);
}
internal static volatile byte[] PlaceholderImageContent;
private Image GetPlaceholderImage()
{
if (PlaceholderImageContent == null)
{
var path = Server.MapPath("~/Content/placeholder.jpg");
PlaceholderImageContent = System.IO.File.ReadAllBytes(path);
}
return new Image
{
Content = PlaceholderImageContent,
ContentType = "image/jpeg"
};
}
}
}

View File

@ -0,0 +1,174 @@
using HPlusSports.Models;
using System;
using System.Linq;
using System.Web.Mvc;
namespace HPlusSports.Controllers
{
[Authorize(Roles = UserRoles.Admin)]
public class InventoryController : Controller
{
private HPlusSportsDbContext _context;
public InventoryController()
: this(new HPlusSportsDbContext())
{
}
public InventoryController(HPlusSportsDbContext context)
{
_context = context;
}
public ActionResult Index()
{
var products =
_context.Products
.OrderBy(x => x.CategoryId)
.ThenBy(x => x.Name);
return View(products);
}
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Product product)
{
if (!ModelState.IsValid)
{
return View();
}
product.LastUpdated = DateTime.UtcNow;
product.LastUpdatedUserId = GetUserId(this);
_context.Products.Add(product);
_context.SaveChanges();
TempData["SuccessMessage"] =
$"Successfully created \"{product.Name}\"";
return RedirectToAction(nameof(Index));
}
[HttpGet]
public ActionResult Update(long id)
{
var existing = _context.Products.Find(id);
if (existing == null)
{
return ProductListError(
$"Couldn't update product #\"{id}\": product not found!"
);
}
return View(existing);
}
[HttpPost]
public ActionResult Update(long id, Product product)
{
if (!ModelState.IsValid)
{
return View();
}
var existing = _context.Products.Find(id);
if (existing == null)
{
return ProductListError(
$"Couldn't update product #\"{id}\": product not found!"
);
}
var hasPriceChanged = existing.Price != product.Price;
existing.CategoryId = product.CategoryId;
existing.Description = product.Description;
existing.MSRP = product.MSRP;
existing.Name = product.Name;
existing.Price = product.Price;
existing.SKU = product.SKU;
existing.Summary = product.Summary;
existing.LastUpdated = DateTime.UtcNow;
existing.LastUpdatedUserId = GetUserId(this);
_context.SaveChanges();
if (hasPriceChanged)
{
var cartsToUpdate =
_context.ShoppingCarts
.Include("Items")
.Where(cart => cart.Items.Any(x => x.SKU == product.SKU));
foreach (var cart in cartsToUpdate)
{
foreach (var cartItem in cart.Items.Where(x => x.SKU == product.SKU))
{
cartItem.Price = product.Price;
}
cart.Recalculate();
}
}
_context.SaveChanges();
TempData["SuccessMessage"] =
$"Successfully updated \"{product.Name}\"";
return RedirectToAction(nameof(Index));
}
public ActionResult Delete(long id)
{
var product = _context.Products.Find(id);
if (product == null)
{
return ProductListError(
$"Couldn't delete \"{product.Name}\": product not found!"
);
}
_context.Products.Remove(product);
_context.SaveChanges();
TempData["SuccessMessage"] =
$"Successfully deleted \"{product.Name}\"";
return RedirectToAction(nameof(Index));
}
private ActionResult ProductListError(string error)
{
TempData["ErrorMessage"] = error;
return RedirectToAction(nameof(Index));
}
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewData["CategoryId"] =
_context.Categories
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString(),
})
.ToArray();
}
// Overwriteable function for unit testing
internal Func<Controller, string> GetUserId =
(controller) => controller.User.Identity.Name;
}
}

View File

@ -0,0 +1,100 @@
using System.Linq;
using System.Web.Mvc;
using HPlusSports.Models;
namespace HPlusSports.Controllers
{
public class ProductsController : Controller
{
public const int DefaultPageSize = 8;
private readonly HPlusSportsDbContext _context;
public ProductsController(HPlusSportsDbContext context)
{
_context = context;
}
public ActionResult Index(int? page = null, int? count = null)
{
return Category(null, page, count);
}
public ActionResult Category(string id, int? page = null, int? count = null)
{
var category = _context.Categories.FirstOrDefault(x => x.Key == id);
IQueryable<Product> products = _context.Products;
if (category == null)
{
products =
products
.OrderBy(x => x.CategoryId)
.ThenBy(x => x.Name);
}
else
{
products =
products
.Where(x => x.CategoryId == category.Id)
.OrderBy(x => x.Name);
}
var skus = products.Select(x => x.SKU);
var ratings = _context.GetProductRatings(skus);
ViewData["Ratings"] = ratings;
ViewData["Category"] = category ?? new Category { Name = "All Categories" };
/**** Paging Logic ****/
var model = products;
var resultsCount = model.Count();
var pageSize = count.GetValueOrDefault(DefaultPageSize);
var currentPage = page.GetValueOrDefault(1);
var pageCount = resultsCount / pageSize + (resultsCount % pageSize > 0 ? 1 : 0);
var previousPage = (currentPage - 1 > 0) ? currentPage - 1 : (int?)null;
var nextPage = (currentPage + 1 <= pageCount) ? currentPage + 1 : (int?)null;
model = model
.Skip((currentPage - 1) * pageSize)
.Take(pageSize);
ViewData["PageSize"] = pageSize;
ViewData["ResultsCount"] = resultsCount;
ViewData["CurrentPage"] = currentPage;
ViewData["PageCount"] = pageCount;
ViewData["PreviousPage"] = previousPage;
ViewData["NextPage"] = nextPage;
/**** End Paging Logic ****/
if (Request.IsAjaxRequest())
{
return PartialView("ProductList", model);
}
return View("ProductList", model);
}
public ActionResult Product(string id)
{
var product = _context.FindProductBySku(id);
if (product == null)
return HttpNotFound();
var imageIds =
product
.Images
.Select(img => img.Id)
.ToArray();
ViewData["Rating"] = _context.GetProductRating(product.SKU);
ViewData["Category"] = product.Category;
ViewData["Images"] = imageIds;
return View(product);
}
}
}