diff --git a/Foxnouns.Backend/Controllers/MembersController.cs b/Foxnouns.Backend/Controllers/MembersController.cs index 76eaa20..3564090 100644 --- a/Foxnouns.Backend/Controllers/MembersController.cs +++ b/Foxnouns.Backend/Controllers/MembersController.cs @@ -41,6 +41,8 @@ public class MembersController( return Ok(memberRenderer.RenderMember(member, CurrentToken)); } + public const int MaxMemberCount = 500; + [HttpPost("/api/v2/users/@me/members")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize("member.create")] @@ -58,6 +60,10 @@ public class MembersController( .. ValidationUtils.ValidateLinks(req.Links) ]); + var memberCount = await db.Members.CountAsync(m => m.UserId == CurrentUser.Id, ct); + if (memberCount >= MaxMemberCount) + throw new ApiError.BadRequest("Maximum number of members reached"); + var member = new Member { Id = snowflakeGenerator.GenerateSnowflake(), diff --git a/Foxnouns.Backend/Controllers/MetaController.cs b/Foxnouns.Backend/Controllers/MetaController.cs index 31c505e..ffd4fe6 100644 --- a/Foxnouns.Backend/Controllers/MetaController.cs +++ b/Foxnouns.Backend/Controllers/MetaController.cs @@ -1,3 +1,4 @@ +using Foxnouns.Backend.Utils; using Microsoft.AspNetCore.Mvc; namespace Foxnouns.Backend.Controllers; @@ -18,14 +19,22 @@ public class MetaController : ApiControllerBase (int)FoxnounsMetrics.UsersActiveMonthCount.Value, (int)FoxnounsMetrics.UsersActiveWeekCount.Value, (int)FoxnounsMetrics.UsersActiveDayCount.Value - )) + ), + new Limits( + MemberCount: MembersController.MaxMemberCount, + BioLength: ValidationUtils.MaxBioLength)) ); } [HttpGet("/api/v2/coffee")] public IActionResult BrewCoffee() => Problem("Sorry, I'm a teapot!", statusCode: StatusCodes.Status418ImATeapot); - private record MetaResponse(string Repository, string Version, string Hash, int Members, UserInfo Users); + private record MetaResponse(string Repository, string Version, string Hash, int Members, UserInfo Users, Limits Limits); private record UserInfo(int Total, int ActiveMonth, int ActiveWeek, int ActiveDay); + + // All limits that the frontend should know about (for UI purposes) + private record Limits( + int MemberCount, + int BioLength); } \ No newline at end of file diff --git a/Foxnouns.Backend/Utils/ValidationUtils.cs b/Foxnouns.Backend/Utils/ValidationUtils.cs index 1650860..f8f8379 100644 --- a/Foxnouns.Backend/Utils/ValidationUtils.cs +++ b/Foxnouns.Backend/Utils/ValidationUtils.cs @@ -127,12 +127,14 @@ public static class ValidationUtils return errors; } + public const int MaxBioLength = 1024; + public static ValidationError? ValidateBio(string? bio) { return bio?.Length switch { - 0 => ValidationError.LengthError("Bio is too short", 1, 1024, bio.Length), - > 1024 => ValidationError.LengthError("Bio is too long", 1, 1024, bio.Length), + 0 => ValidationError.LengthError("Bio is too short", 1, MaxBioLength, bio.Length), + > MaxBioLength => ValidationError.LengthError("Bio is too long", 1, MaxBioLength, bio.Length), _ => null }; }