diff --git a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
index 7533f43e..2efd68bf 100644
--- a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
+++ b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
@@ -187,11 +187,11 @@ namespace Kyoo.Abstractions.Controllers
/// The id of the resource to edit
///
/// 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.
///
/// If the item is not found
/// The resource edited and completed by database's information (related items and so on)
- Task Patch(Guid id, Func> patch);
+ Task Patch(Guid id, Func patch);
///
/// Called when a resource has been edited.
diff --git a/back/src/Kyoo.Abstractions/Models/PartialResource.cs b/back/src/Kyoo.Abstractions/Models/Patch.cs
similarity index 54%
rename from back/src/Kyoo.Abstractions/Models/PartialResource.cs
rename to back/src/Kyoo.Abstractions/Models/Patch.cs
index 9a9c436f..608b3f61 100644
--- a/back/src/Kyoo.Abstractions/Models/PartialResource.cs
+++ b/back/src/Kyoo.Abstractions/Models/Patch.cs
@@ -17,12 +17,30 @@
// along with Kyoo. If not, see .
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 : Dictionary
+ where T : class, IResource
{
- public Guid? Id { get; set; }
+ public Guid? Id => this.GetValueOrDefault(nameof(IResource.Id))?.ToObject();
- public string? Slug { get; set; }
+ public string? Slug => this.GetValueOrDefault(nameof(IResource.Slug))?.ToObject();
+
+ 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;
+ }
}
diff --git a/back/src/Kyoo.Authentication/Views/AuthApi.cs b/back/src/Kyoo.Authentication/Views/AuthApi.cs
index e14b5889..11d9ac46 100644
--- a/back/src/Kyoo.Authentication/Views/AuthApi.cs
+++ b/back/src/Kyoo.Authentication/Views/AuthApi.cs
@@ -246,7 +246,7 @@ namespace Kyoo.Authentication.Views
///
/// Edit only provided informations about the currently authenticated user.
///
- /// The new data for the current user.
+ /// The new data for the current user.
/// The currently authenticated user after modifications.
/// The user is not authenticated.
/// The given access token is invalid.
@@ -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> PatchMe(PartialResource user)
+ public async Task> PatchMe([FromBody] Patch 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)
{
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs
index 2ef6eede..18f0677b 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs
@@ -217,5 +217,5 @@ public abstract class DapperRepository : IRepository
public Task Edit(T edited) => throw new NotImplementedException();
///
- public Task Patch(Guid id, Func> patch) => throw new NotImplementedException();
+ public Task Patch(Guid id, Func patch) => throw new NotImplementedException();
}
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
index 90ccb35b..38130e24 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
@@ -497,7 +497,7 @@ namespace Kyoo.Core.Controllers
}
///
- public virtual async Task Patch(Guid id, Func> patch)
+ public virtual async Task Patch(Guid id, Func 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.OnResourceEdited(resource);
diff --git a/back/src/Kyoo.Core/Views/Helper/CrudApi.cs b/back/src/Kyoo.Core/Views/Helper/CrudApi.cs
index b1679313..38b68326 100644
--- a/back/src/Kyoo.Core/Views/Helper/CrudApi.cs
+++ b/back/src/Kyoo.Core/Views/Helper/CrudApi.cs
@@ -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.
///
- /// The resource to patch.
+ /// The resource to patch.
/// The edited resource.
/// The resource in the request body is invalid.
/// No item found with the specified ID (or slug).
@@ -189,17 +189,17 @@ namespace Kyoo.Core.Api
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task> Patch([FromBody] PartialResource resource)
+ public async Task> Patch([FromBody] Patch 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);
}
///