mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Cleanup ef repositories
This commit is contained in:
parent
69e8340c95
commit
1d553daeaf
@ -31,46 +31,20 @@ namespace Kyoo.Core.Controllers;
|
||||
/// <summary>
|
||||
/// A local repository to handle collections
|
||||
/// </summary>
|
||||
public class CollectionRepository : LocalRepository<Collection>
|
||||
public class CollectionRepository(DatabaseContext database) : LocalRepository<Collection>(database)
|
||||
{
|
||||
/// <summary>
|
||||
/// The database handle
|
||||
/// </summary>
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="CollectionRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="database">The database handle to use</param>
|
||||
/// <param name="thumbs">The thumbnail manager used to store images.</param>
|
||||
public CollectionRepository(DatabaseContext database, IThumbnailsManager thumbs)
|
||||
: base(database, thumbs)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Collection>> Search(
|
||||
string query,
|
||||
Include<Collection>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(_database.Collections, include)
|
||||
return await AddIncludes(Database.Collections, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name + " " + x.Slug, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<Collection> Create(Collection obj)
|
||||
{
|
||||
await base.Create(obj);
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<Collection>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task Validate(Collection resource)
|
||||
{
|
||||
@ -82,21 +56,13 @@ public class CollectionRepository : LocalRepository<Collection>
|
||||
|
||||
public async Task AddMovie(Guid id, Guid movieId)
|
||||
{
|
||||
_database.AddLinks<Collection, Movie>(id, movieId);
|
||||
await _database.SaveChangesAsync();
|
||||
Database.AddLinks<Collection, Movie>(id, movieId);
|
||||
await Database.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task AddShow(Guid id, Guid showId)
|
||||
{
|
||||
_database.AddLinks<Collection, Show>(id, showId);
|
||||
await _database.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(Collection obj)
|
||||
{
|
||||
_database.Entry(obj).State = EntityState.Deleted;
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
Database.AddLinks<Collection, Show>(id, showId);
|
||||
await Database.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,8 @@ namespace Kyoo.Core.Controllers;
|
||||
/// <summary>
|
||||
/// A local repository to handle episodes.
|
||||
/// </summary>
|
||||
public class EpisodeRepository(
|
||||
DatabaseContext database,
|
||||
IRepository<Show> shows,
|
||||
IThumbnailsManager thumbs
|
||||
) : LocalRepository<Episode>(database, thumbs)
|
||||
public class EpisodeRepository(DatabaseContext database, IRepository<Show> shows)
|
||||
: LocalRepository<Episode>(database)
|
||||
{
|
||||
static EpisodeRepository()
|
||||
{
|
||||
@ -64,34 +61,18 @@ public class EpisodeRepository(
|
||||
Include<Episode>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(database.Episodes, include)
|
||||
return await AddIncludes(Database.Episodes, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name!, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
protected override Task<Episode?> GetDuplicated(Episode item)
|
||||
{
|
||||
if (item is { SeasonNumber: not null, EpisodeNumber: not null })
|
||||
return database.Episodes.FirstOrDefaultAsync(x =>
|
||||
x.ShowId == item.ShowId
|
||||
&& x.SeasonNumber == item.SeasonNumber
|
||||
&& x.EpisodeNumber == item.EpisodeNumber
|
||||
);
|
||||
return database.Episodes.FirstOrDefaultAsync(x =>
|
||||
x.ShowId == item.ShowId && x.AbsoluteNumber == item.AbsoluteNumber
|
||||
);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<Episode> Create(Episode obj)
|
||||
{
|
||||
// Set it for the OnResourceCreated event and the return value.
|
||||
obj.ShowSlug = obj.Show?.Slug ?? (await shows.Get(obj.ShowId)).Slug;
|
||||
await base.Create(obj);
|
||||
database.Entry(obj).State = EntityState.Added;
|
||||
await database.SaveChangesAsync(() => GetDuplicated(obj));
|
||||
await IRepository<Episode>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
return await base.Create(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -111,7 +92,7 @@ public class EpisodeRepository(
|
||||
}
|
||||
if (resource.SeasonId == null && resource.SeasonNumber != null)
|
||||
{
|
||||
resource.Season = await database.Seasons.FirstOrDefaultAsync(x =>
|
||||
resource.Season = await Database.Seasons.FirstOrDefaultAsync(x =>
|
||||
x.ShowId == resource.ShowId && x.SeasonNumber == resource.SeasonNumber
|
||||
);
|
||||
}
|
||||
@ -120,14 +101,40 @@ public class EpisodeRepository(
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(Episode obj)
|
||||
{
|
||||
int epCount = await database
|
||||
int epCount = await Database
|
||||
.Episodes.Where(x => x.ShowId == obj.ShowId)
|
||||
.Take(2)
|
||||
.CountAsync();
|
||||
database.Entry(obj).State = EntityState.Deleted;
|
||||
await database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
if (epCount == 1)
|
||||
await shows.Delete(obj.ShowId);
|
||||
else
|
||||
await base.Delete(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task DeleteAll(Filter<Episode> filter)
|
||||
{
|
||||
ICollection<Episode> items = await GetAll(filter);
|
||||
Guid[] ids = items.Select(x => x.Id).ToArray();
|
||||
|
||||
await Database.Set<Episode>().Where(x => ids.Contains(x.Id)).ExecuteDeleteAsync();
|
||||
foreach (Episode resource in items)
|
||||
await IRepository<Episode>.OnResourceDeleted(resource);
|
||||
|
||||
Guid[] showIds = await Database
|
||||
.Set<Episode>()
|
||||
.Where(filter.ToEfLambda())
|
||||
.Select(x => x.Show!)
|
||||
.Where(x => !x.Episodes!.Any())
|
||||
.Select(x => x.Id)
|
||||
.ToArrayAsync();
|
||||
|
||||
if (!showIds.Any())
|
||||
return;
|
||||
|
||||
Filter<Show>[] showFilters = showIds
|
||||
.Select(x => new Filter<Show>.Eq(nameof(Show.Id), x))
|
||||
.ToArray();
|
||||
await shows.DeleteAll(Filter.Or(showFilters)!);
|
||||
}
|
||||
}
|
||||
|
@ -29,38 +29,14 @@ using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Abstractions.Models.Exceptions;
|
||||
using Kyoo.Abstractions.Models.Utils;
|
||||
using Kyoo.Postgresql;
|
||||
using Kyoo.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Core.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// A base class to create repositories using Entity Framework.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of this repository</typeparam>
|
||||
public abstract class LocalRepository<T> : IRepository<T>
|
||||
public abstract class LocalRepository<T>(DatabaseContext database) : IRepository<T>
|
||||
where T : class, IResource, IQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// The Entity Framework's Database handle.
|
||||
/// </summary>
|
||||
protected DbContext Database { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The thumbnail manager used to store images.
|
||||
/// </summary>
|
||||
private readonly IThumbnailsManager _thumbs;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new base <see cref="LocalRepository{T}"/> with the given database handle.
|
||||
/// </summary>
|
||||
/// <param name="database">A database connection to load resources of type <typeparamref name="T"/></param>
|
||||
/// <param name="thumbs">The thumbnail manager used to store images.</param>
|
||||
protected LocalRepository(DbContext database, IThumbnailsManager thumbs)
|
||||
{
|
||||
Database = database;
|
||||
_thumbs = thumbs;
|
||||
}
|
||||
public DatabaseContext Database => database;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Type RepositoryType => typeof(T);
|
||||
@ -127,12 +103,6 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
return query;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a resource from it's ID and make the <see cref="Database"/> instance track it.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the resource</param>
|
||||
/// <exception cref="ItemNotFoundException">If the item is not found</exception>
|
||||
/// <returns>The tracked resource with the given ID</returns>
|
||||
protected virtual async Task<T> GetWithTracking(Guid id)
|
||||
{
|
||||
T? ret = await Database.Set<T>().AsTracking().FirstOrDefaultAsync(x => x.Id == id);
|
||||
@ -174,11 +144,6 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected virtual Task<T?> GetDuplicated(T item)
|
||||
{
|
||||
return GetOrDefault(item.Slug);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task<T?> GetOrDefault(Guid id, Include<T>? include = default)
|
||||
{
|
||||
@ -303,26 +268,9 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
public virtual async Task<T> Create(T obj)
|
||||
{
|
||||
await Validate(obj);
|
||||
if (obj is IThumbnails thumbs)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _thumbs.DownloadImages(thumbs);
|
||||
}
|
||||
catch (DuplicatedItemException e) when (e.Existing is null)
|
||||
{
|
||||
throw new DuplicatedItemException(await GetDuplicated(obj));
|
||||
}
|
||||
if (thumbs.Poster != null)
|
||||
Database.Entry(thumbs).Reference(x => x.Poster).TargetEntry!.State =
|
||||
EntityState.Added;
|
||||
if (thumbs.Thumbnail != null)
|
||||
Database.Entry(thumbs).Reference(x => x.Thumbnail).TargetEntry!.State =
|
||||
EntityState.Added;
|
||||
if (thumbs.Logo != null)
|
||||
Database.Entry(thumbs).Reference(x => x.Logo).TargetEntry!.State =
|
||||
EntityState.Added;
|
||||
}
|
||||
Database.Entry(obj).State = EntityState.Added;
|
||||
await Database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<T>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -346,27 +294,11 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
/// <inheritdoc/>
|
||||
public virtual async Task<T> Edit(T edited)
|
||||
{
|
||||
bool lazyLoading = Database.ChangeTracker.LazyLoadingEnabled;
|
||||
Database.ChangeTracker.LazyLoadingEnabled = false;
|
||||
try
|
||||
{
|
||||
T old = await GetWithTracking(edited.Id);
|
||||
|
||||
Merger.Complete(
|
||||
old,
|
||||
edited,
|
||||
x => x.GetCustomAttribute<LoadableRelationAttribute>() == null
|
||||
);
|
||||
await EditRelations(old, edited);
|
||||
await Database.SaveChangesAsync();
|
||||
await IRepository<T>.OnResourceEdited(old);
|
||||
return old;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Database.ChangeTracker.LazyLoadingEnabled = lazyLoading;
|
||||
Database.ChangeTracker.Clear();
|
||||
}
|
||||
await Validate(edited);
|
||||
Database.Entry(edited).State = EntityState.Modified;
|
||||
await Database.SaveChangesAsync();
|
||||
await IRepository<T>.OnResourceEdited(edited);
|
||||
return edited;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@ -391,39 +323,9 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An overridable method to edit relation of a resource.
|
||||
/// </summary>
|
||||
/// <param name="resource">
|
||||
/// The non edited resource
|
||||
/// </param>
|
||||
/// <param name="changed">
|
||||
/// The new version of <paramref name="resource"/>.
|
||||
/// This item will be saved on the database and replace <paramref name="resource"/>
|
||||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected virtual Task EditRelations(T resource, T changed)
|
||||
{
|
||||
if (resource is IThumbnails thumbs && changed is IThumbnails chng)
|
||||
{
|
||||
Database.Entry(thumbs).Reference(x => x.Poster).IsModified =
|
||||
thumbs.Poster != chng.Poster;
|
||||
Database.Entry(thumbs).Reference(x => x.Thumbnail).IsModified =
|
||||
thumbs.Thumbnail != chng.Thumbnail;
|
||||
Database.Entry(thumbs).Reference(x => x.Logo).IsModified = thumbs.Logo != chng.Logo;
|
||||
}
|
||||
return Validate(resource);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A method called just before saving a new resource to the database.
|
||||
/// It is also called on the default implementation of <see cref="EditRelations"/>
|
||||
/// </summary>
|
||||
/// <param name="resource">The resource that will be saved</param>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// You can throw this if the resource is illegal and should not be saved.
|
||||
/// </exception>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected virtual Task Validate(T resource)
|
||||
{
|
||||
if (
|
||||
@ -433,25 +335,8 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
return Task.CompletedTask;
|
||||
if (string.IsNullOrEmpty(resource.Slug))
|
||||
throw new ArgumentException("Resource can't have null as a slug.");
|
||||
if (int.TryParse(resource.Slug, out int _) || resource.Slug == "random")
|
||||
{
|
||||
try
|
||||
{
|
||||
MethodInfo? setter = typeof(T).GetProperty(nameof(resource.Slug))!.GetSetMethod();
|
||||
if (setter != null)
|
||||
setter.Invoke(resource, new object[] { resource.Slug + '!' });
|
||||
else
|
||||
throw new ArgumentException(
|
||||
"Resources slug can't be number only or the literal \"random\"."
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Resources slug can't be number only or the literal \"random\"."
|
||||
);
|
||||
}
|
||||
}
|
||||
if (resource.Slug == "random")
|
||||
throw new ArgumentException("Resources slug can't be the literal \"random\".");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@ -470,18 +355,20 @@ public abstract class LocalRepository<T> : IRepository<T>
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual Task Delete(T obj)
|
||||
public virtual async Task Delete(T obj)
|
||||
{
|
||||
IRepository<T>.OnResourceDeleted(obj);
|
||||
if (obj is IThumbnails thumbs)
|
||||
return _thumbs.DeleteImages(thumbs);
|
||||
return Task.CompletedTask;
|
||||
await Database.Set<T>().Where(x => x.Id == obj.Id).ExecuteDeleteAsync();
|
||||
await IRepository<T>.OnResourceDeleted(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteAll(Filter<T> filter)
|
||||
public virtual async Task DeleteAll(Filter<T> filter)
|
||||
{
|
||||
foreach (T resource in await GetAll(filter))
|
||||
await Delete(resource);
|
||||
ICollection<T> items = await GetAll(filter);
|
||||
Guid[] ids = items.Select(x => x.Id).ToArray();
|
||||
await Database.Set<T>().Where(x => ids.Contains(x.Id)).ExecuteDeleteAsync();
|
||||
|
||||
foreach (T resource in items)
|
||||
await IRepository<T>.OnResourceDeleted(resource);
|
||||
}
|
||||
}
|
||||
|
@ -27,82 +27,29 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Core.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// A local repository to handle shows
|
||||
/// </summary>
|
||||
public class MovieRepository : LocalRepository<Movie>
|
||||
public class MovieRepository(DatabaseContext database, IRepository<Studio> studios)
|
||||
: LocalRepository<Movie>(database)
|
||||
{
|
||||
/// <summary>
|
||||
/// The database handle
|
||||
/// </summary>
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <summary>
|
||||
/// A studio repository to handle creation/validation of related studios.
|
||||
/// </summary>
|
||||
private readonly IRepository<Studio> _studios;
|
||||
|
||||
public MovieRepository(
|
||||
DatabaseContext database,
|
||||
IRepository<Studio> studios,
|
||||
IThumbnailsManager thumbs
|
||||
)
|
||||
: base(database, thumbs)
|
||||
{
|
||||
_database = database;
|
||||
_studios = studios;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Movie>> Search(
|
||||
string query,
|
||||
Include<Movie>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(_database.Movies, include)
|
||||
return await AddIncludes(Database.Movies, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name + " " + x.Slug, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<Movie> Create(Movie obj)
|
||||
{
|
||||
await base.Create(obj);
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<Movie>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task Validate(Movie resource)
|
||||
{
|
||||
await base.Validate(resource);
|
||||
if (resource.Studio != null)
|
||||
{
|
||||
resource.Studio = await _studios.CreateIfNotExists(resource.Studio);
|
||||
resource.Studio = await studios.CreateIfNotExists(resource.Studio);
|
||||
resource.StudioId = resource.Studio.Id;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task EditRelations(Movie resource, Movie changed)
|
||||
{
|
||||
await Validate(changed);
|
||||
|
||||
if (changed.Studio != null || changed.StudioId == null)
|
||||
{
|
||||
await Database.Entry(resource).Reference(x => x.Studio).LoadAsync();
|
||||
resource.Studio = changed.Studio;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(Movie obj)
|
||||
{
|
||||
_database.Remove(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
}
|
||||
}
|
||||
|
@ -31,16 +31,8 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo.Core.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// A local repository to handle seasons.
|
||||
/// </summary>
|
||||
public class SeasonRepository : LocalRepository<Season>
|
||||
public class SeasonRepository(DatabaseContext database) : LocalRepository<Season>(database)
|
||||
{
|
||||
/// <summary>
|
||||
/// The database handle
|
||||
/// </summary>
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
static SeasonRepository()
|
||||
{
|
||||
// Edit seasons slugs when the show's slug changes.
|
||||
@ -61,31 +53,13 @@ public class SeasonRepository : LocalRepository<Season>
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SeasonRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="database">The database handle that will be used</param>
|
||||
/// <param name="thumbs">The thumbnail manager used to store images.</param>
|
||||
public SeasonRepository(DatabaseContext database, IThumbnailsManager thumbs)
|
||||
: base(database, thumbs)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
protected override Task<Season?> GetDuplicated(Season item)
|
||||
{
|
||||
return _database.Seasons.FirstOrDefaultAsync(x =>
|
||||
x.ShowId == item.ShowId && x.SeasonNumber == item.SeasonNumber
|
||||
);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task<ICollection<Season>> Search(
|
||||
string query,
|
||||
Include<Season>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(_database.Seasons, include)
|
||||
return await AddIncludes(Database.Seasons, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name!, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
@ -94,14 +68,11 @@ public class SeasonRepository : LocalRepository<Season>
|
||||
/// <inheritdoc/>
|
||||
public override async Task<Season> Create(Season obj)
|
||||
{
|
||||
await base.Create(obj);
|
||||
// Set it for the OnResourceCreated event and the return value.
|
||||
obj.ShowSlug =
|
||||
(await _database.Shows.FirstOrDefaultAsync(x => x.Id == obj.ShowId))?.Slug
|
||||
(await Database.Shows.FirstOrDefaultAsync(x => x.Id == obj.ShowId))?.Slug
|
||||
?? throw new ItemNotFoundException($"No show found with ID {obj.ShowId}");
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync(() => GetDuplicated(obj));
|
||||
await IRepository<Season>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
return await base.Create(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@ -120,12 +91,4 @@ public class SeasonRepository : LocalRepository<Season>
|
||||
resource.ShowId = resource.Show.Id;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task Delete(Season obj)
|
||||
{
|
||||
_database.Remove(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
}
|
||||
}
|
||||
|
@ -23,87 +23,33 @@ using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Utils;
|
||||
using Kyoo.Postgresql;
|
||||
using Kyoo.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Core.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// A local repository to handle shows
|
||||
/// </summary>
|
||||
public class ShowRepository : LocalRepository<Show>
|
||||
public class ShowRepository(DatabaseContext database, IRepository<Studio> studios)
|
||||
: LocalRepository<Show>(database)
|
||||
{
|
||||
/// <summary>
|
||||
/// The database handle
|
||||
/// </summary>
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <summary>
|
||||
/// A studio repository to handle creation/validation of related studios.
|
||||
/// </summary>
|
||||
private readonly IRepository<Studio> _studios;
|
||||
|
||||
public ShowRepository(
|
||||
DatabaseContext database,
|
||||
IRepository<Studio> studios,
|
||||
IThumbnailsManager thumbs
|
||||
)
|
||||
: base(database, thumbs)
|
||||
{
|
||||
_database = database;
|
||||
_studios = studios;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Show>> Search(
|
||||
string query,
|
||||
Include<Show>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(_database.Shows, include)
|
||||
return await AddIncludes(Database.Shows, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name + " " + x.Slug, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<Show> Create(Show obj)
|
||||
{
|
||||
await base.Create(obj);
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<Show>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task Validate(Show resource)
|
||||
{
|
||||
await base.Validate(resource);
|
||||
if (resource.Studio != null)
|
||||
{
|
||||
resource.Studio = await _studios.CreateIfNotExists(resource.Studio);
|
||||
resource.Studio = await studios.CreateIfNotExists(resource.Studio);
|
||||
resource.StudioId = resource.Studio.Id;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task EditRelations(Show resource, Show changed)
|
||||
{
|
||||
await Validate(changed);
|
||||
|
||||
if (changed.Studio != null || changed.StudioId == null)
|
||||
{
|
||||
await Database.Entry(resource).Reference(x => x.Studio).LoadAsync();
|
||||
resource.Studio = changed.Studio;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(Show obj)
|
||||
{
|
||||
_database.Remove(obj);
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Utils;
|
||||
using Kyoo.Postgresql;
|
||||
using Kyoo.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Kyoo.Core.Controllers;
|
||||
@ -31,51 +29,17 @@ namespace Kyoo.Core.Controllers;
|
||||
/// <summary>
|
||||
/// A local repository to handle studios
|
||||
/// </summary>
|
||||
public class StudioRepository : LocalRepository<Studio>
|
||||
public class StudioRepository(DatabaseContext database) : LocalRepository<Studio>(database)
|
||||
{
|
||||
/// <summary>
|
||||
/// The database handle
|
||||
/// </summary>
|
||||
private readonly DatabaseContext _database;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="StudioRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="database">The database handle</param>
|
||||
/// <param name="thumbs">The thumbnail manager used to store images.</param>
|
||||
public StudioRepository(DatabaseContext database, IThumbnailsManager thumbs)
|
||||
: base(database, thumbs)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<Studio>> Search(
|
||||
string query,
|
||||
Include<Studio>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(_database.Studios, include)
|
||||
return await AddIncludes(Database.Studios, include)
|
||||
.Where(x => EF.Functions.ILike(x.Name, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<Studio> Create(Studio obj)
|
||||
{
|
||||
await base.Create(obj);
|
||||
_database.Entry(obj).State = EntityState.Added;
|
||||
await _database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<Studio>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(Studio obj)
|
||||
{
|
||||
_database.Entry(obj).State = EntityState.Deleted;
|
||||
await _database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,8 @@ public class UserRepository(
|
||||
DatabaseContext database,
|
||||
DbConnection db,
|
||||
SqlVariableContext context,
|
||||
IThumbnailsManager thumbs,
|
||||
PermissionOption options
|
||||
) : LocalRepository<User>(database, thumbs), IUserRepository
|
||||
) : LocalRepository<User>(database), IUserRepository
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override async Task<ICollection<User>> Search(
|
||||
@ -50,7 +49,7 @@ public class UserRepository(
|
||||
Include<User>? include = default
|
||||
)
|
||||
{
|
||||
return await AddIncludes(database.Users, include)
|
||||
return await AddIncludes(Database.Users, include)
|
||||
.Where(x => EF.Functions.ILike(x.Username, $"%{query}%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
@ -60,26 +59,14 @@ public class UserRepository(
|
||||
public override async Task<User> Create(User obj)
|
||||
{
|
||||
// If no users exists, the new one will be an admin. Give it every permissions.
|
||||
if (!await database.Users.AnyAsync())
|
||||
if (!await Database.Users.AnyAsync())
|
||||
obj.Permissions = PermissionOption.Admin;
|
||||
else if (!options.RequireVerification)
|
||||
obj.Permissions = options.NewUser;
|
||||
else
|
||||
obj.Permissions = Array.Empty<string>();
|
||||
|
||||
await base.Create(obj);
|
||||
database.Entry(obj).State = EntityState.Added;
|
||||
await database.SaveChangesAsync(() => Get(obj.Slug));
|
||||
await IRepository<User>.OnResourceCreated(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task Delete(User obj)
|
||||
{
|
||||
database.Entry(obj).State = EntityState.Deleted;
|
||||
await database.SaveChangesAsync();
|
||||
await base.Delete(obj);
|
||||
return await base.Create(obj);
|
||||
}
|
||||
|
||||
public Task<User?> GetByExternalId(string provider, string id)
|
||||
@ -109,8 +96,8 @@ public class UserRepository(
|
||||
User user = await GetWithTracking(userId);
|
||||
user.ExternalId[provider] = token;
|
||||
// without that, the change tracker does not find the modification. /shrug
|
||||
database.Entry(user).Property(x => x.ExternalId).IsModified = true;
|
||||
await database.SaveChangesAsync();
|
||||
Database.Entry(user).Property(x => x.ExternalId).IsModified = true;
|
||||
await Database.SaveChangesAsync();
|
||||
return user;
|
||||
}
|
||||
|
||||
@ -119,8 +106,8 @@ public class UserRepository(
|
||||
User user = await GetWithTracking(userId);
|
||||
user.ExternalId.Remove(provider);
|
||||
// without that, the change tracker does not find the modification. /shrug
|
||||
database.Entry(user).Property(x => x.ExternalId).IsModified = true;
|
||||
await database.SaveChangesAsync();
|
||||
Database.Entry(user).Property(x => x.ExternalId).IsModified = true;
|
||||
await Database.SaveChangesAsync();
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using AspNetCore.Proxy;
|
||||
|
@ -16,9 +16,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Meilisearch;
|
||||
|
Loading…
x
Reference in New Issue
Block a user