diff --git a/Kyoo.Common/Models/PeopleLink.cs b/Kyoo.Common/Models/PeopleLink.cs index 475af952..5878cfc0 100644 --- a/Kyoo.Common/Models/PeopleLink.cs +++ b/Kyoo.Common/Models/PeopleLink.cs @@ -8,9 +8,23 @@ namespace Kyoo.Models [JsonIgnore] public string PeopleID { get; set; } [JsonIgnore] public virtual People People { get; set; } - public string Slug => People.Slug; - public string Name => People.Name; - public string ExternalIDs => People.ExternalIDs; + public string Slug + { + get => People.Slug; + set => People.Slug = value; + } + + public string Name + { + get => People.Name; + set => People.Name = value; + } + + public string ExternalIDs + { + get => People.ExternalIDs; + set => People.ExternalIDs = value; + } [JsonIgnore] public long ShowID { get; set; } [JsonIgnore] public virtual Show Show { get; set; } diff --git a/Kyoo.Common/Models/Show.cs b/Kyoo.Common/Models/Show.cs index 4453034d..1d69b2be 100644 --- a/Kyoo.Common/Models/Show.cs +++ b/Kyoo.Common/Models/Show.cs @@ -37,7 +37,7 @@ namespace Kyoo.Models set { GenreLinks = value?.Select(x => new GenreLink(this, x)).ToList(); } } [JsonIgnore] public virtual List GenreLinks { get; set; } - [JsonIgnore] public virtual Studio Studio { get; set; } + public virtual Studio Studio { get; set; } [JsonIgnore] public virtual IEnumerable People { get; set; } [JsonIgnore] public virtual IEnumerable Seasons { get; set; } [JsonIgnore] public virtual IEnumerable Episodes { get; set; } @@ -121,8 +121,7 @@ namespace Kyoo.Models ImgThumb ??= other.ImgThumb; ImgLogo ??= other.ImgLogo; ImgBackdrop ??= other.ImgBackdrop; - if (other.Studio != null) - Studio ??= other.Studio; + Studio ??= other.Studio; ExternalIDs = string.Join('|', new [] { ExternalIDs, other.ExternalIDs }.Where(x => !string.IsNullOrEmpty(x))); return this; } diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs index 9cabbd5a..296e8310 100644 --- a/Kyoo.Common/Utility.cs +++ b/Kyoo.Common/Utility.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text.RegularExpressions; using Kyoo.Models; @@ -58,8 +59,6 @@ namespace Kyoo case ImageType.Background: show.ImgBackdrop = imgUrl; break; - default: - break; } } @@ -74,5 +73,28 @@ namespace Kyoo isEqual = (x, y) => x.Equals(y); return list.Concat(second.Where(x => !list.Any(y => isEqual(x, y)))); } + + public static T Complete(T first, T second) + { + Type type = typeof(T); + foreach (PropertyInfo property in type.GetProperties()) + { + MethodInfo getter = property.GetGetMethod(); + MethodInfo setter = property.GetSetMethod(); + + object value = getter != null ? getter.Invoke(second, null) : property.GetValue(second); + object defaultValue = property.PropertyType.IsValueType ? Activator.CreateInstance(property.PropertyType) : null; + + if (value?.Equals(defaultValue) == false) + { + if (setter != null) + setter.Invoke(first, new[] {value}); + else + property.SetValue(second, value); + } + } + + return first; + } } } \ No newline at end of file diff --git a/Kyoo/Controllers/LibraryManager.cs b/Kyoo/Controllers/LibraryManager.cs index 0d1c1ca3..a4e20dac 100644 --- a/Kyoo/Controllers/LibraryManager.cs +++ b/Kyoo/Controllers/LibraryManager.cs @@ -77,10 +77,7 @@ namespace Kyoo.Controllers public Show GetShowBySlug(string slug) { - Show ret = (from show in _database.Shows where show.Slug == slug select show).FirstOrDefault(); - if (ret != null) - ret.Seasons = ret.Seasons.OrderBy(x => x.SeasonNumber); - return ret; + return _database.Shows.FirstOrDefault(show => show.Slug == slug); } public Show GetShow(string path) @@ -350,7 +347,7 @@ namespace Kyoo.Controllers { if (show == null) return 0; - if (_database.Entry(show).State == EntityState.Detached) + if (!_database.Entry(show).IsKeySet) _database.Shows.Add(show); _database.SaveChanges(); return show.ID; diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index 4c2aa336..fcc1332c 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -101,4 +101,7 @@ PreserveNewest + + + diff --git a/Kyoo/Models/DatabaseContext.cs b/Kyoo/Models/DatabaseContext.cs index 2e4d0179..f0d270d8 100644 --- a/Kyoo/Models/DatabaseContext.cs +++ b/Kyoo/Models/DatabaseContext.cs @@ -15,25 +15,58 @@ using Microsoft.Extensions.Options; namespace Kyoo { - public class DatabaseContext : IdentityDbContext, IPersistedGrantDbContext + public class IdentityDatabase : IdentityDbContext, IPersistedGrantDbContext { private readonly IOptions _operationalStoreOptions; - public DatabaseContext(DbContextOptions options, IOptions operationalStoreOptions) + public IdentityDatabase(DbContextOptions options, IOptions operationalStoreOptions) : base(options) { _operationalStoreOptions = operationalStoreOptions; } + public DbSet Accounts { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value); + + modelBuilder.Entity().ToTable("User"); + modelBuilder.Entity>().ToTable("UserRole"); + modelBuilder.Entity>().ToTable("UserLogin"); + modelBuilder.Entity>().ToTable("UserClaim"); + modelBuilder.Entity().ToTable("UserRoles"); + modelBuilder.Entity>().ToTable("UserRoleClaim"); + modelBuilder.Entity>().ToTable("UserToken"); + } + public Task SaveChangesAsync() => base.SaveChangesAsync(); public DbSet PersistedGrants { get; set; } public DbSet DeviceFlowCodes { get; set; } + + } + + public class DatabaseFactory + { + private readonly DbContextOptions _options; - public DbSet Accounts { get; set; } - - - + public DatabaseFactory(DbContextOptions options) + { + _options = options; + } + + public DatabaseContext NewDatabaseConnection() + { + return new DatabaseContext(_options); + } + } + + public class DatabaseContext : DbContext + { + public DatabaseContext(DbContextOptions options) : base(options) {} + public DbSet Libraries { get; set; } public DbSet Collections { get; set; } public DbSet Shows { get; set; } @@ -84,15 +117,13 @@ namespace Kyoo modelBuilder.Entity() .Ignore(x => x.Genres); - - modelBuilder.Entity().ToTable("User"); - modelBuilder.Entity>().ToTable("UserRole"); - modelBuilder.Entity>().ToTable("UserLogin"); - modelBuilder.Entity>().ToTable("UserClaim"); - modelBuilder.Entity().ToTable("UserRoles"); - modelBuilder.Entity>().ToTable("UserRoleClaim"); - modelBuilder.Entity>().ToTable("UserToken"); - modelBuilder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value); + + modelBuilder.Entity() + .Ignore(x => x.Slug); + modelBuilder.Entity() + .Ignore(x => x.Name); + modelBuilder.Entity() + .Ignore(x => x.ExternalIDs); } } } diff --git a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.Designer.cs similarity index 99% rename from Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.Designer.cs rename to Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.Designer.cs index 02f539af..9db66b75 100644 --- a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.Designer.cs @@ -6,10 +6,10 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -namespace Kyoo.Models.DatabaseMigrations.IdentityConfiguration +namespace Kyoo.Models.DatabaseMigrations.IdentitiyConfiguration { [DbContext(typeof(ConfigurationDbContext))] - [Migration("20200330032447_Initial")] + [Migration("20200413152957_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.cs b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.cs similarity index 99% rename from Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.cs rename to Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.cs index 484b19c9..431b2fd9 100644 --- a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200330032447_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/20200413152957_Initial.cs @@ -1,7 +1,7 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace Kyoo.Models.DatabaseMigrations.IdentityConfiguration +namespace Kyoo.Models.DatabaseMigrations.IdentitiyConfiguration { public partial class Initial : Migration { diff --git a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/ConfigurationDbContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/ConfigurationDbContextModelSnapshot.cs index ed67ec67..6e988a02 100644 --- a/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/ConfigurationDbContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/IdentityConfiguration/ConfigurationDbContextModelSnapshot.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -namespace Kyoo.Models.DatabaseMigrations.IdentityConfiguration +namespace Kyoo.Models.DatabaseMigrations.IdentitiyConfiguration { [DbContext(typeof(ConfigurationDbContext))] partial class ConfigurationDbContextModelSnapshot : ModelSnapshot diff --git a/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.Designer.cs new file mode 100644 index 00000000..15958d3a --- /dev/null +++ b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.Designer.cs @@ -0,0 +1,358 @@ +// +using System; +using Kyoo; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kyoo.Models.DatabaseMigrations.IdentityDatbase +{ + [DbContext(typeof(IdentityDatabase))] + [Migration("20200413153045_Initial")] + partial class Initial + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => + { + b.Property("UserCode") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50000); + + b.Property("DeviceCode") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.HasKey("UserCode"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.ToTable("DeviceCodes"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => + { + b.Property("Key") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50000); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("PersistedGrants"); + }); + + modelBuilder.Entity("Kyoo.Models.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("OTAC") + .HasColumnType("TEXT"); + + b.Property("OTACExpires") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoleClaim"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRole"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.cs b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.cs new file mode 100644 index 00000000..2c3bacf1 --- /dev/null +++ b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/20200413153045_Initial.cs @@ -0,0 +1,280 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Kyoo.Models.DatabaseMigrations.IdentityDatbase +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "DeviceCodes", + columns: table => new + { + UserCode = table.Column(maxLength: 200, nullable: false), + DeviceCode = table.Column(maxLength: 200, nullable: false), + SubjectId = table.Column(maxLength: 200, nullable: true), + ClientId = table.Column(maxLength: 200, nullable: false), + CreationTime = table.Column(nullable: false), + Expiration = table.Column(nullable: false), + Data = table.Column(maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); + }); + + migrationBuilder.CreateTable( + name: "PersistedGrants", + columns: table => new + { + Key = table.Column(maxLength: 200, nullable: false), + Type = table.Column(maxLength: 50, nullable: false), + SubjectId = table.Column(maxLength: 200, nullable: true), + ClientId = table.Column(maxLength: 200, nullable: false), + CreationTime = table.Column(nullable: false), + Expiration = table.Column(nullable: true), + Data = table.Column(maxLength: 50000, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PersistedGrants", x => x.Key); + }); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + OTAC = table.Column(nullable: true), + OTACExpires = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 256, nullable: true), + NormalizedName = table.Column(maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UserClaim", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserClaim_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(maxLength: 128, nullable: false), + ProviderKey = table.Column(maxLength: 128, nullable: false), + ProviderDisplayName = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogin_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(maxLength: 128, nullable: false), + Name = table.Column(maxLength: 128, nullable: false), + Value = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserToken_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserRole", + columns: table => new + { + UserId = table.Column(nullable: false), + RoleId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRole", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_UserRole_UserRoles_RoleId", + column: x => x.RoleId, + principalTable: "UserRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRole_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserRoleClaim", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + RoleId = table.Column(nullable: false), + ClaimType = table.Column(nullable: true), + ClaimValue = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoleClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserRoleClaim_UserRoles_RoleId", + column: x => x.RoleId, + principalTable: "UserRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_DeviceCode", + table: "DeviceCodes", + column: "DeviceCode", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_DeviceCodes_Expiration", + table: "DeviceCodes", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_Expiration", + table: "PersistedGrants", + column: "Expiration"); + + migrationBuilder.CreateIndex( + name: "IX_PersistedGrants_SubjectId_ClientId_Type", + table: "PersistedGrants", + columns: new[] { "SubjectId", "ClientId", "Type" }); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserClaim_UserId", + table: "UserClaim", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogin_UserId", + table: "UserLogin", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRole_RoleId", + table: "UserRole", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRoleClaim_RoleId", + table: "UserRoleClaim", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "UserRoles", + column: "NormalizedName", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DeviceCodes"); + + migrationBuilder.DropTable( + name: "PersistedGrants"); + + migrationBuilder.DropTable( + name: "UserClaim"); + + migrationBuilder.DropTable( + name: "UserLogin"); + + migrationBuilder.DropTable( + name: "UserRole"); + + migrationBuilder.DropTable( + name: "UserRoleClaim"); + + migrationBuilder.DropTable( + name: "UserToken"); + + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "User"); + } + } +} diff --git a/Kyoo/Models/DatabaseMigrations/IdentityDatbase/IdentityDatabaseModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/IdentityDatabaseModelSnapshot.cs new file mode 100644 index 00000000..d7eeed8a --- /dev/null +++ b/Kyoo/Models/DatabaseMigrations/IdentityDatbase/IdentityDatabaseModelSnapshot.cs @@ -0,0 +1,356 @@ +// +using System; +using Kyoo; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Kyoo.Models.DatabaseMigrations.IdentityDatbase +{ + [DbContext(typeof(IdentityDatabase))] + partial class IdentityDatabaseModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => + { + b.Property("UserCode") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50000); + + b.Property("DeviceCode") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.HasKey("UserCode"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.ToTable("DeviceCodes"); + }); + + modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => + { + b.Property("Key") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("ClientId") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("CreationTime") + .HasColumnType("TEXT"); + + b.Property("Data") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50000); + + b.Property("Expiration") + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(50); + + b.HasKey("Key"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.ToTable("PersistedGrants"); + }); + + modelBuilder.Entity("Kyoo.Models.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("OTAC") + .HasColumnType("TEXT"); + + b.Property("OTACExpires") + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoleClaim"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRole"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(128); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Kyoo.Models.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.Designer.cs similarity index 57% rename from Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.Designer.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.Designer.cs index e372c27b..eff11353 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.Designer.cs @@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] - [Migration("20200330171153_Initial")] + [Migration("20200413152648_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -18,88 +18,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder .HasAnnotation("ProductVersion", "3.1.3"); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50000); - - b.Property("DeviceCode") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50000); - - b.Property("Expiration") - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Kyoo.Models.Collection", b => { b.Property("ID") @@ -477,208 +395,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("Tracks"); }); - modelBuilder.Entity("Kyoo.Models.User", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("OTAC") - .HasColumnType("TEXT"); - - b.Property("OTACExpires") - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("User"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("UserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRoleClaim"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserClaim"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("UserLogin"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRole"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("UserToken"); - }); - modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { b.HasOne("Kyoo.Models.Collection", "Collection") @@ -774,57 +490,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); #pragma warning restore 612, 618 } } diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.cs similarity index 61% rename from Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.cs index 63a5aad6..b3b6d925 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200330171153_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200413152648_Initial.cs @@ -24,23 +24,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table.PrimaryKey("PK_Collections", x => x.ID); }); - migrationBuilder.CreateTable( - name: "DeviceCodes", - columns: table => new - { - UserCode = table.Column(maxLength: 200, nullable: false), - DeviceCode = table.Column(maxLength: 200, nullable: false), - SubjectId = table.Column(maxLength: 200, nullable: true), - ClientId = table.Column(maxLength: 200, nullable: false), - CreationTime = table.Column(nullable: false), - Expiration = table.Column(nullable: false), - Data = table.Column(maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceCodes", x => x.UserCode); - }); - migrationBuilder.CreateTable( name: "Genres", columns: table => new @@ -85,23 +68,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table.PrimaryKey("PK_Peoples", x => x.Slug); }); - migrationBuilder.CreateTable( - name: "PersistedGrants", - columns: table => new - { - Key = table.Column(maxLength: 200, nullable: false), - Type = table.Column(maxLength: 50, nullable: false), - SubjectId = table.Column(maxLength: 200, nullable: true), - ClientId = table.Column(maxLength: 200, nullable: false), - CreationTime = table.Column(nullable: false), - Expiration = table.Column(nullable: true), - Data = table.Column(maxLength: 50000, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistedGrants", x => x.Key); - }); - migrationBuilder.CreateTable( name: "Studios", columns: table => new @@ -116,47 +82,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table.PrimaryKey("PK_Studios", x => x.ID); }); - migrationBuilder.CreateTable( - name: "User", - columns: table => new - { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false), - OTAC = table.Column(nullable: true), - OTACExpires = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_User", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "UserRoles", - columns: table => new - { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: true), - NormalizedName = table.Column(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserRoles", x => x.Id); - }); - migrationBuilder.CreateTable( name: "Shows", columns: table => new @@ -191,112 +116,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal onDelete: ReferentialAction.Restrict); }); - migrationBuilder.CreateTable( - name: "UserClaim", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserClaim", x => x.Id); - table.ForeignKey( - name: "FK_UserClaim_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserLogin", - columns: table => new - { - LoginProvider = table.Column(maxLength: 128, nullable: false), - ProviderKey = table.Column(maxLength: 128, nullable: false), - ProviderDisplayName = table.Column(nullable: true), - UserId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_UserLogin_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserToken", - columns: table => new - { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(maxLength: 128, nullable: false), - Name = table.Column(maxLength: 128, nullable: false), - Value = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_UserToken_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserRole", - columns: table => new - { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_UserRole", x => new { x.UserId, x.RoleId }); - table.ForeignKey( - name: "FK_UserRole_UserRoles_RoleId", - column: x => x.RoleId, - principalTable: "UserRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_UserRole_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserRoleClaim", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - RoleId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserRoleClaim", x => x.Id); - table.ForeignKey( - name: "FK_UserRoleClaim_UserRoles_RoleId", - column: x => x.RoleId, - principalTable: "UserRoles", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateTable( name: "CollectionLinks", columns: table => new @@ -506,17 +325,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table: "CollectionLinks", column: "ShowID"); - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_DeviceCode", - table: "DeviceCodes", - column: "DeviceCode", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceCodes_Expiration", - table: "DeviceCodes", - column: "Expiration"); - migrationBuilder.CreateIndex( name: "IX_Episodes_SeasonID", table: "Episodes", @@ -557,16 +365,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal table: "PeopleLinks", column: "ShowID"); - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_Expiration", - table: "PersistedGrants", - column: "Expiration"); - - migrationBuilder.CreateIndex( - name: "IX_PersistedGrants_SubjectId_ClientId_Type", - table: "PersistedGrants", - columns: new[] { "SubjectId", "ClientId", "Type" }); - migrationBuilder.CreateIndex( name: "IX_Seasons_ShowID", table: "Seasons", @@ -581,43 +379,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal name: "IX_Tracks_EpisodeID", table: "Tracks", column: "EpisodeID"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "User", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "User", - column: "NormalizedUserName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_UserClaim_UserId", - table: "UserClaim", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_UserLogin_UserId", - table: "UserLogin", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_UserRole_RoleId", - table: "UserRole", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "IX_UserRoleClaim_RoleId", - table: "UserRoleClaim", - column: "RoleId"); - - migrationBuilder.CreateIndex( - name: "RoleNameIndex", - table: "UserRoles", - column: "NormalizedName", - unique: true); } protected override void Down(MigrationBuilder migrationBuilder) @@ -625,9 +386,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal migrationBuilder.DropTable( name: "CollectionLinks"); - migrationBuilder.DropTable( - name: "DeviceCodes"); - migrationBuilder.DropTable( name: "GenreLinks"); @@ -637,27 +395,9 @@ namespace Kyoo.Models.DatabaseMigrations.Internal migrationBuilder.DropTable( name: "PeopleLinks"); - migrationBuilder.DropTable( - name: "PersistedGrants"); - migrationBuilder.DropTable( name: "Tracks"); - migrationBuilder.DropTable( - name: "UserClaim"); - - migrationBuilder.DropTable( - name: "UserLogin"); - - migrationBuilder.DropTable( - name: "UserRole"); - - migrationBuilder.DropTable( - name: "UserRoleClaim"); - - migrationBuilder.DropTable( - name: "UserToken"); - migrationBuilder.DropTable( name: "Genres"); @@ -673,12 +413,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal migrationBuilder.DropTable( name: "Episodes"); - migrationBuilder.DropTable( - name: "UserRoles"); - - migrationBuilder.DropTable( - name: "User"); - migrationBuilder.DropTable( name: "Seasons"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index 7a0d8df9..3e71efe2 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -16,88 +16,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal modelBuilder .HasAnnotation("ProductVersion", "3.1.3"); - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b => - { - b.Property("UserCode") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50000); - - b.Property("DeviceCode") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("Expiration") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.HasKey("UserCode"); - - b.HasIndex("DeviceCode") - .IsUnique(); - - b.HasIndex("Expiration"); - - b.ToTable("DeviceCodes"); - }); - - modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => - { - b.Property("Key") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("CreationTime") - .HasColumnType("TEXT"); - - b.Property("Data") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50000); - - b.Property("Expiration") - .HasColumnType("TEXT"); - - b.Property("SubjectId") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(50); - - b.HasKey("Key"); - - b.HasIndex("Expiration"); - - b.HasIndex("SubjectId", "ClientId", "Type"); - - b.ToTable("PersistedGrants"); - }); - modelBuilder.Entity("Kyoo.Models.Collection", b => { b.Property("ID") @@ -475,208 +393,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("Tracks"); }); - modelBuilder.Entity("Kyoo.Models.User", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("OTAC") - .HasColumnType("TEXT"); - - b.Property("OTACExpires") - .HasColumnType("TEXT"); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("User"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("UserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRoleClaim"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserClaim"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("UserLogin"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("UserRole"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("UserToken"); - }); - modelBuilder.Entity("Kyoo.Models.CollectionLink", b => { b.HasOne("Kyoo.Models.Collection", "Collection") @@ -772,57 +488,6 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Kyoo.Models.User", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); #pragma warning restore 612, 618 } } diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index cefdc297..4115bf34 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -44,10 +44,21 @@ namespace Kyoo services.AddControllers().AddNewtonsoftJson(); services.AddHttpClient(); + services.AddSingleton(x => new DatabaseFactory( + new DbContextOptionsBuilder() + .UseLazyLoadingProxies() + .UseSqlite(_configuration.GetConnectionString("Database")).Options)); + services.AddDbContext(options => { options.UseLazyLoadingProxies() - .UseSqlite(_configuration.GetConnectionString("Database")); + .UseSqlite(_configuration.GetConnectionString("Database")) + .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole())); + }); + + services.AddDbContext(options => + { + options.UseSqlite(_configuration.GetConnectionString("Database")); }); string assemblyName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; @@ -59,7 +70,7 @@ namespace Kyoo }) .AddSignInManager() .AddDefaultTokenProviders() - .AddEntityFrameworkStores(); + .AddEntityFrameworkStores(); services.AddIdentityServer(options => { diff --git a/Kyoo/Tasks/CreateDatabase.cs b/Kyoo/Tasks/CreateDatabase.cs index 83cbbc46..87c4760a 100644 --- a/Kyoo/Tasks/CreateDatabase.cs +++ b/Kyoo/Tasks/CreateDatabase.cs @@ -25,9 +25,11 @@ namespace Kyoo.Tasks { using IServiceScope serviceScope = serviceProvider.CreateScope(); DatabaseContext databaseContext = serviceScope.ServiceProvider.GetService(); + IdentityDatabase identityDatabase = serviceScope.ServiceProvider.GetService(); ConfigurationDbContext identityContext = serviceScope.ServiceProvider.GetService(); databaseContext.Database.Migrate(); + identityDatabase.Database.Migrate(); identityContext.Database.Migrate(); if (!identityContext.Clients.Any()) diff --git a/Kyoo/Views/API/ShowsAPI.cs b/Kyoo/Views/API/ShowsAPI.cs index 8d1f8387..1bf19449 100644 --- a/Kyoo/Views/API/ShowsAPI.cs +++ b/Kyoo/Views/API/ShowsAPI.cs @@ -1,9 +1,11 @@ using Kyoo.Models; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; +using System.Linq; using Kyoo.Controllers; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; +using Microsoft.EntityFrameworkCore; namespace Kyoo.Api { @@ -38,5 +40,22 @@ namespace Kyoo.Api return show; } + + [HttpPost("edit/{slug}")] + // [Authorize(Policy="Write")] + public IActionResult EditShow(string slug, [FromBody] Show show) + { + if (!ModelState.IsValid) + return BadRequest(show); + + Show old = _libraryManager.GetShowBySlug(slug); + if (old == null) + return NotFound(); + show.ID = 0; + //Should prevent duplicates (If the user put another studio, it is always created even if there is already a studio with the same slug. + old = Utility.Complete(old, show); + _libraryManager.RegisterShow(old); + return Ok(); + } } } diff --git a/Kyoo/Views/WebClient b/Kyoo/Views/WebClient index 59727b1e..4288ecd0 160000 --- a/Kyoo/Views/WebClient +++ b/Kyoo/Views/WebClient @@ -1 +1 @@ -Subproject commit 59727b1e361013dd0b9f700a15e5c6111e69c743 +Subproject commit 4288ecd02e4f5f467659eb031fb172372c8c7af4