mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Rework patch apis
This commit is contained in:
parent
e668cdd89c
commit
fabafcb78b
@ -187,11 +187,11 @@ namespace Kyoo.Abstractions.Controllers
|
||||
/// <param name="id">The id of the resource to edit</param>
|
||||
/// <param name="patch">
|
||||
/// A method that will be called when you need to update every properties that you want to
|
||||
/// persist. It can return false to abort the process via an ArgumentException
|
||||
/// persist.
|
||||
/// </param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The resource edited and completed by database's information (related items and so on)</returns>
|
||||
Task<T> Patch(Guid id, Func<T, Task<bool>> patch);
|
||||
Task<T> Patch(Guid id, Func<T, T> patch);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a resource has been edited.
|
||||
|
@ -17,12 +17,30 @@
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Kyoo.Models;
|
||||
|
||||
public class PartialResource
|
||||
public class Patch<T> : Dictionary<string, JObject>
|
||||
where T : class, IResource
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
public Guid? Id => this.GetValueOrDefault(nameof(IResource.Id))?.ToObject<Guid>();
|
||||
|
||||
public string? Slug { get; set; }
|
||||
public string? Slug => this.GetValueOrDefault(nameof(IResource.Slug))?.ToObject<string>();
|
||||
|
||||
public T Apply(T current)
|
||||
{
|
||||
foreach ((string property, JObject value) in this)
|
||||
{
|
||||
PropertyInfo prop = typeof(T).GetProperty(
|
||||
property,
|
||||
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance
|
||||
)!;
|
||||
prop.SetValue(current, value.ToObject(prop.PropertyType));
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
@ -246,7 +246,7 @@ namespace Kyoo.Authentication.Views
|
||||
/// <remarks>
|
||||
/// Edit only provided informations about the currently authenticated user.
|
||||
/// </remarks>
|
||||
/// <param name="user">The new data for the current user.</param>
|
||||
/// <param name="patch">The new data for the current user.</param>
|
||||
/// <returns>The currently authenticated user after modifications.</returns>
|
||||
/// <response code="401">The user is not authenticated.</response>
|
||||
/// <response code="403">The given access token is invalid.</response>
|
||||
@ -255,14 +255,14 @@ namespace Kyoo.Authentication.Views
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(RequestError))]
|
||||
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(RequestError))]
|
||||
public async Task<ActionResult<User>> PatchMe(PartialResource user)
|
||||
public async Task<ActionResult<User>> PatchMe([FromBody] Patch<User> patch)
|
||||
{
|
||||
Guid userId = User.GetIdOrThrow();
|
||||
try
|
||||
{
|
||||
if (user.Id.HasValue && user.Id != userId)
|
||||
if (patch.Id.HasValue && patch.Id != userId)
|
||||
throw new ArgumentException("Can't edit your user id.");
|
||||
return await _users.Patch(userId, TryUpdateModelAsync);
|
||||
return await _users.Patch(userId, patch.Apply);
|
||||
}
|
||||
catch (ItemNotFoundException)
|
||||
{
|
||||
|
@ -217,5 +217,5 @@ public abstract class DapperRepository<T> : IRepository<T>
|
||||
public Task<T> Edit(T edited) => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<T> Patch(Guid id, Func<T, Task<bool>> patch) => throw new NotImplementedException();
|
||||
public Task<T> Patch(Guid id, Func<T, T> patch) => throw new NotImplementedException();
|
||||
}
|
||||
|
@ -497,7 +497,7 @@ namespace Kyoo.Core.Controllers
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<T> Patch(Guid id, Func<T, Task<bool>> patch)
|
||||
public virtual async Task<T> Patch(Guid id, Func<T, T> patch)
|
||||
{
|
||||
bool lazyLoading = Database.ChangeTracker.LazyLoadingEnabled;
|
||||
Database.ChangeTracker.LazyLoadingEnabled = false;
|
||||
@ -505,8 +505,7 @@ namespace Kyoo.Core.Controllers
|
||||
{
|
||||
T resource = await GetWithTracking(id);
|
||||
|
||||
if (!await patch(resource))
|
||||
throw new ArgumentException("Could not patch resource");
|
||||
resource = patch(resource);
|
||||
|
||||
await Database.SaveChangesAsync();
|
||||
await IRepository<T>.OnResourceEdited(resource);
|
||||
|
@ -180,7 +180,7 @@ namespace Kyoo.Core.Api
|
||||
/// Edit only specified properties of an item. If the ID is specified it will be used to identify the resource.
|
||||
/// If not, the slug will be used to identify it.
|
||||
/// </remarks>
|
||||
/// <param name="resource">The resource to patch.</param>
|
||||
/// <param name="patch">The resource to patch.</param>
|
||||
/// <returns>The edited resource.</returns>
|
||||
/// <response code="400">The resource in the request body is invalid.</response>
|
||||
/// <response code="404">No item found with the specified ID (or slug).</response>
|
||||
@ -189,17 +189,17 @@ namespace Kyoo.Core.Api
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<T>> Patch([FromBody] PartialResource resource)
|
||||
public async Task<ActionResult<T>> Patch([FromBody] Patch<T> patch)
|
||||
{
|
||||
if (resource.Id.HasValue)
|
||||
return await Repository.Patch(resource.Id.Value, TryUpdateModelAsync);
|
||||
if (resource.Slug == null)
|
||||
if (patch.Id.HasValue)
|
||||
return await Repository.Patch(patch.Id.Value, patch.Apply);
|
||||
if (patch.Slug == null)
|
||||
throw new ArgumentException(
|
||||
"Either the Id or the slug of the resource has to be defined to edit it."
|
||||
);
|
||||
|
||||
T old = await Repository.Get(resource.Slug);
|
||||
return await Repository.Patch(old.Id, TryUpdateModelAsync);
|
||||
T old = await Repository.Get(patch.Slug);
|
||||
return await Repository.Patch(old.Id, patch.Apply);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
Loading…
x
Reference in New Issue
Block a user