diff --git a/PluralKit.API/Controllers/v2/GroupControllerV2.cs b/PluralKit.API/Controllers/v2/GroupControllerV2.cs index 3604ceaa..4b351e67 100644 --- a/PluralKit.API/Controllers/v2/GroupControllerV2.cs +++ b/PluralKit.API/Controllers/v2/GroupControllerV2.cs @@ -37,12 +37,26 @@ namespace PluralKit.API } [HttpPost("groups")] - public async Task GroupCreate(string group_id) + public async Task GroupCreate([FromBody] JObject data) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + var system = await ResolveSystem("@me"); + + var patch = GroupPatch.FromJson(data); + patch.AssertIsValid(); + if (!patch.Name.IsPresent) + patch.Errors.Add(new ValidationError("name", $"Key 'name' is required when creating new group.")); + if (patch.Errors.Count > 0) + throw new ModelParseError(patch.Errors); + + using var conn = await _db.Obtain(); + using var tx = await conn.BeginTransactionAsync(); + + var newGroup = await _repo.CreateGroup(system.Id, patch.Name.Value, conn); + newGroup = await _repo.UpdateGroup(newGroup.Id, patch, conn); + + await tx.CommitAsync(); + + return Ok(newGroup.ToJson(LookupContext.ByOwner)); } [HttpGet("groups/{groupRef}")] @@ -57,13 +71,24 @@ namespace PluralKit.API return Ok(group.ToJson(this.ContextFor(group), systemStr: system.Hid)); } - [HttpPatch("groups/{group_id}")] - public async Task GroupPatch(string group_id) + [HttpPatch("groups/{groupRef}")] + public async Task DoGroupPatch(string groupRef, [FromBody] JObject data) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + 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 patch = GroupPatch.FromJson(data); + + patch.AssertIsValid(); + if (patch.Errors.Count > 0) + throw new ModelParseError(patch.Errors); + + var newGroup = await _repo.UpdateGroup(group.Id, patch); + return Ok(newGroup.ToJson(LookupContext.ByOwner)); } [HttpDelete("groups/{groupRef}")] diff --git a/PluralKit.API/Controllers/v2/MemberControllerV2.cs b/PluralKit.API/Controllers/v2/MemberControllerV2.cs index 2b72618c..c7b8c090 100644 --- a/PluralKit.API/Controllers/v2/MemberControllerV2.cs +++ b/PluralKit.API/Controllers/v2/MemberControllerV2.cs @@ -40,10 +40,24 @@ namespace PluralKit.API [HttpPost("members")] public async Task MemberCreate([FromBody] JObject data) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + 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.")); + if (patch.Errors.Count > 0) + throw new ModelParseError(patch.Errors); + + var system = await ResolveSystem("@me"); + + using var conn = await _db.Obtain(); + using var tx = await conn.BeginTransactionAsync(); + + var newMember = await _repo.CreateMember(system.Id, patch.Name.Value, conn); + newMember = await _repo.UpdateMember(newMember.Id, patch, conn); + + await tx.CommitAsync(); + + return Ok(newMember.ToJson(LookupContext.ByOwner, v: APIVersion.V2)); } [HttpGet("members/{memberRef}")] @@ -58,13 +72,24 @@ namespace PluralKit.API return Ok(member.ToJson(this.ContextFor(member), systemStr: system.Hid, v: APIVersion.V2)); } - [HttpPatch("members/{member}")] - public async Task MemberPatch(string member, [FromBody] JObject data) + [HttpPatch("members/{memberRef}")] + public async Task DoMemberPatch(string memberRef, [FromBody] JObject data) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + 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 patch = MemberPatch.FromJSON(data, APIVersion.V2); + + 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)); } [HttpDelete("members/{memberRef}")] diff --git a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs index 14f908fe..d291991c 100644 --- a/PluralKit.API/Controllers/v2/SwitchControllerV2.cs +++ b/PluralKit.API/Controllers/v2/SwitchControllerV2.cs @@ -165,8 +165,7 @@ namespace PluralKit.API var valueStr = data.Value("timestamp").NullIfEmpty(); if (valueStr == null) - // todo - throw Errors.GenericBadRequest; + throw new ModelParseError(new List() { new ValidationError("timestamp", $"Key 'timestamp' is required.") }); var value = Instant.FromDateTimeOffset(DateTime.Parse(valueStr).ToUniversalTime()); diff --git a/PluralKit.API/Controllers/v2/SystemControllerV2.cs b/PluralKit.API/Controllers/v2/SystemControllerV2.cs index b7432166..4cbcc1c0 100644 --- a/PluralKit.API/Controllers/v2/SystemControllerV2.cs +++ b/PluralKit.API/Controllers/v2/SystemControllerV2.cs @@ -24,13 +24,18 @@ namespace PluralKit.API else return Ok(system.ToJson(this.ContextFor(system), v: APIVersion.V2)); } - [HttpPatch("{system}")] - public async Task SystemPatch(string system, [FromBody] JObject data) + [HttpPatch] + public async Task DoSystemPatch([FromBody] JObject data) { - return new ObjectResult("Unimplemented") - { - StatusCode = 501 - }; + var system = await ResolveSystem("@me"); + var patch = SystemPatch.FromJSON(data, APIVersion.V2); + + 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, v: APIVersion.V2)); } } } \ No newline at end of file