diff --git a/PluralKit.API/Authentication/AuthExt.cs b/PluralKit.API/Authentication/AuthExt.cs deleted file mode 100644 index 08c8c0b9..00000000 --- a/PluralKit.API/Authentication/AuthExt.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Security.Claims; - -using PluralKit.Core; - -namespace PluralKit.API; - -public static class AuthExt -{ - public static SystemId CurrentSystem(this ClaimsPrincipal user) - { - var claim = user.FindFirst(PKClaims.SystemId); - if (claim == null) throw new ArgumentException("User is unauthorized"); - - if (int.TryParse(claim.Value, out var id)) - return new SystemId(id); - throw new ArgumentException("User has non-integer system ID claim"); - } - - public static LookupContext ContextFor(this ClaimsPrincipal user, PKSystem system) - { - if (!user.Identity.IsAuthenticated) return LookupContext.API; - return system.Id == user.CurrentSystem() ? LookupContext.ByOwner : LookupContext.API; - } - - public static LookupContext ContextFor(this ClaimsPrincipal user, PKMember member) - { - if (!user.Identity.IsAuthenticated) return LookupContext.API; - return member.System == user.CurrentSystem() ? LookupContext.ByOwner : LookupContext.API; - } -} \ No newline at end of file diff --git a/PluralKit.API/Authentication/PKClaims.cs b/PluralKit.API/Authentication/PKClaims.cs deleted file mode 100644 index bcb98c3d..00000000 --- a/PluralKit.API/Authentication/PKClaims.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace PluralKit.API; - -public class PKClaims -{ - public const string SystemId = "PluralKit:SystemId"; -} \ No newline at end of file diff --git a/PluralKit.API/Authentication/SystemTokenAuthenticationHandler.cs b/PluralKit.API/Authentication/SystemTokenAuthenticationHandler.cs deleted file mode 100644 index 7b5b1b6c..00000000 --- a/PluralKit.API/Authentication/SystemTokenAuthenticationHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Security.Claims; -using System.Text.Encodings.Web; - -using Microsoft.AspNetCore.Authentication; -using Microsoft.Extensions.Options; - -using Dapper; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class SystemTokenAuthenticationHandler: AuthenticationHandler -{ - private readonly IDatabase _db; - - public SystemTokenAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, - UrlEncoder encoder, ISystemClock clock, IDatabase db) : base(options, - logger, encoder, clock) - { - _db = db; - } - - protected override async Task HandleAuthenticateAsync() - { - if (!Request.Headers.ContainsKey("Authorization")) - return AuthenticateResult.NoResult(); - - var token = Request.Headers["Authorization"].FirstOrDefault(); - // todo: move this to ModelRepository - var systemId = await _db.Execute(c => - c.QuerySingleOrDefaultAsync("select id from systems where token = @token", - new { token })); - if (systemId == null) return AuthenticateResult.Fail("Invalid system token"); - - var claims = new[] { new Claim(PKClaims.SystemId, systemId.Value.Value.ToString()) }; - var identity = new ClaimsIdentity(claims, Scheme.Name); - var principal = new ClaimsPrincipal(identity); - var ticket = new AuthenticationTicket(principal, Scheme.Name); - ticket.Properties.IsPersistent = false; - ticket.Properties.AllowRefresh = false; - return AuthenticateResult.Success(ticket); - } - - public class Opts: AuthenticationSchemeOptions { } -} \ No newline at end of file diff --git a/PluralKit.API/Authorization/MemberOwnerHandler.cs b/PluralKit.API/Authorization/MemberOwnerHandler.cs deleted file mode 100644 index 7bae4216..00000000 --- a/PluralKit.API/Authorization/MemberOwnerHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class MemberOwnerHandler: AuthorizationHandler -{ - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - OwnSystemRequirement requirement, PKMember resource) - { - if (!context.User.Identity.IsAuthenticated) return Task.CompletedTask; - if (resource.System == context.User.CurrentSystem()) - context.Succeed(requirement); - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/PluralKit.API/Authorization/MemberPrivacyHandler.cs b/PluralKit.API/Authorization/MemberPrivacyHandler.cs deleted file mode 100644 index 4b8b0190..00000000 --- a/PluralKit.API/Authorization/MemberPrivacyHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class MemberPrivacyHandler: AuthorizationHandler, PKMember> -{ - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - PrivacyRequirement requirement, PKMember resource) - { - var level = requirement.Mapper(resource); - var ctx = context.User.ContextFor(resource); - if (level.CanAccess(ctx)) - context.Succeed(requirement); - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/PluralKit.API/Authorization/OwnSystemRequirement.cs b/PluralKit.API/Authorization/OwnSystemRequirement.cs deleted file mode 100644 index 0fed617a..00000000 --- a/PluralKit.API/Authorization/OwnSystemRequirement.cs +++ /dev/null @@ -1,5 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -namespace PluralKit.API; - -public class OwnSystemRequirement: IAuthorizationRequirement { } \ No newline at end of file diff --git a/PluralKit.API/Authorization/PrivacyRequirement.cs b/PluralKit.API/Authorization/PrivacyRequirement.cs deleted file mode 100644 index 30cf5d05..00000000 --- a/PluralKit.API/Authorization/PrivacyRequirement.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class PrivacyRequirement: IAuthorizationRequirement -{ - public readonly Func Mapper; - - public PrivacyRequirement(Func mapper) - { - Mapper = mapper; - } -} \ No newline at end of file diff --git a/PluralKit.API/Authorization/SystemOwnerHandler.cs b/PluralKit.API/Authorization/SystemOwnerHandler.cs deleted file mode 100644 index 08c3a434..00000000 --- a/PluralKit.API/Authorization/SystemOwnerHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class SystemOwnerHandler: AuthorizationHandler -{ - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - OwnSystemRequirement requirement, PKSystem resource) - { - if (!context.User.Identity.IsAuthenticated) return Task.CompletedTask; - if (resource.Id == context.User.CurrentSystem()) - context.Succeed(requirement); - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/PluralKit.API/Authorization/SystemPrivacyHandler.cs b/PluralKit.API/Authorization/SystemPrivacyHandler.cs deleted file mode 100644 index 8e7cccea..00000000 --- a/PluralKit.API/Authorization/SystemPrivacyHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -using PluralKit.Core; - -namespace PluralKit.API; - -public class SystemPrivacyHandler: AuthorizationHandler, PKSystem> -{ - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, - PrivacyRequirement requirement, PKSystem resource) - { - var level = requirement.Mapper(resource); - var ctx = context.User.ContextFor(resource); - if (level.CanAccess(ctx)) - context.Succeed(requirement); - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/PluralKit.API/Controllers/PrivateController.cs b/PluralKit.API/Controllers/PrivateController.cs index c5e0b057..2c0eacf4 100644 --- a/PluralKit.API/Controllers/PrivateController.cs +++ b/PluralKit.API/Controllers/PrivateController.cs @@ -60,7 +60,7 @@ public class PrivateController: PKControllerBase var data = new JObject(); data.Add("privacy", inner); - var patch = MemberPatch.FromJSON(data, APIVersion.V2); + var patch = MemberPatch.FromJSON(data); patch.AssertIsValid(); if (patch.Errors.Count > 0) @@ -135,7 +135,7 @@ public class PrivateController: PKControllerBase var o = new JObject(); - o.Add("system", system.ToJson(LookupContext.ByOwner, APIVersion.V2)); + o.Add("system", system.ToJson(LookupContext.ByOwner)); o.Add("user", user); o.Add("token", system.Token); diff --git a/PluralKit.API/Controllers/v1/AccountController.cs b/PluralKit.API/Controllers/v1/AccountController.cs deleted file mode 100644 index 70c1a68d..00000000 --- a/PluralKit.API/Controllers/v1/AccountController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -using Newtonsoft.Json.Linq; - -using PluralKit.Core; - -namespace PluralKit.API; - -[ApiController] -[Route("v1/a")] -public class AccountController: ControllerBase -{ - private readonly IDatabase _db; - private readonly ModelRepository _repo; - - public AccountController(IDatabase db, ModelRepository repo) - { - _db = db; - _repo = repo; - } - - [HttpGet("{aid}")] - public async Task> GetSystemByAccount(ulong aid) - { - var system = await _repo.GetSystemByAccount(aid); - if (system == null) - return NotFound("Account not found."); - - return Ok(system.ToJson(User.ContextFor(system))); - } -} \ No newline at end of file diff --git a/PluralKit.API/Controllers/v1/MemberController.cs b/PluralKit.API/Controllers/v1/MemberController.cs deleted file mode 100644 index be3ae475..00000000 --- a/PluralKit.API/Controllers/v1/MemberController.cs +++ /dev/null @@ -1,120 +0,0 @@ -using Dapper; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -using Newtonsoft.Json.Linq; - -using PluralKit.Core; - -namespace PluralKit.API; - -[ApiController] -[Route("v1/m")] -public class MemberController: ControllerBase -{ - private readonly IDatabase _db; - private readonly ModelRepository _repo; - private readonly IAuthorizationService _auth; - - public MemberController(IAuthorizationService auth, IDatabase db, ModelRepository repo) - { - _auth = auth; - _db = db; - _repo = repo; - } - - [HttpGet("{hid}")] - public async Task> GetMember(string hid) - { - var member = await _repo.GetMemberByHid(hid); - if (member == null) return NotFound("Member not found."); - - return Ok(member.ToJson(User.ContextFor(member), true)); - } - - [HttpPost] - [Authorize] - public async Task> PostMember([FromBody] JObject properties) - { - if (!properties.ContainsKey("name")) - return BadRequest("Member name must be specified."); - - var systemId = User.CurrentSystem(); - var config = await _repo.GetSystemConfig(systemId); - - await using var conn = await _db.Obtain(); - - // Enforce per-system member limit - var memberCount = await conn.QuerySingleAsync("select count(*) from members where system = @System", - new { System = systemId }); - var memberLimit = config.MemberLimitOverride ?? Limits.MaxMemberCount; - if (memberCount >= memberLimit) - return BadRequest($"Member limit reached ({memberCount} / {memberLimit})."); - - await using var tx = await conn.BeginTransactionAsync(); - var member = await _repo.CreateMember(systemId, properties.Value("name"), conn); - - var patch = MemberPatch.FromJSON(properties); - - patch.AssertIsValid(); - if (patch.Errors.Count > 0) - { - await tx.RollbackAsync(); - - var err = patch.Errors[0]; - if (err is FieldTooLongError) - return BadRequest($"Field {err.Key} is too long " - + $"({(err as FieldTooLongError).ActualLength} > {(err as FieldTooLongError).MaxLength})."); - if (err.Text != null) - return BadRequest(err.Text); - return BadRequest($"Field {err.Key} is invalid."); - } - - member = await _repo.UpdateMember(member.Id, patch, conn); - await tx.CommitAsync(); - return Ok(member.ToJson(User.ContextFor(member), true)); - } - - [HttpPatch("{hid}")] - [Authorize] - public async Task> PatchMember(string hid, [FromBody] JObject changes) - { - var member = await _repo.GetMemberByHid(hid); - if (member == null) return NotFound("Member not found."); - - var res = await _auth.AuthorizeAsync(User, member, "EditMember"); - if (!res.Succeeded) return StatusCode(StatusCodes.Status403Forbidden, $"Member '{hid}' is not part of your system."); - - var patch = MemberPatch.FromJSON(changes); - - patch.AssertIsValid(); - if (patch.Errors.Count > 0) - { - var err = patch.Errors[0]; - if (err is FieldTooLongError) - return BadRequest($"Field {err.Key} is too long " - + $"({(err as FieldTooLongError).ActualLength} > {(err as FieldTooLongError).MaxLength})."); - if (err.Text != null) - return BadRequest(err.Text); - return BadRequest($"Field {err.Key} is invalid."); - } - - var newMember = await _repo.UpdateMember(member.Id, patch); - return Ok(newMember.ToJson(User.ContextFor(newMember), true)); - } - - [HttpDelete("{hid}")] - [Authorize] - public async Task DeleteMember(string hid) - { - var member = await _repo.GetMemberByHid(hid); - if (member == null) return NotFound("Member not found."); - - var res = await _auth.AuthorizeAsync(User, member, "EditMember"); - if (!res.Succeeded) return StatusCode(StatusCodes.Status403Forbidden, $"Member '{hid}' is not part of your system."); - - await _repo.DeleteMember(member.Id); - return Ok(); - } -} \ No newline at end of file diff --git a/PluralKit.API/Controllers/v1/MessageController.cs b/PluralKit.API/Controllers/v1/MessageController.cs deleted file mode 100644 index e9570185..00000000 --- a/PluralKit.API/Controllers/v1/MessageController.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -using Newtonsoft.Json.Linq; - -using PluralKit.Core; - -namespace PluralKit.API; - -[ApiController] -[Route("v1")] -public class MessageController: ControllerBase -{ - private readonly IDatabase _db; - private readonly ModelRepository _repo; - - public MessageController(ModelRepository repo, IDatabase db) - { - _repo = repo; - _db = db; - } - - [HttpGet("msg/{mid}")] - public async Task> GetMessage(ulong mid) - { - var msg = await _db.Execute(c => _repo.GetMessage(c, mid)); - if (msg == null) return NotFound("Message not found."); - - var ctx = msg.System == null ? LookupContext.ByNonOwner : User.ContextFor(msg.System); - return msg.ToJson(ctx, APIVersion.V1); - } -} \ No newline at end of file diff --git a/PluralKit.API/Controllers/v1/SystemController.cs b/PluralKit.API/Controllers/v1/SystemController.cs deleted file mode 100644 index 711176cf..00000000 --- a/PluralKit.API/Controllers/v1/SystemController.cs +++ /dev/null @@ -1,197 +0,0 @@ -using Dapper; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -using NodaTime; - -using PluralKit.Core; - -namespace PluralKit.API; - -public struct SwitchesReturn -{ - [JsonProperty("timestamp")] public Instant Timestamp { get; set; } - [JsonProperty("members")] public IEnumerable Members { get; set; } -} - -public struct FrontersReturn -{ - [JsonProperty("timestamp")] public Instant Timestamp { get; set; } - [JsonProperty("members")] public IEnumerable Members { get; set; } -} - -public struct PostSwitchParams -{ - public Instant? Timestamp { get; set; } - public ICollection Members { get; set; } -} - -[ApiController] -[Route("v1/s")] -public class SystemController: ControllerBase -{ - private readonly IDatabase _db; - private readonly ModelRepository _repo; - private readonly IAuthorizationService _auth; - - public SystemController(IDatabase db, IAuthorizationService auth, ModelRepository repo) - { - _db = db; - _auth = auth; - _repo = repo; - } - - [HttpGet] - [Authorize] - public async Task> GetOwnSystem() - { - var system = await _repo.GetSystem(User.CurrentSystem()); - return system.ToJson(User.ContextFor(system)); - } - - [HttpGet("{hid}")] - public async Task> GetSystem(string hid) - { - var system = await _repo.GetSystemByHid(hid); - if (system == null) return NotFound("System not found."); - return Ok(system.ToJson(User.ContextFor(system))); - } - - [HttpGet("{hid}/members")] - public async Task>> GetMembers(string hid) - { - var system = await _repo.GetSystemByHid(hid); - if (system == null) - return NotFound("System not found."); - - if (!system.MemberListPrivacy.CanAccess(User.ContextFor(system))) - return StatusCode(StatusCodes.Status403Forbidden, "Unauthorized to view member list."); - - var members = _repo.GetSystemMembers(system.Id); - return Ok(await members - .Where(m => m.MemberVisibility.CanAccess(User.ContextFor(system))) - .Select(m => m.ToJson(User.ContextFor(system), needsLegacyProxyTags: true)) - .ToListAsync()); - } - - [HttpGet("{hid}/switches")] - public async Task>> GetSwitches( - string hid, [FromQuery(Name = "before")] Instant? before) - { - if (before == null) before = SystemClock.Instance.GetCurrentInstant(); - - var system = await _repo.GetSystemByHid(hid); - if (system == null) return NotFound("System not found."); - - var auth = await _auth.AuthorizeAsync(User, system, "ViewFrontHistory"); - if (!auth.Succeeded) - return StatusCode(StatusCodes.Status403Forbidden, "Unauthorized to view front history."); - - var res = await _db.Execute(conn => conn.QueryAsync( - @"select *, array( - select members.hid from switch_members, members - where switch_members.switch = switches.id and members.id = switch_members.member - ) as members from switches - where switches.system = @System and switches.timestamp < @Before - order by switches.timestamp desc - limit 100;", - new { System = system.Id, Before = before } - )); - - return Ok(res); - } - - [HttpGet("{hid}/fronters")] - public async Task> GetFronters(string hid) - { - var system = await _repo.GetSystemByHid(hid); - if (system == null) return NotFound("System not found."); - - var auth = await _auth.AuthorizeAsync(User, system, "ViewFront"); - if (!auth.Succeeded) return StatusCode(StatusCodes.Status403Forbidden, "Unauthorized to view fronter."); - - var sw = await _repo.GetLatestSwitch(system.Id); - if (sw == null) return NotFound("System has no registered switches."); - - var members = _db.Execute(conn => _repo.GetSwitchMembers(conn, sw.Id)); - return Ok(new FrontersReturn - { - Timestamp = sw.Timestamp, - Members = await members.Select(m => m.ToJson(User.ContextFor(system), true)).ToListAsync() - }); - } - - [HttpPatch] - [Authorize] - public async Task> EditSystem([FromBody] JObject changes) - { - var system = await _repo.GetSystem(User.CurrentSystem()); - - var patch = SystemPatch.FromJSON(changes); - - patch.AssertIsValid(); - if (patch.Errors.Count > 0) - { - var err = patch.Errors[0]; - if (err is FieldTooLongError) - return BadRequest($"Field {err.Key} is too long " - + $"({(err as FieldTooLongError).ActualLength} > {(err as FieldTooLongError).MaxLength})."); - - return BadRequest($"Field {err.Key} is invalid."); - } - - system = await _repo.UpdateSystem(system!.Id, patch); - return Ok(system.ToJson(User.ContextFor(system))); - } - - [HttpPost("switches")] - [Authorize] - public async Task PostSwitch([FromBody] PostSwitchParams param) - { - if (param.Members.Distinct().Count() != param.Members.Count) - return BadRequest("Duplicate members in member list."); - - await using var conn = await _db.Obtain(); - - // We get the current switch, if it exists - var latestSwitch = await _repo.GetLatestSwitch(User.CurrentSystem()); - if (latestSwitch != null) - { - var latestSwitchMembers = _repo.GetSwitchMembers(conn, latestSwitch.Id); - - // Bail if this switch is identical to the latest one - if (await latestSwitchMembers.Select(m => m.Hid).SequenceEqualAsync(param.Members.ToAsyncEnumerable())) - return BadRequest("New members identical to existing fronters."); - } - - // Resolve member objects for all given IDs - var membersList = - (await conn.QueryAsync("select * from members where hid = any(@Hids)", - new { Hids = param.Members })).ToList(); - - foreach (var member in membersList) - if (member.System != User.CurrentSystem()) - return BadRequest($"Cannot switch to member '{member.Hid}' not in system."); - - // membersList is in DB order, and we want it in actual input order - // so we go through a dict and map the original input appropriately - var membersDict = membersList.ToDictionary(m => m.Hid); - - var membersInOrder = new List(); - // We do this without .Select() since we want to have the early return bail if it doesn't find the member - foreach (var givenMemberId in param.Members) - { - if (!membersDict.TryGetValue(givenMemberId, out var member)) - return BadRequest($"Member '{givenMemberId}' not found."); - membersInOrder.Add(member); - } - - // Finally, log the switch (yay!) - await _repo.AddSwitch(conn, User.CurrentSystem(), membersInOrder.Select(m => m.Id).ToList()); - return NoContent(); - } -} \ No newline at end of file diff --git a/PluralKit.API/Controllers/v2/DiscordControllerV2.cs b/PluralKit.API/Controllers/v2/DiscordControllerV2.cs index a0cde510..477ad8ca 100644 --- a/PluralKit.API/Controllers/v2/DiscordControllerV2.cs +++ b/PluralKit.API/Controllers/v2/DiscordControllerV2.cs @@ -97,6 +97,6 @@ public class DiscordControllerV2: PKControllerBase throw Errors.MessageNotFound; var ctx = msg.System == null ? LookupContext.ByNonOwner : ContextFor(msg.System); - return msg.ToJson(ctx, APIVersion.V2); + return msg.ToJson(ctx); } } \ No newline at end of file diff --git a/PluralKit.API/Controllers/v2/GroupControllerV2.cs b/PluralKit.API/Controllers/v2/GroupControllerV2.cs index 9553e7de..01eee1e2 100644 --- a/PluralKit.API/Controllers/v2/GroupControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupControllerV2.cs @@ -24,7 +24,7 @@ public class GroupControllerV2: PKControllerBase if (with_members && !system.MemberListPrivacy.CanAccess(ctx)) throw Errors.UnauthorizedMemberList; - if (!system.GroupListPrivacy.CanAccess(User.ContextFor(system))) + if (!system.GroupListPrivacy.CanAccess(ContextFor(system))) throw Errors.UnauthorizedGroupList; var groups = _repo.GetSystemGroups(system.Id); diff --git a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs index 99ba21f8..7a40f244 100644 --- a/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupMemberControllerV2.cs @@ -29,7 +29,7 @@ public class GroupMemberControllerV2: PKControllerBase var o = new JArray(); await foreach (var member in members) - o.Add(member.ToJson(ctx, v: APIVersion.V2)); + o.Add(member.ToJson(ctx)); return Ok(o); } diff --git a/PluralKit.API/Controllers/v2/MemberControllerV2.cs b/PluralKit.API/Controllers/v2/MemberControllerV2.cs index 27b58a0a..dfa1eb87 100644 --- a/PluralKit.API/Controllers/v2/MemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/MemberControllerV2.cs @@ -28,7 +28,7 @@ public class MemberControllerV2: PKControllerBase var members = _repo.GetSystemMembers(system.Id); return Ok(await members .Where(m => m.MemberVisibility.CanAccess(ctx)) - .Select(m => m.ToJson(ctx, v: APIVersion.V2)) + .Select(m => m.ToJson(ctx)) .ToListAsync()); } @@ -43,7 +43,7 @@ public class MemberControllerV2: PKControllerBase if (memberCount >= memberLimit) throw Errors.MemberLimitReached; - var patch = MemberPatch.FromJSON(data, APIVersion.V2); + var patch = MemberPatch.FromJSON(data); patch.AssertIsValid(); if (!patch.Name.IsPresent) patch.Errors.Add(new ValidationError("name", "Key 'name' is required when creating new member.")); @@ -64,7 +64,7 @@ public class MemberControllerV2: PKControllerBase await tx.CommitAsync(); - return Ok(newMember.ToJson(LookupContext.ByOwner, v: APIVersion.V2)); + return Ok(newMember.ToJson(LookupContext.ByOwner)); } [HttpGet("members/{memberRef}")] @@ -76,7 +76,7 @@ public class MemberControllerV2: PKControllerBase var system = await _repo.GetSystem(member.System); - return Ok(member.ToJson(ContextFor(member), systemStr: system.Hid, v: APIVersion.V2)); + return Ok(member.ToJson(ContextFor(member), systemStr: system.Hid)); } [HttpPatch("members/{memberRef}")] @@ -89,14 +89,14 @@ public class MemberControllerV2: PKControllerBase if (member.System != system.Id) throw Errors.NotOwnMemberError; - var patch = MemberPatch.FromJSON(data, APIVersion.V2); + var patch = MemberPatch.FromJSON(data); patch.AssertIsValid(); if (patch.Errors.Count > 0) throw new ModelParseError(patch.Errors); var newMember = await _repo.UpdateMember(member.Id, patch); - return Ok(newMember.ToJson(LookupContext.ByOwner, v: APIVersion.V2)); + return Ok(newMember.ToJson(LookupContext.ByOwner)); } [HttpDelete("members/{memberRef}")] diff --git a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs index 4ca15be6..2e580d99 100644 --- a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs +++ b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs @@ -70,7 +70,7 @@ public class SwitchControllerV2: PKControllerBase return Ok(new FrontersReturnNew { Timestamp = sw.Timestamp, - Members = await members.Select(m => m.ToJson(ctx, v: APIVersion.V2)).ToListAsync(), + Members = await members.Select(m => m.ToJson(ctx)).ToListAsync(), Uuid = sw.Uuid, }); } @@ -124,7 +124,7 @@ public class SwitchControllerV2: PKControllerBase { Uuid = newSwitch.Uuid, Timestamp = data.Timestamp != null ? data.Timestamp.Value : newSwitch.Timestamp, - Members = members.Select(x => x.ToJson(LookupContext.ByOwner, v: APIVersion.V2)), + Members = members.Select(x => x.ToJson(LookupContext.ByOwner)), }); } @@ -153,7 +153,7 @@ public class SwitchControllerV2: PKControllerBase { Uuid = sw.Uuid, Timestamp = sw.Timestamp, - Members = await members.Select(m => m.ToJson(ctx, v: APIVersion.V2)).ToListAsync() + Members = await members.Select(m => m.ToJson(ctx)).ToListAsync() }); } @@ -190,7 +190,7 @@ public class SwitchControllerV2: PKControllerBase { Uuid = sw.Uuid, Timestamp = sw.Timestamp, - Members = members.Select(x => x.ToJson(LookupContext.ByOwner, v: APIVersion.V2)) + Members = members.Select(x => x.ToJson(LookupContext.ByOwner)) }); } @@ -238,7 +238,7 @@ public class SwitchControllerV2: PKControllerBase { Uuid = sw.Uuid, Timestamp = sw.Timestamp, - Members = members.Select(x => x.ToJson(LookupContext.ByOwner, v: APIVersion.V2)) + Members = members.Select(x => x.ToJson(LookupContext.ByOwner)) }); } @@ -261,4 +261,10 @@ public class SwitchControllerV2: PKControllerBase return NoContent(); } +} + +public struct PostSwitchParams +{ + public Instant? Timestamp { get; set; } + public ICollection Members { get; set; } } \ No newline at end of file diff --git a/PluralKit.API/Controllers/v2/SystemControllerV2.cs b/PluralKit.API/Controllers/v2/SystemControllerV2.cs index 597c67e0..4842e0e9 100644 --- a/PluralKit.API/Controllers/v2/SystemControllerV2.cs +++ b/PluralKit.API/Controllers/v2/SystemControllerV2.cs @@ -17,7 +17,7 @@ public class SystemControllerV2: PKControllerBase { var system = await ResolveSystem(systemRef); if (system == null) throw Errors.SystemNotFound; - return Ok(system.ToJson(ContextFor(system), APIVersion.V2)); + return Ok(system.ToJson(ContextFor(system))); } [HttpPatch("{systemRef}")] @@ -27,14 +27,14 @@ public class SystemControllerV2: PKControllerBase if (system == null) throw Errors.SystemNotFound; if (ContextFor(system) != LookupContext.ByOwner) throw Errors.GenericMissingPermissions; - var patch = SystemPatch.FromJSON(data, APIVersion.V2); + var patch = SystemPatch.FromJSON(data); patch.AssertIsValid(); if (patch.Errors.Count > 0) throw new ModelParseError(patch.Errors); var newSystem = await _repo.UpdateSystem(system.Id, patch); - return Ok(newSystem.ToJson(LookupContext.ByOwner, APIVersion.V2)); + return Ok(newSystem.ToJson(LookupContext.ByOwner)); } [HttpGet("{systemRef}/settings")] diff --git a/PluralKit.API/Startup.cs b/PluralKit.API/Startup.cs index e99001b0..06c7b6b8 100644 --- a/PluralKit.API/Startup.cs +++ b/PluralKit.API/Startup.cs @@ -28,29 +28,6 @@ public class Startup public void ConfigureServices(IServiceCollection services) { services.AddCors(); - services.AddAuthentication("SystemToken") - .AddScheme("SystemToken", null); - - services.AddAuthorization(options => - { - options.AddPolicy("EditSystem", - p => p.RequireAuthenticatedUser().AddRequirements(new OwnSystemRequirement())); - options.AddPolicy("EditMember", - p => p.RequireAuthenticatedUser().AddRequirements(new OwnSystemRequirement())); - - options.AddPolicy("ViewMembers", - p => p.AddRequirements(new PrivacyRequirement(s => s.MemberListPrivacy))); - options.AddPolicy("ViewFront", - p => p.AddRequirements(new PrivacyRequirement(s => s.FrontPrivacy))); - options.AddPolicy("ViewFrontHistory", - p => p.AddRequirements(new PrivacyRequirement(s => s.FrontHistoryPrivacy))); - }); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddControllers() // sorry MS, this just does *more* .AddNewtonsoftJson(opts => diff --git a/PluralKit.Core/Dispatch/DispatchService.cs b/PluralKit.Core/Dispatch/DispatchService.cs index ce0a2697..58f88b56 100644 --- a/PluralKit.Core/Dispatch/DispatchService.cs +++ b/PluralKit.Core/Dispatch/DispatchService.cs @@ -152,7 +152,7 @@ public class DispatchService data.Event = DispatchEvent.CREATE_MESSAGE; data.SigningToken = system.WebhookToken; data.SystemId = system.Uuid.ToString(); - data.EventData = fullMessage.ToJson(LookupContext.ByOwner, APIVersion.V2); + data.EventData = fullMessage.ToJson(LookupContext.ByOwner); _logger.Debug("Dispatching webhook for message create (system {SystemId})", system.Id); await DoPostRequest(system.Id, system.WebhookUrl, data.GetPayloadBody()); diff --git a/PluralKit.Core/Models/ModelTypes/APIVersion.cs b/PluralKit.Core/Models/ModelTypes/APIVersion.cs deleted file mode 100644 index 080dfb1d..00000000 --- a/PluralKit.Core/Models/ModelTypes/APIVersion.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace PluralKit.Core; - -public enum APIVersion { V1, V2 } \ No newline at end of file diff --git a/PluralKit.Core/Models/PKMember.cs b/PluralKit.Core/Models/PKMember.cs index 13325005..f6030375 100644 --- a/PluralKit.Core/Models/PKMember.cs +++ b/PluralKit.Core/Models/PKMember.cs @@ -105,24 +105,21 @@ public static class PKMemberExt member.MetadataPrivacy.Get(ctx, member.MessageCount); public static JObject ToJson(this PKMember member, LookupContext ctx, bool needsLegacyProxyTags = false, - string systemStr = null, APIVersion v = APIVersion.V1) + string systemStr = null) { var includePrivacy = ctx == LookupContext.ByOwner; var o = new JObject(); o.Add("id", member.Hid); - if (v == APIVersion.V2) - { - o.Add("uuid", member.Uuid.ToString()); - if (systemStr != null) - o.Add("system", systemStr); - } + o.Add("uuid", member.Uuid.ToString()); + if (systemStr != null) + o.Add("system", systemStr); o.Add("name", member.NameFor(ctx)); - // o.Add("color", member.ColorPrivacy.CanAccess(ctx) ? member.Color : null); o.Add("display_name", member.NamePrivacy.CanAccess(ctx) ? member.DisplayName : null); + // o.Add("color", member.ColorPrivacy.CanAccess(ctx) ? member.Color : null); o.Add("color", member.Color); o.Add("birthday", member.BirthdayFor(ctx)?.FormatExport()); o.Add("pronouns", member.PronounsFor(ctx)); @@ -137,53 +134,23 @@ public static class PKMemberExt tagArray.Add(new JObject { { "prefix", tag.Prefix }, { "suffix", tag.Suffix } }); o.Add("proxy_tags", tagArray); - switch (v) + if (includePrivacy) { - case APIVersion.V1: - { - o.Add("privacy", includePrivacy ? member.MemberVisibility.LevelName() : null); + var p = new JObject(); - o.Add("visibility", includePrivacy ? member.MemberVisibility.LevelName() : null); - o.Add("name_privacy", includePrivacy ? member.NamePrivacy.LevelName() : null); - o.Add("description_privacy", includePrivacy ? member.DescriptionPrivacy.LevelName() : null); - o.Add("birthday_privacy", includePrivacy ? member.BirthdayPrivacy.LevelName() : null); - o.Add("pronoun_privacy", includePrivacy ? member.PronounPrivacy.LevelName() : null); - o.Add("avatar_privacy", includePrivacy ? member.AvatarPrivacy.LevelName() : null); - // o.Add("color_privacy", ctx == LookupContext.ByOwner ? (member.ColorPrivacy.LevelName()) : null); - o.Add("metadata_privacy", includePrivacy ? member.MetadataPrivacy.LevelName() : null); + p.Add("visibility", member.MemberVisibility.ToJsonString()); + p.Add("name_privacy", member.NamePrivacy.ToJsonString()); + p.Add("description_privacy", member.DescriptionPrivacy.ToJsonString()); + p.Add("birthday_privacy", member.BirthdayPrivacy.ToJsonString()); + p.Add("pronoun_privacy", member.PronounPrivacy.ToJsonString()); + p.Add("avatar_privacy", member.AvatarPrivacy.ToJsonString()); + p.Add("metadata_privacy", member.MetadataPrivacy.ToJsonString()); - if (member.ProxyTags.Count > 0 && needsLegacyProxyTags) - { - // Legacy compatibility only, TODO: remove at some point - o.Add("prefix", member.ProxyTags?.FirstOrDefault().Prefix); - o.Add("suffix", member.ProxyTags?.FirstOrDefault().Suffix); - } - - break; - } - case APIVersion.V2: - { - if (includePrivacy) - { - var p = new JObject(); - - p.Add("visibility", member.MemberVisibility.ToJsonString()); - p.Add("name_privacy", member.NamePrivacy.ToJsonString()); - p.Add("description_privacy", member.DescriptionPrivacy.ToJsonString()); - p.Add("birthday_privacy", member.BirthdayPrivacy.ToJsonString()); - p.Add("pronoun_privacy", member.PronounPrivacy.ToJsonString()); - p.Add("avatar_privacy", member.AvatarPrivacy.ToJsonString()); - p.Add("metadata_privacy", member.MetadataPrivacy.ToJsonString()); - - o.Add("privacy", p); - } - else - { - o.Add("privacy", null); - } - - break; - } + o.Add("privacy", p); + } + else + { + o.Add("privacy", null); } return o; diff --git a/PluralKit.Core/Models/PKMessage.cs b/PluralKit.Core/Models/PKMessage.cs index 6f6ca04c..b176241e 100644 --- a/PluralKit.Core/Models/PKMessage.cs +++ b/PluralKit.Core/Models/PKMessage.cs @@ -20,7 +20,7 @@ public class FullMessage public PKMember? Member; public PKSystem? System; - public JObject ToJson(LookupContext ctx, APIVersion v) + public JObject ToJson(LookupContext ctx) { var o = new JObject(); @@ -30,8 +30,8 @@ public class FullMessage o.Add("sender", Message.Sender.ToString()); o.Add("channel", Message.Channel.ToString()); o.Add("guild", Message.Guild?.ToString()); - o.Add("system", System?.ToJson(ctx, v)); - o.Add("member", Member?.ToJson(ctx, v: v)); + o.Add("system", System?.ToJson(ctx)); + o.Add("member", Member?.ToJson(ctx)); return o; } diff --git a/PluralKit.Core/Models/PKSystem.cs b/PluralKit.Core/Models/PKSystem.cs index 7d5748d9..e42805cc 100644 --- a/PluralKit.Core/Models/PKSystem.cs +++ b/PluralKit.Core/Models/PKSystem.cs @@ -59,70 +59,42 @@ public static class PKSystemExt public static string DescriptionFor(this PKSystem system, LookupContext ctx) => system.DescriptionPrivacy.Get(ctx, system.Description); - public static JObject ToJson(this PKSystem system, LookupContext ctx, APIVersion v = APIVersion.V1) + public static JObject ToJson(this PKSystem system, LookupContext ctx) { var o = new JObject(); o.Add("id", system.Hid); - if (v == APIVersion.V2) - o.Add("uuid", system.Uuid.ToString()); + o.Add("uuid", system.Uuid.ToString()); o.Add("name", system.Name); o.Add("description", system.DescriptionFor(ctx)); o.Add("tag", system.Tag); - if (v == APIVersion.V2) - o.Add("pronouns", system.PronounPrivacy.Get(ctx, system.Pronouns)); + o.Add("pronouns", system.PronounPrivacy.Get(ctx, system.Pronouns)); o.Add("avatar_url", system.AvatarUrl.TryGetCleanCdnUrl()); o.Add("banner", system.DescriptionPrivacy.Get(ctx, system.BannerImage).TryGetCleanCdnUrl()); o.Add("color", system.Color); o.Add("created", system.Created.FormatExport()); - switch (v) + if (ctx == LookupContext.ByOwner) { - case APIVersion.V1: - { - // this property was moved to SystemConfig - // see notice in /api/legacy docs - o.Add("tz", "UTC"); + // todo: should this be moved to a different JSON model? + o.Add("webhook_url", system.WebhookUrl); + // o.Add("webhook_token", system.WebhookToken); - o.Add("description_privacy", - ctx == LookupContext.ByOwner ? system.DescriptionPrivacy.ToJsonString() : null); - o.Add("member_list_privacy", - ctx == LookupContext.ByOwner ? system.MemberListPrivacy.ToJsonString() : null); - o.Add("group_list_privacy", - ctx == LookupContext.ByOwner ? system.GroupListPrivacy.ToJsonString() : null); - o.Add("front_privacy", ctx == LookupContext.ByOwner ? system.FrontPrivacy.ToJsonString() : null); - o.Add("front_history_privacy", - ctx == LookupContext.ByOwner ? system.FrontHistoryPrivacy.ToJsonString() : null); + var p = new JObject(); - break; - } - case APIVersion.V2: - { - if (ctx == LookupContext.ByOwner) - { - // todo: should this be moved to a different JSON model? - o.Add("webhook_url", system.WebhookUrl); - // o.Add("webhook_token", system.WebhookToken); + p.Add("description_privacy", system.DescriptionPrivacy.ToJsonString()); + p.Add("pronoun_privacy", system.PronounPrivacy.ToJsonString()); + p.Add("member_list_privacy", system.MemberListPrivacy.ToJsonString()); + p.Add("group_list_privacy", system.GroupListPrivacy.ToJsonString()); + p.Add("front_privacy", system.FrontPrivacy.ToJsonString()); + p.Add("front_history_privacy", system.FrontHistoryPrivacy.ToJsonString()); - var p = new JObject(); - - p.Add("description_privacy", system.DescriptionPrivacy.ToJsonString()); - p.Add("pronoun_privacy", system.PronounPrivacy.ToJsonString()); - p.Add("member_list_privacy", system.MemberListPrivacy.ToJsonString()); - p.Add("group_list_privacy", system.GroupListPrivacy.ToJsonString()); - p.Add("front_privacy", system.FrontPrivacy.ToJsonString()); - p.Add("front_history_privacy", system.FrontHistoryPrivacy.ToJsonString()); - - o.Add("privacy", p); - } - else - { - o.Add("privacy", null); - } - - break; - } + o.Add("privacy", p); + } + else + { + o.Add("privacy", null); } return o; diff --git a/PluralKit.Core/Models/Patch/MemberPatch.cs b/PluralKit.Core/Models/Patch/MemberPatch.cs index cefc8ea6..5cfcbaac 100644 --- a/PluralKit.Core/Models/Patch/MemberPatch.cs +++ b/PluralKit.Core/Models/Patch/MemberPatch.cs @@ -79,7 +79,7 @@ public class MemberPatch: PatchObject #nullable disable - public static MemberPatch FromJSON(JObject o, APIVersion v = APIVersion.V1) + public static MemberPatch FromJSON(JObject o, bool isImport = false) { var patch = new MemberPatch(); @@ -109,89 +109,58 @@ public class MemberPatch: PatchObject if (o.ContainsKey("description")) patch.Description = o.Value("description").NullIfEmpty(); if (o.ContainsKey("keep_proxy")) patch.KeepProxy = o.Value("keep_proxy"); - switch (v) + if (isImport) { - case APIVersion.V1: - { - // legacy: used in old export files and APIv1 - if (o.ContainsKey("prefix") || o.ContainsKey("suffix") && !o.ContainsKey("proxy_tags")) - patch.ProxyTags = new[] { new ProxyTag(o.Value("prefix"), o.Value("suffix")) }; - else if (o.ContainsKey("proxy_tags")) - patch.ProxyTags = o.Value("proxy_tags") - .OfType().Select(o => - new ProxyTag(o.Value("prefix"), o.Value("suffix"))) - .Where(p => p.Valid) - .ToArray(); + // legacy: used in old export files and APIv1 + if (o.ContainsKey("prefix") || o.ContainsKey("suffix") && !o.ContainsKey("proxy_tags")) + patch.ProxyTags = new[] { new ProxyTag(o.Value("prefix"), o.Value("suffix")) }; - if (o.ContainsKey("privacy")) - { - var plevel = patch.ParsePrivacy(o, "privacy"); + if (o.ContainsKey("visibility")) patch.Visibility = patch.ParsePrivacy(o, "visibility"); + if (o.ContainsKey("name_privacy")) patch.NamePrivacy = patch.ParsePrivacy(o, "name_privacy"); + if (o.ContainsKey("description_privacy")) + patch.DescriptionPrivacy = patch.ParsePrivacy(o, "description_privacy"); + if (o.ContainsKey("avatar_privacy")) + patch.AvatarPrivacy = patch.ParsePrivacy(o, "avatar_privacy"); + if (o.ContainsKey("birthday_privacy")) + patch.BirthdayPrivacy = patch.ParsePrivacy(o, "birthday_privacy"); + if (o.ContainsKey("pronoun_privacy")) + patch.PronounPrivacy = patch.ParsePrivacy(o, "pronoun_privacy"); + // if (o.ContainsKey("color_privacy")) member.ColorPrivacy = o.ParsePrivacy("member"); + if (o.ContainsKey("metadata_privacy")) + patch.MetadataPrivacy = patch.ParsePrivacy(o, "metadata_privacy"); + } - patch.Visibility = plevel; - patch.NamePrivacy = plevel; - patch.AvatarPrivacy = plevel; - patch.DescriptionPrivacy = plevel; - patch.BirthdayPrivacy = plevel; - patch.PronounPrivacy = plevel; - // member.ColorPrivacy = plevel; - patch.MetadataPrivacy = plevel; - } - else - { - if (o.ContainsKey("visibility")) patch.Visibility = patch.ParsePrivacy(o, "visibility"); - if (o.ContainsKey("name_privacy")) patch.NamePrivacy = patch.ParsePrivacy(o, "name_privacy"); - if (o.ContainsKey("description_privacy")) - patch.DescriptionPrivacy = patch.ParsePrivacy(o, "description_privacy"); - if (o.ContainsKey("avatar_privacy")) - patch.AvatarPrivacy = patch.ParsePrivacy(o, "avatar_privacy"); - if (o.ContainsKey("birthday_privacy")) - patch.BirthdayPrivacy = patch.ParsePrivacy(o, "birthday_privacy"); - if (o.ContainsKey("pronoun_privacy")) - patch.PronounPrivacy = patch.ParsePrivacy(o, "pronoun_privacy"); - // if (o.ContainsKey("color_privacy")) member.ColorPrivacy = o.ParsePrivacy("member"); - if (o.ContainsKey("metadata_privacy")) - patch.MetadataPrivacy = patch.ParsePrivacy(o, "metadata_privacy"); - } + if (o.ContainsKey("proxy_tags")) + patch.ProxyTags = o.Value("proxy_tags") + .OfType().Select(o => + new ProxyTag(o.Value("prefix"), o.Value("suffix"))) + .Where(p => p.Valid) + .ToArray(); - break; - } - case APIVersion.V2: - { - if (o.ContainsKey("proxy_tags")) - patch.ProxyTags = o.Value("proxy_tags") - .OfType().Select(o => - new ProxyTag(o.Value("prefix"), o.Value("suffix"))) - .Where(p => p.Valid) - .ToArray(); + if (o.ContainsKey("privacy") && o["privacy"].Type != JTokenType.Null) + { + var privacy = o.Value("privacy"); - if (o.ContainsKey("privacy") && o["privacy"].Type != JTokenType.Null) - { - var privacy = o.Value("privacy"); + if (privacy.ContainsKey("visibility")) + patch.Visibility = patch.ParsePrivacy(privacy, "visibility"); - if (privacy.ContainsKey("visibility")) - patch.Visibility = patch.ParsePrivacy(privacy, "visibility"); + if (privacy.ContainsKey("name_privacy")) + patch.NamePrivacy = patch.ParsePrivacy(privacy, "name_privacy"); - if (privacy.ContainsKey("name_privacy")) - patch.NamePrivacy = patch.ParsePrivacy(privacy, "name_privacy"); + if (privacy.ContainsKey("description_privacy")) + patch.DescriptionPrivacy = patch.ParsePrivacy(privacy, "description_privacy"); - if (privacy.ContainsKey("description_privacy")) - patch.DescriptionPrivacy = patch.ParsePrivacy(privacy, "description_privacy"); + if (privacy.ContainsKey("avatar_privacy")) + patch.AvatarPrivacy = patch.ParsePrivacy(privacy, "avatar_privacy"); - if (privacy.ContainsKey("avatar_privacy")) - patch.AvatarPrivacy = patch.ParsePrivacy(privacy, "avatar_privacy"); + if (privacy.ContainsKey("birthday_privacy")) + patch.BirthdayPrivacy = patch.ParsePrivacy(privacy, "birthday_privacy"); - if (privacy.ContainsKey("birthday_privacy")) - patch.BirthdayPrivacy = patch.ParsePrivacy(privacy, "birthday_privacy"); + if (privacy.ContainsKey("pronoun_privacy")) + patch.PronounPrivacy = patch.ParsePrivacy(privacy, "pronoun_privacy"); - if (privacy.ContainsKey("pronoun_privacy")) - patch.PronounPrivacy = patch.ParsePrivacy(privacy, "pronoun_privacy"); - - if (privacy.ContainsKey("metadata_privacy")) - patch.MetadataPrivacy = patch.ParsePrivacy(privacy, "metadata_privacy"); - } - - break; - } + if (privacy.ContainsKey("metadata_privacy")) + patch.MetadataPrivacy = patch.ParsePrivacy(privacy, "metadata_privacy"); } return patch; diff --git a/PluralKit.Core/Models/Patch/SystemPatch.cs b/PluralKit.Core/Models/Patch/SystemPatch.cs index f0778399..0fc0ef77 100644 --- a/PluralKit.Core/Models/Patch/SystemPatch.cs +++ b/PluralKit.Core/Models/Patch/SystemPatch.cs @@ -67,7 +67,7 @@ public class SystemPatch: PatchObject #nullable disable - public static SystemPatch FromJSON(JObject o, APIVersion v = APIVersion.V1) + public static SystemPatch FromJSON(JObject o, bool isImport = false) { var patch = new SystemPatch(); if (o.ContainsKey("name")) patch.Name = o.Value("name").NullIfEmpty(); @@ -78,47 +78,38 @@ public class SystemPatch: PatchObject if (o.ContainsKey("banner")) patch.BannerImage = o.Value("banner").NullIfEmpty(); if (o.ContainsKey("color")) patch.Color = o.Value("color").NullIfEmpty(); - switch (v) + if (isImport) { - case APIVersion.V1: - { - if (o.ContainsKey("description_privacy")) - patch.DescriptionPrivacy = patch.ParsePrivacy(o, "description_privacy"); - if (o.ContainsKey("member_list_privacy")) - patch.MemberListPrivacy = patch.ParsePrivacy(o, "member_list_privacy"); - if (o.ContainsKey("front_privacy")) patch.FrontPrivacy = patch.ParsePrivacy(o, "front_privacy"); - if (o.ContainsKey("front_history_privacy")) - patch.FrontHistoryPrivacy = patch.ParsePrivacy(o, "front_history_privacy"); + if (o.ContainsKey("description_privacy")) + patch.DescriptionPrivacy = patch.ParsePrivacy(o, "description_privacy"); + if (o.ContainsKey("member_list_privacy")) + patch.MemberListPrivacy = patch.ParsePrivacy(o, "member_list_privacy"); + if (o.ContainsKey("front_privacy")) patch.FrontPrivacy = patch.ParsePrivacy(o, "front_privacy"); + if (o.ContainsKey("front_history_privacy")) + patch.FrontHistoryPrivacy = patch.ParsePrivacy(o, "front_history_privacy"); + } - break; - } - case APIVersion.V2: - { - if (o.ContainsKey("privacy") && o["privacy"].Type != JTokenType.Null) - { - var privacy = o.Value("privacy"); + if (o.ContainsKey("privacy") && o["privacy"].Type != JTokenType.Null) + { + var privacy = o.Value("privacy"); - if (privacy.ContainsKey("description_privacy")) - patch.DescriptionPrivacy = patch.ParsePrivacy(privacy, "description_privacy"); + if (privacy.ContainsKey("description_privacy")) + patch.DescriptionPrivacy = patch.ParsePrivacy(privacy, "description_privacy"); - if (privacy.ContainsKey("pronoun_privacy")) - patch.PronounPrivacy = patch.ParsePrivacy(privacy, "pronoun_privacy"); + if (privacy.ContainsKey("pronoun_privacy")) + patch.PronounPrivacy = patch.ParsePrivacy(privacy, "pronoun_privacy"); - if (privacy.ContainsKey("member_list_privacy")) - patch.MemberListPrivacy = patch.ParsePrivacy(privacy, "member_list_privacy"); + if (privacy.ContainsKey("member_list_privacy")) + patch.MemberListPrivacy = patch.ParsePrivacy(privacy, "member_list_privacy"); - if (privacy.ContainsKey("group_list_privacy")) - patch.GroupListPrivacy = patch.ParsePrivacy(privacy, "group_list_privacy"); + if (privacy.ContainsKey("group_list_privacy")) + patch.GroupListPrivacy = patch.ParsePrivacy(privacy, "group_list_privacy"); - if (privacy.ContainsKey("front_privacy")) - patch.FrontPrivacy = patch.ParsePrivacy(privacy, "front_privacy"); + if (privacy.ContainsKey("front_privacy")) + patch.FrontPrivacy = patch.ParsePrivacy(privacy, "front_privacy"); - if (privacy.ContainsKey("front_history_privacy")) - patch.FrontHistoryPrivacy = patch.ParsePrivacy(privacy, "front_history_privacy"); - } - - break; - } + if (privacy.ContainsKey("front_history_privacy")) + patch.FrontHistoryPrivacy = patch.ParsePrivacy(privacy, "front_history_privacy"); } return patch; diff --git a/PluralKit.Core/Utils/BulkImporter/PluralKitImport.cs b/PluralKit.Core/Utils/BulkImporter/PluralKitImport.cs index 6428d93d..2c9304e8 100644 --- a/PluralKit.Core/Utils/BulkImporter/PluralKitImport.cs +++ b/PluralKit.Core/Utils/BulkImporter/PluralKitImport.cs @@ -14,7 +14,7 @@ public partial class BulkImporter { private async Task ImportPluralKit(JObject importFile) { - var patch = SystemPatch.FromJSON(importFile); + var patch = SystemPatch.FromJSON(importFile, isImport: true); patch.AssertIsValid(); if (patch.Errors.Count > 0) @@ -100,7 +100,7 @@ public partial class BulkImporter referenceName, _system.Id, isNewMember ); - var patch = MemberPatch.FromJSON(member); + var patch = MemberPatch.FromJSON(member, isImport: true); patch.AssertIsValid(); if (patch.Errors.Count > 0)