fengling-auth-service/Controllers/RolesController.cs
movingsam d4aff05804 refactor: clean up Member module and update Console
- Remove redundant PointsRule repositories (use single PointsRuleRepository)
- Clean up Member migrations and consolidate to single Init migration
- Update Console frontend API and components for Tenant
- Add H5LinkService for member H5 integration
2026-02-18 23:34:40 +08:00

291 lines
8.4 KiB
C#

using Fengling.AuthService.Data;
using Fengling.AuthService.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
namespace Fengling.AuthService.Controllers;
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class RolesController : ControllerBase
{
private readonly ApplicationDbContext _context;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
private readonly ILogger<RolesController> _logger;
public RolesController(
ApplicationDbContext context,
RoleManager<ApplicationRole> roleManager,
UserManager<ApplicationUser> userManager,
ILogger<RolesController> logger)
{
_context = context;
_roleManager = roleManager;
_userManager = userManager;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<object>> GetRoles(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string? name = null,
[FromQuery] string? tenantId = null)
{
var query = _context.Roles.AsQueryable();
if (!string.IsNullOrEmpty(name))
{
query = query.Where(r => r.Name != null && r.Name.Contains(name));
}
if (!string.IsNullOrEmpty(tenantId))
{
query = query.Where(r => r.TenantId.ToString() == tenantId);
}
var totalCount = await query.CountAsync();
var roles = await query
.OrderByDescending(r => r.CreatedTime)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
var result = new List<object>();
foreach (var role in roles)
{
var users = await _userManager.GetUsersInRoleAsync(role.Name!);
result.Add(new
{
id = role.Id,
name = role.Name,
displayName = role.DisplayName,
description = role.Description,
tenantId = role.TenantId,
isSystem = role.IsSystem,
permissions = role.Permissions,
userCount = users.Count,
createdAt = role.CreatedTime,
});
}
return Ok(new
{
items = result,
totalCount,
page,
pageSize
});
}
[HttpGet("{id}")]
public async Task<ActionResult<ApplicationRole>> GetRole(long id)
{
var role = await _context.Roles.FindAsync(id);
if (role == null)
{
return NotFound();
}
return Ok(new
{
id = role.Id,
name = role.Name,
displayName = role.DisplayName,
description = role.Description,
tenantId = role.TenantId,
isSystem = role.IsSystem,
permissions = role.Permissions,
createdAt = role.CreatedTime,
});
}
[HttpGet("{id}/users")]
public async Task<ActionResult<List<object>>> GetRoleUsers(long id)
{
var role = await _context.Roles.FindAsync(id);
if (role == null)
{
return NotFound();
}
var users = await _userManager.GetUsersInRoleAsync(role.Name!);
var result = users.Select(async u => new
{
id = u.Id,
userName = u.UserName,
email = u.Email,
realName = u.RealName,
tenantId = u.TenantInfo.TenantId,
roles = await _userManager.GetRolesAsync(u),
isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow,
createdAt = u.CreatedTime,
});
return Ok(await Task.WhenAll(result));
}
[HttpPost]
public async Task<ActionResult<ApplicationRole>> CreateRole(CreateRoleDto dto)
{
var role = new ApplicationRole
{
Name = dto.Name,
DisplayName = dto.DisplayName,
Description = dto.Description,
TenantId = dto.TenantId,
Permissions = dto.Permissions,
IsSystem = false,
CreatedTime = DateTime.UtcNow,
};
var result = await _roleManager.CreateAsync(role);
if (!result.Succeeded)
{
return BadRequest(result.Errors);
}
await CreateAuditLog("role", "create", "Role", role.Id, role.DisplayName, null, SerializeToJson(dto));
return CreatedAtAction(nameof(GetRole), new { id = role.Id }, role);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateRole(long id, UpdateRoleDto dto)
{
var role = await _context.Roles.FindAsync(id);
if (role == null)
{
return NotFound();
}
if (role.IsSystem)
{
return BadRequest("系统角色不能修改");
}
var oldValue = System.Text.Json.JsonSerializer.Serialize(role);
role.DisplayName = dto.DisplayName;
role.Description = dto.Description;
role.Permissions = dto.Permissions;
await _context.SaveChangesAsync();
await CreateAuditLog("role", "update", "Role", role.Id, role.DisplayName, oldValue, System.Text.Json.JsonSerializer.Serialize(role));
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteRole(long id)
{
var role = await _context.Roles.FindAsync(id);
if (role == null)
{
return NotFound();
}
if (role.IsSystem)
{
return BadRequest("系统角色不能删除");
}
var oldValue = System.Text.Json.JsonSerializer.Serialize(role);
var users = await _userManager.GetUsersInRoleAsync(role.Name!);
foreach (var user in users)
{
await _userManager.RemoveFromRoleAsync(user, role.Name!);
}
_context.Roles.Remove(role);
await _context.SaveChangesAsync();
await CreateAuditLog("role", "delete", "Role", role.Id, role.DisplayName, oldValue);
return NoContent();
}
[HttpDelete("{id}/users/{userId}")]
public async Task<IActionResult> RemoveUserFromRole(long id, long userId)
{
var role = await _context.Roles.FindAsync(id);
if (role == null)
{
return NotFound();
}
var user = await _userManager.FindByIdAsync(userId.ToString());
if (user == null)
{
return NotFound();
}
var result = await _userManager.RemoveFromRoleAsync(user, role.Name!);
if (!result.Succeeded)
{
return BadRequest(result.Errors);
}
await CreateAuditLog("role", "update", "UserRole", null, $"{role.Name} - {user.UserName}");
return NoContent();
}
private async Task CreateAuditLog(string operation, string action, string targetType, long? targetId, string? targetName, string? oldValue = null, string? newValue = null)
{
var userName = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.Identity?.Name ?? "system";
var tenantId = User.FindFirstValue("TenantId");
var log = new AuditLog
{
Operator = userName,
TenantId = tenantId,
Operation = operation,
Action = action,
TargetType = targetType,
TargetId = targetId,
TargetName = targetName,
IpAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown",
Status = "success",
OldValue = oldValue,
NewValue = newValue,
};
_context.AuditLogs.Add(log);
await _context.SaveChangesAsync();
}
private string SerializeToJson(object obj)
{
return System.Text.Json.JsonSerializer.Serialize(obj, new System.Text.Json.JsonSerializerOptions
{
WriteIndented = false
});
}
}
public class CreateRoleDto
{
public string Name { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public string? Description { get; set; }
public long? TenantId { get; set; }
public List<string> Permissions { get; set; } = new();
}
public class UpdateRoleDto
{
public string DisplayName { get; set; } = string.Empty;
public string? Description { get; set; }
public List<string> Permissions { get; set; } = new();
}