diff --git a/Kyoo.Common/Controllers/ILibraryManager.cs b/Kyoo.Common/Controllers/ILibraryManager.cs
index 490f8073..938d3029 100644
--- a/Kyoo.Common/Controllers/ILibraryManager.cs
+++ b/Kyoo.Common/Controllers/ILibraryManager.cs
@@ -77,6 +77,11 @@ namespace Kyoo.Controllers
///
IProviderRepository ProviderRepository { get; }
+ ///
+ /// The repository that handle users.
+ ///
+ IUserRepository UserRepository { get; }
+
///
/// Get the resource by it's ID
///
diff --git a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
index bc30e756..12ea0b2a 100644
--- a/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
+++ b/Kyoo.Common/Controllers/Implementations/LibraryManager.cs
@@ -37,6 +37,8 @@ namespace Kyoo.Controllers
public IGenreRepository GenreRepository { get; }
///
public IProviderRepository ProviderRepository { get; }
+ ///
+ public IUserRepository UserRepository { get; }
///
@@ -58,6 +60,7 @@ namespace Kyoo.Controllers
StudioRepository = GetRepository() as IStudioRepository;
GenreRepository = GetRepository() as IGenreRepository;
ProviderRepository = GetRepository() as IProviderRepository;
+ UserRepository = GetRepository() as IUserRepository;
}
///
diff --git a/Kyoo.CommonAPI/DatabaseContext.cs b/Kyoo.CommonAPI/DatabaseContext.cs
index 2213d807..36cdc47b 100644
--- a/Kyoo.CommonAPI/DatabaseContext.cs
+++ b/Kyoo.CommonAPI/DatabaseContext.cs
@@ -157,6 +157,11 @@ namespace Kyoo
.WithOne(x => x.Episode)
.OnDelete(DeleteBehavior.Cascade);
+ modelBuilder.Entity()
+ .HasOne(x => x.Studio)
+ .WithMany(x => x.Shows)
+ .OnDelete(DeleteBehavior.SetNull);
+
modelBuilder.Entity()
.HasMany(x => x.Libraries)
.WithMany(x => x.Providers)
diff --git a/Kyoo.Postgresql/Migrations/20210627141933_Initial.cs b/Kyoo.Postgresql/Migrations/20210627141933_Initial.cs
index 50bed8f7..29b51490 100644
--- a/Kyoo.Postgresql/Migrations/20210627141933_Initial.cs
+++ b/Kyoo.Postgresql/Migrations/20210627141933_Initial.cs
@@ -226,7 +226,7 @@ namespace Kyoo.Postgresql.Migrations
column: x => x.studio_id,
principalTable: "studios",
principalColumn: "id",
- onDelete: ReferentialAction.Restrict);
+ onDelete: ReferentialAction.SetNull);
});
migrationBuilder.CreateTable(
diff --git a/Kyoo.SqLite/Migrations/20210626141337_Initial.cs b/Kyoo.SqLite/Migrations/20210626141337_Initial.cs
index 87d98348..88823571 100644
--- a/Kyoo.SqLite/Migrations/20210626141337_Initial.cs
+++ b/Kyoo.SqLite/Migrations/20210626141337_Initial.cs
@@ -218,7 +218,7 @@ namespace Kyoo.SqLite.Migrations
column: x => x.StudioID,
principalTable: "Studios",
principalColumn: "ID",
- onDelete: ReferentialAction.Restrict);
+ onDelete: ReferentialAction.SetNull);
});
migrationBuilder.CreateTable(
diff --git a/Kyoo.Tests/Library/RepositoryActivator.cs b/Kyoo.Tests/Library/RepositoryActivator.cs
index bf7b7b41..ee6aa4df 100644
--- a/Kyoo.Tests/Library/RepositoryActivator.cs
+++ b/Kyoo.Tests/Library/RepositoryActivator.cs
@@ -33,6 +33,7 @@ namespace Kyoo.Tests
new Lazy(() => LibraryManager.LibraryRepository));
TrackRepository track = new(_database);
EpisodeRepository episode = new(_database, provider, track);
+ UserRepository user = new(_database);
LibraryManager = new LibraryManager(new IBaseRepository[] {
provider,
@@ -45,7 +46,8 @@ namespace Kyoo.Tests
track,
people,
studio,
- genre
+ genre,
+ user
});
}
diff --git a/Kyoo.Tests/Library/SpecificTests/CollectionsTests.cs b/Kyoo.Tests/Library/SpecificTests/CollectionsTests.cs
new file mode 100644
index 00000000..7a5976de
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/CollectionsTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class CollectionTests : ACollectionTests
+ {
+ public CollectionTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class CollectionTests : ACollectionTests
+ {
+ public CollectionTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class ACollectionTests : RepositoryTests
+ {
+ private readonly ICollectionRepository _repository;
+
+ protected ACollectionTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.CollectionRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/GenreTests.cs b/Kyoo.Tests/Library/SpecificTests/GenreTests.cs
new file mode 100644
index 00000000..d79dba5e
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/GenreTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class GenreTests : AGenreTests
+ {
+ public GenreTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class GenreTests : AGenreTests
+ {
+ public GenreTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class AGenreTests : RepositoryTests
+ {
+ private readonly IGenreRepository _repository;
+
+ protected AGenreTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.GenreRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/LibraryTests.cs b/Kyoo.Tests/Library/SpecificTests/LibraryTests.cs
new file mode 100644
index 00000000..fbed1793
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/LibraryTests.cs
@@ -0,0 +1,36 @@
+using Kyoo.Controllers;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class LibraryTests : ALibraryTests
+ {
+ public LibraryTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class LibraryTests : ALibraryTests
+ {
+ public LibraryTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class ALibraryTests : RepositoryTests
+ {
+ private readonly ILibraryRepository _repository;
+
+ protected ALibraryTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.LibraryRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/PeopleTests.cs b/Kyoo.Tests/Library/SpecificTests/PeopleTests.cs
new file mode 100644
index 00000000..fc8b788d
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/PeopleTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class PeopleTests : APeopleTests
+ {
+ public PeopleTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class PeopleTests : APeopleTests
+ {
+ public PeopleTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class APeopleTests : RepositoryTests
+ {
+ private readonly IPeopleRepository _repository;
+
+ protected APeopleTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.PeopleRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/ProviderTests.cs b/Kyoo.Tests/Library/SpecificTests/ProviderTests.cs
new file mode 100644
index 00000000..853e34a1
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/ProviderTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class ProviderTests : AProviderTests
+ {
+ public ProviderTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class ProviderTests : AProviderTests
+ {
+ public ProviderTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class AProviderTests : RepositoryTests
+ {
+ private readonly IProviderRepository _repository;
+
+ protected AProviderTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.ProviderRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/StudioTests.cs b/Kyoo.Tests/Library/SpecificTests/StudioTests.cs
new file mode 100644
index 00000000..f5093b19
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/StudioTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class StudioTests : AStudioTests
+ {
+ public StudioTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class StudioTests : AStudioTests
+ {
+ public StudioTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class AStudioTests : RepositoryTests
+ {
+ private readonly IStudioRepository _repository;
+
+ protected AStudioTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.StudioRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/SpecificTests/UserTests.cs b/Kyoo.Tests/Library/SpecificTests/UserTests.cs
new file mode 100644
index 00000000..be67296d
--- /dev/null
+++ b/Kyoo.Tests/Library/SpecificTests/UserTests.cs
@@ -0,0 +1,37 @@
+using Kyoo.Controllers;
+using Kyoo.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Kyoo.Tests.Library
+{
+ namespace SqLite
+ {
+ public class UserTests : AUserTests
+ {
+ public UserTests(ITestOutputHelper output)
+ : base(new RepositoryActivator(output)) { }
+ }
+ }
+
+ namespace PostgreSQL
+ {
+ [Collection(nameof(Postgresql))]
+ public class UserTests : AUserTests
+ {
+ public UserTests(PostgresFixture postgres, ITestOutputHelper output)
+ : base(new RepositoryActivator(output, postgres)) { }
+ }
+ }
+
+ public abstract class AUserTests : RepositoryTests
+ {
+ private readonly IUserRepository _repository;
+
+ protected AUserTests(RepositoryActivator repositories)
+ : base(repositories)
+ {
+ _repository = Repositories.LibraryManager.UserRepository;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kyoo.Tests/Library/TestSample.cs b/Kyoo.Tests/Library/TestSample.cs
index 04490604..adbe7d84 100644
--- a/Kyoo.Tests/Library/TestSample.cs
+++ b/Kyoo.Tests/Library/TestSample.cs
@@ -17,6 +17,16 @@ namespace Kyoo.Tests
private static readonly Dictionary> Samples = new()
{
+ {
+ typeof(Models.Library),
+ () => new Models.Library
+ {
+ ID = 1,
+ Slug = "deck",
+ Name = "Deck",
+ Paths = new[] {"/path/to/deck"}
+ }
+ },
{
typeof(Collection),
() => new Collection
@@ -115,6 +125,47 @@ namespace Kyoo.Tests
Name = "The Actor",
Poster = "NicePoster"
}
+ },
+ {
+ typeof(Studio),
+ () => new Studio
+ {
+ ID = 1,
+ Slug = "hyper-studio",
+ Name = "Hyper studio"
+ }
+ },
+ {
+ typeof(Genre),
+ () => new Genre
+ {
+ ID = 1,
+ Slug = "action",
+ Name = "Action"
+ }
+ },
+ {
+ typeof(Provider),
+ () => new Provider
+ {
+ ID = 1,
+ Slug = "tvdb",
+ Name = "The TVDB",
+ Logo = "path/tvdb.svg",
+ LogoExtension = "svg"
+ }
+ },
+ {
+ typeof(User),
+ () => new User
+ {
+ ID = 1,
+ Slug = "user",
+ Username = "User",
+ Email = "user@im-a-user.com",
+ Password = "MD5-encoded",
+ Permissions = new [] {"overall.read"}
+ }
}
};
@@ -157,7 +208,35 @@ namespace Kyoo.Tests
track.EpisodeID = 0;
track.Episode = episode;
context.Tracks.Add(track);
+
+ Studio studio = Get();
+ studio.ID = 0;
+ studio.Shows = new List {show};
+ context.Studios.Add(studio);
+
+ Genre genre = Get();
+ genre.ID = 0;
+ genre.Shows = new List {show};
+ context.Genres.Add(genre);
+
+ People people = Get();
+ people.ID = 0;
+ context.People.Add(people);
+ Provider provider = Get();
+ provider.ID = 0;
+ context.Providers.Add(provider);
+
+ Models.Library library = Get();
+ library.ID = 0;
+ library.Collections = new List {collection};
+ library.Providers = new List {provider};
+ context.Libraries.Add(library);
+
+ User user = Get();
+ user.ID = 0;
+ context.Users.Add(user);
+
context.SaveChanges();
}
diff --git a/Kyoo/Controllers/Repositories/LibraryRepository.cs b/Kyoo/Controllers/Repositories/LibraryRepository.cs
index d569f6fe..02194b77 100644
--- a/Kyoo/Controllers/Repositories/LibraryRepository.cs
+++ b/Kyoo/Controllers/Repositories/LibraryRepository.cs
@@ -63,9 +63,12 @@ namespace Kyoo.Controllers
protected override async Task Validate(Library resource)
{
await base.Validate(resource);
- resource.Providers = await resource.Providers
- .SelectAsync(x => _providers.CreateIfNotExists(x))
- .ToListAsync();
+ await resource.ProviderLinks.ForEachAsync(async id =>
+ {
+ id.Second = await _providers.CreateIfNotExists(id.Second);
+ id.SecondID = id.Second.ID;
+ _database.Entry(id.Second).State = EntityState.Detached;
+ });
}
///