feat: GET /api/v1/users/@me

This commit is contained in:
sam 2024-12-25 16:04:32 -05:00
parent 478ba2a406
commit fe1cf7ce8a
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
3 changed files with 121 additions and 0 deletions

View file

@ -15,6 +15,7 @@
using Foxnouns.Backend.Database; using Foxnouns.Backend.Database;
using Foxnouns.Backend.Database.Models; using Foxnouns.Backend.Database.Models;
using Foxnouns.Backend.Dto.V1; using Foxnouns.Backend.Dto.V1;
using Foxnouns.Backend.Middleware;
using Foxnouns.Backend.Services.V1; using Foxnouns.Backend.Services.V1;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -28,6 +29,14 @@ public class V1ReadController(
DatabaseContext db DatabaseContext db
) : ApiControllerBase ) : ApiControllerBase
{ {
[HttpGet("users/@me")]
[Authorize("identify")]
public async Task<IActionResult> GetMeAsync(CancellationToken ct = default)
{
User user = await usersV1Service.ResolveUserAsync("@me", CurrentToken, ct);
return Ok(await usersV1Service.RenderCurrentUserAsync(user, ct));
}
[HttpGet("users/{userRef}")] [HttpGet("users/{userRef}")]
public async Task<IActionResult> GetUserAsync(string userRef, CancellationToken ct = default) public async Task<IActionResult> GetUserAsync(string userRef, CancellationToken ct = default)
{ {

View file

@ -20,6 +20,7 @@ using Foxnouns.Backend.Services.V1;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using NodaTime;
namespace Foxnouns.Backend.Dto.V1; namespace Foxnouns.Backend.Dto.V1;
@ -42,6 +43,39 @@ public record UserResponse(
Dictionary<Guid, CustomPreference> CustomPreferences Dictionary<Guid, CustomPreference> CustomPreferences
); );
public record CurrentUserResponse(
string Id,
Snowflake IdNew,
string Sid,
string Name,
string? DisplayName,
string? Bio,
string? MemberTitle,
string? Avatar,
string[] Links,
FieldEntry[] Names,
PronounEntry[] Pronouns,
ProfileField[] Fields,
PrideFlag[] Flags,
PartialMember[] Members,
int? UtcOffset,
Dictionary<Guid, CustomPreference> CustomPreferences,
Instant CreatedAt,
string? Timezone,
bool IsAdmin,
bool ListPrivate,
Instant LastSidReroll,
string? Discord,
string? DiscordUsername,
string? Google,
string? GoogleUsername,
string? Tumblr,
string? TumblrUsername,
string? Fediverse,
string? FediverseUsername,
string? FediverseInstance
);
public record CustomPreference( public record CustomPreference(
string Icon, string Icon,
string Tooltip, string Tooltip,

View file

@ -122,6 +122,84 @@ public class UsersV1Service(DatabaseContext db)
); );
} }
public async Task<CurrentUserResponse> RenderCurrentUserAsync(
User user,
CancellationToken ct = default
)
{
List<Member> members = await db
.Members.Where(m => m.UserId == user.Id)
.OrderBy(m => m.Name)
.ToListAsync(ct);
List<UserFlag> flags = await db
.UserFlags.Where(f => f.UserId == user.Id)
.OrderBy(f => f.Id)
.ToListAsync(ct);
int? utcOffset = null;
if (
user.Timezone != null
&& TimeZoneInfo.TryFindSystemTimeZoneById(user.Timezone, out TimeZoneInfo? tz)
)
{
utcOffset = (int)tz.GetUtcOffset(DateTimeOffset.UtcNow).TotalSeconds;
}
List<AuthMethod> authMethods = await db
.AuthMethods.Include(a => a.FediverseApplication)
.Where(a => a.UserId == user.Id)
.OrderBy(a => a.Id)
.ToListAsync(ct);
AuthMethod? discord = authMethods.FirstOrDefault(a => a.AuthType is AuthType.Discord);
AuthMethod? google = authMethods.FirstOrDefault(a => a.AuthType is AuthType.Google);
AuthMethod? tumblr = authMethods.FirstOrDefault(a => a.AuthType is AuthType.Tumblr);
AuthMethod? fediverse = authMethods.FirstOrDefault(a => a.AuthType is AuthType.Fediverse);
return new CurrentUserResponse(
user.LegacyId,
user.Id,
user.Sid,
user.Username,
user.DisplayName,
user.Bio,
user.MemberTitle,
user.Avatar,
user.Links,
Names: FieldEntry.FromEntries(user.Names, user.CustomPreferences),
Pronouns: PronounEntry.FromPronouns(user.Pronouns, user.CustomPreferences),
Fields: ProfileField.FromFields(user.Fields, user.CustomPreferences),
Flags: flags
.Where(f => f.PrideFlag.Hash != null)
.Select(f => new PrideFlag(
f.PrideFlag.LegacyId,
f.PrideFlag.Id,
f.PrideFlag.Hash!,
f.PrideFlag.Name,
f.PrideFlag.Description
))
.ToArray(),
Members: members.Select(m => RenderPartialMember(m, user.CustomPreferences)).ToArray(),
utcOffset,
CustomPreferences: RenderCustomPreferences(user.CustomPreferences),
user.Id.Time,
user.Timezone,
user.Role is UserRole.Admin,
user.ListHidden,
user.LastSidReroll,
discord?.RemoteId,
discord?.RemoteUsername,
google?.RemoteId,
google?.RemoteUsername,
tumblr?.RemoteId,
tumblr?.RemoteUsername,
fediverse?.RemoteId,
fediverse?.RemoteUsername,
fediverse?.FediverseApplication?.Domain
);
}
private static Dictionary<Guid, CustomPreference> RenderCustomPreferences( private static Dictionary<Guid, CustomPreference> RenderCustomPreferences(
Dictionary<Snowflake, User.CustomPreference> customPreferences Dictionary<Snowflake, User.CustomPreference> customPreferences
) => ) =>