From 1fda6ec919d26bbca4b857ba61126209061503a1 Mon Sep 17 00:00:00 2001 From: Ske Date: Fri, 9 Oct 2020 12:18:29 +0200 Subject: [PATCH] Add per-system member/group limit override --- PluralKit.API/Controllers/v1/MemberController.cs | 13 ++++++++----- PluralKit.Bot/Commands/Groups.cs | 5 +++-- PluralKit.Bot/Commands/Member.cs | 5 +++-- PluralKit.Bot/Errors.cs | 2 +- PluralKit.Core/Database/Database.cs | 2 +- PluralKit.Core/Database/Migrations/10.sql | 11 +++++++++++ PluralKit.Core/Models/PKSystem.cs | 2 ++ PluralKit.Core/Utils/Limits.cs | 2 +- 8 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 PluralKit.Core/Database/Migrations/10.sql diff --git a/PluralKit.API/Controllers/v1/MemberController.cs b/PluralKit.API/Controllers/v1/MemberController.cs index bea62798..539893c2 100644 --- a/PluralKit.API/Controllers/v1/MemberController.cs +++ b/PluralKit.API/Controllers/v1/MemberController.cs @@ -40,18 +40,21 @@ namespace PluralKit.API [Authorize] public async Task> PostMember([FromBody] JObject properties) { - var system = User.CurrentSystem(); if (!properties.ContainsKey("name")) return BadRequest("Member name must be specified."); + + var systemId = User.CurrentSystem(); await using var conn = await _db.Obtain(); + var systemData = await _repo.GetSystem(conn, systemId); // Enforce per-system member limit - var memberCount = await conn.QuerySingleAsync("select count(*) from members where system = @System", new {System = system}); - if (memberCount >= Limits.MaxMemberCount) - return BadRequest($"Member limit reached ({memberCount} / {Limits.MaxMemberCount})."); + var memberCount = await conn.QuerySingleAsync("select count(*) from members where system = @System", new {System = systemId}); + var memberLimit = systemData?.MemberLimitOverride ?? Limits.MaxMemberCount; + if (memberCount >= memberLimit) + return BadRequest($"Member limit reached ({memberCount} / {memberLimit})."); - var member = await _repo.CreateMember(conn, system, properties.Value("name")); + var member = await _repo.CreateMember(conn, systemId, properties.Value("name")); MemberPatch patch; try { diff --git a/PluralKit.Bot/Commands/Groups.cs b/PluralKit.Bot/Commands/Groups.cs index 732e85f2..9e00c2f6 100644 --- a/PluralKit.Bot/Commands/Groups.cs +++ b/PluralKit.Bot/Commands/Groups.cs @@ -38,8 +38,9 @@ namespace PluralKit.Bot // Check group cap var existingGroupCount = await conn.QuerySingleAsync("select count(*) from groups where system = @System", new { System = ctx.System.Id }); - if (existingGroupCount >= Limits.MaxGroupCount) - throw new PKError($"System has reached the maximum number of groups ({Limits.MaxGroupCount}). Please delete unused groups first in order to create new ones."); + var groupLimit = ctx.System.GroupLimitOverride ?? Limits.MaxGroupCount; + if (existingGroupCount >= groupLimit) + throw new PKError($"System has reached the maximum number of groups ({groupLimit}). Please delete unused groups first in order to create new ones."); // Warn if there's already a group by this name var existingGroup = await _repo.GetGroupByName(conn, ctx.System.Id, groupName); diff --git a/PluralKit.Bot/Commands/Member.cs b/PluralKit.Bot/Commands/Member.cs index 737b84f5..6b2c2bf9 100644 --- a/PluralKit.Bot/Commands/Member.cs +++ b/PluralKit.Bot/Commands/Member.cs @@ -37,8 +37,9 @@ namespace PluralKit.Bot // Enforce per-system member limit var memberCount = await _repo.GetSystemMemberCount(conn, ctx.System.Id); - if (memberCount >= Limits.MaxMemberCount) - throw Errors.MemberLimitReachedError; + var memberLimit = ctx.System.MemberLimitOverride ?? Limits.MaxMemberCount; + if (memberCount >= memberLimit) + throw Errors.MemberLimitReachedError(memberLimit); // Create the member var member = await _repo.CreateMember(conn, ctx.System.Id, memberName); diff --git a/PluralKit.Bot/Errors.cs b/PluralKit.Bot/Errors.cs index a136ece0..79600f68 100644 --- a/PluralKit.Bot/Errors.cs +++ b/PluralKit.Bot/Errors.cs @@ -44,7 +44,7 @@ namespace PluralKit.Bot { public static PKError DescriptionTooLongError(int length) => new PKError($"Description too long ({length}/{Limits.MaxDescriptionLength} characters)."); public static PKError MemberNameTooLongError(int length) => new PKError($"Member name too long ({length}/{Limits.MaxMemberNameLength} characters)."); public static PKError MemberPronounsTooLongError(int length) => new PKError($"Member pronouns too long ({length}/{Limits.MaxMemberNameLength} characters)."); - public static PKError MemberLimitReachedError => new PKError($"System has reached the maximum number of members ({Limits.MaxMemberCount}). Please delete unused members first in order to create new ones."); + public static PKError MemberLimitReachedError(int limit) => new PKError($"System has reached the maximum number of members ({limit}). Please delete unused members first in order to create new ones."); public static PKError NoMembersError => new PKError("Your system has no members! Please create at least one member before using this command."); public static PKError InvalidColorError(string color) => new PKError($"\"{color}\" is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000)."); diff --git a/PluralKit.Core/Database/Database.cs b/PluralKit.Core/Database/Database.cs index 0bc88ad1..bfa66101 100644 --- a/PluralKit.Core/Database/Database.cs +++ b/PluralKit.Core/Database/Database.cs @@ -19,7 +19,7 @@ namespace PluralKit.Core internal class Database: IDatabase { private const string RootPath = "PluralKit.Core.Database"; // "resource path" root for SQL files - private const int TargetSchemaVersion = 9; + private const int TargetSchemaVersion = 10; private readonly CoreConfig _config; private readonly ILogger _logger; diff --git a/PluralKit.Core/Database/Migrations/10.sql b/PluralKit.Core/Database/Migrations/10.sql new file mode 100644 index 00000000..d2c4e174 --- /dev/null +++ b/PluralKit.Core/Database/Migrations/10.sql @@ -0,0 +1,11 @@ +-- SCHEMA VERSION 10: 2020-10-09 -- +-- Member/group limit override per-system + +alter table systems add column member_limit_override smallint default null; +alter table systems add column group_limit_override smallint default null; + +-- Lowering global limit to 1000 in this commit, so increase it for systems already above that +update systems s set member_count_override = 1500 + where (select count(*) from members m where m.system = s.id) > 1000; + +update info set schema_version = 10; \ No newline at end of file diff --git a/PluralKit.Core/Models/PKSystem.cs b/PluralKit.Core/Models/PKSystem.cs index 1dd5a8c9..9962e75f 100644 --- a/PluralKit.Core/Models/PKSystem.cs +++ b/PluralKit.Core/Models/PKSystem.cs @@ -23,6 +23,8 @@ namespace PluralKit.Core { public PrivacyLevel FrontPrivacy { get; } public PrivacyLevel FrontHistoryPrivacy { get; } public PrivacyLevel GroupListPrivacy { get; } + public int? MemberLimitOverride { get; } + public int? GroupLimitOverride { get; } [JsonIgnore] public DateTimeZone Zone => DateTimeZoneProviders.Tzdb.GetZoneOrNull(UiTz); } diff --git a/PluralKit.Core/Utils/Limits.cs b/PluralKit.Core/Utils/Limits.cs index c1e44563..1d2246ef 100644 --- a/PluralKit.Core/Utils/Limits.cs +++ b/PluralKit.Core/Utils/Limits.cs @@ -5,7 +5,7 @@ namespace PluralKit.Core { public static readonly int MaxSystemNameLength = 100; public static readonly int MaxSystemTagLength = MaxProxyNameLength - 1; - public static readonly int MaxMemberCount = 1500; + public static readonly int MaxMemberCount = 1000; public static readonly int MaxMembersWarnThreshold = MaxMemberCount - 50; public static readonly int MaxGroupCount = 250; public static readonly int MaxDescriptionLength = 1000;