mirror of
https://github.com/rudollee/LearningMVC.git
synced 2025-06-06 15:36:11 +00:00
Ch. 12 SportsStore Security and Finish
This commit is contained in:
parent
7841e9077e
commit
933829c866
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
46
SportsStore.WebUI/Controllers/AccountController.cs
Normal file
46
SportsStore.WebUI/Controllers/AccountController.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
SportsStore.WebUI/Infrastructure/Abstract/IAuthProvider.cs
Normal file
14
SportsStore.WebUI/Infrastructure/Abstract/IAuthProvider.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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<IOrderProcessor>().To<EmailOrderProcessor>().WithConstructorArgument("settings", emailSettings);
|
||||
|
||||
|
||||
kernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
|
||||
}
|
||||
}
|
||||
}
|
17
SportsStore.WebUI/Models/LoginViewModel.cs
Normal file
17
SportsStore.WebUI/Models/LoginViewModel.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
@ -141,6 +141,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="App_Start\NinjectWebCommon.cs" />
|
||||
<Compile Include="App_Start\RouteConfig.cs" />
|
||||
<Compile Include="Controllers\AccountController.cs" />
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="Controllers\CartController.cs" />
|
||||
<Compile Include="Controllers\NavController.cs" />
|
||||
@ -149,9 +150,12 @@
|
||||
<DependentUpon>Global.asax</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="HtmlHelpers\PagingHelpers.cs" />
|
||||
<Compile Include="Infrastructure\Abstract\IAuthProvider.cs" />
|
||||
<Compile Include="Infrastructure\Binders\CartModelBinder.cs" />
|
||||
<Compile Include="Infrastructure\Concrete\FormsAuthProvider.cs" />
|
||||
<Compile Include="Infrastructure\NinjectDependencyResolver.cs" />
|
||||
<Compile Include="Models\CartIndexViewModel.cs" />
|
||||
<Compile Include="Models\LoginViewModel.cs" />
|
||||
<Compile Include="Models\PagingInfo.cs" />
|
||||
<Compile Include="Models\ProductsListViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@ -177,6 +181,7 @@
|
||||
<Content Include="Views\Shared\_AdminLayout.cshtml" />
|
||||
<Content Include="Views\Admin\Index.cshtml" />
|
||||
<Content Include="Views\Admin\Edit.cshtml" />
|
||||
<Content Include="Views\Account\Login.cshtml" />
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>Web.config</DependentUpon>
|
||||
</None>
|
||||
|
27
SportsStore.WebUI/Views/Account/Login.cshtml
Normal file
27
SportsStore.WebUI/Views/Account/Login.cshtml
Normal file
@ -0,0 +1,27 @@
|
||||
@model SportsStore.WebUI.Models.LoginViewModel
|
||||
@{
|
||||
ViewBag.Title = "Admin: Log in";
|
||||
Layout = "~/Views/Shared/_AdminLayout.cshtml";
|
||||
}
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<h3>Log in</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="lead">Please log in to access the administration area:</p>
|
||||
@using (Html.BeginForm())
|
||||
{
|
||||
@Html.ValidationSummary()
|
||||
<div class="form-group">
|
||||
<label>User Name:</label>
|
||||
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control"})
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password:</label>
|
||||
@Html.PasswordFor(m => m.Password, new { @class = "form-control"})
|
||||
</div>
|
||||
<input type="submit" value="Log in" class="btn btn-primary" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
@ -18,28 +18,58 @@
|
||||
<h3>Edit @Model.Name</h3>
|
||||
</div>
|
||||
|
||||
@using (Html.BeginForm("Edit", "Admin"))
|
||||
@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
|
||||
{
|
||||
<div class="panel-body">
|
||||
@Html.HiddenFor(m => m.ProductID)
|
||||
@foreach (var property in ViewData.ModelMetadata.Properties)
|
||||
{
|
||||
if (property.PropertyName != "ProeuctID")
|
||||
switch (property.PropertyName)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label>@(property.DisplayName ?? property.PropertyName)</label>
|
||||
@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 })
|
||||
<div class="form-group">
|
||||
<label>@(property.DisplayName ?? property.PropertyName)</label>
|
||||
@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)
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@Html.TextBox(property.PropertyName, null, new { @class = "form-control" })
|
||||
}
|
||||
@Html.ValidationMessage(property.PropertyName)
|
||||
</div>
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
<div class="form-group">
|
||||
<div style="position:relative;">
|
||||
<label>Image</label>
|
||||
<a class="btn" href="javascript:;">
|
||||
Choose File...
|
||||
<input type="file" name="Image" size="40"
|
||||
style="position:absolute; z-index:2; top: 0; left: 0; filter: alpha(opacity=0); opacity: 0; background-color: transparent; color: transparent;"
|
||||
onchange="$("#upload-file-info").html($(this).val());' />
|
||||
</a>
|
||||
<span class="label label-info" id="upload-file-info" />
|
||||
</div>
|
||||
@if (Model.ImageData == null)
|
||||
{
|
||||
<div class="form-control-static">No Image</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<img class="img-thumbnail" width="150" height="150" src="@Url.Action("GetImage", "Product", new { Model.ProductID })" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-footer">
|
||||
|
@ -1,6 +1,12 @@
|
||||
@model SportsStore.Domain.Entities.Product
|
||||
|
||||
<div class="well">
|
||||
@if (Model.ImageData != null)
|
||||
{
|
||||
<div class="pull-left" style="margin-right: 10px">
|
||||
<img class="img-thumbnail" width="75" height="75" src="@Url.Action("GetImage", "Product", new { Model.ProductID })" />
|
||||
</div>
|
||||
}
|
||||
<h3>
|
||||
<strong>@Model.Name</strong>
|
||||
<span class="pull-right label label-primary">@Model.Price</span>
|
||||
|
@ -22,6 +22,13 @@
|
||||
<compilation debug="true" targetFramework="4.5.2" />
|
||||
<httpRuntime targetFramework="4.5.2" />
|
||||
<globalization culture="en-US" uiCulture="en-US" />
|
||||
<authentication mode="Forms">
|
||||
<forms loginUrl="~/Account/Login" timeout="2880" >
|
||||
<credentials passwordFormat="Clear">
|
||||
<user name="admin" password="secret"/>
|
||||
</credentials>
|
||||
</forms>
|
||||
</authentication>
|
||||
</system.web>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
Loading…
x
Reference in New Issue
Block a user