diff --git a/SportsStore.Domain/Concrete/EFProductRepository.cs b/SportsStore.Domain/Concrete/EFProductRepository.cs index 273d9f5..6866e4a 100644 --- a/SportsStore.Domain/Concrete/EFProductRepository.cs +++ b/SportsStore.Domain/Concrete/EFProductRepository.cs @@ -31,6 +31,8 @@ namespace SportsStore.Domain.Concrete dbEntry.Description = product.Description; dbEntry.Price = product.Price; dbEntry.Category = product.Category; + dbEntry.ImageData = product.ImageData; + dbEntry.ImageMimeType = product.ImageMimeType; } } diff --git a/SportsStore.Domain/Entities/Product.cs b/SportsStore.Domain/Entities/Product.cs index 1f30bb3..ff360ef 100644 --- a/SportsStore.Domain/Entities/Product.cs +++ b/SportsStore.Domain/Entities/Product.cs @@ -25,5 +25,8 @@ namespace SportsStore.Domain.Entities [Required(ErrorMessage = "Please specify a category")] public string Category { get; set; } + + public byte[] ImageData { get; set; } + public string ImageMimeType { get; set; } } } \ No newline at end of file diff --git a/SportsStore.WebUI/Controllers/AccountController.cs b/SportsStore.WebUI/Controllers/AccountController.cs new file mode 100644 index 0000000..6648664 --- /dev/null +++ b/SportsStore.WebUI/Controllers/AccountController.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Mvc; +using SportsStore.WebUI.Infrastructure.Abstract; +using SportsStore.WebUI.Models; + +namespace SportsStore.WebUI.Controllers +{ + public class AccountController : Controller + { + IAuthProvider authProvider; + + public AccountController(IAuthProvider auth) + { + authProvider = auth; + } + + public ViewResult Login() + { + return View(); + } + + [HttpPost] + public ActionResult Login(LoginViewModel model, string returnUrl) + { + if (ModelState.IsValid) + { + if (authProvider.Authenticate(model.UserName, model.Password)) + { + return Redirect(returnUrl ?? Url.Action("Index", "Admin")); + } + else + { + ModelState.AddModelError("", "Incorrect username or password"); + return View(); + } + } + else + { + return View(); + } + } + } +} \ No newline at end of file diff --git a/SportsStore.WebUI/Controllers/AdminController.cs b/SportsStore.WebUI/Controllers/AdminController.cs index c7b00fd..227a717 100644 --- a/SportsStore.WebUI/Controllers/AdminController.cs +++ b/SportsStore.WebUI/Controllers/AdminController.cs @@ -8,6 +8,7 @@ using SportsStore.Domain.Entities; namespace SportsStore.WebUI.Controllers { + [Authorize] public class AdminController : Controller { private IProductRepository repository; @@ -30,10 +31,16 @@ namespace SportsStore.WebUI.Controllers } [HttpPost] - public ActionResult Edit(Product product) + public ActionResult Edit(Product product, HttpPostedFileBase image = null) { if (ModelState.IsValid) { + if (image != null) + { + product.ImageMimeType = image.ContentType; + product.ImageData = new byte[image.ContentLength]; + image.InputStream.Read(product.ImageData, 0, image.ContentLength); + } repository.SaveProduct(product); TempData["message"] = string.Format("{0} has been saved", product.Name); return RedirectToAction("Index"); diff --git a/SportsStore.WebUI/Controllers/ProductController.cs b/SportsStore.WebUI/Controllers/ProductController.cs index e443367..d7736d8 100644 --- a/SportsStore.WebUI/Controllers/ProductController.cs +++ b/SportsStore.WebUI/Controllers/ProductController.cs @@ -53,5 +53,17 @@ namespace SportsStore.WebUI.Controllers return View(model); } + public FileContentResult GetImage(int productId) + { + Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId); + if (prod != null) + { + return File(prod.ImageData, prod.ImageMimeType); + } + else + { + return null; + } + } } } \ No newline at end of file diff --git a/SportsStore.WebUI/Infrastructure/Abstract/IAuthProvider.cs b/SportsStore.WebUI/Infrastructure/Abstract/IAuthProvider.cs new file mode 100644 index 0000000..d6bebab --- /dev/null +++ b/SportsStore.WebUI/Infrastructure/Abstract/IAuthProvider.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SportsStore.WebUI.Infrastructure.Abstract; + +namespace SportsStore.WebUI.Infrastructure.Abstract +{ + public interface IAuthProvider + { + bool Authenticate(string username, string password); + } +} diff --git a/SportsStore.WebUI/Infrastructure/Concrete/FormsAuthProvider.cs b/SportsStore.WebUI/Infrastructure/Concrete/FormsAuthProvider.cs new file mode 100644 index 0000000..c8ad01a --- /dev/null +++ b/SportsStore.WebUI/Infrastructure/Concrete/FormsAuthProvider.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Security; +using SportsStore.WebUI.Infrastructure.Abstract; + +namespace SportsStore.WebUI.Infrastructure.Concrete +{ + public class FormsAuthProvider : IAuthProvider + { + public bool Authenticate(string username, string password) + { + bool result = FormsAuthentication.Authenticate(username, password); + if (result) + { + FormsAuthentication.SetAuthCookie(username, false); + } + + return result; + } + } +} \ No newline at end of file diff --git a/SportsStore.WebUI/Infrastructure/NinjectDependencyResolver.cs b/SportsStore.WebUI/Infrastructure/NinjectDependencyResolver.cs index cfa17aa..401d728 100644 --- a/SportsStore.WebUI/Infrastructure/NinjectDependencyResolver.cs +++ b/SportsStore.WebUI/Infrastructure/NinjectDependencyResolver.cs @@ -9,6 +9,8 @@ using Ninject; using SportsStore.Domain.Abstract; using SportsStore.Domain.Concrete; using SportsStore.Domain.Entities; +using SportsStore.WebUI.Infrastructure.Abstract; +using SportsStore.WebUI.Infrastructure.Concrete; namespace SportsStore.WebUI.Infrastructure { @@ -51,7 +53,7 @@ namespace SportsStore.WebUI.Infrastructure kernel.Bind().To().WithConstructorArgument("settings", emailSettings); - + kernel.Bind().To(); } } } \ No newline at end of file diff --git a/SportsStore.WebUI/Models/LoginViewModel.cs b/SportsStore.WebUI/Models/LoginViewModel.cs new file mode 100644 index 0000000..703562d --- /dev/null +++ b/SportsStore.WebUI/Models/LoginViewModel.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.ComponentModel.DataAnnotations; + +namespace SportsStore.WebUI.Models +{ + public class LoginViewModel + { + [Required] + public string UserName { get; set; } + + [Required] + public string Password { get; set; } + } +} \ No newline at end of file diff --git a/SportsStore.WebUI/SportsStore.WebUI.csproj b/SportsStore.WebUI/SportsStore.WebUI.csproj index b6688f3..7e648c5 100644 --- a/SportsStore.WebUI/SportsStore.WebUI.csproj +++ b/SportsStore.WebUI/SportsStore.WebUI.csproj @@ -141,6 +141,7 @@ + @@ -149,9 +150,12 @@ Global.asax + + + @@ -177,6 +181,7 @@ + Web.config diff --git a/SportsStore.WebUI/Views/Account/Login.cshtml b/SportsStore.WebUI/Views/Account/Login.cshtml new file mode 100644 index 0000000..3f6d7b5 --- /dev/null +++ b/SportsStore.WebUI/Views/Account/Login.cshtml @@ -0,0 +1,27 @@ +@model SportsStore.WebUI.Models.LoginViewModel +@{ + ViewBag.Title = "Admin: Log in"; + Layout = "~/Views/Shared/_AdminLayout.cshtml"; +} + +
+
+

Log in

+
+
+

Please log in to access the administration area:

+ @using (Html.BeginForm()) + { + @Html.ValidationSummary() +
+ + @Html.TextBoxFor(m => m.UserName, new { @class = "form-control"}) +
+
+ + @Html.PasswordFor(m => m.Password, new { @class = "form-control"}) +
+ + } +
+
\ No newline at end of file diff --git a/SportsStore.WebUI/Views/Admin/Edit.cshtml b/SportsStore.WebUI/Views/Admin/Edit.cshtml index e005e49..d477dd6 100644 --- a/SportsStore.WebUI/Views/Admin/Edit.cshtml +++ b/SportsStore.WebUI/Views/Admin/Edit.cshtml @@ -18,28 +18,58 @@

Edit @Model.Name

- @using (Html.BeginForm("Edit", "Admin")) + @using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) {
@Html.HiddenFor(m => m.ProductID) @foreach (var property in ViewData.ModelMetadata.Properties) { - if (property.PropertyName != "ProeuctID") + switch (property.PropertyName) { -
- - @if (property.PropertyName == "Description") + case "ProductID": + case "ImageData": + case "ImageMimeType": + break; + default: + if (property.PropertyName != "ProeuctID") { - @Html.TextArea(property.PropertyName, null, new { @class = "form-control", rows = 5 }) +
+ + @if (property.PropertyName == "Description") + { + @Html.TextArea(property.PropertyName, null, new { @class = "form-control", rows = 5 }) + } + else + { + @Html.TextBox(property.PropertyName, null, new { @class = "form-control" }) + } + @Html.ValidationMessage(property.PropertyName) +
} - else - { - @Html.TextBox(property.PropertyName, null, new { @class = "form-control" }) - } - @Html.ValidationMessage(property.PropertyName) -
+ break; } + } +
+ + @if (Model.ImageData == null) + { +
No Image
+ } + else + { + + } +