feat(backend): add member GET endpoints, POST /users/@me/members endpoint
This commit is contained in:
parent
16f230b97d
commit
e7ec0e6661
10 changed files with 152 additions and 55 deletions
68
Foxnouns.Backend/Controllers/MembersController.cs
Normal file
68
Foxnouns.Backend/Controllers/MembersController.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using Foxnouns.Backend.Database;
|
||||
using Foxnouns.Backend.Database.Models;
|
||||
using Foxnouns.Backend.Middleware;
|
||||
using Foxnouns.Backend.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Foxnouns.Backend.Controllers;
|
||||
|
||||
[Route("/api/v2/users/{userRef}/members")]
|
||||
public class MembersController(
|
||||
ILogger logger,
|
||||
DatabaseContext db,
|
||||
MemberRendererService memberRendererService,
|
||||
ISnowflakeGenerator snowflakeGenerator) : ApiControllerBase
|
||||
{
|
||||
private readonly ILogger _logger = logger.ForContext<MembersController>();
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType<IEnumerable<MemberRendererService.PartialMember>>(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetMembersAsync(string userRef)
|
||||
{
|
||||
var user = await db.ResolveUserAsync(userRef, CurrentToken);
|
||||
return Ok(await memberRendererService.RenderUserMembersAsync(user, CurrentToken));
|
||||
}
|
||||
|
||||
[HttpGet("{memberRef}")]
|
||||
[ProducesResponseType<MemberRendererService.MemberResponse>(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetMemberAsync(string userRef, string memberRef)
|
||||
{
|
||||
var member = await db.ResolveMemberAsync(userRef, memberRef, CurrentToken);
|
||||
return Ok(memberRendererService.RenderMember(member, CurrentToken));
|
||||
}
|
||||
|
||||
[HttpPost("/api/v2/users/@me/members")]
|
||||
[ProducesResponseType<MemberRendererService.MemberResponse>(StatusCodes.Status200OK)]
|
||||
[Authorize("member.create")]
|
||||
public async Task<IActionResult> CreateMemberAsync([FromBody] CreateMemberRequest req)
|
||||
{
|
||||
await using var tx = await db.Database.BeginTransactionAsync();
|
||||
|
||||
// "Translation of the 'string.Equals' overload with a 'StringComparison' parameter is not supported."
|
||||
// Member names are case-insensitive, so we need to compare the lowercase forms of both.
|
||||
#pragma warning disable CA1862
|
||||
if (await db.Members.AnyAsync(m => m.UserId == CurrentUser!.Id && m.Name.ToLower() == req.Name.ToLower()))
|
||||
#pragma warning restore CA1862
|
||||
{
|
||||
throw new ApiError.BadRequest("A member with that name already exists", "name");
|
||||
}
|
||||
|
||||
var member = new Member
|
||||
{
|
||||
Id = snowflakeGenerator.GenerateSnowflake(),
|
||||
Name = req.Name,
|
||||
User = CurrentUser!
|
||||
};
|
||||
db.Add(member);
|
||||
|
||||
_logger.Debug("Creating member {MemberName} ({Id}) for {UserId}", member.Name, member.Id, CurrentUser!.Id);
|
||||
|
||||
await db.SaveChangesAsync();
|
||||
await tx.CommitAsync();
|
||||
|
||||
return Ok(memberRendererService.RenderMember(member, CurrentToken));
|
||||
}
|
||||
|
||||
public record CreateMemberRequest(string Name);
|
||||
}
|
|
@ -11,7 +11,7 @@ public class MetaController(DatabaseContext db, IClock clock) : ApiControllerBas
|
|||
private const string Repository = "https://codeberg.org/pronounscc/pronouns.cc";
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MetaResponse))]
|
||||
[ProducesResponseType<MetaResponse>(StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetMeta()
|
||||
{
|
||||
var now = clock.GetCurrentInstant();
|
||||
|
|
|
@ -16,16 +16,7 @@ public class UsersController(DatabaseContext db, UserRendererService userRendere
|
|||
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetUserAsync(string userRef)
|
||||
{
|
||||
var user = await db.ResolveUserAsync(userRef);
|
||||
return await GetUserInnerAsync(user);
|
||||
}
|
||||
|
||||
[HttpGet("@me")]
|
||||
[Authorize("identify")]
|
||||
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> GetMeAsync()
|
||||
{
|
||||
var user = await db.ResolveUserAsync(CurrentUser!.Id);
|
||||
var user = await db.ResolveUserAsync(userRef, CurrentToken);
|
||||
return await GetUserInnerAsync(user);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue