diff --git a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs index 6b0ce6c9..48cf7787 100644 --- a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Dapper; + using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Linq; @@ -59,58 +62,195 @@ namespace PluralKit.API return Ok(o); } - [HttpPut("groups/{group_id}/members/{member_id}")] - public async Task GroupMemberPut(string group_id, string member_id) + [HttpPut("groups/{groupRef}/members/{memberRef}")] + public async Task GroupMemberPut(string groupRef, string memberRef) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + var system = await ResolveSystem("@me"); + + var group = await ResolveGroup(groupRef); + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupError; + + var member = await ResolveMember(memberRef); + Console.WriteLine(member); + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.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() { member.Id }); + + return NoContent(); } - [HttpPut("groups/{group_id}/members")] - public async Task GroupMembersPut(string group_id, [FromBody] JArray members) + [HttpPut("groups/{groupRef}/members")] + public async Task GroupMembersPut(string groupRef, [FromBody] JArray memberRefs) { - return new ObjectResult("Unimplemented") + if (memberRefs.Count == 0) + throw APIErrors.GenericBadRequest; + + var system = await ResolveSystem("@me"); + + var group = await ResolveGroup(groupRef); + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupError; + + var members = new List(); + + foreach (var JmemberRef in memberRefs) { - StatusCode = 501 - }; + var memberRef = JmemberRef.Value(); + var member = await ResolveMember(memberRef); + + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.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/{group_id}/members/{member_id}")] - public async Task GroupMemberDelete(string group_id, string member_id) + [HttpDelete("groups/{groupRef}/members/{memberRef}")] + public async Task GroupMemberDelete(string groupRef, string memberRef) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + var system = await ResolveSystem("@me"); + + var group = await ResolveGroup(groupRef); + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupError; + + var member = await ResolveMember(memberRef); + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.NotOwnMemberError; + + await _repo.RemoveMembersFromGroup(group.Id, new List() { member.Id }); + + return NoContent(); } - [HttpDelete("groups/{group_id}/members")] - public async Task GroupMembersDelete(string group_id, [FromBody] JArray members) + [HttpDelete("groups/{groupRef}/members")] + public async Task GroupMembersDelete(string groupRef, [FromBody] JArray memberRefs) { - return new ObjectResult("Unimplemented") + if (memberRefs.Count == 0) + throw APIErrors.GenericBadRequest; + + var system = await ResolveSystem("@me"); + + var group = await ResolveGroup(groupRef); + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupError; + + var members = new List(); + + foreach (var JmemberRef in memberRefs) { - StatusCode = 501 - }; + var memberRef = JmemberRef.Value(); + var member = await ResolveMember(memberRef); + + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.NotOwnMemberError; + + members.Add(member.Id); + } + + await _repo.RemoveMembersFromGroup(group.Id, members); + + return NoContent(); } - [HttpPut("members/{member_id}/groups")] - public async Task MemberGroupsPut(string member_id, [FromBody] JArray groups) + [HttpPut("members/{memberRef}/groups")] + public async Task MemberGroupsPut(string memberRef, [FromBody] JArray groupRefs) { - return new ObjectResult("Unimplemented") + if (groupRefs.Count == 0) + throw APIErrors.GenericBadRequest; + + var system = await ResolveSystem("@me"); + + var member = await ResolveMember(memberRef); + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.NotOwnMemberError; + + var groups = new List(); + + foreach (var JgroupRef in groupRefs) { - StatusCode = 501 - }; + var groupRef = JgroupRef.Value(); + var group = await ResolveGroup(groupRef); + + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupErrorWithRef(groupRef); + + groups.Add(group.Id); + } + + var existingGroups = await _repo.GetMemberGroups(member.Id).Select(x => x.Id).ToListAsync(); + groups = groups.Where(x => !existingGroups.Contains(x)).ToList(); + + if (groups.Count > 0) + await _repo.AddGroupsToMember(member.Id, groups); + + return NoContent(); } - [HttpDelete("members/{member_id}/groups")] - public async Task MemberGroupsDelete(string member_id, [FromBody] JArray groups) + [HttpDelete("members/{memberRef}/groups")] + public async Task MemberGroupsDelete(string memberRef, [FromBody] JArray groupRefs) { - return new ObjectResult("Unimplemented") + if (groupRefs.Count == 0) + throw APIErrors.GenericBadRequest; + + var system = await ResolveSystem("@me"); + + var member = await ResolveMember(memberRef); + if (member == null) + throw APIErrors.MemberNotFound; + if (member.System != system.Id) + throw APIErrors.NotOwnMemberError; + + var groups = new List(); + + foreach (var JgroupRef in groupRefs) { - StatusCode = 501 - }; + var groupRef = JgroupRef.Value(); + var group = await ResolveGroup(groupRef); + + if (group == null) + throw APIErrors.GroupNotFound; + if (group.System != system.Id) + throw APIErrors.NotOwnGroupErrorWithRef(groupRef); + + groups.Add(group.Id); + } + + await _repo.RemoveGroupsFromMember(member.Id, groups); + + return NoContent(); } } diff --git a/PluralKit.API/Errors.cs b/PluralKit.API/Errors.cs index 43fee534..18d43edc 100644 --- a/PluralKit.API/Errors.cs +++ b/PluralKit.API/Errors.cs @@ -51,9 +51,12 @@ namespace PluralKit.API 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"); public static PKError UnauthorizedCurrentFronters = new(403, 30004, "Unauthorized to view current fronters."); - public static PKError UnauthorizedFrontHistory = new(403, 30004, "Unauthorized to view front history."); + public static PKError UnauthorizedFrontHistory = new(403, 30005, "Unauthorized to view front history."); public static PKError NotOwnMemberError = new(403, 40001, "Target member is not part of your system."); public static PKError NotOwnGroupError = new(403, 40002, "Target group is not part of your system."); + // todo: somehow add the memberRef to the JSON + public static PKError NotOwnMemberErrorWithRef(string memberRef) => new(403, 40003, $"Member '{memberRef}' is not part of your system."); + public static PKError NotOwnGroupErrorWithRef(string groupRef) => new(403, 40004, $"Group '{groupRef}' is not part of your system."); public static PKError Unimplemented = new(501, 50001, "Unimplemented"); } } \ No newline at end of file