feat(backend): add short ID reroll endpoints
This commit is contained in:
parent
e76c634738
commit
b5f9ef9bd6
3 changed files with 61 additions and 2 deletions
|
@ -9,6 +9,7 @@ using Foxnouns.Backend.Services;
|
||||||
using Foxnouns.Backend.Utils;
|
using Foxnouns.Backend.Utils;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NodaTime;
|
||||||
|
|
||||||
namespace Foxnouns.Backend.Controllers;
|
namespace Foxnouns.Backend.Controllers;
|
||||||
|
|
||||||
|
@ -19,7 +20,8 @@ public class MembersController(
|
||||||
MemberRendererService memberRenderer,
|
MemberRendererService memberRenderer,
|
||||||
ISnowflakeGenerator snowflakeGenerator,
|
ISnowflakeGenerator snowflakeGenerator,
|
||||||
ObjectStorageService objectStorageService,
|
ObjectStorageService objectStorageService,
|
||||||
IQueue queue) : ApiControllerBase
|
IQueue queue,
|
||||||
|
IClock clock) : ApiControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger = logger.ForContext<MembersController>();
|
private readonly ILogger _logger = logger.ForContext<MembersController>();
|
||||||
|
|
||||||
|
@ -114,4 +116,25 @@ public class MembersController(
|
||||||
List<FieldEntry>? Names,
|
List<FieldEntry>? Names,
|
||||||
List<Pronoun>? Pronouns,
|
List<Pronoun>? Pronouns,
|
||||||
List<Field>? Fields);
|
List<Field>? Fields);
|
||||||
|
|
||||||
|
[HttpPost("/api/v2/users/@me/members/{memberRef}/reroll-sid")]
|
||||||
|
[Authorize("member.update")]
|
||||||
|
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
||||||
|
public async Task<IActionResult> RerollSidAsync(string memberRef)
|
||||||
|
{
|
||||||
|
var member = await db.ResolveMemberAsync(CurrentUser!.Id, memberRef);
|
||||||
|
|
||||||
|
var minTimeAgo = clock.GetCurrentInstant() - Duration.FromHours(1);
|
||||||
|
if (CurrentUser!.LastSidReroll > minTimeAgo)
|
||||||
|
throw new ApiError.BadRequest("Cannot reroll short ID yet");
|
||||||
|
|
||||||
|
await db.Members.Where(m => m.Id == member.Id)
|
||||||
|
.ExecuteUpdateAsync(s => s
|
||||||
|
.SetProperty(m => m.Sid, _ => db.FindFreeMemberSid()));
|
||||||
|
|
||||||
|
// Re-fetch member so we can be sure the sid is correct
|
||||||
|
var updatedMember = await db.ResolveMemberAsync(CurrentUser!.Id, memberRef);
|
||||||
|
|
||||||
|
return Ok(memberRenderer.RenderMember(updatedMember, CurrentToken));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ using Foxnouns.Backend.Services;
|
||||||
using Foxnouns.Backend.Utils;
|
using Foxnouns.Backend.Utils;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NodaTime;
|
||||||
|
|
||||||
namespace Foxnouns.Backend.Controllers;
|
namespace Foxnouns.Backend.Controllers;
|
||||||
|
|
||||||
|
@ -16,7 +17,8 @@ public class UsersController(
|
||||||
DatabaseContext db,
|
DatabaseContext db,
|
||||||
UserRendererService userRenderer,
|
UserRendererService userRenderer,
|
||||||
ISnowflakeGenerator snowflakeGenerator,
|
ISnowflakeGenerator snowflakeGenerator,
|
||||||
IQueue queue) : ApiControllerBase
|
IQueue queue,
|
||||||
|
IClock clock) : ApiControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet("{userRef}")]
|
[HttpGet("{userRef}")]
|
||||||
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
||||||
|
@ -213,4 +215,22 @@ public class UsersController(
|
||||||
{
|
{
|
||||||
public bool? DarkMode { get; init; }
|
public bool? DarkMode { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("@me/reroll-sid")]
|
||||||
|
[Authorize("user.update")]
|
||||||
|
[ProducesResponseType<UserRendererService.UserResponse>(statusCode: StatusCodes.Status200OK)]
|
||||||
|
public async Task<IActionResult> RerollSidAsync()
|
||||||
|
{
|
||||||
|
var minTimeAgo = clock.GetCurrentInstant() - Duration.FromHours(1);
|
||||||
|
if (CurrentUser!.LastSidReroll > minTimeAgo)
|
||||||
|
throw new ApiError.BadRequest("Cannot reroll short ID yet");
|
||||||
|
|
||||||
|
await db.Users.Where(u => u.Id == CurrentUser.Id)
|
||||||
|
.ExecuteUpdateAsync(s => s
|
||||||
|
.SetProperty(u => u.Sid, _ => db.FindFreeUserSid())
|
||||||
|
.SetProperty(u => u.LastSidReroll, _ => clock.GetCurrentInstant()));
|
||||||
|
|
||||||
|
var user = await db.ResolveUserAsync(CurrentUser.Id);
|
||||||
|
return Ok(await userRenderer.RenderUserAsync(user, CurrentUser, CurrentToken, renderMembers: false));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -76,7 +76,23 @@ public class DatabaseContext : DbContext
|
||||||
modelBuilder.Entity<Member>().Property(m => m.Fields).HasColumnType("jsonb");
|
modelBuilder.Entity<Member>().Property(m => m.Fields).HasColumnType("jsonb");
|
||||||
modelBuilder.Entity<Member>().Property(m => m.Names).HasColumnType("jsonb");
|
modelBuilder.Entity<Member>().Property(m => m.Names).HasColumnType("jsonb");
|
||||||
modelBuilder.Entity<Member>().Property(m => m.Pronouns).HasColumnType("jsonb");
|
modelBuilder.Entity<Member>().Property(m => m.Pronouns).HasColumnType("jsonb");
|
||||||
|
|
||||||
|
modelBuilder.HasDbFunction(typeof(DatabaseContext).GetMethod(nameof(FindFreeUserSid))!)
|
||||||
|
.HasName("find_free_user_sid");
|
||||||
|
|
||||||
|
modelBuilder.HasDbFunction(typeof(DatabaseContext).GetMethod(nameof(FindFreeMemberSid))!)
|
||||||
|
.HasName("find_free_member_sid");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dummy method that calls <c>find_free_user_sid()</c> when used in an EF Core query.
|
||||||
|
/// </summary>
|
||||||
|
public string FindFreeUserSid() => throw new NotSupportedException();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dummy method that calls <c>find_free_member_sid()</c> when used in an EF Core query.
|
||||||
|
/// </summary>
|
||||||
|
public string FindFreeMemberSid() => throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "UnusedType.Global", Justification = "Used by EF Core's migration generator")]
|
[SuppressMessage("ReSharper", "UnusedType.Global", Justification = "Used by EF Core's migration generator")]
|
||||||
|
|
Loading…
Reference in a new issue