- 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
291 lines
8.4 KiB
C#
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();
|
|
}
|