Create User works

This commit is contained in:
2012-12-27 22:04:21 -05:00
parent 05d1ae4ec6
commit 7eff2f343a
32 changed files with 615 additions and 583 deletions
@@ -1,4 +1,4 @@
using MileageTraker.Web.Membership; using MileageTraker.Web.Utility;
using NUnit.Framework; using NUnit.Framework;
namespace Web.Tests.Membership namespace Web.Tests.Membership
@@ -12,14 +12,12 @@ namespace Web.Tests.ViewModels
var vm = new CreateUserViewModel(); var vm = new CreateUserViewModel();
var email = vm.Email = "bob@dobalina.com"; var email = vm.Email = "bob@dobalina.com";
var firstName = vm.FirstName = "bob"; var userName = vm.Username = "bob dobalina";
var lastName = vm.LastName = "dobalina";
var user = vm.CloneToUser(); var user = vm.ToUser();
Assert.That(user.Email, Is.EqualTo(email)); Assert.That(user.Email, Is.EqualTo(email));
Assert.That(user.FirstName, Is.EqualTo(firstName)); Assert.That(user.Username, Is.EqualTo(userName));
Assert.That(user.LastName, Is.EqualTo(lastName));
} }
} }
} }
+1 -1
View File
@@ -84,7 +84,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="DAL\VehicleImporterTests.cs" /> <Compile Include="DAL\VehicleImporterTests.cs" />
<Compile Include="Membership\CryptoTests.cs" /> <Compile Include="Utility\CryptoTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utility\AlgorithmsTests.cs" /> <Compile Include="Utility\AlgorithmsTests.cs" />
<Compile Include="Utility\CustomExtensionsTests.cs" /> <Compile Include="Utility\CustomExtensionsTests.cs" />
+4
View File
@@ -6,6 +6,10 @@
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>
+20
View File
@@ -0,0 +1,20 @@
using System.Web.Mvc;
using MileageTraker.Web.DAL;
namespace MileageTraker.Web.Attributes
{
public class UserActivityAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext != null)
{
using (var ds = new DataService())
{
ds.UpdateUserLastActivity(filterContext.HttpContext.User.Identity.Name);
}
}
base.OnActionExecuting(filterContext);
}
}
}
+44 -5
View File
@@ -3,6 +3,20 @@ body {
padding-top: 60px; padding-top: 60px;
} }
#content > form {
max-width: 400px;
padding: 10px;
margin: 0 auto 20px;
background-color: whitesmoke;
border: 1px solid #e5e5e5;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05);
box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
.brand .brand
{ {
background: url(images/Header.png) no-repeat left center; background: url(images/Header.png) no-repeat left center;
@@ -42,6 +56,23 @@ body {
margin: 0; margin: 0;
} }
.breadcrumb {
display: inline-block;
margin-bottom: 10px;
}
.form-horizontal .control-label {
width: 140px;
}
.form-horizontal .controls {
margin-left: 160px;
}
.form-horizontal .control-group {
margin-bottom: 10px;
}
footer { footer {
background-color: #101010; background-color: #101010;
color: #666; color: #666;
@@ -137,10 +168,17 @@ dl.inline {
padding: 0; padding: 0;
} }
.container-fluid { #content {
padding: 0 10px; padding: 0 10px;
} }
.navbar .container-fluid {
padding: 0 10px;
}
.navbar .brand {
}
.input-mini { .input-mini {
width: 60px !important; width: 60px !important;
} }
@@ -166,20 +204,21 @@ dl.inline {
padding: 0; padding: 0;
} }
.container-fluid { #content {
padding: 0 10px; padding: 0 10px;
} }
.brand { .brand {
background: url(images/Header.mobile.png) no-repeat left center; background: url(images/Header.mobile.png) no-repeat left center;
height: 28px; height: 28px;
width: 205px; width: 205px;
} }
.navbar .container-fluid {
padding: 0 10px;
}
.navbar .brand { .navbar .brand {
margin-left: 5px;
padding: 10px 0;
} }
fieldset legend { fieldset legend {
+37 -37
View File
@@ -1,7 +1,6 @@
using System; using System;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Security; using System.Web.Security;
using MileageTraker.Web.Membership;
using MileageTraker.Web.ViewModels.Account; using MileageTraker.Web.ViewModels.Account;
namespace MileageTraker.Web.Controllers namespace MileageTraker.Web.Controllers
@@ -21,11 +20,16 @@ namespace MileageTraker.Web.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl) public ActionResult Login(LoginViewModel model, string returnUrl)
{ {
if (ModelState.IsValid && WebSecurity.Login(model.EmailAddress, model.Password, model.RememberMe)) if (ModelState.IsValid)
{ {
var success = Membership.ValidateUser(model.Username, model.Password);
if (success)
{
FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
// TODO: send notification to user // TODO: send notification to user
return RedirectToLocal(returnUrl); return RedirectToLocal(returnUrl);
} }
}
// If we got this far, something failed, redisplay form // If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect."); ModelState.AddModelError("", "The user name or password provided is incorrect.");
@@ -36,48 +40,47 @@ namespace MileageTraker.Web.Controllers
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken]
public ActionResult LogOff() public ActionResult LogOff()
{ {
WebSecurity.Logout(); FormsAuthentication.SignOut();
// TODO: send notification to user // TODO: send notification to user
return RedirectToAction("Index", "CreateLog"); return RedirectToAction("Index", "CreateLog");
} }
[AllowAnonymous] //[AllowAnonymous]
public ActionResult Register() //public ActionResult Register()
{ //{
return View(); // return View();
} //}
[HttpPost] //[HttpPost]
[AllowAnonymous] //[AllowAnonymous]
[ValidateAntiForgeryToken] //[ValidateAntiForgeryToken]
public ActionResult Register(RegisterModel model) //public ActionResult Register(RegisterModel model)
{ //{
if (ModelState.IsValid) // if (ModelState.IsValid)
{ // {
// Attempt to register the user // // Attempt to register the user
try // try
{ // {
WebSecurity.CreateUserAndAccount(model.UserName, model.Password); // WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
WebSecurity.Login(model.UserName, model.Password); // WebSecurity.Login(model.UserName, model.Password);
return RedirectToAction("Login"); // return RedirectToAction("Login");
} // }
catch (MembershipCreateUserException e) // catch (MembershipCreateUserException e)
{ // {
ModelState.AddModelError("", ErrorCodeToString(e.StatusCode)); // ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
} // }
} // }
// If we got this far, something failed, redisplay form // // If we got this far, something failed, redisplay form
return View(model); // return View(model);
} //}
public ActionResult Manage(ManageMessageId? message) public ActionResult Manage(ManageMessageId? message)
{ {
ViewBag.StatusMessage = ViewBag.StatusMessage =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
: ""; : "";
ViewBag.ReturnUrl = Url.Action("Manage"); ViewBag.ReturnUrl = Url.Action("Manage");
return View(); return View();
@@ -95,9 +98,10 @@ namespace MileageTraker.Web.Controllers
bool changePasswordSucceeded; bool changePasswordSucceeded;
try try
{ {
changePasswordSucceeded = WebSecurity.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword); var currentUser = Membership.GetUser(User.Identity.Name, true);
changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
} }
catch (Exception ex) catch (Exception)
{ {
changePasswordSucceeded = false; changePasswordSucceeded = false;
} }
@@ -106,11 +110,8 @@ namespace MileageTraker.Web.Controllers
{ {
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess }); return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
} }
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid."); ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
} }
}
// If we got this far, something failed, redisplay form // If we got this far, something failed, redisplay form
return View(model); return View(model);
@@ -129,7 +130,6 @@ namespace MileageTraker.Web.Controllers
{ {
ChangePasswordSuccess, ChangePasswordSuccess,
SetPasswordSuccess, SetPasswordSuccess,
RemoveLoginSuccess,
} }
private static string ErrorCodeToString(MembershipCreateStatus createStatus) private static string ErrorCodeToString(MembershipCreateStatus createStatus)
+85 -13
View File
@@ -1,14 +1,15 @@
using System; using System;
using System.Data;
using System.Linq; using System.Linq;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Security;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.Models; using MileageTraker.Web.Models;
using MileageTraker.Web.Context;
using MileageTraker.Web.ViewModels.User; using MileageTraker.Web.ViewModels.User;
namespace MileageTraker.Web.Controllers namespace MileageTraker.Web.Controllers
{ {
[Authorize(Roles = "Administrator, Developer")] [Authorize(Roles = "Administrator, Developer")]
[UserActivity]
public class UserController : ControllerBase public class UserController : ControllerBase
{ {
public ActionResult Index() public ActionResult Index()
@@ -18,32 +19,66 @@ namespace MileageTraker.Web.Controllers
public ActionResult Details(Guid id) public ActionResult Details(Guid id)
{ {
var user = DataService.GetUser(id); var user = Membership.GetUser(id);
if (user == null) if (user == null)
{ {
return HttpNotFound(); return HttpNotFound();
} }
return View(user); return View(DataService.GetUser(id));
} }
public ActionResult Create() public ActionResult Create()
{ {
return View(); var vm = new CreateUserViewModel
{
AvailableRoles = Roles.GetAllRoles()
};
return View(vm);
} }
[HttpPost] [HttpPost]
public ActionResult Create(CreateUserViewModel createUserViewModel) public ActionResult Create(CreateUserViewModel viewModel)
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
var user = createUserViewModel.CloneToUser(); var hasRoles = viewModel.Roles != null && viewModel.Roles.Any();
user.UserId = Guid.NewGuid();
//db.Users.Add(user); MembershipCreateStatus membershipCreateStatus;
//db.SaveChanges(); var membershipUser =
Membership.CreateUser(
viewModel.Username,
viewModel.Password,
viewModel.Email,
null,
null,
hasRoles,
out membershipCreateStatus);
if (membershipUser == null)
{
ModelState.AddModelError("", ErrorCodeToString(membershipCreateStatus));
viewModel.AvailableRoles = Roles.GetAllRoles();
return View(viewModel);
}
if (hasRoles)
{
Roles.AddUserToRoles(
membershipUser.UserName,
viewModel.Roles);
}
var user = DataService.GetUser(
(Guid) membershipUser.ProviderUserKey);
user.FullName = viewModel.FullName;
DataService.UpdateUserPersonalInfo(user);
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
return View(createUserViewModel); viewModel.AvailableRoles = Roles.GetAllRoles();
return View(viewModel);
} }
public ActionResult Edit(Guid id) public ActionResult Edit(Guid id)
@@ -61,11 +96,48 @@ namespace MileageTraker.Web.Controllers
{ {
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
//db.Entry(user).State = EntityState.Modified; DataService.UpdateUser(user);
//db.SaveChanges();
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
return View(user); return View(user);
} }
private static string ErrorCodeToString(MembershipCreateStatus createStatus)
{
// See http://go.microsoft.com/fwlink/?LinkID=177550 for
// a full list of status codes.
switch (createStatus)
{
case MembershipCreateStatus.DuplicateUserName:
return "User name already exists. Please enter a different user name.";
case MembershipCreateStatus.DuplicateEmail:
return "A user name for that e-mail address already exists. Please enter a different e-mail address.";
case MembershipCreateStatus.InvalidPassword:
return "The password provided is invalid. Please enter a valid password value.";
case MembershipCreateStatus.InvalidEmail:
return "The e-mail address provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidAnswer:
return "The password retrieval answer provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidQuestion:
return "The password retrieval question provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.InvalidUserName:
return "The user name provided is invalid. Please check the value and try again.";
case MembershipCreateStatus.ProviderError:
return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
case MembershipCreateStatus.UserRejected:
return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
default:
return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
}
}
} }
} }
@@ -1,21 +1,15 @@
using System; using System;
using System.Data.SqlTypes;
using System.Linq; using System.Linq;
using System.Security.Cryptography;
using System.Web;
using System.Web.Security; using System.Web.Security;
using MileageTraker.Web.Context;
using MileageTraker.Web.Models; using MileageTraker.Web.Models;
using MileageTraker.Web.Utility; using MileageTraker.Web.Utility;
namespace MileageTraker.Web.Membership namespace MileageTraker.Web.DAL
{ {
public class CodeFirstMembershipProvider : MembershipProvider public class CodeFirstMembershipProvider : MembershipProvider
{ {
#region Properties #region Properties
private const int TokenSizeInBytes = 16;
public override string ApplicationName public override string ApplicationName
{ {
get { return GetType().Assembly.GetName().Name; } get { return GetType().Assembly.GetName().Name; }
@@ -92,15 +86,15 @@ namespace MileageTraker.Web.Membership
return null; return null;
} }
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
if (context.Users.Any(usr => usr.Username == username)) if (context.FindUserByUsername(username) != null)
{ {
status = MembershipCreateStatus.DuplicateUserName; status = MembershipCreateStatus.DuplicateUserName;
return null; return null;
} }
if (context.Users.Any(usr => usr.Email == email)) if (context.FindUserByUsername(email) != null)
{ {
status = MembershipCreateStatus.DuplicateEmail; status = MembershipCreateStatus.DuplicateEmail;
return null; return null;
@@ -113,28 +107,16 @@ namespace MileageTraker.Web.Membership
Password = hashedPassword, Password = hashedPassword,
IsApproved = isApproved, IsApproved = isApproved,
Email = email, Email = email,
CreateDate = DateTime.UtcNow, Created = DateTime.Now,
LastPasswordChangedDate = DateTime.UtcNow, FullName = "Temp Name"
PasswordFailuresSinceLastSuccess = 0,
LastLoginDate = DateTime.UtcNow,
LastActivityDate = DateTime.UtcNow,
LastLockoutDate = SqlDateTime.MinValue.Value,
IsLockedOut = false,
LastPasswordFailureDate = SqlDateTime.MinValue.Value
}; };
context.Users.Add(newUser); context.AddUser(newUser);
context.SaveChanges();
status = MembershipCreateStatus.Success; status = MembershipCreateStatus.Success;
return newUser.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name); return newUser.ToMembershipUser(Membership.Provider.Name);
} }
} }
public string CreateUserAndAccount(string userName, string password, bool requireConfirmation)
{
return CreateAccount(userName, password, requireConfirmation);
}
public override bool ValidateUser(string username, string password) public override bool ValidateUser(string username, string password)
{ {
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
@@ -145,9 +127,9 @@ namespace MileageTraker.Web.Membership
{ {
return false; return false;
} }
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
User user = context.Users.FirstOrDefault(usr => usr.Username == username); var user = context.FindUserByUsername(username);
if (user == null) if (user == null)
{ {
return false; return false;
@@ -165,8 +147,8 @@ namespace MileageTraker.Web.Membership
if (verificationSucceeded) if (verificationSucceeded)
{ {
user.PasswordFailuresSinceLastSuccess = 0; user.PasswordFailuresSinceLastSuccess = 0;
user.LastLoginDate = DateTime.UtcNow; user.LastLoginDate = DateTime.Now;
user.LastActivityDate = DateTime.UtcNow; user.LastActivityDate = DateTime.Now;
} }
else else
{ {
@@ -174,16 +156,16 @@ namespace MileageTraker.Web.Membership
if (failures < MaxInvalidPasswordAttempts) if (failures < MaxInvalidPasswordAttempts)
{ {
user.PasswordFailuresSinceLastSuccess += 1; user.PasswordFailuresSinceLastSuccess += 1;
user.LastPasswordFailureDate = DateTime.UtcNow; user.LastPasswordFailureDate = DateTime.Now;
} }
else if (failures >= MaxInvalidPasswordAttempts) else if (failures >= MaxInvalidPasswordAttempts)
{ {
user.LastPasswordFailureDate = DateTime.UtcNow; user.LastPasswordFailureDate = DateTime.Now;
user.LastLockoutDate = DateTime.UtcNow; user.LastLockoutDate = DateTime.Now;
user.IsLockedOut = true; user.IsLockedOut = true;
} }
} }
context.SaveChanges(); context.UpdateUser(user);
return verificationSucceeded; return verificationSucceeded;
} }
} }
@@ -194,9 +176,9 @@ namespace MileageTraker.Web.Membership
{ {
return null; return null;
} }
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
var user = context.Users.FirstOrDefault(usr => usr.Username == username); var user = context.FindUserByUsername(username);
if (user == null) if (user == null)
{ {
return null; return null;
@@ -204,26 +186,23 @@ namespace MileageTraker.Web.Membership
if (userIsOnline) if (userIsOnline)
{ {
user.LastActivityDate = DateTime.UtcNow; user.LastActivityDate = DateTime.Now;
context.SaveChanges(); context.UpdateUser(user);
} }
return user.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name); return user.ToMembershipUser(System.Web.Security.Membership.Provider.Name);
} }
} }
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{ {
if (providerUserKey is Guid) if (!(providerUserKey is Guid))
{
}
else
{ {
return null; return null;
} }
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
var user = context.Users.Find(providerUserKey); var user = context.GetUser((Guid)providerUserKey);
if (user == null) if (user == null)
{ {
return null; return null;
@@ -231,20 +210,20 @@ namespace MileageTraker.Web.Membership
if (userIsOnline) if (userIsOnline)
{ {
user.LastActivityDate = DateTime.UtcNow; user.LastActivityDate = DateTime.Now;
context.SaveChanges(); context.UpdateUser(user);
} }
return user.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name); return user.ToMembershipUser(System.Web.Security.Membership.Provider.Name);
} }
} }
public override bool ChangePassword(string username, string oldPassword, string newPassword) public override bool ChangePassword(string username, string currentPassword, string newPassword)
{ {
if (string.IsNullOrEmpty(username)) if (string.IsNullOrEmpty(username))
{ {
return false; return false;
} }
if (string.IsNullOrEmpty(oldPassword)) if (string.IsNullOrEmpty(currentPassword))
{ {
return false; return false;
} }
@@ -252,15 +231,15 @@ namespace MileageTraker.Web.Membership
{ {
return false; return false;
} }
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
User user = context.Users.FirstOrDefault(usr => usr.Username == username); var user = context.FindUserByUsername(username);
if (user == null) if (user == null)
{ {
return false; return false;
} }
var hashedPassword = user.Password; var hashedPassword = user.Password;
var verificationSucceeded = (hashedPassword != null && Crypto.VerifyHashedPassword(hashedPassword, oldPassword)); var verificationSucceeded = (hashedPassword != null && Crypto.VerifyHashedPassword(hashedPassword, currentPassword));
if (verificationSucceeded) if (verificationSucceeded)
{ {
user.PasswordFailuresSinceLastSuccess = 0; user.PasswordFailuresSinceLastSuccess = 0;
@@ -271,15 +250,15 @@ namespace MileageTraker.Web.Membership
if (failures < MaxInvalidPasswordAttempts) if (failures < MaxInvalidPasswordAttempts)
{ {
user.PasswordFailuresSinceLastSuccess += 1; user.PasswordFailuresSinceLastSuccess += 1;
user.LastPasswordFailureDate = DateTime.UtcNow; user.LastPasswordFailureDate = DateTime.Now;
} }
else if (failures >= MaxInvalidPasswordAttempts) else if (failures >= MaxInvalidPasswordAttempts)
{ {
user.LastPasswordFailureDate = DateTime.UtcNow; user.LastPasswordFailureDate = DateTime.Now;
user.LastLockoutDate = DateTime.UtcNow; user.LastLockoutDate = DateTime.Now;
user.IsLockedOut = true; user.IsLockedOut = true;
} }
context.SaveChanges(); context.UpdateUser(user);
return false; return false;
} }
var newHashedPassword = Crypto.HashPassword(newPassword); var newHashedPassword = Crypto.HashPassword(newPassword);
@@ -288,22 +267,22 @@ namespace MileageTraker.Web.Membership
return false; return false;
} }
user.Password = newHashedPassword; user.Password = newHashedPassword;
user.LastPasswordChangedDate = DateTime.UtcNow; user.LastPasswordChangedDate = DateTime.Now;
context.SaveChanges(); context.UpdateUser(user);
return true; return true;
} }
} }
public override bool UnlockUser(string userName) public override bool UnlockUser(string userName)
{ {
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
var user = context.Users.FirstOrDefault(usr => usr.Username == userName); var user = context.FindUserByUsername(userName);
if (user != null) if (user != null)
{ {
user.IsLockedOut = false; user.IsLockedOut = false;
user.PasswordFailuresSinceLastSuccess = 0; user.PasswordFailuresSinceLastSuccess = 0;
context.SaveChanges(); context.UpdateUser(user);
return true; return true;
} }
return false; return false;
@@ -313,36 +292,22 @@ namespace MileageTraker.Web.Membership
public override int GetNumberOfUsersOnline() public override int GetNumberOfUsersOnline()
{ {
var dateActive = CustomExtensions.UserOnlineThreshold(); var dateActive = CustomExtensions.UserOnlineThreshold();
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
return context.Users.Count(usr => usr.LastActivityDate > dateActive); return context.GetUsers().Count(usr => usr.LastActivityDate > dateActive);
} }
} }
public override bool DeleteUser(string username, bool deleteAllRelatedData) public override bool DeleteUser(string username, bool deleteAllRelatedData)
{ {
if (string.IsNullOrEmpty(username)) throw new NotSupportedException();
{
return false;
}
using (var context = new MileageTrakerContext())
{
var user = context.Users.FirstOrDefault(usr => usr.Username == username);
if (user != null)
{
context.Users.Remove(user);
context.SaveChanges();
return true;
}
return false;
}
} }
public override string GetUserNameByEmail(string email) public override string GetUserNameByEmail(string email)
{ {
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
var user = context.Users.FirstOrDefault(usr => usr.Email == email); var user = context.FindUserByEmail(email);
if (user != null) if (user != null)
{ {
return user.Username; return user.Username;
@@ -355,18 +320,18 @@ namespace MileageTraker.Web.Membership
out int totalRecords) out int totalRecords)
{ {
var membershipUsers = new MembershipUserCollection(); var membershipUsers = new MembershipUserCollection();
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
totalRecords = context.Users.Count(user => user.Email == emailToMatch); totalRecords = context.GetUsers().Count(user => user.Email == emailToMatch);
var users = var users =
context.Users.Where(usr => usr.Email == emailToMatch) context.GetUsers().Where(usr => usr.Email == emailToMatch)
.OrderBy(usrn => usrn.Username) .OrderBy(usrn => usrn.Username)
.Skip(pageIndex*pageSize) .Skip(pageIndex*pageSize)
.Take(pageSize); .Take(pageSize);
foreach (var user in users) foreach (var user in users)
{ {
membershipUsers.Add( membershipUsers.Add(
user.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name)); user.ToMembershipUser(Membership.Provider.Name));
} }
} }
return membershipUsers; return membershipUsers;
@@ -376,17 +341,17 @@ namespace MileageTraker.Web.Membership
out int totalRecords) out int totalRecords)
{ {
var membershipUsers = new MembershipUserCollection(); var membershipUsers = new MembershipUserCollection();
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
totalRecords = context.Users.Count(Usr => Usr.Username == usernameToMatch); totalRecords = context.GetUsers().Count(usr => usr.Username == usernameToMatch);
var users = var users =
context.Users.Where(usr => usr.Username == usernameToMatch) context.GetUsers().Where(usr => usr.Username == usernameToMatch)
.OrderBy(usrn => usrn.Username) .OrderBy(usrn => usrn.Username)
.Skip(pageIndex*pageSize) .Skip(pageIndex*pageSize)
.Take(pageSize); .Take(pageSize);
foreach (var user in users) foreach (var user in users)
{ {
membershipUsers.Add(user.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name)); membershipUsers.Add(user.ToMembershipUser(Membership.Provider.Name));
} }
} }
return membershipUsers; return membershipUsers;
@@ -395,92 +360,76 @@ namespace MileageTraker.Web.Membership
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{ {
var membershipUsers = new MembershipUserCollection(); var membershipUsers = new MembershipUserCollection();
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
totalRecords = context.Users.Count(); totalRecords = context.GetUsers().Count();
var users = var users =
context.Users context.GetUsers()
.OrderBy(usrn => usrn.Username) .OrderBy(usrn => usrn.Username)
.Skip(pageIndex*pageSize) .Skip(pageIndex*pageSize)
.Take(pageSize); .Take(pageSize);
foreach (var user in users) foreach (var user in users)
{ {
membershipUsers.Add(user.CloneToMembershipUser(System.Web.Security.Membership.Provider.Name)); membershipUsers.Add(user.ToMembershipUser(Membership.Provider.Name));
} }
} }
return membershipUsers; return membershipUsers;
} }
public string CreateAccount(string userName, string password, bool requireConfirmationToken) //public string CreateAccount(string userName, string password, bool requireConfirmationToken)
{ //{
if (string.IsNullOrEmpty(userName)) // if (string.IsNullOrEmpty(userName))
{ // {
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidUserName); // throw new MembershipCreateUserException(MembershipCreateStatus.InvalidUserName);
} // }
if (string.IsNullOrEmpty(password)) // if (string.IsNullOrEmpty(password))
{ // {
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword); // throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
} // }
var hashedPassword = Crypto.HashPassword(password); // var hashedPassword = Crypto.HashPassword(password);
if (hashedPassword.Length > 128) // if (hashedPassword.Length > 128)
{ // {
throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword); // throw new MembershipCreateUserException(MembershipCreateStatus.InvalidPassword);
} // }
using (var context = new MileageTrakerContext()) // using (var context = new MileageTrakerContext())
{ // {
if (context.Users.Any(usr => usr.Username == userName)) // if (context.Users.Any(usr => usr.Username == userName))
{ // {
throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName); // throw new MembershipCreateUserException(MembershipCreateStatus.DuplicateUserName);
} // }
var token = string.Empty; // var token = string.Empty;
if (requireConfirmationToken) // if (requireConfirmationToken)
{ // {
token = GenerateToken(); // token = Algorithms.GenerateToken();
} // }
var newUser = new User // var newUser = new User
{ // {
UserId = Guid.NewGuid(), // UserId = Guid.NewGuid(),
Username = userName, // Username = userName,
Password = hashedPassword, // Password = hashedPassword,
IsApproved = !requireConfirmationToken, // IsApproved = !requireConfirmationToken,
Email = string.Empty, // Email = string.Empty,
CreateDate = DateTime.UtcNow, // Created = DateTime.Now,
LastPasswordChangedDate = DateTime.UtcNow, // LastPasswordChangedDate = DateTime.Now,
PasswordFailuresSinceLastSuccess = 0, // PasswordFailuresSinceLastSuccess = 0,
LastLoginDate = DateTime.UtcNow, // LastLoginDate = SqlDateTime.MinValue.Value,
LastActivityDate = DateTime.UtcNow, // LastActivityDate = SqlDateTime.MinValue.Value,
LastLockoutDate = SqlDateTime.MinValue.Value, // LastLockoutDate = SqlDateTime.MinValue.Value,
IsLockedOut = false, // IsLockedOut = false,
LastPasswordFailureDate = SqlDateTime.MinValue.Value, // LastPasswordFailureDate = SqlDateTime.MinValue.Value
ConfirmationToken = token // };
};
context.Users.Add(newUser); // context.Users.Add(newUser);
context.SaveChanges(); // context.SaveChanges();
return token; // return token;
} // }
} //}
private static string GenerateToken()
{
using (var prng = new RNGCryptoServiceProvider())
{
return GenerateToken(prng);
}
}
private static string GenerateToken(RandomNumberGenerator generator)
{
var tokenBytes = new byte[TokenSizeInBytes];
generator.GetBytes(tokenBytes);
return HttpServerUtility.UrlTokenEncode(tokenBytes);
}
#endregion #endregion
@@ -4,7 +4,7 @@ using System.Web.Security;
using MileageTraker.Web.Context; using MileageTraker.Web.Context;
using MileageTraker.Web.Models; using MileageTraker.Web.Models;
namespace MileageTraker.Web.Membership namespace MileageTraker.Web.DAL
{ {
public class CodeFirstRoleProvider : RoleProvider public class CodeFirstRoleProvider : RoleProvider
{ {
@@ -101,6 +101,7 @@ namespace MileageTraker.Web.Membership
public override string[] FindUsersInRole(string roleName, string usernameToMatch) public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{ {
throw new NotSupportedException();
if (string.IsNullOrEmpty(roleName)) if (string.IsNullOrEmpty(roleName))
{ {
return null; return null;
@@ -122,6 +123,7 @@ namespace MileageTraker.Web.Membership
public override void CreateRole(string roleName) public override void CreateRole(string roleName)
{ {
throw new NotSupportedException();
if (!string.IsNullOrEmpty(roleName)) if (!string.IsNullOrEmpty(roleName))
{ {
using (var context = new MileageTrakerContext()) using (var context = new MileageTrakerContext())
@@ -143,6 +145,7 @@ namespace MileageTraker.Web.Membership
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{ {
throw new NotSupportedException();
if (string.IsNullOrEmpty(roleName)) if (string.IsNullOrEmpty(roleName))
{ {
return false; return false;
@@ -173,10 +176,10 @@ namespace MileageTraker.Web.Membership
public override void AddUsersToRoles(string[] usernames, string[] roleNames) public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{ {
using (var context = new MileageTrakerContext()) using (var context = new DataService())
{ {
var users = context.Users.Where(usr => usernames.Contains(usr.Username)).ToList(); var users = context.GetUsers().Where(usr => usernames.Contains(usr.Username)).ToList();
var roles = context.Roles.Where(rl => roleNames.Contains(rl.RoleName)).ToList(); var roles = context.GetRoles().Where(rl => roleNames.Contains(rl.RoleName)).ToList();
foreach (var user in users) foreach (var user in users)
{ {
foreach (var role in roles) foreach (var role in roles)
@@ -186,13 +189,14 @@ namespace MileageTraker.Web.Membership
user.Roles.Add(role); user.Roles.Add(role);
} }
} }
context.UpdateUser(user);
} }
context.SaveChanges();
} }
} }
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{ {
throw new NotSupportedException();
using (var context = new MileageTrakerContext()) using (var context = new MileageTrakerContext())
{ {
foreach (var username in usernames) foreach (var username in usernames)
+62
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.SqlTypes;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -440,6 +441,46 @@ namespace MileageTraker.Web.DAL
#endregion #endregion
public void AddUser(User user)
{
user.Created = DateTime.Now;
_db.Users.Add(user);
_db.SaveChanges();
}
public void UpdateUser(User user)
{
_db.Entry(user).State = EntityState.Modified;
_db.SaveChanges();
}
/// <summary>
/// Update only fields not needing extra membership provider support
/// </summary>
public void UpdateUserPersonalInfo(User user)
{
var original = GetUser(user.UserId);
original.Comment = user.Comment;
original.Email = user.Email;
original.FullName = user.FullName;
original.Username = user.Username;
UpdateUser(original);
}
public void UpdateUserLastActivity(string username)
{
var user = FindUserByUsername(username);
if (user != null)
{
user.LastActivityDate = DateTime.Now;
UpdateUser(user);
}
}
public IQueryable<User> GetUsers() public IQueryable<User> GetUsers()
{ {
return _db.Users; return _db.Users;
@@ -450,6 +491,27 @@ namespace MileageTraker.Web.DAL
return _db.Users.Find(guid); return _db.Users.Find(guid);
} }
public User FindUserByUsername(string username)
{
return _db.Users.FirstOrDefault(u => username.Equals(u.Username, StringComparison.InvariantCultureIgnoreCase));
}
public User FindUserByEmail(string email)
{
return _db.Users.FirstOrDefault(u => email.Equals(u.Email, StringComparison.InvariantCultureIgnoreCase));
}
public IQueryable<Role> GetRoles()
{
return _db.Roles;
}
public Role GetRoleByName(string roleName)
{
return
(from role in _db.Roles
where roleName == role.RoleName
select role).FirstOrDefault();
}
} }
} }
-175
View File
@@ -1,175 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using MileageTraker.Web.Context;
namespace MileageTraker.Web.Membership
{
public static class WebSecurity
{
public static HttpContextBase Context
{
get { return new HttpContextWrapper(HttpContext.Current); }
}
public static HttpRequestBase Request
{
get { return Context.Request; }
}
public static HttpResponseBase Response
{
get { return Context.Response; }
}
public static IPrincipal User
{
get { return Context.User; }
}
public static bool IsAuthenticated
{
get { return User.Identity.IsAuthenticated; }
}
public static MembershipCreateStatus Register(string username, string password, string email, bool isApproved,
string firstName, string lastName)
{
MembershipCreateStatus createStatus;
System.Web.Security.Membership.CreateUser(username, password, email, null, null, isApproved, Guid.NewGuid(),
out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
using (var context = new MileageTrakerContext())
{
var user = context.Users.First(usr => usr.Username == username);
user.FirstName = firstName;
user.LastName = lastName;
context.SaveChanges();
}
if (isApproved)
{
FormsAuthentication.SetAuthCookie(username, false);
}
}
return createStatus;
}
public static Boolean Login(string username, string password, bool persistCookie = false)
{
var success = System.Web.Security.Membership.ValidateUser(username, password);
if (success)
{
FormsAuthentication.SetAuthCookie(username, persistCookie);
}
return success;
}
public static void Logout()
{
FormsAuthentication.SignOut();
}
public static MembershipUser GetUser(string username)
{
return System.Web.Security.Membership.GetUser(username);
}
public static bool ChangePassword(string userName, string currentPassword, string newPassword)
{
var success = false;
try
{
var currentUser = System.Web.Security.Membership.GetUser(userName, true);
success = currentUser.ChangePassword(currentPassword, newPassword);
}
catch (ArgumentException)
{
}
return success;
}
public static bool DeleteUser(string username)
{
return System.Web.Security.Membership.DeleteUser(username);
}
public static Guid GetUserId(string userName)
{
var user = System.Web.Security.Membership.GetUser(userName);
return (Guid) user.ProviderUserKey;
}
public static string CreateAccount(string userName, string password)
{
return CreateAccount(userName, password, requireConfirmationToken: false);
}
public static string CreateAccount(string userName, string password, bool requireConfirmationToken = false)
{
var codeFirstMembership = (CodeFirstMembershipProvider)System.Web.Security.Membership.Provider;
return codeFirstMembership.CreateAccount(userName, password, requireConfirmationToken);
}
public static string CreateUserAndAccount(string userName, string password)
{
return CreateUserAndAccount(userName, password, propertyValues: null);
}
public static string CreateUserAndAccount(string userName, string password, bool requireConfirmation)
{
return CreateUserAndAccount(userName, password, null, requireConfirmation);
}
public static string CreateUserAndAccount(string userName, string password, IDictionary<string, object> values)
{
return CreateUserAndAccount(userName, password, values, requireConfirmationToken: false);
}
private static string CreateUserAndAccount(string userName, string password, object propertyValues = null,
bool requireConfirmationToken = false)
{
var codeFirstMembership = (CodeFirstMembershipProvider)System.Web.Security.Membership.Provider;
//IDictionary<string, object> values = null;
//if (propertyValues != null)
//{
// values = new RouteValueDictionary(propertyValues);
//}
return codeFirstMembership.CreateUserAndAccount(userName, password, requireConfirmationToken);
}
public static List<MembershipUser> FindUsersByEmail(string email, int pageIndex, int pageSize)
{
int totalRecords;
return
System.Web.Security.Membership.FindUsersByEmail(email, pageIndex, pageSize, out totalRecords)
.Cast<MembershipUser>()
.ToList();
}
public static List<MembershipUser> FindUsersByName(string username, int pageIndex, int pageSize)
{
int totalRecords;
return
System.Web.Security.Membership.FindUsersByName(username, pageIndex, pageSize, out totalRecords)
.Cast<MembershipUser>()
.ToList();
}
public static List<MembershipUser> GetAllUsers(int pageIndex, int pageSize)
{
int totalRecords;
return
System.Web.Security.Membership.GetAllUsers(pageIndex, pageSize, out totalRecords).Cast<MembershipUser>().ToList();
}
}
}
-24
View File
@@ -1,24 +0,0 @@
// <auto-generated />
namespace MileageTraker.Web.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
public sealed partial class AddMembership : IMigrationMetadata
{
string IMigrationMetadata.Id
{
get { return "201212191949311_AddMembership"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return "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"; }
}
}
}
+24
View File
@@ -0,0 +1,24 @@
// <auto-generated />
namespace MileageTraker.Web.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
public sealed partial class AddMembership : IMigrationMetadata
{
string IMigrationMetadata.Id
{
get { return "201212261822498_AddMembership"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return "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"; }
}
}
}
@@ -11,26 +11,25 @@ namespace MileageTraker.Web.Migrations
c => new c => new
{ {
UserId = c.Guid(nullable: false), UserId = c.Guid(nullable: false),
Username = c.String(nullable: false), Username = c.String(nullable: false, maxLength: 64),
Email = c.String(), Email = c.String(nullable: false, maxLength: 64),
Password = c.String(nullable: false), FullName = c.String(nullable: false, maxLength: 128),
FirstName = c.String(), Password = c.String(nullable: false, maxLength: 128),
LastName = c.String(),
Comment = c.String(), Comment = c.String(),
IsApproved = c.Boolean(nullable: false), IsApproved = c.Boolean(nullable: false),
PasswordFailuresSinceLastSuccess = c.Int(nullable: false), PasswordFailuresSinceLastSuccess = c.Int(nullable: false),
LastPasswordFailureDate = c.DateTime(), LastPasswordFailureDate = c.DateTime(nullable: false),
LastActivityDate = c.DateTime(), LastActivityDate = c.DateTime(nullable: false),
LastLockoutDate = c.DateTime(), LastLockoutDate = c.DateTime(nullable: false),
LastLoginDate = c.DateTime(), LastLoginDate = c.DateTime(nullable: false),
ConfirmationToken = c.String(), Created = c.DateTime(nullable: false),
CreateDate = c.DateTime(),
IsLockedOut = c.Boolean(nullable: false), IsLockedOut = c.Boolean(nullable: false),
LastPasswordChangedDate = c.DateTime(), LastPasswordChangedDate = c.DateTime(nullable: false),
PasswordVerificationToken = c.String(), PasswordResetToken = c.String(maxLength: 128),
PasswordVerificationTokenExpirationDate = c.DateTime(),
}) })
.PrimaryKey(t => t.UserId); .PrimaryKey(t => t.UserId)
.Index(t => t.Username, unique: true)
.Index(t => t.Email, unique: true);
CreateTable( CreateTable(
"Role", "Role",
@@ -71,9 +70,8 @@ namespace MileageTraker.Web.Migrations
([UserId] ([UserId]
,[Username] ,[Username]
,[Email] ,[Email]
,[FullName]
,[Password] ,[Password]
,[FirstName]
,[LastName]
,[Comment] ,[Comment]
,[IsApproved] ,[IsApproved]
,[PasswordFailuresSinceLastSuccess] ,[PasswordFailuresSinceLastSuccess]
@@ -81,31 +79,26 @@ namespace MileageTraker.Web.Migrations
,[LastActivityDate] ,[LastActivityDate]
,[LastLockoutDate] ,[LastLockoutDate]
,[LastLoginDate] ,[LastLoginDate]
,[ConfirmationToken] ,[Created]
,[CreateDate]
,[IsLockedOut] ,[IsLockedOut]
,[LastPasswordChangedDate] ,[LastPasswordChangedDate]
,[PasswordVerificationToken] ,[PasswordResetToken])
,[PasswordVerificationTokenExpirationDate])
VALUES VALUES
('33EA9A48-628A-458C-A9C9-FBB318C3CF0E' ('33EA9A48-628A-458C-A9C9-FBB318C3CF0E'
,'james.kolpack'
,'james.kolpack@gmail.com' ,'james.kolpack@gmail.com'
,'james.kolpack@gmail.com' ,'James Kolpack'
,'AH6VqEzZky4QfexgSwJIgg5gHrjaKGEk7pxUVBZz7X1Vkl31TlCUz9yTxmJN3/IDag==' ,'AH6VqEzZky4QfexgSwJIgg5gHrjaKGEk7pxUVBZz7X1Vkl31TlCUz9yTxmJN3/IDag=='
,'James'
,'Kolpack'
,NULL ,NULL
,1 ,1
,0 ,0
,'1753-1-1' ,'1753-1-1'
,GETDATE()
,'1753-1-1' ,'1753-1-1'
,NULL ,'1753-1-1'
,NULL ,'1753-1-1'
,GETDATE() ,GETDATE()
,0 ,0
,GETDATE() ,'1753-1-1'
,NULL
,NULL)"); ,NULL)");
Sql(@"INSERT INTO [RoleUser] Sql(@"INSERT INTO [RoleUser]
+57 -37
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Data.SqlTypes;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Security; using System.Web.Security;
@@ -10,66 +11,85 @@ namespace MileageTraker.Web.Models
{ {
[Key] [Key]
[HiddenInput(DisplayValue = false)] [HiddenInput(DisplayValue = false)]
public virtual Guid UserId { get; set; } public Guid UserId { get; set; }
[Required] [Required]
[Display(Name = "Email")] [StringLength(64)]
[DataType(DataType.EmailAddress)] public string Username { get; set; }
public virtual String Username { get; set; }
[HiddenInput(DisplayValue = false)] [Required]
[StringLength(64)]
[DataType(DataType.EmailAddress)] [DataType(DataType.EmailAddress)]
public virtual String Email { get; set; } public string Email { get; set; }
[Required]
[StringLength(128)]
[RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Need complete name")]
public string FullName { get; set; }
[Required, DataType(DataType.Password)] [Required, DataType(DataType.Password)]
public virtual String Password { get; set; } [StringLength(128)]
public string Password { get; set; }
public virtual String FirstName { get; set; }
public virtual String LastName { get; set; }
[DataType(DataType.MultilineText)] [DataType(DataType.MultilineText)]
public virtual String Comment { get; set; } public string Comment { get; set; }
[HiddenInput(DisplayValue = false)] [HiddenInput(DisplayValue = false)]
public virtual Boolean IsApproved { get; set; } public bool IsApproved { get; set; }
[HiddenInput] [HiddenInput]
public virtual int PasswordFailuresSinceLastSuccess { get; set; } public int PasswordFailuresSinceLastSuccess { get; set; }
public virtual DateTime? LastPasswordFailureDate { get; set; }
public virtual DateTime? LastActivityDate { get; set; }
public virtual DateTime? LastLockoutDate { get; set; }
public virtual DateTime? LastLoginDate { get; set; }
[HiddenInput(DisplayValue = false)] [HiddenInput(DisplayValue = false)]
public virtual String ConfirmationToken { get; set; } [DataType(DataType.Date)]
public DateTime LastPasswordFailureDate { get; set; }
[HiddenInput]
public virtual DateTime? CreateDate { get; set; }
[HiddenInput]
public virtual Boolean IsLockedOut { get; set; }
[HiddenInput]
public virtual DateTime? LastPasswordChangedDate { get; set; }
// TODO: change to Password Reset Token
[HiddenInput(DisplayValue = false)]
public virtual String PasswordVerificationToken { get; set; }
[HiddenInput(DisplayValue = false)] [HiddenInput(DisplayValue = false)]
public virtual DateTime? PasswordVerificationTokenExpirationDate { get; set; } [DataType(DataType.DateTime)]
public DateTime LastActivityDate { get; set; }
[HiddenInput(DisplayValue = false)]
[DataType(DataType.Date)]
public DateTime LastLockoutDate { get; set; }
[HiddenInput(DisplayValue = false)]
[DataType(DataType.Date)]
public DateTime LastLoginDate { get; set; }
[HiddenInput(DisplayValue = false)]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
[HiddenInput]
public bool IsLockedOut { get; set; }
[HiddenInput]
[DataType(DataType.Date)]
public DateTime LastPasswordChangedDate { get; set; }
[HiddenInput(DisplayValue = false)]
[StringLength(128)]
public string PasswordResetToken { get; set; }
[HiddenInput] [HiddenInput]
public virtual ICollection<Role> Roles { get; set; } public virtual ICollection<Role> Roles { get; set; }
public MembershipUser CloneToMembershipUser(string providerName) public User()
{
LastActivityDate = SqlDateTime.MinValue.Value;
LastLockoutDate = SqlDateTime.MinValue.Value;
LastLoginDate = SqlDateTime.MinValue.Value;
LastPasswordChangedDate = SqlDateTime.MinValue.Value;
LastPasswordFailureDate = SqlDateTime.MinValue.Value;
}
public MembershipUser ToMembershipUser(string providerName)
{ {
return new MembershipUser(providerName, Username, UserId, return new MembershipUser(providerName, Username, UserId,
Email, null, null, Email, null, null,
IsApproved, IsLockedOut, CreateDate.Value, IsApproved, IsLockedOut, Created,
LastLoginDate.Value, LastActivityDate.Value, LastLoginDate, LastActivityDate,
LastPasswordChangedDate.Value, LastLockoutDate.Value); LastPasswordChangedDate, LastLockoutDate);
} }
} }
} }
+21 -2
View File
@@ -86,12 +86,12 @@ $(function () {
text: "<p class=\"loading\">Recent Logs...</p>", text: "<p class=\"loading\">Recent Logs...</p>",
}, },
style: { style: {
width: 320, width: 310,
classes: 'qtip-light' classes: 'qtip-light'
}, },
position: { position: {
my: "top right", my: "top right",
at: "bottom left" at: "bottom right"
}, },
hide: { hide: {
fixed: true, fixed: true,
@@ -114,6 +114,19 @@ $(function () {
} }
}); });
$(function() {
// move checkbox elements into their labels
$('label[for]').each(function() {
var $label = $(this);
var $for = $label.attr('for');
var $input = $('input#' + $for + ':checkbox');
if ($input.length > 0) {
$input.prependTo($label);
$label.addClass('checkbox');
}
});
});
$(function() { $(function() {
// Add active class to nav // Add active class to nav
var idNavActiveRegex = { 'log-nav': /\/log/i, 'vehicle-nav': /\/vehicle/i }; var idNavActiveRegex = { 'log-nav': /\/log/i, 'vehicle-nav': /\/vehicle/i };
@@ -160,6 +173,12 @@ $(function() {
} }
}); });
$(function () {
$('input#Username').keyup(function (e) {
$('input#Email').val($(this).val() + "@ethra.org");
});
});
$(function() { $(function() {
// add qtip // add qtip
$("a.qtip-modal").each(function () { bindQtipModal($(this)); }); $("a.qtip-modal").each(function () { bindQtipModal($(this)); });
+19
View File
@@ -1,6 +1,8 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Cryptography;
using System.Web;
namespace MileageTraker.Web.Utility namespace MileageTraker.Web.Utility
{ {
@@ -83,5 +85,22 @@ namespace MileageTraker.Web.Utility
|| existingDate < date && existingNumber < number || existingDate < date && existingNumber < number
|| existingDate > date && existingNumber > number; || existingDate > date && existingNumber > number;
} }
private const int TokenSizeInBytes = 16;
public static string GenerateToken()
{
using (var prng = new RNGCryptoServiceProvider())
{
return GenerateToken(prng);
}
}
private static string GenerateToken(RandomNumberGenerator generator)
{
var tokenBytes = new byte[TokenSizeInBytes];
generator.GetBytes(tokenBytes);
return HttpServerUtility.UrlTokenEncode(tokenBytes);
}
} }
} }
@@ -1,10 +1,8 @@
using System; using System;
using System.Globalization;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
namespace MileageTraker.Web.Membership namespace MileageTraker.Web.Utility
{ {
public static class Crypto public static class Crypto
{ {
@@ -12,34 +10,6 @@ namespace MileageTraker.Web.Membership
private const int Pbkdf2SubkeyLength = 256/8; private const int Pbkdf2SubkeyLength = 256/8;
private const int SaltSize = 128/8; private const int SaltSize = 128/8;
private static string Hash(string input, string algorithm = "sha256")
{
if (input == null)
{
throw new ArgumentNullException("input");
}
return Hash(Encoding.UTF8.GetBytes(input), algorithm);
}
private static string Hash(byte[] input, string algorithm = "sha256")
{
if (input == null)
{
throw new ArgumentNullException("input");
}
using (var alg = HashAlgorithm.Create(algorithm))
{
if (alg != null)
{
var hashData = alg.ComputeHash(input);
return BinaryToHex(hashData);
}
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "not supported hash alg", algorithm));
}
}
/* ======================= /* =======================
* HASHED PASSWORD FORMATS * HASHED PASSWORD FORMATS
* ======================= * =======================
@@ -100,20 +70,6 @@ namespace MileageTraker.Web.Membership
return ByteArraysEqual(storedSubkey, generatedSubkey); return ByteArraysEqual(storedSubkey, generatedSubkey);
} }
private static string BinaryToHex(byte[] data)
{
var hex = new char[data.Length*2];
for (int iter = 0; iter < data.Length; iter++)
{
var hexChar = ((byte) (data[iter] >> 4));
hex[iter*2] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
hexChar = ((byte) (data[iter] & 0xF));
hex[iter*2 + 1] = (char) (hexChar > 9 ? hexChar + 0x37 : hexChar + 0x30);
}
return new string(hex);
}
// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized. // Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
[MethodImpl(MethodImplOptions.NoOptimization)] [MethodImpl(MethodImplOptions.NoOptimization)]
private static bool ByteArraysEqual(byte[] a, byte[] b) private static bool ByteArraysEqual(byte[] a, byte[] b)
+1 -1
View File
@@ -171,7 +171,7 @@ namespace MileageTraker.Web.Utility
/// </summary> /// </summary>
public static DateTime UserOnlineThreshold() public static DateTime UserOnlineThreshold()
{ {
return DateTime.UtcNow.Subtract( return DateTime.Now.Subtract(
TimeSpan.FromMinutes( TimeSpan.FromMinutes(
Convert.ToDouble( Convert.ToDouble(
System.Web.Security.Membership.UserIsOnlineTimeWindow))); System.Web.Security.Membership.UserIsOnlineTimeWindow)));
+1 -4
View File
@@ -1,18 +1,15 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using MileageTraker.Web.Attributes; using MileageTraker.Web.Attributes;
using MileageTraker.Web.Utility;
namespace MileageTraker.Web.ViewModels.Account namespace MileageTraker.Web.ViewModels.Account
{ {
public class LoginViewModel public class LoginViewModel
{ {
[Required] [Required]
[Display(Name = "Email Address")] public string Username { get; set; }
public string EmailAddress { get; set; }
[Required] [Required]
[DataType(DataType.Password)] [DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; } public string Password { get; set; }
[Display(Name = "Remember me?")] [Display(Name = "Remember me?")]
+32 -9
View File
@@ -1,32 +1,55 @@
using System.ComponentModel.DataAnnotations; using System.Collections.Generic;
using System.Web.Mvc; using System.ComponentModel.DataAnnotations;
using AutoMapper; using AutoMapper;
using MileageTraker.Web.Attributes;
using MileageTraker.Web.DAL;
using MileageTraker.Web.Models;
namespace MileageTraker.Web.ViewModels.User namespace MileageTraker.Web.ViewModels.User
{ {
public class CreateUserViewModel public class CreateUserViewModel
{ {
[Required]
[StringLength(64)]
[InputSize("small")]
public string Username { get; set; }
[Required] [Required]
[DataType(DataType.EmailAddress)] [DataType(DataType.EmailAddress)]
[RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}", ErrorMessage = "Must be an email address")] [RegularExpression(@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}", ErrorMessage = "Must be an email address")]
[InputSize("large")]
public string Email { get; set; } public string Email { get; set; }
[Required] [Required]
[StringLength(50, MinimumLength = 2)] [StringLength(128)]
public string FirstName { get; set; } [RegularExpression(@"[A-Za-z().]+(\s+[A-Za-z().]+)+", ErrorMessage = "Need complete name")]
[InputSize("medium")]
public string FullName { get; set; }
[Required] [Required, DataType(DataType.Password)]
[StringLength(50, MinimumLength = 2)] [StringLength(16, MinimumLength = 6)]
public string LastName { get; set; } public string Password { get; set; }
public MultiSelectList Roles { get; set; } public string[] Roles { get; set; }
public IList<string> AvailableRoles { get; set; }
public IList<string> SelectedRoles { get; set; }
static CreateUserViewModel() static CreateUserViewModel()
{ {
Mapper.CreateMap<CreateUserViewModel, Models.User>(); Mapper.CreateMap<CreateUserViewModel, Models.User>();
Mapper.CreateMap<string, Role>()
.ConvertUsing(
roleName =>
{
using (var ds = new DataService())
{
return ds.GetRoleByName(roleName);
}
});
} }
public Models.User CloneToUser() public Models.User ToUser()
{ {
var user = new Models.User(); var user = new Models.User();
Mapper.Map(this, user); Mapper.Map(this, user);
@@ -2,9 +2,10 @@
@{ @{
Layout = null; Layout = null;
var lowerPropertyName = @CustomExtensions.LowercaseFirst(ViewData.ModelMetadata.PropertyName); var lowerPropertyName = @CustomExtensions.LowercaseFirst(ViewData.ModelMetadata.PropertyName);
var units = (string)ViewData.ModelMetadata.AdditionalValues["Units"]; var values = ViewData.ModelMetadata.AdditionalValues;
var formatHint = (string)ViewData.ModelMetadata.AdditionalValues["FormatHint"]; var units = values.ContainsKey("Units") ? (string)values["Units"] : null;
var editLabel = (bool)ViewData.ModelMetadata.AdditionalValues["EditLabel"]; var formatHint = values.ContainsKey("FormatHint") ? (string)values["FormatHint"] : null;
var editLabel = values.ContainsKey("EditLabel") ? (bool) values["EditLabel"] : true;
} }
<div class="control-group @lowerPropertyName"> <div class="control-group @lowerPropertyName">
+1 -1
View File
@@ -40,7 +40,7 @@
</div> </div>
</div> </div>
</header> </header>
<div class="container-fluid"> <div id="content" class="container-fluid">
@RenderBody() @RenderBody()
</div> </div>
<footer> <footer>
+10
View File
@@ -0,0 +1,10 @@
@model MileageTraker.Web.ViewModels.User.CreateUserViewModel
@{
Layout = "~/Views/Shared/EditorTemplates/_FieldLayout.cshtml";
}
@Html.CheckBoxListFor(
m => m.Roles,
m => m.AvailableRoles,
m => m,
m => m,
m => m.Roles)
+1
View File
@@ -13,6 +13,7 @@
<fieldset> <fieldset>
<legend></legend> <legend></legend>
@Html.EditorForModel() @Html.EditorForModel()
@Html.Partial("_Roles", Model)
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
<input type="submit" value="Create" class="btn btn-primary" /> <input type="submit" value="Create" class="btn btn-primary" />
+1 -2
View File
@@ -8,9 +8,8 @@
<h2>@ViewBag.Title</h2> <h2>@ViewBag.Title</h2>
@Html.DisplayFor(m => m.Email)
@Html.DisplayFor(m => m.Username) @Html.DisplayFor(m => m.Username)
@Html.DisplayFor(m => m.FirstName)
@Html.DisplayFor(m => m.LastName)
<dl class="dl-horizontal roles"> <dl class="dl-horizontal roles">
<dt> <dt>
+17 -5
View File
@@ -18,17 +18,29 @@
@grid.GetHtml(columns: @grid.GetHtml(columns:
grid.Columns( grid.Columns(
grid.Column("Username", format: grid.Column("Username", format:
@<text>@Html.Encode(item.Username) @<text>
<span title="@Html.Encode(item.Email)">
@Html.Encode(item.Username)
</span>
@if (item.LastActivityDate > CustomExtensions.UserOnlineThreshold()) { @if (item.LastActivityDate > CustomExtensions.UserOnlineThreshold()) {
<span class='label label-info'>Online</span> <span class='label label-info'>Online</span>
} }
@if (item.IsLockedOut) { @if (item.IsLockedOut) {
<span class='label label-warning' title="@string.Format("Locked out on {0:d}", item.LastLockoutDate)">Locked Out</span> <span class='label label-warning' title="@string.Format("Locked out on {0:d}", item.LastLockoutDate)">Locked Out</span>
}</text> ), }</text> ),
grid.Column("FirstName", "First Name"), grid.Column("FullName", "Full Name"),
grid.Column("LastName", "Last Name"), grid.Column("Roles", format:
grid.Column("Roles", format: item => @<text>
string.Join(", ", Roles.Provider.GetRolesForUser(item.Username) )), @{ var roles = Roles.Provider.GetRolesForUser(item.Username); }
@if (roles.Length > 0)
{
@Html.Encode(string.Join(", ", roles))
}
else
{
<span class='label label-warning'>No Role</span>
}
</text>),
grid.Column(format: grid.Column(format:
@<div class='btn-group'> @<div class='btn-group'>
@Html.ActionLink("Edit", "Edit", new { id = item.UserId }, new { @class = "btn btn-mini" }) @Html.ActionLink("Edit", "Edit", new { id = item.UserId }, new { @class = "btn btn-mini" })
+7 -3
View File
@@ -40,12 +40,12 @@
</authentication> </authentication>
<membership defaultProvider="CodeFirstMembershipProvider"> <membership defaultProvider="CodeFirstMembershipProvider">
<providers> <providers>
<add name="CodeFirstMembershipProvider" type="MileageTraker.Web.Membership.CodeFirstMembershipProvider" connectionStringName="MileageTrakerContext" /> <add name="CodeFirstMembershipProvider" type="MileageTraker.Web.DAL.CodeFirstMembershipProvider" connectionStringName="MileageTrakerContext" />
</providers> </providers>
</membership> </membership>
<roleManager enabled="true" defaultProvider="CodeFirstRoleProvider"> <roleManager enabled="true" defaultProvider="CodeFirstRoleProvider">
<providers> <providers>
<add name="CodeFirstRoleProvider" type="MileageTraker.Web.Membership.CodeFirstRoleProvider" connectionStringName="MileageTrakerContext" /> <add name="CodeFirstRoleProvider" type="MileageTraker.Web.DAL.CodeFirstRoleProvider" connectionStringName="MileageTrakerContext" />
</providers> </providers>
</roleManager> </roleManager>
</system.web> </system.web>
@@ -57,12 +57,16 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0" /> <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly> <dependentAssembly>
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" /> <assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" /> <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly> </dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
<log4net> <log4net>
+11 -7
View File
@@ -64,6 +64,9 @@
<Private>True</Private> <Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference> </Reference>
<Reference Include="MvcCheckBoxList">
<HintPath>..\packages\MvcCheckBoxList.1.4.3.0\lib\MvcCheckBoxList.dll</HintPath>
</Reference>
<Reference Include="System.configuration" /> <Reference Include="System.configuration" />
<Reference Include="System.Data.Entity" /> <Reference Include="System.Data.Entity" />
<Reference Include="System.Web.ApplicationServices" /> <Reference Include="System.Web.ApplicationServices" />
@@ -112,16 +115,15 @@
<Compile Include="Attributes\InputSizeAttribute.cs" /> <Compile Include="Attributes\InputSizeAttribute.cs" />
<Compile Include="Attributes\NoEditLabelAttribute.cs" /> <Compile Include="Attributes\NoEditLabelAttribute.cs" />
<Compile Include="Attributes\UnitsAttribute.cs" /> <Compile Include="Attributes\UnitsAttribute.cs" />
<Compile Include="Attributes\UserActivityAttribute.cs" />
<Compile Include="Context\MileageTrakerContext.cs" /> <Compile Include="Context\MileageTrakerContext.cs" />
<Compile Include="Controllers\AccountController.cs" /> <Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\CityController.cs" /> <Compile Include="Controllers\CityController.cs" />
<Compile Include="Controllers\ControllerBase.cs" /> <Compile Include="Controllers\ControllerBase.cs" />
<Compile Include="Controllers\EmployeeController.cs" /> <Compile Include="Controllers\EmployeeController.cs" />
<Compile Include="Controllers\UserController.cs" /> <Compile Include="Controllers\UserController.cs" />
<Compile Include="Membership\CodeFirstMembershipProvider.cs" /> <Compile Include="DAL\CodeFirstMembershipProvider.cs" />
<Compile Include="Membership\CodeFirstRoleProvider.cs" /> <Compile Include="DAL\CodeFirstRoleProvider.cs" />
<Compile Include="Membership\Crypto.cs" />
<Compile Include="Membership\WebSecurity.cs" />
<Compile Include="Migrations\201204181847082_InitialMigration.cs" /> <Compile Include="Migrations\201204181847082_InitialMigration.cs" />
<Compile Include="Migrations\201204181847082_InitialMigration.Designer.cs"> <Compile Include="Migrations\201204181847082_InitialMigration.Designer.cs">
<DependentUpon>201204181847082_InitialMigration.cs</DependentUpon> <DependentUpon>201204181847082_InitialMigration.cs</DependentUpon>
@@ -130,13 +132,14 @@
<Compile Include="Migrations\201212042021486_AddVehiclePreviousLog.Designer.cs"> <Compile Include="Migrations\201212042021486_AddVehiclePreviousLog.Designer.cs">
<DependentUpon>201212042021486_AddVehiclePreviousLog.cs</DependentUpon> <DependentUpon>201212042021486_AddVehiclePreviousLog.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migrations\201212191949311_AddMembership.cs" /> <Compile Include="Migrations\201212261822498_AddMembership.cs" />
<Compile Include="Migrations\201212191949311_AddMembership.Designer.cs"> <Compile Include="Migrations\201212261822498_AddMembership.Designer.cs">
<DependentUpon>201212191949311_AddMembership.cs</DependentUpon> <DependentUpon>201212261822498_AddMembership.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migrations\Configuration.cs" /> <Compile Include="Migrations\Configuration.cs" />
<Compile Include="Models\Role.cs" /> <Compile Include="Models\Role.cs" />
<Compile Include="Models\User.cs" /> <Compile Include="Models\User.cs" />
<Compile Include="Utility\Crypto.cs" />
<Compile Include="ViewModels\Account\ChangePasswordViewModel.cs" /> <Compile Include="ViewModels\Account\ChangePasswordViewModel.cs" />
<Compile Include="ViewModels\Account\LoginViewModel.cs" /> <Compile Include="ViewModels\Account\LoginViewModel.cs" />
<Compile Include="ViewModels\Account\RegisterModel.cs" /> <Compile Include="ViewModels\Account\RegisterModel.cs" />
@@ -270,6 +273,7 @@
<Content Include="Views\Shared\EditorTemplates\EmailAddress.cshtml" /> <Content Include="Views\Shared\EditorTemplates\EmailAddress.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\EmailAddress.cshtml" /> <Content Include="Views\Shared\DisplayTemplates\EmailAddress.cshtml" />
<Content Include="Views\Shared\DisplayTemplates\Boolean.cshtml" /> <Content Include="Views\Shared\DisplayTemplates\Boolean.cshtml" />
<Content Include="Views\Shared\_Roles.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="packages.config"> <Content Include="packages.config">
+1
View File
@@ -11,5 +11,6 @@
<package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net40" /> <package id="Microsoft.AspNet.Razor" version="2.0.20715.0" targetFramework="net40" />
<package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net40" /> <package id="Microsoft.AspNet.WebPages" version="2.0.20710.0" targetFramework="net40" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" /> <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net40" />
<package id="MvcCheckBoxList" version="1.4.3.0" targetFramework="net40" />
<package id="Twitter.Bootstrap" version="2.2.2" targetFramework="net40" /> <package id="Twitter.Bootstrap" version="2.2.2" targetFramework="net40" />
</packages> </packages>