[WIP] feat: scoped api keys

This commit is contained in:
Iris System 2025-08-17 02:47:01 -07:00
parent e7ee593a85
commit 06cb160f95
45 changed files with 1264 additions and 154 deletions

View file

@ -15,11 +15,18 @@ public class AuthorizationTokenHandlerMiddleware
public async Task Invoke(HttpContext ctx, IDatabase db, ApiConfig cfg)
{
if (cfg.TrustAuth
&& ctx.Request.Headers.TryGetValue("X-PluralKit-SystemId", out var sidHeaders)
&& sidHeaders.Count > 0
&& int.TryParse(sidHeaders[0], out var systemId))
ctx.Items.Add("SystemId", new SystemId(systemId));
if (cfg.TrustAuth)
{
if (ctx.Request.Headers.TryGetValue("X-PluralKit-SystemId", out var sidHeaders)
&& sidHeaders.Count > 0
&& int.TryParse(sidHeaders[0], out var systemId))
ctx.Items.Add("SystemId", new SystemId(systemId));
if (ctx.Request.Headers.TryGetValue("X-PluralKit-PrivacyLevel", out var levelHeaders)
&& levelHeaders.Count > 0)
ctx.Items.Add("LookupContext",
levelHeaders[0].ToLower().Trim() == "private" ? LookupContext.ByOwner : LookupContext.ByNonOwner);
}
if (cfg.TrustAuth
&& ctx.Request.Headers.TryGetValue("X-PluralKit-AppId", out var aidHeaders)

View file

@ -101,24 +101,48 @@ public class PKControllerBase: ControllerBase
return null;
}
protected bool IsAuthenticatedAs(SystemId system)
{
HttpContext.Items.TryGetValue("SystemId", out var systemId);
return systemId != null && (SystemId)systemId == system;
}
protected LookupContext ContextFor(PKSystem system)
{
HttpContext.Items.TryGetValue("SystemId", out var systemId);
if (systemId == null) return LookupContext.ByNonOwner;
return (SystemId)systemId == system.Id ? LookupContext.ByOwner : LookupContext.ByNonOwner;
HttpContext.Items.TryGetValue("LookupContext", out var lookupCtx);
if (systemId != null && (SystemId)systemId == system.Id)
{
if (lookupCtx != null) return (LookupContext)lookupCtx;
return LookupContext.ByOwner;
}
return LookupContext.ByNonOwner;
}
protected LookupContext ContextFor(PKMember member)
{
HttpContext.Items.TryGetValue("SystemId", out var systemId);
if (systemId == null) return LookupContext.ByNonOwner;
return (SystemId)systemId == member.System ? LookupContext.ByOwner : LookupContext.ByNonOwner;
HttpContext.Items.TryGetValue("LookupContext", out var lookupCtx);
if (systemId != null && (SystemId)systemId == member.System)
{
if (lookupCtx != null) return (LookupContext)lookupCtx;
return LookupContext.ByOwner;
}
return LookupContext.ByNonOwner;
}
protected LookupContext ContextFor(PKGroup group)
{
HttpContext.Items.TryGetValue("SystemId", out var systemId);
if (systemId == null) return LookupContext.ByNonOwner;
return (SystemId)systemId == group.System ? LookupContext.ByOwner : LookupContext.ByNonOwner;
HttpContext.Items.TryGetValue("LookupContext", out var lookupCtx);
if (systemId != null && (SystemId)systemId == group.System)
{
if (lookupCtx != null) return (LookupContext)lookupCtx;
return LookupContext.ByOwner;
}
return LookupContext.ByNonOwner;
}
}

View file

@ -21,7 +21,7 @@ public class GroupControllerV2: PKControllerBase
var ctx = ContextFor(system);
if (!system.GroupListPrivacy.CanAccess(ContextFor(system)))
if (!IsAuthenticatedAs(system.Id) && !system.GroupListPrivacy.CanAccess(ContextFor(system)))
throw Errors.UnauthorizedGroupList;
var groups = _repo.GetSystemGroups(system.Id);

View file

@ -19,10 +19,9 @@ public class GroupMemberControllerV2: PKControllerBase
if (group == null)
throw Errors.GroupNotFound;
var ctx = ContextFor(group);
if (!group.ListPrivacy.CanAccess(ctx))
if (!IsAuthenticatedAs(group.System) && !group.ListPrivacy.CanAccess(ctx))
throw Errors.UnauthorizedGroupMemberList;
var system = await _repo.GetSystem(group.System);
@ -154,7 +153,7 @@ public class GroupMemberControllerV2: PKControllerBase
var ctx = ContextFor(member);
var system = await _repo.GetSystem(member.System);
if (!system.GroupListPrivacy.CanAccess(ctx))
if (!IsAuthenticatedAs(member.System) && !system.GroupListPrivacy.CanAccess(ctx))
throw Errors.UnauthorizedGroupList;
var groups = _repo.GetMemberGroups(member.Id).Where(g => g.Visibility.CanAccess(ctx));

View file

@ -26,7 +26,7 @@ public class MemberControllerV2: PKControllerBase
var ctx = ContextFor(system);
if (!system.MemberListPrivacy.CanAccess(ContextFor(system)))
if (!IsAuthenticatedAs(system.Id) && !system.MemberListPrivacy.CanAccess(ContextFor(system)))
throw Errors.UnauthorizedMemberList;
var members = _repo.GetSystemMembers(system.Id);

View file

@ -28,7 +28,7 @@ public class SwitchControllerV2: PKControllerBase
var ctx = ContextFor(system);
if (!system.FrontHistoryPrivacy.CanAccess(ctx))
if (!IsAuthenticatedAs(system.Id) && !system.FrontHistoryPrivacy.CanAccess(ctx))
throw Errors.UnauthorizedFrontHistory;
if (before == null)
@ -59,7 +59,7 @@ public class SwitchControllerV2: PKControllerBase
var ctx = ContextFor(system);
if (!system.FrontPrivacy.CanAccess(ctx))
if (!IsAuthenticatedAs(system.Id) && !system.FrontPrivacy.CanAccess(ctx))
throw Errors.UnauthorizedCurrentFronters;
var sw = await _repo.GetLatestSwitch(system.Id);
@ -145,7 +145,7 @@ public class SwitchControllerV2: PKControllerBase
var ctx = ContextFor(system);
if (!system.FrontHistoryPrivacy.CanAccess(ctx))
if (!IsAuthenticatedAs(system.Id) && !system.FrontHistoryPrivacy.CanAccess(ctx))
throw Errors.SwitchNotFoundPublic;
var members = _db.Execute(conn => _repo.GetSwitchMembers(conn, sw.Id));