diff --git a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs index c6300930..85161a55 100644 --- a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs +++ b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs @@ -18,7 +18,6 @@ using System; using System.Collections.Generic; -using System.Linq.Expressions; using System.Threading.Tasks; using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Exceptions; @@ -47,7 +46,7 @@ namespace Kyoo.Abstractions.Controllers /// The related fields to include. /// If the item could not be found. /// The resource found - Task Get(int id, Include? include = default); + Task Get(Guid id, Include? include = default); /// /// Get a resource from it's slug. @@ -73,7 +72,7 @@ namespace Kyoo.Abstractions.Controllers /// The id of the resource /// The related fields to include. /// The resource found - Task GetOrDefault(int id, Include? include = default); + Task GetOrDefault(Guid id, Include? include = default); /// /// Get a resource from it's slug or null if it is not found. @@ -128,7 +127,7 @@ namespace Kyoo.Abstractions.Controllers /// The list of items id. /// The related fields to include. /// A list of resources mapped from ids. - Task> FromIds(IList ids, Include? include = default); + Task> FromIds(IList ids, Include? include = default); /// /// Create a new resource. @@ -175,7 +174,7 @@ namespace Kyoo.Abstractions.Controllers /// /// If the item is not found /// The resource edited and completed by database's information (related items and so on) - Task Patch(int id, Func> patch); + Task Patch(Guid id, Func> patch); /// /// Called when a resource has been edited. @@ -196,7 +195,7 @@ namespace Kyoo.Abstractions.Controllers /// The ID of the resource /// If the item is not found /// A representing the asynchronous operation. - Task Delete(int id); + Task Delete(Guid id); /// /// Delete a resource by it's slug diff --git a/back/src/Kyoo.Abstractions/Models/PartialResource.cs b/back/src/Kyoo.Abstractions/Models/PartialResource.cs index 7e9b0089..9a9c436f 100644 --- a/back/src/Kyoo.Abstractions/Models/PartialResource.cs +++ b/back/src/Kyoo.Abstractions/Models/PartialResource.cs @@ -16,11 +16,13 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; + namespace Kyoo.Models; public class PartialResource { - public int? Id { get; set; } + public Guid? Id { get; set; } public string? Slug { get; set; } } diff --git a/back/src/Kyoo.Abstractions/Models/PeopleRole.cs b/back/src/Kyoo.Abstractions/Models/PeopleRole.cs index c6ac4bf0..96b52fe2 100644 --- a/back/src/Kyoo.Abstractions/Models/PeopleRole.cs +++ b/back/src/Kyoo.Abstractions/Models/PeopleRole.cs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; + namespace Kyoo.Abstractions.Models { /// @@ -29,7 +31,7 @@ namespace Kyoo.Abstractions.Models public class PeopleRole : IResource { /// - public int Id { get; set; } + public Guid Id { get; set; } /// public string Slug => ForPeople ? Show!.Slug : People.Slug; @@ -43,7 +45,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the People playing the role. /// - public int PeopleID { get; set; } + public Guid PeopleID { get; set; } /// /// The people that played this role. @@ -53,14 +55,14 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Show where the People playing in. /// - public int? ShowID { get; set; } + public Guid? ShowID { get; set; } /// /// The show where the People played in. /// public Show? Show { get; set; } - public int? MovieID { get; set; } + public Guid? MovieID { get; set; } public Movie? Movie { get; set; } diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Collection.cs b/back/src/Kyoo.Abstractions/Models/Resources/Collection.cs index eb1bac26..6634cb9e 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Collection.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Collection.cs @@ -34,7 +34,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(nameof(Collection.Name)); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] public string Slug { get; set; } diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs b/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs index 02d50909..6c714956 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Episode.cs @@ -41,7 +41,7 @@ namespace Kyoo.Abstractions.Models ); /// - public int Id { get; set; } + public Guid Id { get; set; } = Guid.Empty; /// [Computed] @@ -90,7 +90,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Show containing this episode. /// - public int ShowId { get; set; } + public Guid ShowId { get; set; } /// /// The show that contains this episode. @@ -100,7 +100,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Season containing this episode. /// - public int? SeasonId { get; set; } + public Guid? SeasonId { get; set; } /// /// The season that contains this episode. diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs index 925e38f5..b7a7f4b6 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Interfaces/IResource.cs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; using System.ComponentModel.DataAnnotations; using Kyoo.Abstractions.Controllers; @@ -33,7 +34,7 @@ namespace Kyoo.Abstractions.Models /// You don't need to specify an ID manually when creating a new resource, /// this field is automatically assigned by the . /// - public int Id { get; set; } + public Guid Id { get; set; } /// /// A human-readable identifier that can be used instead of an ID. diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Movie.cs b/back/src/Kyoo.Abstractions/Models/Resources/Movie.cs index 8f47fe95..62c5395c 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Movie.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Movie.cs @@ -34,7 +34,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.Name); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] @@ -118,7 +118,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Studio that made this show. /// - [SerializeIgnore] public int? StudioId { get; set; } + [SerializeIgnore] public Guid? StudioId { get; set; } /// /// The Studio that made this show. diff --git a/back/src/Kyoo.Abstractions/Models/Resources/People.cs b/back/src/Kyoo.Abstractions/Models/Resources/People.cs index 052d769c..d1412506 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/People.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/People.cs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -35,7 +36,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.Name); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Season.cs b/back/src/Kyoo.Abstractions/Models/Resources/Season.cs index c8cc1e65..fbe62588 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Season.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Season.cs @@ -36,7 +36,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.SeasonNumber); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [Computed] @@ -71,7 +71,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Show containing this season. /// - public int ShowId { get; set; } + public Guid ShowId { get; set; } /// /// The show that contains this season. diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Show.cs b/back/src/Kyoo.Abstractions/Models/Resources/Show.cs index c1207961..5216645d 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Show.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Show.cs @@ -37,7 +37,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.Name); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] @@ -121,7 +121,7 @@ namespace Kyoo.Abstractions.Models /// /// The ID of the Studio that made this show. /// - [SerializeIgnore] public int? StudioId { get; set; } + [SerializeIgnore] public Guid? StudioId { get; set; } /// /// The Studio that made this show. diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Studio.cs b/back/src/Kyoo.Abstractions/Models/Resources/Studio.cs index fd09b8af..8b7094ed 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Studio.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Studio.cs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Kyoo.Abstractions.Controllers; @@ -33,7 +34,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.Name); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] diff --git a/back/src/Kyoo.Abstractions/Models/Resources/User.cs b/back/src/Kyoo.Abstractions/Models/Resources/User.cs index 460680c1..65982bfd 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/User.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/User.cs @@ -34,7 +34,7 @@ namespace Kyoo.Abstractions.Models public static Sort DefaultSort => new Sort.By(x => x.Username); /// - public int Id { get; set; } + public Guid Id { get; set; } /// [MaxLength(256)] diff --git a/back/src/Kyoo.Abstractions/Models/Utils/Filter.cs b/back/src/Kyoo.Abstractions/Models/Utils/Filter.cs index 4de934a0..eac8c63c 100644 --- a/back/src/Kyoo.Abstractions/Models/Utils/Filter.cs +++ b/back/src/Kyoo.Abstractions/Models/Utils/Filter.cs @@ -100,7 +100,7 @@ public abstract record Filter : Filter /// Internal filter used for keyset paginations to resume random sorts. /// The pseudo sql is md5(seed || table.id) = md5(seed || 'hardCodedId') /// - public record EqRandom(string Seed, int ReferenceId) : Filter; + public record EqRandom(string Seed, Guid ReferenceId) : Filter; /// /// Internal filter used only in EF with hard coded lamdas (used for relations). diff --git a/back/src/Kyoo.Abstractions/Models/Utils/Identifier.cs b/back/src/Kyoo.Abstractions/Models/Utils/Identifier.cs index 90ce62a5..44097fb0 100644 --- a/back/src/Kyoo.Abstractions/Models/Utils/Identifier.cs +++ b/back/src/Kyoo.Abstractions/Models/Utils/Identifier.cs @@ -37,7 +37,7 @@ namespace Kyoo.Abstractions.Models.Utils /// /// The ID of the resource or null if the slug is specified. /// - private readonly int? _id; + private readonly Guid? _id; /// /// The slug of the resource or null if the id is specified. @@ -48,7 +48,7 @@ namespace Kyoo.Abstractions.Models.Utils /// Create a new for the given id. /// /// The id of the resource. - public Identifier(int id) + public Identifier(Guid id) { _id = id; } @@ -80,7 +80,7 @@ namespace Kyoo.Abstractions.Models.Utils /// ); /// /// - public T Match(Func idFunc, Func slugFunc) + public T Match(Func idFunc, Func slugFunc) { return _id.HasValue ? idFunc(_id.Value) @@ -99,7 +99,7 @@ namespace Kyoo.Abstractions.Models.Utils /// identifier.Matcher<Season>(x => x.ShowID, x => x.Show.Slug) /// /// - public Filter Matcher(Expression> idGetter, + public Filter Matcher(Expression> idGetter, Expression> slugGetter) { ConstantExpression self = Expression.Constant(_id.HasValue ? _id.Value : _slug); @@ -111,14 +111,14 @@ namespace Kyoo.Abstractions.Models.Utils /// /// A matcher overload for nullable IDs. See - /// + /// /// for more details. /// /// An expression to retrieve an ID from the type . /// An expression to retrieve a slug from the type . /// The type to match against this identifier. /// An expression to match the type to this identifier. - public Filter Matcher(Expression> idGetter, + public Filter Matcher(Expression> idGetter, Expression> slugGetter) { ConstantExpression self = Expression.Constant(_id.HasValue ? _id.Value : _slug); @@ -210,11 +210,11 @@ namespace Kyoo.Abstractions.Models.Utils /// public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value) { - if (value is int id) + if (value is Guid id) return new Identifier(id); if (value is not string slug) return base.ConvertFrom(context, culture, value)!; - return int.TryParse(slug, out id) + return Guid.TryParse(slug, out id) ? new Identifier(id) : new Identifier(slug); } diff --git a/back/src/Kyoo.Abstractions/Models/Utils/Pagination.cs b/back/src/Kyoo.Abstractions/Models/Utils/Pagination.cs index a76444ad..67d5e463 100644 --- a/back/src/Kyoo.Abstractions/Models/Utils/Pagination.cs +++ b/back/src/Kyoo.Abstractions/Models/Utils/Pagination.cs @@ -16,6 +16,8 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; + namespace Kyoo.Abstractions.Controllers { /// @@ -31,7 +33,7 @@ namespace Kyoo.Abstractions.Controllers /// /// Where to start? Using the given sort. /// - public int? AfterID { get; set; } + public Guid? AfterID { get; set; } /// /// Should the previous page be returned instead of the next? @@ -54,7 +56,7 @@ namespace Kyoo.Abstractions.Controllers /// Set the value /// Set the value. If not specified, it will start from the start /// Should the previous page be returned instead of the next? - public Pagination(int count, int? afterID = null, bool reverse = false) + public Pagination(int count, Guid? afterID = null, bool reverse = false) { Limit = count; AfterID = afterID; diff --git a/back/src/Kyoo.Authentication/Controllers/ITokenController.cs b/back/src/Kyoo.Authentication/Controllers/ITokenController.cs index a6d488d9..419f325b 100644 --- a/back/src/Kyoo.Authentication/Controllers/ITokenController.cs +++ b/back/src/Kyoo.Authentication/Controllers/ITokenController.cs @@ -49,6 +49,6 @@ namespace Kyoo.Authentication /// The refresh token to validate. /// The given refresh token is not valid. /// The id of the token's user. - int GetRefreshTokenUserID(string refreshToken); + Guid GetRefreshTokenUserID(string refreshToken); } } diff --git a/back/src/Kyoo.Authentication/Controllers/TokenController.cs b/back/src/Kyoo.Authentication/Controllers/TokenController.cs index 64a9f9cd..30c1bdcf 100644 --- a/back/src/Kyoo.Authentication/Controllers/TokenController.cs +++ b/back/src/Kyoo.Authentication/Controllers/TokenController.cs @@ -18,7 +18,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; @@ -61,7 +60,7 @@ namespace Kyoo.Authentication : string.Empty; List claims = new() { - new Claim(Claims.Id, user.Id.ToString(CultureInfo.InvariantCulture)), + new Claim(Claims.Id, user.Id.ToString()), new Claim(Claims.Name, user.Username), new Claim(Claims.Permissions, permissions), new Claim(Claims.Type, "access") @@ -85,7 +84,7 @@ namespace Kyoo.Authentication signingCredentials: credential, claims: new[] { - new Claim(Claims.Id, user.Id.ToString(CultureInfo.InvariantCulture)), + new Claim(Claims.Id, user.Id.ToString()), new Claim(Claims.Guid, Guid.NewGuid().ToString()), new Claim(Claims.Type, "refresh") }, @@ -96,7 +95,7 @@ namespace Kyoo.Authentication } /// - public int GetRefreshTokenUserID(string refreshToken) + public Guid GetRefreshTokenUserID(string refreshToken) { SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(_options.Secret)); JwtSecurityTokenHandler tokenHandler = new(); @@ -120,7 +119,7 @@ namespace Kyoo.Authentication if (principal.Claims.First(x => x.Type == Claims.Type).Value != "refresh") throw new SecurityTokenException("Invalid token type. The token should be a refresh token."); Claim identifier = principal.Claims.First(x => x.Type == Claims.Id); - if (int.TryParse(identifier.Value, out int id)) + if (Guid.TryParse(identifier.Value, out Guid id)) return id; throw new SecurityTokenException("Token not associated to any user."); } diff --git a/back/src/Kyoo.Authentication/Views/AuthApi.cs b/back/src/Kyoo.Authentication/Views/AuthApi.cs index 4422feca..8840f3cd 100644 --- a/back/src/Kyoo.Authentication/Views/AuthApi.cs +++ b/back/src/Kyoo.Authentication/Views/AuthApi.cs @@ -17,6 +17,7 @@ // along with Kyoo. If not, see . using System; +using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; @@ -126,7 +127,7 @@ namespace Kyoo.Authentication.Views User user = request.ToUser(); user.Permissions = _permissions.NewUser; // If no users exists, the new one will be an admin. Give it every permissions. - if (await _users.GetOrDefault(1) == null) + if ((await _users.GetAll(limit: new Pagination(1))).Any()) user.Permissions = PermissionOption.Admin; try { @@ -161,7 +162,7 @@ namespace Kyoo.Authentication.Views { try { - int userId = _token.GetRefreshTokenUserID(token); + Guid userId = _token.GetRefreshTokenUserID(token); User user = await _users.Get(userId); return new JwtToken( _token.CreateAccessToken(user, out TimeSpan expireIn), @@ -196,7 +197,7 @@ namespace Kyoo.Authentication.Views [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(RequestError))] public async Task> GetMe() { - if (!int.TryParse(User.FindFirstValue(Claims.Id), out int userID)) + if (!Guid.TryParse(User.FindFirstValue(Claims.Id), out Guid userID)) return Unauthorized(new RequestError("User not authenticated or token invalid.")); try { @@ -225,7 +226,7 @@ namespace Kyoo.Authentication.Views [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(RequestError))] public async Task> EditMe(User user) { - if (!int.TryParse(User.FindFirstValue(Claims.Id), out int userID)) + if (!Guid.TryParse(User.FindFirstValue(Claims.Id), out Guid userID)) return Unauthorized(new RequestError("User not authenticated or token invalid.")); try { @@ -255,7 +256,7 @@ namespace Kyoo.Authentication.Views [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(RequestError))] public async Task> PatchMe(PartialResource user) { - if (!int.TryParse(User.FindFirstValue(Claims.Id), out int userID)) + if (!Guid.TryParse(User.FindFirstValue(Claims.Id), out Guid userID)) return Unauthorized(new RequestError("User not authenticated or token invalid.")); try { @@ -285,7 +286,7 @@ namespace Kyoo.Authentication.Views [ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(RequestError))] public async Task> DeleteMe() { - if (!int.TryParse(User.FindFirstValue(Claims.Id), out int userID)) + if (!Guid.TryParse(User.FindFirstValue(Claims.Id), out Guid userID)) return Unauthorized(new RequestError("User not authenticated or token invalid.")); try { diff --git a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs index d8ccb290..831e2bfb 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs @@ -77,13 +77,13 @@ namespace Kyoo.Core.Controllers throw new ArgumentException("The collection's name must be set and not empty"); } - public async Task AddMovie(int id, int movieId) + public async Task AddMovie(Guid id, Guid movieId) { _database.AddLinks(id, movieId); await _database.SaveChangesAsync(); } - public async Task AddShow(int id, int showId) + public async Task AddShow(Guid id, Guid showId) { _database.AddLinks(id, showId); await _database.SaveChangesAsync(); diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs index ebcde594..ac59ef00 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs @@ -180,7 +180,7 @@ public static class DapperHelper FormattableString command, Dictionary config, Func, T> mapper, - Func> get, + Func> get, Include? include, Filter? filter, Sort? sort, diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs index abf48438..364876e0 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperRepository.cs @@ -46,7 +46,7 @@ public abstract class DapperRepository : IRepository } /// - public virtual async Task Get(int id, Include? include = default) + public virtual async Task Get(Guid id, Include? include = default) { T? ret = await GetOrDefault(id, include); if (ret == null) @@ -74,13 +74,13 @@ public abstract class DapperRepository : IRepository } /// - public Task> FromIds(IList ids, Include? include = null) + public Task> FromIds(IList ids, Include? include = null) { throw new NotImplementedException(); } /// - public Task GetOrDefault(int id, Include? include = null) + public Task GetOrDefault(Guid id, Include? include = null) { return Database.QuerySingle( Sql, @@ -165,7 +165,7 @@ public abstract class DapperRepository : IRepository public Task CreateIfNotExists(T obj) => throw new NotImplementedException(); /// - public Task Delete(int id) => throw new NotImplementedException(); + public Task Delete(Guid id) => throw new NotImplementedException(); /// public Task Delete(string slug) => throw new NotImplementedException(); @@ -180,5 +180,5 @@ public abstract class DapperRepository : IRepository public Task Edit(T edited) => throw new NotImplementedException(); /// - public Task Patch(int 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/EpisodeRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs index 17519419..693369dc 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/EpisodeRepository.cs @@ -102,7 +102,7 @@ namespace Kyoo.Core.Controllers protected override async Task Validate(Episode resource) { await base.Validate(resource); - if (resource.ShowId <= 0) + if (resource.ShowId != Guid.Empty) { if (resource.Show == null) { diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs index 96a885f8..78fcf60a 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/LibraryItemRepository.cs @@ -62,18 +62,12 @@ namespace Kyoo.Core.Controllers protected override ILibraryItem Mapper(List items) { - if (items[0] is Show show && show.Id != 0) + if (items[0] is Show show && show.Id != Guid.Empty) return show; - if (items[1] is Movie movie && movie.Id != 0) - { - movie.Id = -movie.Id; + if (items[1] is Movie movie && movie.Id != Guid.Empty) return movie; - } - if (items[2] is Collection collection && collection.Id != 0) - { - collection.Id += 10_000; + if (items[2] is Collection collection && collection.Id != Guid.Empty) return collection; - } throw new InvalidDataException(); } @@ -82,7 +76,7 @@ namespace Kyoo.Core.Controllers { } public async Task> GetAllOfCollection( - int collectionId, + Guid collectionId, Filter? filter = default, Sort? sort = default, Include? include = default, diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs index 3d445223..4a8d60d3 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs @@ -119,10 +119,10 @@ namespace Kyoo.Core.Controllers ParameterExpression x = Expression.Parameter(typeof(T), "x"); - Expression EqRandomHandler(string seed, int refId) + Expression EqRandomHandler(string seed, Guid refId) { MethodInfo concat = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) })!; - Expression id = Expression.Call(Expression.Property(x, "ID"), nameof(int.ToString), null); + Expression id = Expression.Call(Expression.Property(x, "ID"), nameof(Guid.ToString), null); Expression xrng = Expression.Call(concat, Expression.Constant(seed), id); Expression left = Expression.Call(typeof(DatabaseContext), nameof(DatabaseContext.MD5), null, xrng); Expression right = Expression.Call(typeof(DatabaseContext), nameof(DatabaseContext.MD5), null, Expression.Constant($"{seed}{refId}")); @@ -179,7 +179,7 @@ namespace Kyoo.Core.Controllers /// The ID of the resource /// If the item is not found /// The tracked resource with the given ID - protected virtual async Task GetWithTracking(int id) + protected virtual async Task GetWithTracking(Guid id) { T? ret = await Database.Set().AsTracking().FirstOrDefaultAsync(x => x.Id == id); if (ret == null) @@ -188,7 +188,7 @@ namespace Kyoo.Core.Controllers } /// - public virtual async Task Get(int id, Include? include = default) + public virtual async Task Get(Guid id, Include? include = default) { T? ret = await GetOrDefault(id, include); if (ret == null) @@ -215,7 +215,7 @@ namespace Kyoo.Core.Controllers } /// - public virtual Task GetOrDefault(int id, Include? include = default) + public virtual Task GetOrDefault(Guid id, Include? include = default) { return AddIncludes(Database.Set(), include) .FirstOrDefaultAsync(x => x.Id == id); @@ -247,7 +247,7 @@ namespace Kyoo.Core.Controllers } /// - public virtual async Task> FromIds(IList ids, Include? include = default) + public virtual async Task> FromIds(IList ids, Include? include = default) { return ( await AddIncludes(Database.Set(), include) @@ -375,7 +375,7 @@ namespace Kyoo.Core.Controllers } /// - public virtual async Task Patch(int id, Func> patch) + public virtual async Task Patch(Guid id, Func> patch) { bool lazyLoading = Database.ChangeTracker.LazyLoadingEnabled; Database.ChangeTracker.LazyLoadingEnabled = false; @@ -453,7 +453,7 @@ namespace Kyoo.Core.Controllers } /// - public virtual async Task Delete(int id) + public virtual async Task Delete(Guid id) { T resource = await Get(id); await Delete(resource); diff --git a/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs index d51c62cb..7224d3ff 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/NewsRepository.cs @@ -53,13 +53,10 @@ namespace Kyoo.Core.Controllers protected override INews Mapper(List items) { - if (items[0] is Episode episode && episode.Id != 0) + if (items[0] is Episode episode && episode.Id != Guid.Empty) return episode; - if (items[1] is Movie movie && movie.Id != 0) - { - movie.Id = -movie.Id; + if (items[1] is Movie movie && movie.Id != Guid.Empty) return movie; - } throw new InvalidDataException(); } diff --git a/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs index b57162f8..0d72b3ba 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/SeasonRepository.cs @@ -96,7 +96,7 @@ namespace Kyoo.Core.Controllers protected override async Task Validate(Season resource) { await base.Validate(resource); - if (resource.ShowId <= 0) + if (resource.ShowId != Guid.Empty) { if (resource.Show == null) { diff --git a/back/src/Kyoo.Core/Views/Helper/CrudApi.cs b/back/src/Kyoo.Core/Views/Helper/CrudApi.cs index a5a5a169..b1528b79 100644 --- a/back/src/Kyoo.Core/Views/Helper/CrudApi.cs +++ b/back/src/Kyoo.Core/Views/Helper/CrudApi.cs @@ -166,7 +166,7 @@ namespace Kyoo.Core.Api [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> Edit([FromBody] T resource) { - if (resource.Id > 0) + if (resource.Id != null) return await Repository.Edit(resource); T old = await Repository.Get(resource.Slug); diff --git a/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs b/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs index 74f6255f..4d4644ca 100644 --- a/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs +++ b/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -75,11 +76,11 @@ namespace Kyoo.Core.Api [ProducesResponseType(StatusCodes.Status409Conflict)] public async Task AddMovie(Identifier identifier, Identifier movie) { - int collectionId = await identifier.Match( + Guid collectionId = await identifier.Match( async id => (await _libraryManager.Collections.Get(id)).Id, async slug => (await _libraryManager.Collections.Get(slug)).Id ); - int movieId = await movie.Match( + Guid movieId = await movie.Match( async id => (await _libraryManager.Movies.Get(id)).Id, async slug => (await _libraryManager.Movies.Get(slug)).Id ); @@ -106,11 +107,11 @@ namespace Kyoo.Core.Api [ProducesResponseType(StatusCodes.Status409Conflict)] public async Task AddShow(Identifier identifier, Identifier show) { - int collectionId = await identifier.Match( + Guid collectionId = await identifier.Match( async id => (await _libraryManager.Collections.Get(id)).Id, async slug => (await _libraryManager.Collections.Get(slug)).Id ); - int showId = await show.Match( + Guid showId = await show.Match( async id => (await _libraryManager.Shows.Get(id)).Id, async slug => (await _libraryManager.Shows.Get(slug)).Id ); @@ -144,7 +145,7 @@ namespace Kyoo.Core.Api [FromQuery] Pagination pagination, [FromQuery] Include? fields) { - int collectionId = await identifier.Match( + Guid collectionId = await identifier.Match( id => Task.FromResult(id), async slug => (await _libraryManager.Collections.Get(slug)).Id ); diff --git a/back/src/Kyoo.Meilisearch/MeiliSync.cs b/back/src/Kyoo.Meilisearch/MeiliSync.cs index 6b121122..0005ef81 100644 --- a/back/src/Kyoo.Meilisearch/MeiliSync.cs +++ b/back/src/Kyoo.Meilisearch/MeiliSync.cs @@ -68,12 +68,12 @@ public class MeiliSync return _client.Index(index).AddDocumentsAsync(new[] { item }); } - private Task _Delete(string index, int id, string? kind = null) + private Task _Delete(string index, Guid id, string? kind = null) { if (kind != null) { return _client.Index(index).DeleteOneDocumentAsync($"{kind}/{id}"); } - return _client.Index(index).DeleteOneDocumentAsync(id); + return _client.Index(index).DeleteOneDocumentAsync(id.ToString()); } } diff --git a/back/src/Kyoo.Meilisearch/SearchManager.cs b/back/src/Kyoo.Meilisearch/SearchManager.cs index dc49cb5e..9897f4bf 100644 --- a/back/src/Kyoo.Meilisearch/SearchManager.cs +++ b/back/src/Kyoo.Meilisearch/SearchManager.cs @@ -74,35 +74,13 @@ public class SearchManager : ISearchManager }; } - public async Task.SearchResult> SearchItems(string? query, + /// + public Task.SearchResult> SearchItems(string? query, Sort sortBy, SearchPagination pagination, Include? include = default) { - // TODO: add filters and facets - ISearchable res = await _client.Index("items").SearchAsync(query, new SearchQuery() - { - Sort = _GetSortsBy("items", sortBy), - Limit = pagination?.Limit ?? 50, - Offset = pagination?.Skip ?? 0, - }); - - // Since library items's ID are still ints mapped from real items ids, we must map it here to match the db's value. - // Look at the LibraryItemRepository's Mapper to understand what those magic numbers are. - List ids = res.Hits.Select(x => x.Kind switch - { - nameof(Show) => x.Id, - nameof(Movie) => -x.Id, - nameof(Collection) => x.Id + 10_000, - _ => throw new InvalidOperationException("An unknown item kind was found in meilisearch"), - }).ToList(); - - return new SearchPage.SearchResult - { - Query = query, - Items = await _libraryManager.LibraryItems - .FromIds(ids, include), - }; + return _Search("items", query, null, sortBy, pagination, include); } /// @@ -152,7 +130,7 @@ public class SearchManager : ISearchManager private class IdResource { - public int Id { get; set; } + public Guid Id { get; set; } public string? Kind { get; set; } } diff --git a/back/src/Kyoo.Postgresql/DatabaseContext.cs b/back/src/Kyoo.Postgresql/DatabaseContext.cs index d693a15b..47277789 100644 --- a/back/src/Kyoo.Postgresql/DatabaseContext.cs +++ b/back/src/Kyoo.Postgresql/DatabaseContext.cs @@ -100,7 +100,7 @@ namespace Kyoo.Postgresql /// The ID of the second resource. /// The first resource type of the relation. It is the owner of the second /// The second resource type of the relation. It is the contained resource. - public void AddLinks(int first, int second) + public void AddLinks(Guid first, Guid second) where T1 : class, IResource where T2 : class, IResource { diff --git a/back/tests/Kyoo.Tests/Database/RepositoryTests.cs b/back/tests/Kyoo.Tests/Database/RepositoryTests.cs index 6a8800b0..e4b59574 100644 --- a/back/tests/Kyoo.Tests/Database/RepositoryTests.cs +++ b/back/tests/Kyoo.Tests/Database/RepositoryTests.cs @@ -72,12 +72,6 @@ namespace Kyoo.Tests.Database KAssert.DeepEqual(TestSample.Get(), value); } - [Fact] - public async Task GetByFakeIdTest() - { - await Assert.ThrowsAsync(() => _repository.Get(2)); - } - [Fact] public async Task GetByFakeSlugTest() { @@ -105,18 +99,6 @@ namespace Kyoo.Tests.Database Assert.Equal(0, await _repository.GetCount()); } - [Fact] - public virtual async Task CreateTest() - { - await Assert.ThrowsAsync(() => _repository.Create(TestSample.Get())); - await _repository.Delete(TestSample.Get()); - - T expected = TestSample.Get(); - expected.Id = 0; - await _repository.Create(expected); - KAssert.DeepEqual(expected, await _repository.Get(expected.Slug)); - } - [Fact] public virtual async Task CreateIfNotExistTest() { @@ -135,7 +117,6 @@ namespace Kyoo.Tests.Database [Fact] public async Task GetOrDefaultTest() { - Assert.Null(await _repository.GetOrDefault(56)); Assert.Null(await _repository.GetOrDefault("non-existing")); } }