From fd49e7e4ea10256e7d159efc999f6b11a5e5d9a6 Mon Sep 17 00:00:00 2001 From: spiral Date: Wed, 13 Oct 2021 09:08:17 -0400 Subject: [PATCH] refactor(apiv2): rename APIErrors to Errors, move IsUserError to helper method --- PluralKit.API/Controllers/PKControllerBase.cs | 2 +- .../Controllers/v2/GroupControllerV2.cs | 10 +-- .../Controllers/v2/GroupMemberControllerV2.cs | 62 +++++++++---------- .../Controllers/v2/GuildControllerV2.cs | 22 +++---- .../Controllers/v2/MemberControllerV2.cs | 10 +-- .../Controllers/v2/MiscControllerV2.cs | 2 +- .../Controllers/v2/SwitchControllerV2.cs | 50 +++++++-------- PluralKit.API/Errors.cs | 19 +++++- PluralKit.API/Startup.cs | 5 +- 9 files changed, 98 insertions(+), 84 deletions(-) diff --git a/PluralKit.API/Controllers/PKControllerBase.cs b/PluralKit.API/Controllers/PKControllerBase.cs index 50172df7..0e97e0a9 100644 --- a/PluralKit.API/Controllers/PKControllerBase.cs +++ b/PluralKit.API/Controllers/PKControllerBase.cs @@ -36,7 +36,7 @@ namespace PluralKit.API { HttpContext.Items.TryGetValue("SystemId", out var systemId); if (systemId == null) - throw APIErrors.GenericAuthError; + throw Errors.GenericAuthError; return _repo.GetSystem((SystemId)systemId); } diff --git a/PluralKit.API/Controllers/v2/GroupControllerV2.cs b/PluralKit.API/Controllers/v2/GroupControllerV2.cs index d29a31f9..3604ceaa 100644 --- a/PluralKit.API/Controllers/v2/GroupControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupControllerV2.cs @@ -22,12 +22,12 @@ namespace PluralKit.API { var system = await ResolveSystem(systemRef); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var ctx = this.ContextFor(system); if (!system.GroupListPrivacy.CanAccess(User.ContextFor(system))) - throw APIErrors.UnauthorizedGroupList; + throw Errors.UnauthorizedGroupList; var groups = _repo.GetSystemGroups(system.Id); return Ok(await groups @@ -50,7 +50,7 @@ namespace PluralKit.API { var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; var system = await _repo.GetSystem(group.System); @@ -71,11 +71,11 @@ namespace PluralKit.API { var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; var system = await ResolveSystem("@me"); if (system.Id != group.System) - throw APIErrors.NotOwnGroupError; + throw Errors.NotOwnGroupError; await _repo.DeleteGroup(group.Id); diff --git a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs index 48cf7787..dd3da730 100644 --- a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs @@ -25,12 +25,12 @@ namespace PluralKit.API { var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; var ctx = this.ContextFor(group); if (!group.ListPrivacy.CanAccess(ctx)) - throw APIErrors.UnauthorizedGroupMemberList; + throw Errors.UnauthorizedGroupMemberList; var members = _repo.GetGroupMembers(group.Id).Where(m => m.MemberVisibility.CanAccess(ctx)); @@ -50,7 +50,7 @@ namespace PluralKit.API var system = await _repo.GetSystem(member.System); if (!system.GroupListPrivacy.CanAccess(ctx)) - throw APIErrors.UnauthorizedGroupList; + throw Errors.UnauthorizedGroupList; var groups = _repo.GetMemberGroups(member.Id).Where(g => g.Visibility.CanAccess(ctx)); @@ -69,16 +69,16 @@ namespace PluralKit.API var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupError; + throw Errors.NotOwnGroupError; var member = await ResolveMember(memberRef); Console.WriteLine(member); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; var existingMembers = await _repo.GetGroupMembers(group.Id).Select(x => x.Id).ToListAsync(); if (!existingMembers.Contains(member.Id)) @@ -91,15 +91,15 @@ namespace PluralKit.API public async Task GroupMembersPut(string groupRef, [FromBody] JArray memberRefs) { if (memberRefs.Count == 0) - throw APIErrors.GenericBadRequest; + throw Errors.GenericBadRequest; var system = await ResolveSystem("@me"); var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupError; + throw Errors.NotOwnGroupError; var members = new List(); @@ -109,9 +109,9 @@ namespace PluralKit.API var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberErrorWithRef(memberRef); + throw Errors.NotOwnMemberErrorWithRef(memberRef); members.Add(member.Id); } @@ -132,15 +132,15 @@ namespace PluralKit.API var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupError; + throw Errors.NotOwnGroupError; var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; await _repo.RemoveMembersFromGroup(group.Id, new List() { member.Id }); @@ -151,15 +151,15 @@ namespace PluralKit.API public async Task GroupMembersDelete(string groupRef, [FromBody] JArray memberRefs) { if (memberRefs.Count == 0) - throw APIErrors.GenericBadRequest; + throw Errors.GenericBadRequest; var system = await ResolveSystem("@me"); var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupError; + throw Errors.NotOwnGroupError; var members = new List(); @@ -169,9 +169,9 @@ namespace PluralKit.API var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; members.Add(member.Id); } @@ -185,15 +185,15 @@ namespace PluralKit.API public async Task MemberGroupsPut(string memberRef, [FromBody] JArray groupRefs) { if (groupRefs.Count == 0) - throw APIErrors.GenericBadRequest; + throw Errors.GenericBadRequest; var system = await ResolveSystem("@me"); var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; var groups = new List(); @@ -203,9 +203,9 @@ namespace PluralKit.API var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupErrorWithRef(groupRef); + throw Errors.NotOwnGroupErrorWithRef(groupRef); groups.Add(group.Id); } @@ -223,15 +223,15 @@ namespace PluralKit.API public async Task MemberGroupsDelete(string memberRef, [FromBody] JArray groupRefs) { if (groupRefs.Count == 0) - throw APIErrors.GenericBadRequest; + throw Errors.GenericBadRequest; var system = await ResolveSystem("@me"); var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; var groups = new List(); @@ -241,9 +241,9 @@ namespace PluralKit.API var group = await ResolveGroup(groupRef); if (group == null) - throw APIErrors.GroupNotFound; + throw Errors.GroupNotFound; if (group.System != system.Id) - throw APIErrors.NotOwnGroupErrorWithRef(groupRef); + throw Errors.NotOwnGroupErrorWithRef(groupRef); groups.Add(group.Id); } diff --git a/PluralKit.API/Controllers/v2/GuildControllerV2.cs b/PluralKit.API/Controllers/v2/GuildControllerV2.cs index 6c098eff..2f5ffc47 100644 --- a/PluralKit.API/Controllers/v2/GuildControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GuildControllerV2.cs @@ -23,7 +23,7 @@ namespace PluralKit.API var system = await ResolveSystem("@me"); var settings = await _repo.GetSystemGuild(guild_id, system.Id, defaultInsert: false); if (settings == null) - throw APIErrors.SystemGuildNotFound; + throw Errors.SystemGuildNotFound; PKMember member = null; if (settings.AutoproxyMember != null) @@ -38,7 +38,7 @@ namespace PluralKit.API var system = await ResolveSystem("@me"); var settings = await _repo.GetSystemGuild(guild_id, system.Id, defaultInsert: false); if (settings == null) - throw APIErrors.SystemGuildNotFound; + throw Errors.SystemGuildNotFound; MemberId? memberId = null; if (data.ContainsKey("autoproxy_member")) @@ -47,7 +47,7 @@ namespace PluralKit.API { var member = await ResolveMember(data.Value("autoproxy_member")); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; memberId = member.Id; } @@ -66,10 +66,10 @@ namespace PluralKit.API if (patch.AutoproxyMode.IsPresent) { if (patch.AutoproxyMode.Value == AutoproxyMode.Member) - throw APIErrors.MissingAutoproxyMember; + throw Errors.MissingAutoproxyMember; } else if (settings.AutoproxyMode == AutoproxyMode.Member) - throw APIErrors.MissingAutoproxyMember; + throw Errors.MissingAutoproxyMember; var newSettings = await _repo.UpdateSystemGuild(system.Id, guild_id, patch); @@ -85,13 +85,13 @@ namespace PluralKit.API var system = await ResolveSystem("@me"); var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; var settings = await _repo.GetMemberGuild(guild_id, member.Id, defaultInsert: false); if (settings == null) - throw APIErrors.MemberGuildNotFound; + throw Errors.MemberGuildNotFound; return Ok(settings.ToJson()); } @@ -102,13 +102,13 @@ namespace PluralKit.API var system = await ResolveSystem("@me"); var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; var settings = await _repo.GetMemberGuild(guild_id, member.Id, defaultInsert: false); if (settings == null) - throw APIErrors.MemberGuildNotFound; + throw Errors.MemberGuildNotFound; var patch = MemberGuildPatch.FromJson(data); diff --git a/PluralKit.API/Controllers/v2/MemberControllerV2.cs b/PluralKit.API/Controllers/v2/MemberControllerV2.cs index 38b958d4..2b72618c 100644 --- a/PluralKit.API/Controllers/v2/MemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/MemberControllerV2.cs @@ -23,12 +23,12 @@ namespace PluralKit.API { var system = await ResolveSystem(systemRef); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var ctx = this.ContextFor(system); if (!system.MemberListPrivacy.CanAccess(this.ContextFor(system))) - throw APIErrors.UnauthorizedMemberList; + throw Errors.UnauthorizedMemberList; var members = _repo.GetSystemMembers(system.Id); return Ok(await members @@ -51,7 +51,7 @@ namespace PluralKit.API { var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; var system = await _repo.GetSystem(member.System); @@ -72,11 +72,11 @@ namespace PluralKit.API { var member = await ResolveMember(memberRef); if (member == null) - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; var system = await ResolveSystem("@me"); if (system.Id != member.System) - throw APIErrors.NotOwnMemberError; + throw Errors.NotOwnMemberError; await _repo.DeleteMember(member.Id); diff --git a/PluralKit.API/Controllers/v2/MiscControllerV2.cs b/PluralKit.API/Controllers/v2/MiscControllerV2.cs index 1e015b37..3fdff9a7 100644 --- a/PluralKit.API/Controllers/v2/MiscControllerV2.cs +++ b/PluralKit.API/Controllers/v2/MiscControllerV2.cs @@ -35,7 +35,7 @@ namespace PluralKit.API { var msg = await _db.Execute(c => _repo.GetMessage(c, messageId)); if (msg == null) - throw APIErrors.MessageNotFound; + throw Errors.MessageNotFound; var ctx = this.ContextFor(msg.System); diff --git a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs index fe79760e..14f908fe 100644 --- a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs +++ b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs @@ -29,12 +29,12 @@ namespace PluralKit.API { var system = await ResolveSystem(systemRef); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var ctx = this.ContextFor(system); if (!system.FrontHistoryPrivacy.CanAccess(ctx)) - throw APIErrors.UnauthorizedFrontHistory; + throw Errors.UnauthorizedFrontHistory; if (before == null) before = SystemClock.Instance.GetCurrentInstant(); @@ -58,12 +58,12 @@ namespace PluralKit.API { var system = await ResolveSystem(systemRef); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var ctx = this.ContextFor(system); if (!system.FrontPrivacy.CanAccess(ctx)) - throw APIErrors.UnauthorizedCurrentFronters; + throw Errors.UnauthorizedCurrentFronters; var sw = await _repo.GetLatestSwitch(system.Id); if (sw == null) @@ -83,12 +83,12 @@ namespace PluralKit.API public async Task SwitchCreate([FromBody] PostSwitchParams data) { if (data.Members.Distinct().Count() != data.Members.Count) - throw APIErrors.DuplicateMembersInList; + throw Errors.DuplicateMembersInList; var system = await ResolveSystem("@me"); if (data.Timestamp != null && await _repo.GetSwitches(system.Id).Select(x => x.Timestamp).ContainsAsync(data.Timestamp.Value)) - throw APIErrors.SameSwitchTimestampError; + throw Errors.SameSwitchTimestampError; var members = new List(); @@ -97,9 +97,9 @@ namespace PluralKit.API var member = await ResolveMember(memberRef); if (member == null) // todo: which member - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberErrorWithRef(memberRef); + throw Errors.NotOwnMemberErrorWithRef(memberRef); members.Add(member); } @@ -111,7 +111,7 @@ namespace PluralKit.API // Bail if this switch is identical to the latest one if (await latestSwitchMembers.Select(m => m.Hid).SequenceEqualAsync(members.Select(m => m.Hid).ToAsyncEnumerable())) - throw APIErrors.SameSwitchMembersError; + throw Errors.SameSwitchMembersError; } var newSwitch = await _db.Execute(conn => _repo.AddSwitch(conn, system.Id, members.Select(m => m.Id).ToList())); @@ -131,20 +131,20 @@ namespace PluralKit.API public async Task SwitchGet(string systemRef, string switchRef) { if (!Guid.TryParse(switchRef, out var switchId)) - throw APIErrors.InvalidSwitchId; + throw Errors.InvalidSwitchId; var system = await ResolveSystem(systemRef); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var sw = await _repo.GetSwitchByUuid(switchId); if (sw == null || system.Id != sw.System) - throw APIErrors.SwitchNotFoundPublic; + throw Errors.SwitchNotFoundPublic; var ctx = this.ContextFor(system); if (!system.FrontHistoryPrivacy.CanAccess(ctx)) - throw APIErrors.SwitchNotFoundPublic; + throw Errors.SwitchNotFoundPublic; var members = _db.Execute(conn => _repo.GetSwitchMembers(conn, sw.Id)); return Ok(new FrontersReturnNew @@ -161,25 +161,25 @@ namespace PluralKit.API // for now, don't need to make a PatchObject for this, since it's only one param if (!Guid.TryParse(switchRef, out var switchId)) - throw APIErrors.InvalidSwitchId; + throw Errors.InvalidSwitchId; var valueStr = data.Value("timestamp").NullIfEmpty(); if (valueStr == null) // todo - throw APIErrors.GenericBadRequest; + throw Errors.GenericBadRequest; var value = Instant.FromDateTimeOffset(DateTime.Parse(valueStr).ToUniversalTime()); var system = await ResolveSystem("@me"); if (system == null) - throw APIErrors.SystemNotFound; + throw Errors.SystemNotFound; var sw = await _repo.GetSwitchByUuid(switchId); if (sw == null || system.Id != sw.System) - throw APIErrors.SwitchNotFoundPublic; + throw Errors.SwitchNotFoundPublic; if (await _repo.GetSwitches(system.Id).Select(x => x.Timestamp).ContainsAsync(value)) - throw APIErrors.SameSwitchTimestampError; + throw Errors.SameSwitchTimestampError; await _repo.MoveSwitch(sw.Id, value); @@ -198,13 +198,13 @@ namespace PluralKit.API if (!Guid.TryParse(switchRef, out var switchId)) if (data.Distinct().Count() != data.Count) - throw APIErrors.DuplicateMembersInList; + throw Errors.DuplicateMembersInList; var system = await ResolveSystem("@me"); var sw = await _repo.GetSwitchByUuid(switchId); if (sw == null) - throw APIErrors.SwitchNotFound; + throw Errors.SwitchNotFound; var members = new List(); @@ -215,9 +215,9 @@ namespace PluralKit.API var member = await ResolveMember(memberRef); if (member == null) // todo: which member - throw APIErrors.MemberNotFound; + throw Errors.MemberNotFound; if (member.System != system.Id) - throw APIErrors.NotOwnMemberErrorWithRef(memberRef); + throw Errors.NotOwnMemberErrorWithRef(memberRef); members.Add(member); } @@ -225,7 +225,7 @@ namespace PluralKit.API var latestSwitchMembers = _db.Execute(conn => _repo.GetSwitchMembers(conn, sw.Id)); if (await latestSwitchMembers.Select(m => m.Hid).SequenceEqualAsync(members.Select(m => m.Hid).ToAsyncEnumerable())) - throw APIErrors.SameSwitchMembersError; + throw Errors.SameSwitchMembersError; await _db.Execute(conn => _repo.EditSwitch(conn, sw.Id, members.Select(x => x.Id).ToList())); return Ok(new FrontersReturnNew @@ -240,12 +240,12 @@ namespace PluralKit.API public async Task SwitchDelete(string switchRef) { if (!Guid.TryParse(switchRef, out var switchId)) - throw APIErrors.InvalidSwitchId; + throw Errors.InvalidSwitchId; var system = await ResolveSystem("@me"); var sw = await _repo.GetSwitchByUuid(switchId); if (sw == null || system.Id != sw.System) - throw APIErrors.SwitchNotFoundPublic; + throw Errors.SwitchNotFoundPublic; await _repo.DeleteSwitch(sw.Id); diff --git a/PluralKit.API/Errors.cs b/PluralKit.API/Errors.cs index a2cfe8bb..d1045a00 100644 --- a/PluralKit.API/Errors.cs +++ b/PluralKit.API/Errors.cs @@ -75,7 +75,7 @@ namespace PluralKit.API } } - public static class APIErrors + public static class Errors { public static PKError GenericBadRequest = new(400, 0, "400: Bad Request"); public static PKError GenericAuthError = new(401, 0, "401: Missing or invalid Authorization header"); @@ -104,4 +104,21 @@ namespace PluralKit.API public static PKError InvalidSwitchId = new(400, 40006, "Invalid switch ID."); public static PKError Unimplemented = new(501, 50001, "Unimplemented"); } + + public static class APIErrorHandlerExt + { + public static bool IsUserError(this Exception exc) + { + // caused by users sending an incorrect JSON type (array where an object is expected, etc) + if (exc is InvalidCastException && exc.Message.Contains("Newtonsoft.Json")) + return true; + + // Hacky parsing of timestamps results in hacky error handling. Probably fix this one at some point. + if (exc is FormatException && exc.Message.Contains("was not recognized as a valid DateTime")) + return true; + + // This may expanded at some point. + return false; + } + } } \ No newline at end of file diff --git a/PluralKit.API/Startup.cs b/PluralKit.API/Startup.cs index c21b5a64..df292497 100644 --- a/PluralKit.API/Startup.cs +++ b/PluralKit.API/Startup.cs @@ -140,10 +140,7 @@ namespace PluralKit.API var exc = ctx.Features.Get(); // handle common ISEs that are generated by invalid user input - if ( - (exc.Error is InvalidCastException && exc.Error.Message.Contains("Newtonsoft.Json")) - || (exc.Error is FormatException && exc.Error.Message.Contains("was not recognized as a valid DateTime")) - ) + if (exc.Error.IsUserError()) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("{\"message\":\"400: Bad Request\",\"code\":0}");