Skip to content

Commit

Permalink
Can now manually change a user's password via User Administration.
Browse files Browse the repository at this point in the history
  • Loading branch information
troygoode committed Sep 2, 2010
1 parent 3e87d25 commit c287eb3
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 21 deletions.
5 changes: 3 additions & 2 deletions README.markdown
Expand Up @@ -40,8 +40,9 @@ instructions:

1. Make sure you've configured your `web.config` properly for Membership and Roles. If you aren't sure of how to do this, take a look at the first two articles in [this series by Scott Mitchell at 4GuysFromRolla](http://www.4guysfromrolla.com/articles/120705-1.aspx). *Hint:* Use C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe, and then grant your web site's application pool user access to the database.
2. Change the "Administrator" value of the `Authorize` attribute in the `UserAdministrationController.cs` file (line 11) to whatever role you want to require a user to have in order to view/use the User Administration area. If a user tries to navigate to the User Administration area without this role, they will be redirected to the login page (even if they're already logged in).
3. Make sure the user identity of your application pool has sufficient permissions to the aspnet database.
4. Add the following code to your `global.asax` to keep the membership system updated with each user's last activity date:
3. Configure the `system.net/mailSettings/smtp` node in your web.config file with the appropriate SMTP settings so that emails can be sent for password change/reset events.
4. Make sure the user identity of your application pool has sufficient permissions to the aspnet database.
5. Add the following code to your `global.asax` to keep the membership system updated with each user's last activity date:
<pre>
protected void Application_AuthenticateRequest()
{
Expand Down
72 changes: 71 additions & 1 deletion SampleWebsite.Tests/UserAdministrationControllerFacts.cs
Expand Up @@ -6,6 +6,7 @@
using System.Web.Security;
using Moq;
using MvcMembership;
using MvcMembership.Settings;
using PagedList;
using SampleWebsite.Areas.UserAdministration.Controllers;
using SampleWebsite.Areas.UserAdministration.Models.UserAdministration;
Expand All @@ -17,14 +18,15 @@ namespace SampleWebsite.Tests
public class UserAdministrationControllerFacts
{
private readonly UserAdministrationController _controller;
private readonly Mock<IMembershipSettings> _membershipSettings = new Mock<IMembershipSettings>();
private readonly Mock<IUserService> _userService = new Mock<IUserService>();
private readonly Mock<IPasswordService> _passwordService = new Mock<IPasswordService>();
private readonly Mock<IRolesService> _rolesService = new Mock<IRolesService>();
private readonly Mock<ISmtpClient> _smtpClient = new Mock<ISmtpClient>();

public UserAdministrationControllerFacts()
{
_controller = new UserAdministrationController(_userService.Object, _passwordService.Object, _rolesService.Object, _smtpClient.Object);
_controller = new UserAdministrationController(_membershipSettings.Object, _userService.Object, _passwordService.Object, _rolesService.Object, _smtpClient.Object);
}

[Fact]
Expand Down Expand Up @@ -176,6 +178,7 @@ public void Role_looks_up_users_in_role_and_passes_to_view()
public void Details_returns_default_view()
{
//arrange
_membershipSettings.SetupGet(x => x.Password.ResetOrRetrieval.CanReset).Returns(true);
_userService.Setup(x => x.Get(It.IsAny<Guid>())).Returns(new Mock<MembershipUser>().Object);

//act
Expand All @@ -192,6 +195,7 @@ public void Details_looks_MembershipUser_up_by_id_and_passes_to_view()
//arrange
var id = Guid.NewGuid();
var user = new Mock<MembershipUser>().Object;
_membershipSettings.SetupGet(x => x.Password.ResetOrRetrieval.CanReset).Returns(true);
_userService.Setup(x => x.Get(id)).Returns(user).Verifiable();

//act
Expand All @@ -207,6 +211,7 @@ public void Details_looks_MembershipUser_up_by_id_and_passes_to_view()
public void Details_looks_roles_up_by_username_and_passes_to_view()
{
//arrange
_membershipSettings.SetupGet(x => x.Password.ResetOrRetrieval.CanReset).Returns(true);
var id = Guid.NewGuid();
var username = new Random().Next().ToString();
var user = new Mock<MembershipUser>();
Expand Down Expand Up @@ -234,6 +239,7 @@ public void Details_looks_roles_up_by_username_and_passes_to_view()
public void Details_uses_UserName_as_DisplayName()
{
//arrange
_membershipSettings.SetupGet(x => x.Password.ResetOrRetrieval.CanReset).Returns(true);
var id = Guid.NewGuid();
const string username = "Lorem Ipsum";
var user = new Mock<MembershipUser>();
Expand Down Expand Up @@ -459,6 +465,70 @@ public void ResetPassword_sends_new_password_to_user_via_email()
Assert.True(emailIsValid);
}

[Fact]
public void ChangePassword_redirects_to_Details()
{
//arrange
var id = Guid.NewGuid();
var user = new Mock<MembershipUser>();
user.SetupGet(x => x.Email).Returns(new Random().Next() + "@domain.com");
_userService.Setup(x => x.Get(id)).Returns(user.Object);

//act
var result = _controller.ChangePassword(id, string.Empty);

//assert
Assert.Equal("Details", result.RouteValues["action"]);
Assert.Null(result.RouteValues["controller"]);
Assert.Equal(id, result.RouteValues["id"]);
}

[Fact]
public void ChangePassword_calls_ChangePassword_method_and_passes_new_password()
{
//arrange
var id = Guid.NewGuid();
var password = new Random().Next().ToString();
var user = new Mock<MembershipUser>();
user.SetupGet(x => x.Email).Returns(new Random().Next() + "@domain.com");
_userService.Setup(x => x.Get(id)).Returns(user.Object);

//act
_controller.ChangePassword(id, password);

//assert
_passwordService.Verify(x => x.ChangePassword(user.Object, password));
}

[Fact]
public void ChangePassword_sends_new_password_to_user_via_email()
{
//arrange
var id = Guid.NewGuid();
//arrange - generate new password
var newPassword = new Random().Next().ToString();
var emailAddress = new Random().Next() + "@domain.com";
//arrange - retrieve user & email address
var user = new Mock<MembershipUser>();
user.SetupGet(x => x.Email).Returns(emailAddress);
_userService.Setup(x => x.Get(id)).Returns(user.Object);
//arrange - verify the message that is sent to the user
var emailIsValid = false;
_smtpClient.Setup(x => x.Send(It.IsAny<MailMessage>())).Callback<MailMessage>(msg =>
{
if (msg.To.Count == 1 &&
msg.To[0].Address == emailAddress &&
msg.Body.Contains(newPassword))
emailIsValid = true;
});

//act
_controller.ChangePassword(id, newPassword);

//assert
Assert.True(emailIsValid);
}

[Fact]
public void AddToRole_redirects_to_details()
{
Expand Down
Expand Up @@ -4,6 +4,7 @@
using System.Web.Mvc;
using System.Web.Security;
using MvcMembership;
using MvcMembership.Settings;
using SampleWebsite.Areas.UserAdministration.Models.UserAdministration;

namespace SampleWebsite.Areas.UserAdministration.Controllers
Expand All @@ -17,11 +18,13 @@ public class UserAdministrationController : Controller
private const string ResetPasswordSubject = "Your New Password";
private readonly IRolesService _rolesService;
private readonly ISmtpClient _smtpClient;
private readonly IMembershipSettings _membershipSettings;
private readonly IUserService _userService;
private readonly IPasswordService _passwordService;

public UserAdministrationController()
: this(
new AspNetMembershipProviderSettingsWrapper(Membership.Provider),
new AspNetMembershipProviderWrapper(Membership.Provider),
new AspNetMembershipProviderWrapper(Membership.Provider),
new AspNetRoleProviderWrapper(Roles.Provider),
Expand All @@ -30,11 +33,13 @@ public UserAdministrationController()
}

public UserAdministrationController(
IMembershipSettings membershipSettings,
IUserService userService,
IPasswordService passwordService,
IRolesService rolesService,
ISmtpClient smtpClient)
{
_membershipSettings = membershipSettings;
_userService = userService;
_passwordService = passwordService;
_rolesService = rolesService;
Expand Down Expand Up @@ -79,6 +84,7 @@ public ViewResult Details(Guid id)
var userRoles = _rolesService.FindByUser(user);
return View(new DetailsViewModel
{
AllowChangePassword = _membershipSettings.Password.ResetOrRetrieval.CanReset,
DisplayName = user.UserName,
User = user,
Roles = _rolesService.FindAll().ToDictionary(role => role, role => userRoles.Contains(role)),
Expand Down Expand Up @@ -139,6 +145,18 @@ public RedirectToRouteResult ResetPassword(Guid id, string answer)
return RedirectToAction("Details", new { id });
}

[AcceptVerbs(HttpVerbs.Post)]
public RedirectToRouteResult ChangePassword(Guid id, string password)
{
var user = _userService.Get(id);
_passwordService.ChangePassword(user, password);

var body = ResetPasswordBody + password;
_smtpClient.Send(new MailMessage(ResetPasswordFromAddress, user.Email, ResetPasswordSubject, body));

return RedirectToAction("Details", new { id });
}

[AcceptVerbs(HttpVerbs.Post)]
public RedirectToRouteResult AddToRole(Guid id, string role)
{
Expand Down
Expand Up @@ -20,6 +20,7 @@ public enum StatusEnum
public string DisplayName { get; set; }
public StatusEnum Status { get; set; }
public MembershipUser User { get; set; }
public bool AllowChangePassword { get; set; }
public IDictionary<string, bool> Roles { get; set; }
}
}
Expand Up @@ -78,24 +78,36 @@
</dl>
<% } %>

<% using(Html.BeginForm("ResetPassword", "UserAdministration", new{ id = Model.User.ProviderUserKey })){ %>
<fieldset>
<p>
<dl class="mvcMembership">
<dt>Password Question:</dt>
<% if(string.IsNullOrEmpty(Model.User.PasswordQuestion) || string.IsNullOrEmpty(Model.User.PasswordQuestion.Trim())){ %>
<dd><em>No password question defined.</em></dd>
<% }else{ %>
<dd><%: Model.User.PasswordQuestion %></dd>
<% } %>
</dl>
</p>
<p>
<label for="answer">Password Answer:</label>
<% =Html.TextBox("answer") %>
</p>
<input type="submit" value="Reset Password" />
</fieldset>
<% if(Model.AllowChangePassword){ %>
<% using(Html.BeginForm("ChangePassword", "UserAdministration", new{ id = Model.User.ProviderUserKey })){ %>
<fieldset>
<p>
<label for="password">New Password:</label>
<% =Html.TextBox("password") %>
</p>
<input type="submit" value="Change Password" />
</fieldset>
<% } %>
<% }else{ %>
<% using(Html.BeginForm("ResetPassword", "UserAdministration", new{ id = Model.User.ProviderUserKey })){ %>
<fieldset>
<p>
<dl class="mvcMembership">
<dt>Password Question:</dt>
<% if(string.IsNullOrEmpty(Model.User.PasswordQuestion) || string.IsNullOrEmpty(Model.User.PasswordQuestion.Trim())){ %>
<dd><em>No password question defined.</em></dd>
<% }else{ %>
<dd><%: Model.User.PasswordQuestion %></dd>
<% } %>
</dl>
</p>
<p>
<label for="answer">Password Answer:</label>
<% =Html.TextBox("answer") %>
</p>
<input type="submit" value="Reset Password" />
</fieldset>
<% } %>
<% } %>

<% } %>
Expand Down

0 comments on commit c287eb3

Please sign in to comment.