diff --git a/Foxnouns.Backend/Controllers/V1/UsersV1Controller.cs b/Foxnouns.Backend/Controllers/V1/V1ReadController.cs similarity index 82% rename from Foxnouns.Backend/Controllers/V1/UsersV1Controller.cs rename to Foxnouns.Backend/Controllers/V1/V1ReadController.cs index 51e2b17..5f69c20 100644 --- a/Foxnouns.Backend/Controllers/V1/UsersV1Controller.cs +++ b/Foxnouns.Backend/Controllers/V1/V1ReadController.cs @@ -22,7 +22,7 @@ using Microsoft.EntityFrameworkCore; namespace Foxnouns.Backend.Controllers.V1; [Route("/api/v1")] -public class UsersV1Controller( +public class V1ReadController( UsersV1Service usersV1Service, MembersV1Service membersV1Service, DatabaseContext db @@ -85,4 +85,27 @@ public class UsersV1Controller( return Ok(responses); } + + [HttpGet("users/{userRef}/members/{memberRef}")] + public async Task GetUserMemberAsync( + string userRef, + string memberRef, + CancellationToken ct = default + ) + { + Member member = await membersV1Service.ResolveMemberAsync( + userRef, + memberRef, + CurrentToken, + ct + ); + return Ok( + await membersV1Service.RenderMemberAsync( + member, + CurrentToken, + renderFlags: true, + ct: ct + ) + ); + } } diff --git a/Foxnouns.Backend/Services/V1/MembersV1Service.cs b/Foxnouns.Backend/Services/V1/MembersV1Service.cs index b11a510..632226c 100644 --- a/Foxnouns.Backend/Services/V1/MembersV1Service.cs +++ b/Foxnouns.Backend/Services/V1/MembersV1Service.cs @@ -21,7 +21,7 @@ using PrideFlag = Foxnouns.Backend.Dto.V1.PrideFlag; namespace Foxnouns.Backend.Services.V1; -public class MembersV1Service(DatabaseContext db) +public class MembersV1Service(DatabaseContext db, UsersV1Service usersV1Service) { public async Task ResolveMemberAsync(string id, CancellationToken ct = default) { @@ -44,6 +44,43 @@ public class MembersV1Service(DatabaseContext db) throw new ApiError.NotFound("No member with that ID found.", ErrorCode.MemberNotFound); } + public async Task ResolveMemberAsync( + string userRef, + string memberRef, + Token? token, + CancellationToken ct = default + ) + { + User user = await usersV1Service.ResolveUserAsync(userRef, token, ct); + + Member? member; + if (Snowflake.TryParse(memberRef, out Snowflake? sf)) + { + member = await db + .Members.Include(m => m.User) + .FirstOrDefaultAsync(m => m.Id == sf && m.UserId == user.Id, ct); + if (member != null) + return member; + } + + member = await db + .Members.Include(m => m.User) + .FirstOrDefaultAsync(m => m.LegacyId == memberRef && m.UserId == user.Id, ct); + if (member != null) + return member; + + member = await db + .Members.Include(m => m.User) + .FirstOrDefaultAsync(m => m.Name == memberRef && m.UserId == user.Id, ct); + if (member != null) + return member; + + throw new ApiError.NotFound( + "No member with that ID or name found.", + ErrorCode.MemberNotFound + ); + } + public async Task RenderMemberAsync( Member m, Token? token = default,