password reset added
This commit is contained in:
@@ -1,4 +1,23 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace SportsDivision.Application.DTOs;
|
||||
public class UserDto { public string Id { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string FullName { get; set; } = string.Empty; public string Role { get; set; } = string.Empty; public int? SchoolId { get; set; } public string? SchoolName { get; set; } public bool IsActive { get; set; } }
|
||||
public class UserCreateDto { public string Email { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Role { get; set; } = string.Empty; public int? SchoolId { get; set; } }
|
||||
public class UserUpdateDto { public string Id { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Role { get; set; } = string.Empty; public int? SchoolId { get; set; } public bool IsActive { get; set; } }
|
||||
public class ResetPasswordDto
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string FullName { get; set; } = string.Empty;
|
||||
|
||||
[Required(ErrorMessage = "New password is required.")]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "New Password")]
|
||||
public string NewPassword { get; set; } = string.Empty;
|
||||
|
||||
[Required(ErrorMessage = "Please confirm the new password.")]
|
||||
[DataType(DataType.Password)]
|
||||
[Display(Name = "Confirm Password")]
|
||||
[Compare(nameof(NewPassword), ErrorMessage = "Passwords do not match.")]
|
||||
public string ConfirmPassword { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
@@ -202,6 +202,51 @@ public class UserManagementController : Controller
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> ResetPassword(string id)
|
||||
{
|
||||
var user = await _userManager.FindByIdAsync(id);
|
||||
if (user == null) return NotFound();
|
||||
|
||||
return View(new ResetPasswordDto
|
||||
{
|
||||
Id = user.Id,
|
||||
Email = user.Email ?? string.Empty,
|
||||
FullName = user.FullName
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> ResetPassword(ResetPasswordDto dto)
|
||||
{
|
||||
var user = await _userManager.FindByIdAsync(dto.Id);
|
||||
if (user == null) return NotFound();
|
||||
|
||||
// Keep display fields populated regardless of the posted values.
|
||||
dto.Email = user.Email ?? string.Empty;
|
||||
dto.FullName = user.FullName;
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(dto);
|
||||
}
|
||||
|
||||
var token = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||
var result = await _userManager.ResetPasswordAsync(user, token, dto.NewPassword);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
return View(dto);
|
||||
}
|
||||
|
||||
TempData["SuccessMessage"] = $"Password reset successfully for {user.Email}.";
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
private async Task PopulateDropdowns()
|
||||
{
|
||||
ViewBag.Roles = await _roleManager.Roles.Select(r => r.Name).ToListAsync();
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<th>Role</th>
|
||||
<th>School</th>
|
||||
<th>Status</th>
|
||||
<th style="width: 160px;">Actions</th>
|
||||
<th style="width: 200px;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -78,6 +78,9 @@
|
||||
<a asp-action="Edit" asp-route-id="@user.Id" class="btn btn-sm btn-outline-primary" title="Edit">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<a asp-action="ResetPassword" asp-route-id="@user.Id" class="btn btn-sm btn-outline-secondary" title="Reset Password">
|
||||
<i class="bi bi-key"></i>
|
||||
</a>
|
||||
<form asp-action="ToggleActive" asp-route-id="@user.Id" method="post" class="d-inline">
|
||||
@Html.AntiForgeryToken()
|
||||
@if (user.IsActive)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
@model ResetPasswordDto
|
||||
@{
|
||||
ViewData["Title"] = "Reset Password";
|
||||
}
|
||||
|
||||
<h2 class="page-header">
|
||||
<i class="bi bi-key me-2"></i>Reset Password
|
||||
</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<p class="text-muted">
|
||||
Set a new password for <strong>@Model.FullName</strong> (@Model.Email).
|
||||
The user will need to sign in with this new password.
|
||||
</p>
|
||||
|
||||
<form asp-action="ResetPassword" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
<input asp-for="Id" type="hidden" />
|
||||
<input asp-for="Email" type="hidden" />
|
||||
<input asp-for="FullName" type="hidden" />
|
||||
<div asp-validation-summary="All" class="text-danger mb-3"></div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="NewPassword" class="form-label">New Password</label>
|
||||
<input asp-for="NewPassword" class="form-control" type="password" autocomplete="new-password" required />
|
||||
<span asp-validation-for="NewPassword" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label asp-for="ConfirmPassword" class="form-label">Confirm Password</label>
|
||||
<input asp-for="ConfirmPassword" class="form-control" type="password" autocomplete="new-password" required />
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-key me-1"></i>Reset Password
|
||||
</button>
|
||||
<a asp-action="Index" class="btn btn-outline-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
<partial name="_ValidationScriptsPartial" />
|
||||
}
|
||||
Reference in New Issue
Block a user