fix: align backend APIs and upload flow

This commit is contained in:
2026-09-15 14:10:55 +08:00
parent 32177a7293
commit 53e6195938
149 changed files with 4791 additions and 435 deletions
@@ -32,7 +32,8 @@ namespace GroupService.WebApi.Controllers.Group
[ProducesDefaultResponseType(typeof(Result<GroupResponse>))]
public async Task<IActionResult> GetOne(Guid groupId)
{
return Ok(await service.GetByIdAsync(groupId));
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
return Ok(await service.GetByIdAsync(groupId, Guid.Parse(userId)));
}
[HttpPost]
@@ -49,5 +50,13 @@ namespace GroupService.WebApi.Controllers.Group
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
return Ok(await service.UpdateAsync(new GroupUpdateCommand(Guid.Parse(userId), request.GroupId, request.Avatar, request.GroupName, request.Description)));
}
[HttpPost]
[UnitOfWork(typeof(GroupDbContext))]
public async Task<IActionResult> Dissolve([FromQuery] Guid groupId)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
return Ok(await service.DissolveAsync(groupId, Guid.Parse(userId)));
}
}
}
@@ -1,6 +1,8 @@
using GroupService.Infrastructure;
using GroupService.WebApi.Application.GroupMember;
using IM.ASPNETCore;
using IM.Commons;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
@@ -11,25 +13,36 @@ namespace GroupService.WebApi.Controllers.GroupMember
public class GroupMemberController : ControllerBase
{
private readonly GroupMemberService service;
private readonly IConfiguration configuration;
public GroupMemberController(GroupMemberService service)
public GroupMemberController(GroupMemberService service, IConfiguration configuration)
{
this.service = service;
this.configuration = configuration;
}
[HttpGet]
public async Task<IActionResult> CheckMember(Guid userId, Guid groupId)
{
var expectedKey = configuration["InternalApiKey"];
var suppliedKey = Request.Headers["X-Internal-Api-Key"].ToString();
if (string.IsNullOrWhiteSpace(expectedKey) || suppliedKey != expectedKey)
{
return Unauthorized(Result.Fail(ResultCode.AUTH_FAILED));
}
return Ok(await service.CheckMemberAsync(groupId, userId));
}
[HttpGet]
[Authorize]
public async Task<IActionResult> List(Guid groupId)
{
return Ok(await service.GetByGroupIdAsync(groupId));
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
return Ok(await service.GetByGroupIdAsync(groupId, Guid.Parse(userId)));
}
[HttpPost]
[Authorize]
[UnitOfWork(typeof(GroupDbContext))]
public async Task<IActionResult> Delete([FromQuery] Guid memberId)
{
@@ -37,6 +50,15 @@ namespace GroupService.WebApi.Controllers.GroupMember
return Ok(await service.DeleteAsync(memberId, Guid.Parse(userId)));
}
[HttpPost]
[Authorize]
[UnitOfWork(typeof(GroupDbContext))]
public async Task<IActionResult> Leave([FromQuery] Guid groupId)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
return Ok(await service.LeaveAsync(groupId, Guid.Parse(userId)));
}
}
}
@@ -0,0 +1,40 @@
using GroupService.Infrastructure;
using GroupService.Domain.Enums;
using IM.InitCommon.Management;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace GroupService.WebApi.Controllers;
[ApiController, Route("internal/management")]
public sealed class ManagementController(GroupDbContext db) : ControllerBase
{
[HttpGet("summary")] public async Task<object> Summary() => new { total = await db.Groups.CountAsync() };
[HttpGet("list")] public async Task<object> List(string? q, string? status, int page = 1, int size = 8)
{
page = Math.Max(1, page); size = Math.Clamp(size, 1, 100);
var query = db.Groups.AsNoTracking().Where(x => q == null || x.Name.Contains(q) || x.Id.ToString() == q || x.GroupMaster.ToString() == q || db.GroupMembers.Any(m => m.GroupId == x.Id && m.UserId == x.GroupMaster && m.GroupNickName.Contains(q)));
if (!string.IsNullOrEmpty(status)) query = query.Where(x => x.Status == (status == "封禁" ? GroupState.Blocked : GroupState.Normal));
return new { items = await query.OrderByDescending(x => x.CreationTime).Skip((page - 1) * size).Take(size).Select(x => new { x.Id, x.Name, ownerId = x.GroupMaster, ownerName = db.GroupMembers.Where(m => m.GroupId == x.Id && m.UserId == x.GroupMaster).Select(m => m.GroupNickName).FirstOrDefault(), memberCount = db.GroupMembers.Count(m => m.GroupId == x.Id), status = x.Status == GroupState.Blocked ? "封禁" : "正常", createdAt = x.CreationTime }).ToListAsync(), total = await query.CountAsync(), page, size };
}
[HttpGet("detail/{id:guid}")] public async Task<IActionResult> Detail(Guid id)
{
var g = await db.Groups.AsNoTracking().SingleOrDefaultAsync(x => x.Id == id); if (g is null) return NotFound();
return Ok(new { g.Id, g.Name, ownerId = g.GroupMaster, g.Announcement, authority = g.Authority, memberCount = await db.GroupMembers.CountAsync(x => x.GroupId == id), status = g.Status == GroupState.Blocked ? "封禁" : "正常", createdAt = g.CreationTime });
}
[HttpGet("members/{id:guid}")] public async Task<object> Members(Guid id, string? q, int page = 1, int size = 8)
{
page = Math.Max(1, page); size = Math.Clamp(size, 1, 100); var query = db.GroupMembers.AsNoTracking().Where(x => x.GroupId == id && (q == null || x.GroupNickName.Contains(q) || x.UserId.ToString() == q));
return new { items = await query.OrderBy(x => x.UserId).Skip((page - 1) * size).Take(size).Select(x => new { id = x.UserId, name = x.GroupNickName, x.Role }).ToListAsync(), total = await query.CountAsync(), page, size };
}
[HttpGet("user/{id:guid}/groups")] public async Task<object> UserGroups(Guid id) => await db.Groups.Where(x => db.GroupMembers.Any(m => m.GroupId == x.Id && m.UserId == id)).Select(x => new { x.Id, x.Name, status = x.Status == GroupState.Blocked ? "封禁" : "正常" }).Take(100).ToListAsync();
[HttpGet("access/{id:guid}/{userId:guid}")] public async Task<object> Access(Guid id, Guid userId) => new { exists = await db.Groups.AnyAsync(x => x.Id == id), enabled = await db.Groups.AnyAsync(x => x.Id == id && x.Status == GroupState.Normal), member = await db.GroupMembers.AnyAsync(x => x.GroupId == id && x.UserId == userId) };
[HttpPost("action")] public async Task<IActionResult> Action(InternalAction command, CancellationToken ct)
{
if (command.Action is not "封禁" and not "解封") return BadRequest();
return Ok(await ReceiptStore.Execute(db, command, async () => {
var g = await db.Groups.SingleOrDefaultAsync(x => x.Id == command.TargetId, ct) ?? throw new InvalidOperationException("群组不存在");
var before = g.Status == GroupState.Blocked ? "封禁" : "正常"; if (command.Action == "封禁") g.Ban(notify: false); else g.Unban();
return new ActionReceipt(g.Name, before, command.Action == "封禁" ? "封禁" : "正常");
}, ct));
}
}