refactor(apiv2): rewrite group member endpoints to be cleaner
This commit is contained in:
parent
93eef82a83
commit
c7126840ed
@ -42,6 +42,115 @@ namespace PluralKit.API
|
||||
return Ok(o);
|
||||
}
|
||||
|
||||
[HttpPost("groups/{groupRef}/members/add")]
|
||||
public async Task<IActionResult> AddGroupMembers(string groupRef, [FromBody] JArray memberRefs)
|
||||
{
|
||||
if (memberRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var members = new List<MemberId>();
|
||||
|
||||
foreach (var JmemberRef in memberRefs)
|
||||
{
|
||||
var memberRef = JmemberRef.Value<string>();
|
||||
var member = await ResolveMember(memberRef);
|
||||
|
||||
// todo: have a list of these errors instead of immediately throwing
|
||||
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFoundWithRef(memberRef);
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberErrorWithRef(memberRef);
|
||||
|
||||
members.Add(member.Id);
|
||||
}
|
||||
|
||||
var existingMembers = await _repo.GetGroupMembers(group.Id).Select(x => x.Id).ToListAsync();
|
||||
members = members.Where(x => !existingMembers.Contains(x)).ToList();
|
||||
|
||||
if (members.Count > 0)
|
||||
await _repo.AddMembersToGroup(group.Id, members);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("groups/{groupRef}/members/remove")]
|
||||
public async Task<IActionResult> RemoveGroupMembers(string groupRef, [FromBody] JArray memberRefs)
|
||||
{
|
||||
if (memberRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var members = new List<MemberId>();
|
||||
|
||||
foreach (var JmemberRef in memberRefs)
|
||||
{
|
||||
var memberRef = JmemberRef.Value<string>();
|
||||
var member = await ResolveMember(memberRef);
|
||||
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFoundWithRef(memberRef);
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberErrorWithRef(memberRef);
|
||||
|
||||
members.Add(member.Id);
|
||||
}
|
||||
|
||||
await _repo.RemoveMembersFromGroup(group.Id, members);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("groups/{groupRef}/members/overwrite")]
|
||||
public async Task<IActionResult> OverwriteGroupMembers(string groupRef, [FromBody] JArray memberRefs)
|
||||
{
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var members = new List<MemberId>();
|
||||
|
||||
foreach (var JmemberRef in memberRefs)
|
||||
{
|
||||
var memberRef = JmemberRef.Value<string>();
|
||||
var member = await ResolveMember(memberRef);
|
||||
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFoundWithRef(memberRef);
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberErrorWithRef(memberRef);
|
||||
|
||||
members.Add(member.Id);
|
||||
}
|
||||
|
||||
await _repo.ClearGroupMembers(group.Id);
|
||||
|
||||
if (members.Count > 0)
|
||||
await _repo.AddMembersToGroup(group.Id, members);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("members/{memberRef}/groups")]
|
||||
public async Task<IActionResult> GetMemberGroups(string memberRef)
|
||||
{
|
||||
@ -62,127 +171,8 @@ namespace PluralKit.API
|
||||
return Ok(o);
|
||||
}
|
||||
|
||||
[HttpPut("groups/{groupRef}/members/{memberRef}")]
|
||||
public async Task<IActionResult> GroupMemberPut(string groupRef, string memberRef)
|
||||
{
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var member = await ResolveMember(memberRef);
|
||||
Console.WriteLine(member);
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFound;
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberError;
|
||||
|
||||
var existingMembers = await _repo.GetGroupMembers(group.Id).Select(x => x.Id).ToListAsync();
|
||||
if (!existingMembers.Contains(member.Id))
|
||||
await _repo.AddMembersToGroup(group.Id, new List<MemberId>() { member.Id });
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPut("groups/{groupRef}/members")]
|
||||
public async Task<IActionResult> GroupMembersPut(string groupRef, [FromBody] JArray memberRefs)
|
||||
{
|
||||
if (memberRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var members = new List<MemberId>();
|
||||
|
||||
foreach (var JmemberRef in memberRefs)
|
||||
{
|
||||
var memberRef = JmemberRef.Value<string>();
|
||||
var member = await ResolveMember(memberRef);
|
||||
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFound;
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberErrorWithRef(memberRef);
|
||||
|
||||
members.Add(member.Id);
|
||||
}
|
||||
|
||||
var existingMembers = await _repo.GetGroupMembers(group.Id).Select(x => x.Id).ToListAsync();
|
||||
members = members.Where(x => !existingMembers.Contains(x)).ToList();
|
||||
|
||||
if (members.Count > 0)
|
||||
await _repo.AddMembersToGroup(group.Id, members);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("groups/{groupRef}/members/{memberRef}")]
|
||||
public async Task<IActionResult> GroupMemberDelete(string groupRef, string memberRef)
|
||||
{
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var member = await ResolveMember(memberRef);
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFound;
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberError;
|
||||
|
||||
await _repo.RemoveMembersFromGroup(group.Id, new List<MemberId>() { member.Id });
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("groups/{groupRef}/members")]
|
||||
public async Task<IActionResult> GroupMembersDelete(string groupRef, [FromBody] JArray memberRefs)
|
||||
{
|
||||
if (memberRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var group = await ResolveGroup(groupRef);
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupError;
|
||||
|
||||
var members = new List<MemberId>();
|
||||
|
||||
foreach (var JmemberRef in memberRefs)
|
||||
{
|
||||
var memberRef = JmemberRef.Value<string>();
|
||||
var member = await ResolveMember(memberRef);
|
||||
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFound;
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberError;
|
||||
|
||||
members.Add(member.Id);
|
||||
}
|
||||
|
||||
await _repo.RemoveMembersFromGroup(group.Id, members);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPut("members/{memberRef}/groups")]
|
||||
public async Task<IActionResult> MemberGroupsPut(string memberRef, [FromBody] JArray groupRefs)
|
||||
[HttpPost("members/{memberRef}/groups/add")]
|
||||
public async Task<IActionResult> AddMemberGroups(string memberRef, [FromBody] JArray groupRefs)
|
||||
{
|
||||
if (groupRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
@ -219,8 +209,8 @@ namespace PluralKit.API
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("members/{memberRef}/groups")]
|
||||
public async Task<IActionResult> MemberGroupsDelete(string memberRef, [FromBody] JArray groupRefs)
|
||||
[HttpPost("members/{memberRef}/groups/remove")]
|
||||
public async Task<IActionResult> RemoveMemberGroups(string memberRef, [FromBody] JArray groupRefs)
|
||||
{
|
||||
if (groupRefs.Count == 0)
|
||||
throw Errors.GenericBadRequest;
|
||||
@ -241,7 +231,7 @@ namespace PluralKit.API
|
||||
var group = await ResolveGroup(groupRef);
|
||||
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFound;
|
||||
throw Errors.GroupNotFoundWithRef(groupRef);
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupErrorWithRef(groupRef);
|
||||
|
||||
@ -253,5 +243,39 @@ namespace PluralKit.API
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("members/{memberRef}/groups/overwrite")]
|
||||
public async Task<IActionResult> OverwriteMemberGroups(string memberRef, [FromBody] JArray groupRefs)
|
||||
{
|
||||
var system = await ResolveSystem("@me");
|
||||
|
||||
var member = await ResolveMember(memberRef);
|
||||
if (member == null)
|
||||
throw Errors.MemberNotFound;
|
||||
if (member.System != system.Id)
|
||||
throw Errors.NotOwnMemberError;
|
||||
|
||||
var groups = new List<GroupId>();
|
||||
|
||||
foreach (var JgroupRef in groupRefs)
|
||||
{
|
||||
var groupRef = JgroupRef.Value<string>();
|
||||
var group = await ResolveGroup(groupRef);
|
||||
|
||||
if (group == null)
|
||||
throw Errors.GroupNotFoundWithRef(groupRef);
|
||||
if (group.System != system.Id)
|
||||
throw Errors.NotOwnGroupErrorWithRef(groupRef);
|
||||
|
||||
groups.Add(group.Id);
|
||||
}
|
||||
|
||||
await _repo.ClearMemberGroups(member.Id);
|
||||
|
||||
if (groups.Count > 0)
|
||||
await _repo.AddGroupsToMember(member.Id, groups);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -71,12 +71,14 @@ namespace PluralKit.API
|
||||
public static PKError GenericAuthError = new(401, 0, "401: Missing or invalid Authorization header");
|
||||
public static PKError SystemNotFound = new(404, 20001, "System not found.");
|
||||
public static PKError MemberNotFound = new(404, 20002, "Member not found.");
|
||||
public static PKError GroupNotFound = new(404, 20003, "Group not found.");
|
||||
public static PKError MessageNotFound = new(404, 20004, "Message not found.");
|
||||
public static PKError SwitchNotFound = new(404, 20005, "Switch not found.");
|
||||
public static PKError SwitchNotFoundPublic = new(404, 20005, "Switch not found, switch associated with different system, or unauthorized to view front history.");
|
||||
public static PKError SystemGuildNotFound = new(404, 20006, "No system guild settings found for target guild.");
|
||||
public static PKError MemberGuildNotFound = new(404, 20007, "No member guild settings found for target guild.");
|
||||
public static PKError MemberNotFoundWithRef(string memberRef) => new(404, 20003, $"Member '{memberRef}' not found.");
|
||||
public static PKError GroupNotFound = new(404, 20004, "Group not found.");
|
||||
public static PKError GroupNotFoundWithRef(string groupRef) => new(404, 20005, $"Group '{groupRef}' not found.");
|
||||
public static PKError MessageNotFound = new(404, 20006, "Message not found.");
|
||||
public static PKError SwitchNotFound = new(404, 20007, "Switch not found.");
|
||||
public static PKError SwitchNotFoundPublic = new(404, 20008, "Switch not found, switch associated with different system, or unauthorized to view front history.");
|
||||
public static PKError SystemGuildNotFound = new(404, 20009, "No system guild settings found for target guild.");
|
||||
public static PKError MemberGuildNotFound = new(404, 20010, "No member guild settings found for target guild.");
|
||||
public static PKError UnauthorizedMemberList = new(403, 30001, "Unauthorized to view member list");
|
||||
public static PKError UnauthorizedGroupList = new(403, 30002, "Unauthorized to view group list");
|
||||
public static PKError UnauthorizedGroupMemberList = new(403, 30003, "Unauthorized to view group member list");
|
||||
|
@ -76,5 +76,21 @@ namespace PluralKit.Core
|
||||
.WhereIn("member_id", members);
|
||||
return _db.ExecuteQuery(query);
|
||||
}
|
||||
|
||||
public Task ClearGroupMembers(GroupId group)
|
||||
{
|
||||
_logger.Information("Cleared members of {GroupId}", group);
|
||||
var query = new Query("group_members").AsDelete()
|
||||
.Where("group_id", group);
|
||||
return _db.ExecuteQuery(query);
|
||||
}
|
||||
|
||||
public Task ClearMemberGroups(MemberId member)
|
||||
{
|
||||
_logger.Information("Cleared groups of {GroupId}", member);
|
||||
var query = new Query("group_members").AsDelete()
|
||||
.Where("member_id", member);
|
||||
return _db.ExecuteQuery(query);
|
||||
}
|
||||
}
|
||||
}
|
@ -89,20 +89,26 @@ GET `/members/{memberRef}/groups`
|
||||
|
||||
### Add Member To Groups
|
||||
|
||||
PUT `/members/{memberRef}/groups`
|
||||
POST `/members/{memberRef}/groups/add`
|
||||
|
||||
::: warning
|
||||
Not all HTTP implementations support PUT requests with a body. If yours does not, consider using the [Add Member To Group](#add-member-to-group) endpoint instead.
|
||||
:::
|
||||
Takes a list of group references as input. Returns 204 No Content on success.
|
||||
|
||||
### Remove Member From Groups
|
||||
|
||||
DELETE `/members/{memberRef}/groups`
|
||||
POST `/members/{memberRef}/groups/remove`
|
||||
|
||||
::: warning
|
||||
Not all HTTP implementations support DELETE requests with a body. If yours does not, consider using the [Remove Member From Group](#remove-member-from-group) endpoint instead.
|
||||
::: tip
|
||||
If you want to remove *all* groups from a member, consider using the [Overwrite Member Groups](#overwrite-member-groups) endpoint instead.
|
||||
:::
|
||||
|
||||
Takes a list of group references as input. Returns 204 No Content on success.
|
||||
|
||||
### Overwrite Member Groups
|
||||
|
||||
POST `/members/{memberRef}/groups/overwrite`
|
||||
|
||||
Takes a list of group references as input. (An empty list is accepted.) Returns 204 No Content on success.
|
||||
|
||||
### Get Member Guild Settings
|
||||
|
||||
GET `/members/{memberRef}/guilds/{guild_id}`
|
||||
@ -164,30 +170,29 @@ Returns 204 No Content on success.
|
||||
|
||||
GET `/groups/{groupRef}/members`
|
||||
|
||||
### Add Member To Group
|
||||
|
||||
PUT `/groups/{groupRef}/members/{memberRef}`
|
||||
Returns an array of [member objects](/api/models#member-model).
|
||||
|
||||
### Add Members To Group
|
||||
|
||||
PUT `/groups/{groupRef}/members`
|
||||
POST `/groups/{groupRef}/members/add`
|
||||
|
||||
::: warning
|
||||
Not all HTTP implementations support PUT requests with a body. If yours does not, consider using the [Add Member To Group](#add-group-member) endpoint instead.
|
||||
:::
|
||||
Takes an array of member references as input. Returns 204 No Content on success.
|
||||
|
||||
### Remove Member From Group
|
||||
|
||||
DELETE `/groups/{groupRef}/members/{memberRef}`
|
||||
POST `/groups/{groupRef}/members/remove`
|
||||
|
||||
### Remove Members From Group
|
||||
|
||||
DELETE `/groups/{groupRef}/members`
|
||||
|
||||
::: warning
|
||||
Not all HTTP implementations support DELETE requests with a body. If yours does not, consider using the [Remove Member From Group](#remove-member-from-group) endpoint instead.
|
||||
::: tip
|
||||
If you want to remove *all* members from a group, consider using the [Overwrite Group Members](#overwrite-group-members) endpoint instead.
|
||||
:::
|
||||
|
||||
Takes an array of member references as input. Returns 204 No Content on success.
|
||||
|
||||
### Overwrite Group Members
|
||||
|
||||
POST `/groups/{groupRef}/members/overwrite`
|
||||
|
||||
Takes an array of member references as input. (An empty list is accepted.) Returns 204 No Content on success.
|
||||
|
||||
---
|
||||
## Switches
|
||||
|
@ -35,12 +35,14 @@ When something goes wrong, the API will send back a 4xx HTTP status code, along
|
||||
|0|401|Missing or invalid Authorization header|
|
||||
|20001|404|System not found.|
|
||||
|20002|404|Member not found.|
|
||||
|20003|404|Group not found.|
|
||||
|20004|404|Message not found.|
|
||||
|20005|404|Switch not found.|
|
||||
|20005|404|Switch not found, switch associated with different system, or unauthorized to view front history.|
|
||||
|20006|404|No system guild settings found for target guild.|
|
||||
|20007|404|No member guild settings found for target guild.|
|
||||
|20003|404|Member '{memberRef}' not found.|
|
||||
|20004|404|Group not found.|
|
||||
|20005|404|Group '{groupRef}' not found.|
|
||||
|20006|404|Message not found.|
|
||||
|20007|404|Switch not found.|
|
||||
|20008|404|Switch not found, switch associated with different system, or unauthorized to view front history.|
|
||||
|20009|404|No system guild settings found for target guild.|
|
||||
|20010|404|No member guild settings found for target guild.|
|
||||
|30001|403|Unauthorized to view member list|
|
||||
|30002|403|Unauthorized to view group list|
|
||||
|30003|403|Unauthorized to view group member list|
|
||||
@ -48,8 +50,8 @@ When something goes wrong, the API will send back a 4xx HTTP status code, along
|
||||
|30005|403|Unauthorized to view front history.|
|
||||
|30006|403|Target member is not part of your system.|
|
||||
|30007|403|Target group is not part of your system.|
|
||||
|30008|403|$Member '{memberRef}' is not part of your system.|
|
||||
|30009|403|$Group '{groupRef}' is not part of your system.|
|
||||
|30008|403|Member '{memberRef}' is not part of your system.|
|
||||
|30009|403|Group '{groupRef}' is not part of your system.|
|
||||
|40002|400|Missing autoproxy member for member-mode autoproxy.|
|
||||
|40003|400|Duplicate members in member list.|
|
||||
|40004|400|Member list identical to current fronter list.|
|
||||
|
Loading…
Reference in New Issue
Block a user