From 0b5dde065a501c95251c92eba1b75f93d74a0bc4 Mon Sep 17 00:00:00 2001 From: James Kolpack Date: Fri, 23 Sep 2016 15:12:46 -0400 Subject: [PATCH] Add user management --- .../Controllers/ProfileController.cs | 1 + .../Controllers/UserController.cs | 94 +++++++++++ .../Helpers/AngularModelHelper.cs | 3 + .../InventoryTraker.Web.csproj | 15 +- InventoryTraker.Web/Models/UserCreateForm.cs | 31 ++++ InventoryTraker.Web/Models/UserEditForm.cs | 29 ++++ InventoryTraker.Web/Models/UserViewModel.cs | 24 +++ .../Views/Inventory/Index.cshtml | 2 +- .../Views/InventoryType/Index.cshtml | 4 +- .../Views/Shared/_Navigation.cshtml | 29 ++-- InventoryTraker.Web/Views/User/Index.cshtml | 16 ++ .../js/authentication/LoginController.js | 46 +++--- .../js/inventory/InventoryAddDirective.js | 17 +- .../inventory/InventoryDistributeDirective.js | 17 +- .../js/inventory/InventoryEditDirective.js | 23 ++- .../js/inventory/InventoryListController.js | 46 +++--- .../js/inventory/InventoryListDirective.js | 18 +- .../js/inventory/inventoryInfoDirective.js | 19 +-- .../js/inventory/inventoryRemoveDirective.js | 19 +-- .../js/inventory/inventorySvc.js | 154 +++++++++--------- .../InventoryTypeAddDirective.js | 18 +- .../inventoryType/InventoryTypeController.js | 41 ++--- .../InventoryTypeEditDirective.js | 24 ++- .../InventoryTypeListDirective.js | 24 ++- .../js/inventoryType/inventoryTypeSvc.js | 68 ++++---- .../js/profile/EditProfileController.js | 44 +++-- .../js/report/DistributionReportController.js | 24 ++- .../js/report/DistributionReportDirective.js | 19 +-- .../js/report/MovementReportController.js | 22 ++- .../js/report/MovementReportDirective.js | 19 +-- InventoryTraker.Web/js/report/reportSvc.js | 72 ++++---- .../js/transaction/TransactionController.js | 141 ++++++++-------- .../js/transaction/transactionSvc.js | 56 +++---- InventoryTraker.Web/js/user/UserController.js | 29 ++++ .../js/user/UserCreateDirective.js | 37 +++++ .../js/user/UserEditDirective.js | 42 +++++ .../js/user/UserListDirective.js | 27 +++ .../js/user/templates/userCreate.tmpl.cshtml | 27 +++ .../js/user/templates/userEdit.tmpl.cshtml | 27 +++ .../js/user/templates/userList.tmpl.cshtml | 16 ++ InventoryTraker.Web/js/user/userSvc.js | 42 +++++ .../js/utility/DateRangeQueryDirective.js | 1 - .../js/utility/DownloadService.js | 24 ++- InventoryTraker.Web/js/utility/ErrorList.js | 25 ++- .../utility/FormGroupValidationDirective.js | 42 +++-- InventoryTraker.Web/js/utility/FormatCases.js | 17 +- .../js/utility/HideZeroFilter.js | 13 +- .../utility/InputValidationIconsDirective.js | 38 ++--- .../js/utility/MonthQueryDirective.js | 47 +++--- .../js/utility/MvcGridDirective.js | 46 ------ .../js/utility/ParseDateFilter.js | 15 +- .../js/utility/StatusMessage.js | 25 ++- InventoryTraker.Web/js/utility/ToUnits.js | 17 +- 53 files changed, 1046 insertions(+), 690 deletions(-) create mode 100644 InventoryTraker.Web/Controllers/UserController.cs create mode 100644 InventoryTraker.Web/Models/UserCreateForm.cs create mode 100644 InventoryTraker.Web/Models/UserEditForm.cs create mode 100644 InventoryTraker.Web/Models/UserViewModel.cs create mode 100644 InventoryTraker.Web/Views/User/Index.cshtml create mode 100644 InventoryTraker.Web/js/user/UserController.js create mode 100644 InventoryTraker.Web/js/user/UserCreateDirective.js create mode 100644 InventoryTraker.Web/js/user/UserEditDirective.js create mode 100644 InventoryTraker.Web/js/user/UserListDirective.js create mode 100644 InventoryTraker.Web/js/user/templates/userCreate.tmpl.cshtml create mode 100644 InventoryTraker.Web/js/user/templates/userEdit.tmpl.cshtml create mode 100644 InventoryTraker.Web/js/user/templates/userList.tmpl.cshtml create mode 100644 InventoryTraker.Web/js/user/userSvc.js delete mode 100644 InventoryTraker.Web/js/utility/MvcGridDirective.js diff --git a/InventoryTraker.Web/Controllers/ProfileController.cs b/InventoryTraker.Web/Controllers/ProfileController.cs index 491ec70..1257acd 100644 --- a/InventoryTraker.Web/Controllers/ProfileController.cs +++ b/InventoryTraker.Web/Controllers/ProfileController.cs @@ -1,5 +1,6 @@ using System.Web.Mvc; using AutoMapper; +using InventoryTraker.Web.Core; using InventoryTraker.Web.Identity; using InventoryTraker.Web.Models; using Microsoft.AspNet.Identity; diff --git a/InventoryTraker.Web/Controllers/UserController.cs b/InventoryTraker.Web/Controllers/UserController.cs new file mode 100644 index 0000000..629d1c6 --- /dev/null +++ b/InventoryTraker.Web/Controllers/UserController.cs @@ -0,0 +1,94 @@ +using System.Linq; +using System.Threading.Tasks; +using System.Web.Mvc; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using InventoryTraker.Web.Attributes; +using InventoryTraker.Web.Core; +using InventoryTraker.Web.Identity; +using InventoryTraker.Web.Models; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security.DataProtection; + +namespace InventoryTraker.Web.Controllers +{ + public class UserController : ControllerBase + { + private readonly ApplicationUserManager _userManager; + + public UserController(ApplicationUserManager userManager) + { + _userManager = userManager; + } + + public ActionResult Index() + { + return View(); + } + + public JsonResult All() + { + var users = + _userManager + .Users + .ProjectTo() + .OrderBy(u => u.UserName); + + return BetterJson(users); + } + + [ActionLog] + [HttpPost] + public async Task Create(UserEditForm form) + { + if (!ModelState.IsValid) + return GetModelStateErrorListJson(); + + var user = + new User + { + Email = form.Email, + UserName = form.UserName + }; + + var identityResult = await _userManager.CreateAsync(user, form.Password); + + if (!identityResult.Succeeded) + return GetErrorListJson(identityResult.Errors.ToArray()); + + return BetterJson(Mapper.Map(user)); + } + + [ActionLog] + [HttpPost] + public async Task Edit(UserEditForm form) + { + if (!ModelState.IsValid) + return GetModelStateErrorListJson(); + + var user = _userManager.FindByEmail(form.Email); + + user.UserName = form.UserName; + user.Email = form.Email; + + if (!string.IsNullOrEmpty(form.Password)) + { + var provider = new DpapiDataProtectionProvider("Inventory Traker"); + _userManager.UserTokenProvider = new DataProtectorTokenProvider( + provider.Create("EmailConfirmation")); + var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user.Id); + var resetResult = await _userManager.ResetPasswordAsync(user.Id, resetToken, form.Password); + if (!resetResult.Succeeded) + return GetErrorListJson(resetResult.Errors.ToArray()); + } + + var identityResult = _userManager.Update(user); + + if (!identityResult.Succeeded) + return GetErrorListJson(identityResult.Errors.ToArray()); + + return BetterJson(Mapper.Map(user)); + } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Helpers/AngularModelHelper.cs b/InventoryTraker.Web/Helpers/AngularModelHelper.cs index c27277d..7a86f97 100644 --- a/InventoryTraker.Web/Helpers/AngularModelHelper.cs +++ b/InventoryTraker.Web/Helpers/AngularModelHelper.cs @@ -119,6 +119,9 @@ namespace InventoryTraker.Web.Helpers if (metadata.DataTypeName == "EmailAddress") input.Attr("type", "email"); + if (metadata.DataTypeName == "Password") + input.Attr("type", "password"); + if (metadata.ModelType == typeof(DateTime)) { //input.Attr("type", "date"); diff --git a/InventoryTraker.Web/InventoryTraker.Web.csproj b/InventoryTraker.Web/InventoryTraker.Web.csproj index ff03f21..605ee7f 100644 --- a/InventoryTraker.Web/InventoryTraker.Web.csproj +++ b/InventoryTraker.Web/InventoryTraker.Web.csproj @@ -232,6 +232,11 @@ + + + + + @@ -263,7 +268,6 @@ - @@ -310,6 +314,9 @@ + + + Designer @@ -335,6 +342,7 @@ + @@ -370,6 +378,9 @@ 201609201242047_Initial.cs + + + @@ -418,6 +429,7 @@ + Web.config @@ -430,6 +442,7 @@ 201609201242047_Initial.cs + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/InventoryTraker.Web/Models/UserCreateForm.cs b/InventoryTraker.Web/Models/UserCreateForm.cs new file mode 100644 index 0000000..1d255cc --- /dev/null +++ b/InventoryTraker.Web/Models/UserCreateForm.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; + +namespace InventoryTraker.Web.Models +{ + public class UserCreateForm + { + [Required] + [StringLength(128)] + [RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Need complete name")] + public string UserName { get; set; } + + [Required] + [DataType(DataType.EmailAddress)] + [RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}", ErrorMessage = "Must be an email address")] + public string Email { get; set; } + + [Required] + [DataType(DataType.Password)] + public string Password { get; set; } + + [Required(ErrorMessage = "Confirm Password is required")] + [DataType(DataType.Password)] + [Compare("Password")] + public string ConfirmPassword { get; set; } + + public override string ToString() + { + return $"UserName: {UserName}, email: {Email}"; + } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Models/UserEditForm.cs b/InventoryTraker.Web/Models/UserEditForm.cs new file mode 100644 index 0000000..73e3223 --- /dev/null +++ b/InventoryTraker.Web/Models/UserEditForm.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; + +namespace InventoryTraker.Web.Models +{ + public class UserEditForm + { + [Required] + [StringLength(128)] + [RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Need complete name")] + public string UserName { get; set; } + + [Required] + [DataType(DataType.EmailAddress)] + [RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}", ErrorMessage = "Must be an email address")] + public string Email { get; set; } + + [DataType(DataType.Password)] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Compare("Password")] + public string ConfirmPassword { get; set; } + + public override string ToString() + { + return $"UserName: {UserName}, email: {Email}"; + } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Models/UserViewModel.cs b/InventoryTraker.Web/Models/UserViewModel.cs new file mode 100644 index 0000000..025697d --- /dev/null +++ b/InventoryTraker.Web/Models/UserViewModel.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using Heroic.AutoMapper; +using InventoryTraker.Web.Core; + +namespace InventoryTraker.Web.Models +{ + public class UserViewModel : IMapFrom + { + [Required] + [StringLength(128)] + [RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Need complete name")] + public string UserName { get; set; } + + [Required] + [DataType(DataType.EmailAddress)] + [RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}", ErrorMessage = "Must be an email address")] + public string Email { get; set; } + + public override string ToString() + { + return $"UserName: {UserName}, email: {Email}"; + } + } +} \ No newline at end of file diff --git a/InventoryTraker.Web/Views/Inventory/Index.cshtml b/InventoryTraker.Web/Views/Inventory/Index.cshtml index e603bbd..2a032ec 100644 --- a/InventoryTraker.Web/Views/Inventory/Index.cshtml +++ b/InventoryTraker.Web/Views/Inventory/Index.cshtml @@ -4,7 +4,7 @@

- Inventory + @ViewBag.Title

Current inventory

diff --git a/InventoryTraker.Web/Views/InventoryType/Index.cshtml b/InventoryTraker.Web/Views/InventoryType/Index.cshtml index 1f9e0cd..d7ac58a 100644 --- a/InventoryTraker.Web/Views/InventoryType/Index.cshtml +++ b/InventoryTraker.Web/Views/InventoryType/Index.cshtml @@ -1,12 +1,12 @@ @model dynamic @{ - ViewBag.Title = "Inventory"; + ViewBag.Title = "Commodity Types"; }

- Commodity Types + @ViewBag.Title

Add diff --git a/InventoryTraker.Web/Views/Shared/_Navigation.cshtml b/InventoryTraker.Web/Views/Shared/_Navigation.cshtml index f27d29f..a27efb4 100644 --- a/InventoryTraker.Web/Views/Shared/_Navigation.cshtml +++ b/InventoryTraker.Web/Views/Shared/_Navigation.cshtml @@ -10,19 +10,22 @@ Inventory Traker
- +