mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Starting to rework related properties loading. (Removing lazy loading)
This commit is contained in:
parent
f9e0c23e62
commit
3fe7c83415
@ -60,6 +60,10 @@ namespace Kyoo.Controllers
|
|||||||
Task<Genre> GetGenre(Expression<Func<Genre, bool>> where);
|
Task<Genre> GetGenre(Expression<Func<Genre, bool>> where);
|
||||||
Task<Studio> GetStudio(Expression<Func<Studio, bool>> where);
|
Task<Studio> GetStudio(Expression<Func<Studio, bool>> where);
|
||||||
Task<People> GetPerson(Expression<Func<People, bool>> where);
|
Task<People> GetPerson(Expression<Func<People, bool>> where);
|
||||||
|
|
||||||
|
Task Load<T, T2>([NotNull] T obj, Expression<Func<T, T2>> member)
|
||||||
|
where T : class, IResource
|
||||||
|
where T2 : class;
|
||||||
|
|
||||||
// Library Items relations
|
// Library Items relations
|
||||||
Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
Task<ICollection<LibraryItem>> GetItemsFromLibrary(int id,
|
||||||
|
@ -33,12 +33,8 @@ namespace Kyoo.Controllers
|
|||||||
Key = ExpressionRewrite.Rewrite<Func<T, object>>(key);
|
Key = ExpressionRewrite.Rewrite<Func<T, object>>(key);
|
||||||
Descendant = descendant;
|
Descendant = descendant;
|
||||||
|
|
||||||
if (Key == null ||
|
if (!Utility.IsPropertyExpression(Key))
|
||||||
Key.Body is MemberExpression ||
|
throw new ArgumentException("The given sort key is not valid.");
|
||||||
Key.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)Key.Body).Operand is MemberExpression)
|
|
||||||
return;
|
|
||||||
|
|
||||||
throw new ArgumentException("The given sort key is not valid.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sort(string sortBy)
|
public Sort(string sortBy)
|
||||||
|
@ -6,7 +6,7 @@ using Kyoo.Models;
|
|||||||
|
|
||||||
namespace Kyoo.Controllers
|
namespace Kyoo.Controllers
|
||||||
{
|
{
|
||||||
public class LibraryManager : ILibraryManager
|
public abstract class ALibraryManager : ILibraryManager
|
||||||
{
|
{
|
||||||
public ILibraryRepository LibraryRepository { get; }
|
public ILibraryRepository LibraryRepository { get; }
|
||||||
public ILibraryItemRepository LibraryItemRepository { get; }
|
public ILibraryItemRepository LibraryItemRepository { get; }
|
||||||
@ -20,7 +20,7 @@ namespace Kyoo.Controllers
|
|||||||
public IPeopleRepository PeopleRepository { get; }
|
public IPeopleRepository PeopleRepository { get; }
|
||||||
public IProviderRepository ProviderRepository { get; }
|
public IProviderRepository ProviderRepository { get; }
|
||||||
|
|
||||||
public LibraryManager(ILibraryRepository libraryRepository,
|
public ALibraryManager(ILibraryRepository libraryRepository,
|
||||||
ILibraryItemRepository libraryItemRepository,
|
ILibraryItemRepository libraryItemRepository,
|
||||||
ICollectionRepository collectionRepository,
|
ICollectionRepository collectionRepository,
|
||||||
IShowRepository showRepository,
|
IShowRepository showRepository,
|
||||||
@ -235,6 +235,10 @@ namespace Kyoo.Controllers
|
|||||||
return PeopleRepository.Get(where);
|
return PeopleRepository.Get(where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract Task Load<T, T2>(T obj, Expression<Func<T, T2>> member)
|
||||||
|
where T : class, IResource
|
||||||
|
where T2 : class;
|
||||||
|
|
||||||
public Task<ICollection<Library>> GetLibraries(Expression<Func<Library, bool>> where = null,
|
public Task<ICollection<Library>> GetLibraries(Expression<Func<Library, bool>> where = null,
|
||||||
Sort<Library> sort = default,
|
Sort<Library> sort = default,
|
||||||
Pagination page = default)
|
Pagination page = default)
|
@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2020.3.0" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
7
Kyoo.Common/Models/Attributes/ComposedSlug.cs
Normal file
7
Kyoo.Common/Models/Attributes/ComposedSlug.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Kyoo.Models.Attributes
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class ComposedSlug : Attribute { }
|
||||||
|
}
|
@ -4,6 +4,7 @@ using Kyoo.Models.Attributes;
|
|||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
{
|
{
|
||||||
|
[ComposedSlug]
|
||||||
public class Episode : IResource, IOnMerge
|
public class Episode : IResource, IOnMerge
|
||||||
{
|
{
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
||||||
@ -28,7 +29,7 @@ namespace Kyoo.Models
|
|||||||
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
[JsonIgnore] public virtual IEnumerable<Track> Tracks { get; set; }
|
||||||
|
|
||||||
public string ShowTitle => Show.Title;
|
public string ShowTitle => Show.Title;
|
||||||
public string Slug => GetSlug(Show.Slug, SeasonNumber, EpisodeNumber);
|
public string Slug => Show != null ? GetSlug(Show.Slug, SeasonNumber, EpisodeNumber) : ID.ToString();
|
||||||
public string Thumb
|
public string Thumb
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -3,6 +3,7 @@ using Kyoo.Models.Attributes;
|
|||||||
|
|
||||||
namespace Kyoo.Models
|
namespace Kyoo.Models
|
||||||
{
|
{
|
||||||
|
[ComposedSlug]
|
||||||
public class Season : IResource
|
public class Season : IResource
|
||||||
{
|
{
|
||||||
[JsonIgnore] public int ID { get; set; }
|
[JsonIgnore] public int ID { get; set; }
|
||||||
@ -10,7 +11,7 @@ namespace Kyoo.Models
|
|||||||
|
|
||||||
public int SeasonNumber { get; set; } = -1;
|
public int SeasonNumber { get; set; } = -1;
|
||||||
|
|
||||||
public string Slug => $"{Show.Slug}-s{SeasonNumber}";
|
public string Slug => Show != null ? $"{Show.Slug}-s{SeasonNumber}" : ID.ToString();
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public int? Year { get; set; }
|
public int? Year { get; set; }
|
||||||
|
@ -17,6 +17,13 @@ namespace Kyoo
|
|||||||
{
|
{
|
||||||
public static class Utility
|
public static class Utility
|
||||||
{
|
{
|
||||||
|
public static bool IsPropertyExpression<T, T2>(Expression<Func<T, T2>> ex)
|
||||||
|
{
|
||||||
|
return ex == null ||
|
||||||
|
ex.Body is MemberExpression ||
|
||||||
|
ex.Body.NodeType == ExpressionType.Convert && ((UnaryExpression)ex.Body).Operand is MemberExpression;
|
||||||
|
}
|
||||||
|
|
||||||
public static string ToSlug(string str)
|
public static string ToSlug(string str)
|
||||||
{
|
{
|
||||||
if (str == null)
|
if (str == null)
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.3" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
|
||||||
<PackageReference Include="Npgsql" Version="4.1.3" />
|
<PackageReference Include="Npgsql" Version="5.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -153,6 +153,7 @@ namespace Kyoo.Controllers
|
|||||||
if (edited == null)
|
if (edited == null)
|
||||||
throw new ArgumentNullException(nameof(edited));
|
throw new ArgumentNullException(nameof(edited));
|
||||||
|
|
||||||
|
bool lazyLoading = Database.ChangeTracker.LazyLoadingEnabled;
|
||||||
Database.ChangeTracker.LazyLoadingEnabled = false;
|
Database.ChangeTracker.LazyLoadingEnabled = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -193,7 +194,7 @@ namespace Kyoo.Controllers
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Database.ChangeTracker.LazyLoadingEnabled = true;
|
Database.ChangeTracker.LazyLoadingEnabled = lazyLoading;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +207,7 @@ namespace Kyoo.Controllers
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(resource.Slug))
|
if (string.IsNullOrEmpty(resource.Slug))
|
||||||
throw new ArgumentException("Resource can't have null as a slug.");
|
throw new ArgumentException("Resource can't have null as a slug.");
|
||||||
if (int.TryParse(resource.Slug, out int _))
|
if (int.TryParse(resource.Slug, out int _) && typeof(T).GetCustomAttribute<ComposedSlug>() == null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -352,7 +353,7 @@ namespace Kyoo.Controllers
|
|||||||
throw new ArgumentNullException(nameof(edited));
|
throw new ArgumentNullException(nameof(edited));
|
||||||
if (edited is TInternal intern)
|
if (edited is TInternal intern)
|
||||||
return Edit(intern, resetOld).Cast<T>();
|
return Edit(intern, resetOld).Cast<T>();
|
||||||
TInternal obj = new TInternal();
|
TInternal obj = new();
|
||||||
Utility.Assign(obj, edited);
|
Utility.Assign(obj, edited);
|
||||||
return base.Edit(obj, resetOld).Cast<T>();
|
return base.Edit(obj, resetOld).Cast<T>();
|
||||||
}
|
}
|
||||||
@ -365,7 +366,7 @@ namespace Kyoo.Controllers
|
|||||||
throw new ArgumentNullException(nameof(obj));
|
throw new ArgumentNullException(nameof(obj));
|
||||||
if (obj is TInternal intern)
|
if (obj is TInternal intern)
|
||||||
return Delete(intern);
|
return Delete(intern);
|
||||||
TInternal item = new TInternal();
|
TInternal item = new();
|
||||||
Utility.Assign(item, obj);
|
Utility.Assign(item, obj);
|
||||||
return Delete(item);
|
return Delete(item);
|
||||||
}
|
}
|
||||||
|
51
Kyoo/Controllers/LibraryManager.cs
Normal file
51
Kyoo/Controllers/LibraryManager.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Kyoo.Models;
|
||||||
|
|
||||||
|
namespace Kyoo.Controllers
|
||||||
|
{
|
||||||
|
public class LibaryManager : ALibraryManager
|
||||||
|
{
|
||||||
|
private readonly DatabaseContext _database;
|
||||||
|
|
||||||
|
public LibaryManager(ILibraryRepository libraryRepository,
|
||||||
|
ILibraryItemRepository libraryItemRepository,
|
||||||
|
ICollectionRepository collectionRepository,
|
||||||
|
IShowRepository showRepository,
|
||||||
|
ISeasonRepository seasonRepository,
|
||||||
|
IEpisodeRepository episodeRepository,
|
||||||
|
ITrackRepository trackRepository,
|
||||||
|
IGenreRepository genreRepository,
|
||||||
|
IStudioRepository studioRepository,
|
||||||
|
IProviderRepository providerRepository,
|
||||||
|
IPeopleRepository peopleRepository,
|
||||||
|
DatabaseContext database)
|
||||||
|
: base(libraryRepository,
|
||||||
|
libraryItemRepository,
|
||||||
|
collectionRepository,
|
||||||
|
showRepository,
|
||||||
|
seasonRepository,
|
||||||
|
episodeRepository,
|
||||||
|
trackRepository,
|
||||||
|
genreRepository,
|
||||||
|
studioRepository,
|
||||||
|
providerRepository,
|
||||||
|
peopleRepository)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task Load<T, T2>(T obj, Expression<Func<T, T2>> member)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
throw new ArgumentNullException(nameof(obj));
|
||||||
|
if (!Utility.IsPropertyExpression(member) || member == null)
|
||||||
|
throw new ArgumentException($"{nameof(member)} is not a property.");
|
||||||
|
if (typeof(IEnumerable).IsAssignableFrom(typeof(T2)))
|
||||||
|
return _database.Entry(obj).Collection(member).LoadAsync();
|
||||||
|
return _database.Entry(obj).Reference(member).LoadAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,30 +20,30 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="IdentityServer4" Version="3.1.2" />
|
<PackageReference Include="IdentityServer4" Version="4.1.1" />
|
||||||
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="3.1.2" />
|
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="4.1.1" />
|
||||||
<PackageReference Include="IdentityServer4.EntityFramework" Version="3.1.2" />
|
<PackageReference Include="IdentityServer4.EntityFramework" Version="4.1.1" />
|
||||||
<PackageReference Include="IdentityServer4.EntityFramework.Storage" Version="3.1.2" />
|
<PackageReference Include="IdentityServer4.EntityFramework.Storage" Version="4.1.1" />
|
||||||
<PackageReference Include="IdentityServer4.Storage" Version="3.1.2" />
|
<PackageReference Include="IdentityServer4.Storage" Version="4.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.3" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.3" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
|
||||||
<PackageReference Include="Portable.BouncyCastle" Version="1.8.6.7" />
|
<PackageReference Include="Portable.BouncyCastle" Version="1.8.9" />
|
||||||
<ProjectReference Include="../Kyoo.Common/Kyoo.Common.csproj" />
|
<ProjectReference Include="../Kyoo.Common/Kyoo.Common.csproj" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.12" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="3.1.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.3">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="3.1.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="5.0.3" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.3" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<ProjectReference Include="../Kyoo.CommonAPI/Kyoo.CommonAPI.csproj" />
|
<ProjectReference Include="../Kyoo.CommonAPI/Kyoo.CommonAPI.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -10,6 +11,8 @@ using Npgsql;
|
|||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
|
//TODO disable lazy loading a provide a LoadAsync method in the library manager.
|
||||||
|
|
||||||
public class DatabaseContext : DbContext
|
public class DatabaseContext : DbContext
|
||||||
{
|
{
|
||||||
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
|
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
|
||||||
@ -41,10 +44,10 @@ namespace Kyoo
|
|||||||
NpgsqlConnection.GlobalTypeMapper.MapEnum<StreamType>();
|
NpgsqlConnection.GlobalTypeMapper.MapEnum<StreamType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ValueComparer<IEnumerable<string>> _stringArrayComparer =
|
private readonly ValueComparer<IEnumerable<string>> _stringArrayComparer = new(
|
||||||
new ValueComparer<IEnumerable<string>>(
|
(l1, l2) => l1.SequenceEqual(l2),
|
||||||
(l1, l2) => l1.SequenceEqual(l2),
|
arr => arr.Aggregate(0, (i, s) => s.GetHashCode())
|
||||||
arr => arr.Aggregate(0, (i, s) => s.GetHashCode()));
|
);
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@ -266,7 +269,7 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
|
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
|
||||||
CancellationToken cancellationToken = new CancellationToken())
|
CancellationToken cancellationToken = new())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -281,7 +284,7 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
|
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -297,7 +300,7 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> SaveChangesAsync(string duplicateMessage,
|
public async Task<int> SaveChangesAsync(string duplicateMessage,
|
||||||
CancellationToken cancellationToken = new CancellationToken())
|
CancellationToken cancellationToken = new())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -312,7 +315,7 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> SaveIfNoDuplicates(CancellationToken cancellationToken = new CancellationToken())
|
public async Task<int> SaveIfNoDuplicates(CancellationToken cancellationToken = new())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -324,13 +327,12 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsDuplicateException(DbUpdateException ex)
|
private static bool IsDuplicateException(Exception ex)
|
||||||
{
|
{
|
||||||
return ex.InnerException is PostgresException inner
|
return ex.InnerException is PostgresException {SqlState: PostgresErrorCodes.UniqueViolation};
|
||||||
&& inner.SqlState == PostgresErrorCodes.UniqueViolation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DiscardChanges()
|
private void DiscardChanges()
|
||||||
{
|
{
|
||||||
foreach (EntityEntry entry in ChangeTracker.Entries().Where(x => x.State != EntityState.Unchanged
|
foreach (EntityEntry entry in ChangeTracker.Entries().Where(x => x.State != EntityState.Unchanged
|
||||||
&& x.State != EntityState.Detached))
|
&& x.State != EntityState.Detached))
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using IdentityServer4.Models;
|
using IdentityServer4.Models;
|
||||||
|
|
||||||
namespace Kyoo
|
namespace Kyoo
|
||||||
{
|
{
|
||||||
public class IdentityContext
|
public static class IdentityContext
|
||||||
{
|
{
|
||||||
public static IEnumerable<IdentityResource> GetIdentityResources()
|
public static IEnumerable<IdentityResource> GetIdentityResources()
|
||||||
{
|
{
|
||||||
@ -19,7 +20,7 @@ namespace Kyoo
|
|||||||
{
|
{
|
||||||
return new List<Client>
|
return new List<Client>
|
||||||
{
|
{
|
||||||
new Client
|
new()
|
||||||
{
|
{
|
||||||
ClientId = "kyoo.webapp",
|
ClientId = "kyoo.webapp",
|
||||||
|
|
||||||
@ -38,6 +39,38 @@ namespace Kyoo
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<ApiScope> GetScopes()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new ApiScope
|
||||||
|
{
|
||||||
|
Name = "kyoo.read",
|
||||||
|
DisplayName = "Read only access to the API.",
|
||||||
|
},
|
||||||
|
new ApiScope
|
||||||
|
{
|
||||||
|
Name = "kyoo.write",
|
||||||
|
DisplayName = "Read and write access to the public API"
|
||||||
|
},
|
||||||
|
new ApiScope
|
||||||
|
{
|
||||||
|
Name = "kyoo.play",
|
||||||
|
DisplayName = "Allow playback of movies and episodes."
|
||||||
|
},
|
||||||
|
new ApiScope
|
||||||
|
{
|
||||||
|
Name = "kyoo.download",
|
||||||
|
DisplayName = "Allow downloading of episodes and movies from kyoo."
|
||||||
|
},
|
||||||
|
new ApiScope
|
||||||
|
{
|
||||||
|
Name = "kyoo.admin",
|
||||||
|
DisplayName = "Full access to the admin's API and the public API."
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerable<ApiResource> GetApis()
|
public static IEnumerable<ApiResource> GetApis()
|
||||||
{
|
{
|
||||||
@ -46,34 +79,7 @@ namespace Kyoo
|
|||||||
new ApiResource
|
new ApiResource
|
||||||
{
|
{
|
||||||
Name = "Kyoo",
|
Name = "Kyoo",
|
||||||
Scopes =
|
Scopes = GetScopes().Select(x => x.Name).ToArray()
|
||||||
{
|
|
||||||
new Scope
|
|
||||||
{
|
|
||||||
Name = "kyoo.read",
|
|
||||||
DisplayName = "Read only access to the API.",
|
|
||||||
},
|
|
||||||
new Scope
|
|
||||||
{
|
|
||||||
Name = "kyoo.write",
|
|
||||||
DisplayName = "Read and write access to the public API"
|
|
||||||
},
|
|
||||||
new Scope
|
|
||||||
{
|
|
||||||
Name = "kyoo.play",
|
|
||||||
DisplayName = "Allow playback of movies and episodes."
|
|
||||||
},
|
|
||||||
new Scope
|
|
||||||
{
|
|
||||||
Name = "kyoo.download",
|
|
||||||
DisplayName = "Allow downloading of episodes and movies from kyoo."
|
|
||||||
},
|
|
||||||
new Scope
|
|
||||||
{
|
|
||||||
Name = "kyoo.admin",
|
|
||||||
DisplayName = "Full access to the admin's API and the public API."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using IdentityServer4.Extensions;
|
||||||
using IdentityServer4.Services;
|
using IdentityServer4.Services;
|
||||||
using Kyoo.Api;
|
using Kyoo.Api;
|
||||||
using Kyoo.Controllers;
|
using Kyoo.Controllers;
|
||||||
@ -47,8 +48,7 @@ namespace Kyoo
|
|||||||
|
|
||||||
services.AddDbContext<DatabaseContext>(options =>
|
services.AddDbContext<DatabaseContext>(options =>
|
||||||
{
|
{
|
||||||
options.UseLazyLoadingProxies()
|
options.UseNpgsql(_configuration.GetConnectionString("Database"));
|
||||||
.UseNpgsql(_configuration.GetConnectionString("Database"));
|
|
||||||
// .EnableSensitiveDataLogging()
|
// .EnableSensitiveDataLogging()
|
||||||
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
|
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
|
||||||
}, ServiceLifetime.Transient);
|
}, ServiceLifetime.Transient);
|
||||||
@ -72,7 +72,6 @@ namespace Kyoo
|
|||||||
services.AddIdentityServer(options =>
|
services.AddIdentityServer(options =>
|
||||||
{
|
{
|
||||||
options.IssuerUri = publicUrl;
|
options.IssuerUri = publicUrl;
|
||||||
options.PublicOrigin = publicUrl;
|
|
||||||
options.UserInteraction.LoginUrl = publicUrl + "login";
|
options.UserInteraction.LoginUrl = publicUrl + "login";
|
||||||
options.UserInteraction.ErrorUrl = publicUrl + "error";
|
options.UserInteraction.ErrorUrl = publicUrl + "error";
|
||||||
options.UserInteraction.LogoutUrl = publicUrl + "logout";
|
options.UserInteraction.LogoutUrl = publicUrl + "logout";
|
||||||
@ -92,6 +91,7 @@ namespace Kyoo
|
|||||||
options.EnableTokenCleanup = true;
|
options.EnableTokenCleanup = true;
|
||||||
})
|
})
|
||||||
.AddInMemoryIdentityResources(IdentityContext.GetIdentityResources())
|
.AddInMemoryIdentityResources(IdentityContext.GetIdentityResources())
|
||||||
|
.AddInMemoryApiScopes(IdentityContext.GetScopes())
|
||||||
.AddInMemoryApiResources(IdentityContext.GetApis())
|
.AddInMemoryApiResources(IdentityContext.GetApis())
|
||||||
.AddProfileService<AccountController>()
|
.AddProfileService<AccountController>()
|
||||||
.AddSigninKeys(_configuration);
|
.AddSigninKeys(_configuration);
|
||||||
@ -157,7 +157,7 @@ namespace Kyoo
|
|||||||
services.AddHostedService(provider => (TaskManager)provider.GetService<ITaskManager>());
|
services.AddHostedService(provider => (TaskManager)provider.GetService<ITaskManager>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
@ -186,6 +186,11 @@ namespace Kyoo
|
|||||||
MinimumSameSitePolicy = SameSiteMode.Strict
|
MinimumSameSitePolicy = SameSiteMode.Strict
|
||||||
});
|
});
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
app.Use((ctx, next) =>
|
||||||
|
{
|
||||||
|
ctx.SetIdentityServerOrigin(_configuration.GetValue<string>("public_url"));
|
||||||
|
return next();
|
||||||
|
});
|
||||||
app.UseIdentityServer();
|
app.UseIdentityServer();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
@ -98,10 +98,9 @@ namespace Kyoo.Tasks
|
|||||||
await _thumbnails!.Validate(episode, true);
|
await _thumbnails!.Validate(episode, true);
|
||||||
if (subs)
|
if (subs)
|
||||||
{
|
{
|
||||||
// TODO this doesn't work.
|
// TODO handle external subtites.
|
||||||
IEnumerable<Track> tracks = (await _transcoder!.ExtractInfos(episode.Path))
|
episode.Tracks = (await _transcoder!.ExtractInfos(episode.Path))
|
||||||
.Where(x => x.Type != StreamType.Font);
|
.Where(x => x.Type != StreamType.Font);
|
||||||
episode.Tracks = tracks;
|
|
||||||
await _library.EditEpisode(episode, false);
|
await _library.EditEpisode(episode, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user