#nullable disable
using APP.Models;
using CORE.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages;
// Generated from Custom MVC Template.
namespace MVC.Controllers
{
public class UsersController : Controller
{
// Service injections:
private readonly IService<UserRequest, UserResponse> _userService;
private readonly IService<StatusRequest, StatusResponse> _statusService;
/*
Can be uncommented and used for many to many relationships,
"entity" may be replaced with the related entity name in
the controller and views.
*/
private readonly IService<RoleRequest, RoleResponse> _roleService;
public UsersController(
IService<UserRequest, UserResponse> userService
, IService<StatusRequest, StatusResponse> statusService
/*
Can be uncommented and used for many to many relationships,
"entity" may be replaced with the related entity name
in the controller and views.
*/
, IService<RoleRequest, RoleResponse> roleService
)
{
_userService = userService;
_statusService = statusService;
/*
Can be uncommented and used for many to many relationships,
"entity" may be replaced with the related entity name
in the controller and views.
*/
_roleService = roleService;
}
private void SetViewData()
{
/*
ViewBag and ViewData are the same collection (dictionary).
They carry extra data other than the model from a controller
action to its view, or between views.
*/
// Related items service logic to set ViewData (Id and Name
// parameters may need to be changed in the SelectList constructor
// according to the model):
ViewData["StatusId"] = new SelectList(_statusService.List(),
"Id", "Title"); // Second parameter changed from Name to Title.
/*
Can be uncommented and used for many to many relationships,
"entity" may be replaced with the related entity name
in the controller and views.
*/
ViewBag.RoleIds = new MultiSelectList(_roleService.List(),
"Id", "Name");
}
private void SetTempData(string message, string key = "Message")
{
/*
TempData is used to carry extra data to the redirected controller action's view.
*/
TempData[key] = message;
}
// GET: Users
[Authorize] // Only authenticated users can execute this action.
public IActionResult Index()
{
// Get collection service logic:
var list = _userService.List();
return View(list); // return response collection as model to the Index view
}
// GET: Users/Details/5
[Authorize] // Only authenticated users can execute this action.
public IActionResult Details(int id)
{
// Check if the user is in Admin role or trying to make
// the operation on his/her own account.
if (!IsOwnAccount(id) && !User.IsInRole("Admin"))
{
SetTempData("You are not authorized for this operation!");
return RedirectToAction(nameof(Index));
}
// Get item service logic:
var item = _userService.Single(id);
return View(item); // return response item as model to the Details view
}
// GET: Users/Create
[Authorize(Roles = "Admin")]
// Only authenticated users with role Admin can execute this action.
public IActionResult Create()
{
SetViewData(); // set ViewData dictionary to carry extra data other than the model to the view
return View(); // return Create view with no model
}
// POST: Users/Create
[Authorize(Roles = "Admin")]
// Only authenticated users with role Admin can execute this action.
[HttpPost, ValidateAntiForgeryToken]
public IActionResult Create(UserRequest user)
{
if (ModelState.IsValid) // check data annotation validation errors in the request
{
// Insert item service logic:
var response = _userService.Add(user);
if (response.IsSuccessful)
{
SetTempData(response.Message); // set TempData dictionary to carry the message to the redirected action's view
return RedirectToAction(nameof(Details), new { id = response.Id }); // redirect to Details action with id parameter as response.Id route value
}
ModelState.AddModelError("", response.Message); // to display service error message in the validation summary of the view
}
SetViewData(); // set ViewData dictionary to carry extra data other than the model to the view
return View(user); // return request as model to the Create view
}
// GET: Users/Edit/5
[Authorize] // Only authenticated users can execute this action.
public IActionResult Edit(int id)
{
// Check if the user is in Admin role or trying to make
// the operation on his/her own account.
if (!IsOwnAccount(id) && !User.IsInRole("Admin"))
{
SetTempData("You are not authorized for this operation!");
return RedirectToAction(nameof(Index));
}
// Get item to edit service logic:
var item = _userService.Edit(id);
SetViewData(); // set ViewData dictionary to carry extra data
// other than the model to the view
return View(item); // return request as model to the Edit view
}
// POST: Users/Edit
[HttpPost, ValidateAntiForgeryToken]
[Authorize] // Only authenticated users can execute this action.
public IActionResult Edit(UserRequest user)
{
// Check if the user is in Admin role or trying to make
// the operation on his/her own account.
if (!IsOwnAccount(user.Id) && !User.IsInRole("Admin"))
{
SetTempData("You are not authorized for this operation!");
return RedirectToAction(nameof(Index));
}
// Because we don't get the values for the Score, StatusId and
// RoleIds properties from the user request for users not in
// the Admin role, and Score, StatusId and RoleIds are required,
// we must remove the ModelState errors for these properties
// to prevent validation failures.
if (!User.IsInRole("Admin"))
{
ModelState.Remove(nameof(UserRequest.Score));
ModelState.Remove(nameof(UserRequest.StatusId));
ModelState.Remove(nameof(UserRequest.RoleIds));
}
if (ModelState.IsValid)
// check data annotation validation errors in the request
{
// Update item service logic:
var response = _userService.Update(user);
if (response.IsSuccessful)
{
SetTempData(response.Message);
// set TempData dictionary to carry the message
// to the redirected action's view
return RedirectToAction(nameof(Details),
new { id = response.Id });
// redirect to Details action with id parameter as
// response.Id route value
}
ModelState.AddModelError("", response.Message);
// to display service error message in the
// validation summary of the view
}
SetViewData();
// set ViewData dictionary to carry extra data other than
// the model to the view
return View(user); // return request as model to the Edit view
}
// GET: Users/Delete/5
[Authorize] // Only authenticated users can execute this action.
public IActionResult Delete(int id)
{
// Check if the user is in Admin role or trying to make
// the operation on his/her own account.
if (!IsOwnAccount(id) && !User.IsInRole("Admin"))
{
SetTempData("You are not authorized for this operation!");
return RedirectToAction(nameof(Index));
}
// Get item to delete service logic:
var item = _userService.Single(id);
return View(item);
// return response item as model to the Delete view
}
// POST: Users/Delete
[HttpPost, ValidateAntiForgeryToken, ActionName("Delete")]
[Authorize] // Only authenticated users can execute this action.
public IActionResult DeleteConfirmed(int id)
{
// Check if the user is in Admin role or trying to make
// the operation on his/her own account.
if (!IsOwnAccount(id) && !User.IsInRole("Admin"))
{
SetTempData("You are not authorized for this operation!");
return RedirectToAction(nameof(Index));
}
// Delete item service logic:
var response = _userService.Remove(id);
SetTempData(response.Message);
// set TempData dictionary to carry the message
// to the redirected action's view
// if the user deleted his/her own account, log out the user
if (IsOwnAccount(id))
return RedirectToAction("Logout", "Auth");
return RedirectToAction(nameof(Index));
// redirect to the Index action
}
/// <summary>
/// For regular users can only make operations on their own accounts.
/// </summary>
/// <param name="id">User ID.</param>
/// <returns>bool</returns>
bool IsOwnAccount(int id) // private is default if not written
{
// getting the authenticated user ID value for the claim type
// "Id" from the user's claims and checking if it matches
// the provided id parameter of a user
return id.ToString() == (User.Claims.SingleOrDefault(
claim => claim.Type == "Id")?.Value ?? string.Empty);
}
}
}