feat: with_members query string on /systems/:ref/members endpoint

This commit is contained in:
spiral 2021-11-01 00:12:11 -04:00
parent 8d02af7b94
commit 44ccf01f93
No known key found for this signature in database
GPG Key ID: A6059F0CA0E1BD31
5 changed files with 47 additions and 18 deletions

View File

@ -18,7 +18,7 @@ namespace PluralKit.API
public GroupControllerV2(IServiceProvider svc) : base(svc) { } public GroupControllerV2(IServiceProvider svc) : base(svc) { }
[HttpGet("systems/{systemRef}/groups")] [HttpGet("systems/{systemRef}/groups")]
public async Task<IActionResult> GetSystemGroups(string systemRef) public async Task<IActionResult> GetSystemGroups(string systemRef, [FromQuery] bool with_members)
{ {
var system = await ResolveSystem(systemRef); var system = await ResolveSystem(systemRef);
if (system == null) if (system == null)
@ -26,14 +26,29 @@ namespace PluralKit.API
var ctx = this.ContextFor(system); var ctx = this.ContextFor(system);
if (with_members && !system.MemberListPrivacy.CanAccess(ctx))
throw Errors.UnauthorizedMemberList;
if (!system.GroupListPrivacy.CanAccess(User.ContextFor(system))) if (!system.GroupListPrivacy.CanAccess(User.ContextFor(system)))
throw Errors.UnauthorizedGroupList; throw Errors.UnauthorizedGroupList;
var groups = _repo.GetSystemGroups(system.Id); var groups = _repo.GetSystemGroups(system.Id);
return Ok(await groups
var j_groups = await groups
.Where(g => g.Visibility.CanAccess(ctx)) .Where(g => g.Visibility.CanAccess(ctx))
.Select(g => g.ToJson(ctx)) .Select(g => g.ToJson(ctx, needsMembersArray: with_members))
.ToListAsync()); .ToListAsync();
if (with_members && j_groups.Count > 0)
{
var q = await _repo.GetGroupMemberInfo(await groups.Select(x => x.Id).ToListAsync());
foreach (var row in q)
if (row.MemberVisibility.CanAccess(ctx))
((JArray)j_groups.Find(x => x.Value<string>("id") == row.Group)["members"]).Add(row.MemberUuid);
}
return Ok(j_groups);
} }
[HttpPost("groups")] [HttpPost("groups")]

View File

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using SqlKata; using SqlKata;
@ -25,6 +27,15 @@ namespace PluralKit.Core
return _db.QueryStream<PKMember>(query); return _db.QueryStream<PKMember>(query);
} }
public Task<IEnumerable<GroupMember>> GetGroupMemberInfo(IEnumerable<GroupId> ids)
{
return _db.Query<GroupMember>(new Query("group_members")
.LeftJoin("groups", "groups.id", "group_members.group_id")
.LeftJoin("members", "members.id", "group_members.member_id")
.Select("groups.hid as group", "members.hid as member", "members.uuid as member_uuid", "members.member_visibility")
.WhereIn("group_members.group_id", ids.Select(x => x.Value).ToArray()));
}
// todo: add this to metrics tracking // todo: add this to metrics tracking
public async Task AddGroupsToMember(MemberId member, IReadOnlyCollection<GroupId> groups) public async Task AddGroupsToMember(MemberId member, IReadOnlyCollection<GroupId> groups)
{ {
@ -93,4 +104,12 @@ namespace PluralKit.Core
return _db.ExecuteQuery(query); return _db.ExecuteQuery(query);
} }
} }
public class GroupMember
{
public string Group { get; set; }
public string Member { get; set; }
public Guid MemberUuid { get; set; }
public PrivacyLevel MemberVisibility { get; set; }
}
} }

View File

@ -61,7 +61,7 @@ namespace PluralKit.Core
public static string? IconFor(this PKGroup group, LookupContext ctx) => public static string? IconFor(this PKGroup group, LookupContext ctx) =>
group.IconPrivacy.Get(ctx, group.Icon?.TryGetCleanCdnUrl()); group.IconPrivacy.Get(ctx, group.Icon?.TryGetCleanCdnUrl());
public static JObject ToJson(this PKGroup group, LookupContext ctx, string? systemStr = null, bool isExport = false) public static JObject ToJson(this PKGroup group, LookupContext ctx, string? systemStr = null, bool needsMembersArray = false)
{ {
var o = new JObject(); var o = new JObject();
@ -80,7 +80,7 @@ namespace PluralKit.Core
o.Add("created", group.Created.FormatExport()); o.Add("created", group.Created.FormatExport());
if (isExport) if (needsMembersArray)
o.Add("members", new JArray()); o.Add("members", new JArray());
if (ctx == LookupContext.ByOwner) if (ctx == LookupContext.ByOwner)

View File

@ -40,15 +40,11 @@ namespace PluralKit.Core
o.Add("members", new JArray((await _repo.GetSystemMembers(system.Id).ToListAsync()).Select(m => m.ToJson(LookupContext.ByOwner)))); o.Add("members", new JArray((await _repo.GetSystemMembers(system.Id).ToListAsync()).Select(m => m.ToJson(LookupContext.ByOwner))));
var groups = (await _repo.GetSystemGroups(system.Id).ToListAsync()); var groups = (await _repo.GetSystemGroups(system.Id).ToListAsync());
var j_groups = groups.Select(x => x.ToJson(LookupContext.ByOwner, isExport: true)).ToList(); var j_groups = groups.Select(x => x.ToJson(LookupContext.ByOwner, needsMembersArray: true)).ToList();
if (groups.Count > 0) if (groups.Count > 0)
{ {
var q = await conn.QueryAsync<GroupMember>(@$"select groups.hid as group, members.hid as member from group_members var q = await _repo.GetGroupMemberInfo(groups.Select(x => x.Id));
left join groups on groups.id = group_members.group_id
left join members on members.id = group_members.member_id
where group_members.group_id in ({string.Join(", ", groups.Select(x => x.Id.Value.ToString()))})
");
foreach (var row in q) foreach (var row in q)
((JArray)j_groups.Find(x => x.Value<string>("id") == row.Group)["members"]).Add(row.Member); ((JArray)j_groups.Find(x => x.Value<string>("id") == row.Group)["members"]).Add(row.Member);
@ -80,10 +76,4 @@ namespace PluralKit.Core
} }
} }
public class GroupMember
{
public string Group { get; set; }
public string Member { get; set; }
}
} }

View File

@ -136,6 +136,11 @@ Returns a [member guild settings](/api/models#member-guild-settings) object on s
GET `/systems/{systemRef}/groups` GET `/systems/{systemRef}/groups`
Query String Parameters
|name|type|description
|---|---|---|
|with_members|boolean|includes `members` key with array of member UUIDs in each group object|
Returns a list of [group objects](/api/models/#group-model). Returns a list of [group objects](/api/models/#group-model).
### Create Group ### Create Group