ref: project structure
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
using AutoMapper;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using mws.backend.dotnet.application.Common;
|
||||
using mws.backend.dotnet.application.Permissions;
|
||||
using mws.backend.dotnet.application.Users;
|
||||
using mws.backend.dotnet.domain.Users;
|
||||
using mws.backend.dotnet.infrastructure.Persistence;
|
||||
|
||||
namespace mws.backend.dotnet.api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/users")]
|
||||
[Authorize]
|
||||
public class UsersController(ISender sender, AppDbContext db, IPermissionService permissions, IMapper mapper) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PagedResult<UserDto>>> GetAll([FromQuery] string? q, [FromQuery] int page = 1, [FromQuery] int pageSize = 20, CancellationToken ct = default)
|
||||
{
|
||||
return Ok(await sender.Send(new GetUsersQuery(User.GetUserId(), q, page, pageSize), ct));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<UserDto>> Create([FromBody] CreateUserRequest request, CancellationToken ct)
|
||||
{
|
||||
return Ok(await sender.Send(new CreateUserCommand(User.GetUserId(), request), ct));
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
public async Task<ActionResult<UserDto>> Update(Guid id, [FromBody] UpdateUserRequest request, CancellationToken ct)
|
||||
{
|
||||
return Ok(await sender.Send(new UpdateUserCommand(User.GetUserId(), id, request), ct));
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
await sender.Send(new DeleteUserCommand(User.GetUserId(), id), ct);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/reset-password")]
|
||||
public async Task<IActionResult> ResetPassword(Guid id, [FromBody] ResetPasswordRequest request, CancellationToken ct)
|
||||
{
|
||||
await sender.Send(new ResetPasswordCommand(User.GetUserId(), id, request), ct);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("list")]
|
||||
public async Task<ActionResult<List<UserDto>>> GetList([FromQuery] string? q, CancellationToken ct)
|
||||
{
|
||||
var query = db.Users.AsQueryable();
|
||||
if (!string.IsNullOrWhiteSpace(q))
|
||||
{
|
||||
var lower = q.Trim().ToLower();
|
||||
query = query.Where(u => u.Username.ToLower().Contains(lower) || u.DisplayName.ToLower().Contains(lower));
|
||||
}
|
||||
|
||||
var users = await query.OrderBy(u => u.DisplayName).ToListAsync(ct);
|
||||
return Ok(mapper.Map<List<UserDto>>(users));
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/roles")]
|
||||
public async Task<ActionResult<UserRoleDetailDto>> GetUserRoles(Guid id, CancellationToken ct)
|
||||
{
|
||||
await permissions.EnsureAsync(User.GetUserId(), "permissions", PermissionAction.View, ct);
|
||||
|
||||
var user = await db.Users
|
||||
.Include(u => u.UserRoles)
|
||||
.ThenInclude(ur => ur.Role)
|
||||
.FirstOrDefaultAsync(u => u.Id == id, ct);
|
||||
|
||||
if (user is null) return NotFound("User not found");
|
||||
|
||||
var allRoles = await db.Roles.Include(r => r.Permissions).OrderBy(r => r.Name).ToListAsync(ct);
|
||||
var assignedRoleIds = user.UserRoles.Select(ur => ur.RoleId).ToHashSet();
|
||||
|
||||
var assigned = allRoles.Where(r => assignedRoleIds.Contains(r.Id)).ToList();
|
||||
var unassigned = allRoles.Where(r => !assignedRoleIds.Contains(r.Id)).ToList();
|
||||
|
||||
return Ok(new UserRoleDetailDto
|
||||
{
|
||||
UserId = user.Id,
|
||||
Username = user.Username,
|
||||
DisplayName = user.DisplayName,
|
||||
AssignedRoles = mapper.Map<List<RoleDto>>(assigned),
|
||||
UnassignedRoles = mapper.Map<List<RoleDto>>(unassigned)
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/roles")]
|
||||
public async Task<IActionResult> AssignRole(Guid id, [FromBody] AssignRoleRequest req, CancellationToken ct)
|
||||
{
|
||||
await permissions.EnsureAsync(User.GetUserId(), "permissions", PermissionAction.Edit, ct);
|
||||
|
||||
var user = await db.Users.Include(u => u.UserRoles).FirstOrDefaultAsync(u => u.Id == id, ct);
|
||||
if (user is null) return NotFound("User not found");
|
||||
|
||||
if (!user.UserRoles.Any(ur => ur.RoleId == req.RoleId))
|
||||
{
|
||||
user.UserRoles.Add(new UserRole { UserId = id, RoleId = req.RoleId });
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}/roles/{roleId:guid}")]
|
||||
public async Task<IActionResult> UnassignRole(Guid id, Guid roleId, CancellationToken ct)
|
||||
{
|
||||
await permissions.EnsureAsync(User.GetUserId(), "permissions", PermissionAction.Edit, ct);
|
||||
|
||||
var ur = await db.UserRoles.FirstOrDefaultAsync(x => x.UserId == id && x.RoleId == roleId, ct);
|
||||
if (ur != null)
|
||||
{
|
||||
db.UserRoles.Remove(ur);
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/permissions")]
|
||||
public async Task<ActionResult<List<MenuItemDto>>> GetUserPermissions(Guid id, CancellationToken ct)
|
||||
{
|
||||
await permissions.EnsureAsync(User.GetUserId(), "permissions", PermissionAction.View, ct);
|
||||
|
||||
var roleIds = await db.UserRoles.Where(ur => ur.UserId == id).Select(ur => ur.RoleId).ToListAsync(ct);
|
||||
var permissionsList = await db.RolePermissions.Where(p => roleIds.Contains(p.RoleId)).ToListAsync(ct);
|
||||
|
||||
var merged = permissionsList.GroupBy(p => p.Screen).ToDictionary(
|
||||
g => g.Key,
|
||||
g => new
|
||||
{
|
||||
CanView = g.Any(p => p.CanView),
|
||||
CanCreate = g.Any(p => p.CanCreate),
|
||||
CanEdit = g.Any(p => p.CanEdit),
|
||||
CanDelete = g.Any(p => p.CanDelete),
|
||||
}
|
||||
);
|
||||
|
||||
var res = ScreenCatalog.Screens.Select(s =>
|
||||
{
|
||||
merged.TryGetValue(s.Key, out var p);
|
||||
return new MenuItemDto
|
||||
{
|
||||
Key = s.Key,
|
||||
Label = s.Label,
|
||||
Path = s.Path,
|
||||
CanView = p?.CanView ?? false,
|
||||
CanCreate = p?.CanCreate ?? false,
|
||||
CanEdit = p?.CanEdit ?? false,
|
||||
CanDelete = p?.CanDelete ?? false,
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user