diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj index ea2b29ef..174707ee 100644 --- a/Kyoo/Kyoo.csproj +++ b/Kyoo/Kyoo.csproj @@ -90,6 +90,7 @@ + diff --git a/Kyoo/Models/DatabaseContext.cs b/Kyoo/Models/DatabaseContext.cs index f6114a09..3330c04e 100644 --- a/Kyoo/Models/DatabaseContext.cs +++ b/Kyoo/Models/DatabaseContext.cs @@ -1,13 +1,15 @@ using System; using System.Linq; using Kyoo.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Kyoo { - public class DatabaseContext : DbContext + public class DatabaseContext : IdentityDbContext { public DatabaseContext(DbContextOptions options) : base(options) { } @@ -63,9 +65,14 @@ namespace Kyoo modelBuilder.Entity() .Ignore(x => x.Genres); - - // modelBuilder.Entity() - // .Ignore(x => x.Shows); + + modelBuilder.Entity().ToTable("Account"); + modelBuilder.Entity>().ToTable("UserRole"); + modelBuilder.Entity>().ToTable("UserLogin"); + modelBuilder.Entity>().ToTable("UserClaim"); + modelBuilder.Entity().ToTable("UserRoles"); + modelBuilder.Entity>().ToTable("UserRoleClaim"); + modelBuilder.Entity>().ToTable("UserToken"); } } } diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.Designer.cs deleted file mode 100644 index ff44ad18..00000000 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.Designer.cs +++ /dev/null @@ -1,496 +0,0 @@ -// -using System; -using Kyoo; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Kyoo.Models.DatabaseMigrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20200303213358_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.1.2"); - - modelBuilder.Entity("Kyoo.Models.Collection", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ImgPrimary") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("Poster") - .HasColumnType("TEXT"); - - b.Property("Slug") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.ToTable("Collections"); - }); - - modelBuilder.Entity("Kyoo.Models.CollectionLink", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CollectionID") - .HasColumnType("INTEGER"); - - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.HasKey("ID"); - - b.HasIndex("CollectionID"); - - b.HasIndex("ShowID"); - - b.ToTable("CollectionLinks"); - }); - - modelBuilder.Entity("Kyoo.Models.Episode", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AbsoluteNumber") - .HasColumnType("INTEGER"); - - b.Property("EpisodeNumber") - .HasColumnType("INTEGER"); - - b.Property("ExternalIDs") - .HasColumnType("TEXT"); - - b.Property("ImgPrimary") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("ReleaseDate") - .HasColumnType("TEXT"); - - b.Property("Runtime") - .HasColumnType("INTEGER"); - - b.Property("SeasonID") - .HasColumnType("INTEGER"); - - b.Property("SeasonNumber") - .HasColumnType("INTEGER"); - - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("SeasonID"); - - b.HasIndex("ShowID"); - - b.ToTable("Episodes"); - }); - - modelBuilder.Entity("Kyoo.Models.Genre", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Slug") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.ToTable("Genres"); - }); - - modelBuilder.Entity("Kyoo.Models.GenreLink", b => - { - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.Property("GenreID") - .HasColumnType("INTEGER"); - - b.HasKey("ShowID", "GenreID"); - - b.HasIndex("GenreID"); - - b.ToTable("GenreLinks"); - }); - - modelBuilder.Entity("Kyoo.Models.Library", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Paths") - .HasColumnType("TEXT"); - - b.Property("Providers") - .HasColumnType("TEXT"); - - b.Property("Slug") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.ToTable("Libraries"); - }); - - modelBuilder.Entity("Kyoo.Models.LibraryLink", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CollectionID") - .HasColumnType("INTEGER"); - - b.Property("LibraryID") - .HasColumnType("INTEGER"); - - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.HasKey("ID"); - - b.HasIndex("CollectionID"); - - b.HasIndex("LibraryID"); - - b.HasIndex("ShowID"); - - b.ToTable("LibraryLinks"); - }); - - modelBuilder.Entity("Kyoo.Models.People", b => - { - b.Property("Slug") - .HasColumnType("TEXT"); - - b.Property("ExternalIDs") - .HasColumnType("TEXT"); - - b.Property("ImgPrimary") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.HasKey("Slug"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("PeopleID") - .HasColumnType("TEXT"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("PeopleID"); - - b.HasIndex("ShowID"); - - b.ToTable("PeopleLinks"); - }); - - modelBuilder.Entity("Kyoo.Models.Season", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ExternalIDs") - .HasColumnType("TEXT"); - - b.Property("ImgPrimary") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("SeasonNumber") - .HasColumnType("INTEGER"); - - b.Property("ShowID") - .HasColumnType("INTEGER"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Year") - .HasColumnType("INTEGER"); - - b.HasKey("ID"); - - b.HasIndex("ShowID"); - - b.ToTable("Seasons"); - }); - - modelBuilder.Entity("Kyoo.Models.Show", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Aliases") - .HasColumnType("TEXT"); - - b.Property("EndYear") - .HasColumnType("INTEGER"); - - b.Property("ExternalIDs") - .HasColumnType("TEXT"); - - b.Property("ImgBackdrop") - .HasColumnType("TEXT"); - - b.Property("ImgLogo") - .HasColumnType("TEXT"); - - b.Property("ImgPrimary") - .HasColumnType("TEXT"); - - b.Property("ImgThumb") - .HasColumnType("TEXT"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("Slug") - .HasColumnType("TEXT"); - - b.Property("StartYear") - .HasColumnType("INTEGER"); - - b.Property("Status") - .HasColumnType("INTEGER"); - - b.Property("StudioID") - .HasColumnType("INTEGER"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("TrailerUrl") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("StudioID"); - - b.ToTable("Shows"); - }); - - modelBuilder.Entity("Kyoo.Models.Studio", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("Slug") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.ToTable("Studios"); - }); - - modelBuilder.Entity("Kyoo.Models.Track", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("EpisodeID") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("ID"); - - b.HasIndex("EpisodeID"); - - b.ToTable("Tracks"); - }); - - modelBuilder.Entity("Kyoo.Models.CollectionLink", b => - { - b.HasOne("Kyoo.Models.Collection", "Collection") - .WithMany() - .HasForeignKey("CollectionID"); - - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany() - .HasForeignKey("ShowID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Kyoo.Models.Episode", b => - { - b.HasOne("Kyoo.Models.Season", "Season") - .WithMany("Episodes") - .HasForeignKey("SeasonID"); - - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany("Episodes") - .HasForeignKey("ShowID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Kyoo.Models.GenreLink", b => - { - b.HasOne("Kyoo.Models.Genre", "Genre") - .WithMany() - .HasForeignKey("GenreID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany("GenreLinks") - .HasForeignKey("ShowID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Kyoo.Models.LibraryLink", b => - { - b.HasOne("Kyoo.Models.Collection", "Collection") - .WithMany() - .HasForeignKey("CollectionID"); - - b.HasOne("Kyoo.Models.Library", "Library") - .WithMany() - .HasForeignKey("LibraryID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany() - .HasForeignKey("ShowID"); - }); - - modelBuilder.Entity("Kyoo.Models.PeopleLink", b => - { - b.HasOne("Kyoo.Models.People", "People") - .WithMany("Roles") - .HasForeignKey("PeopleID"); - - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany("People") - .HasForeignKey("ShowID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Kyoo.Models.Season", b => - { - b.HasOne("Kyoo.Models.Show", "Show") - .WithMany("Seasons") - .HasForeignKey("ShowID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Kyoo.Models.Show", b => - { - b.HasOne("Kyoo.Models.Studio", "Studio") - .WithMany() - .HasForeignKey("StudioID"); - }); - - modelBuilder.Entity("Kyoo.Models.Track", b => - { - b.HasOne("Kyoo.Models.Episode", "Episode") - .WithMany("Tracks") - .HasForeignKey("EpisodeID") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.cs deleted file mode 100644 index 99fe4424..00000000 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Kyoo.Models.DatabaseMigrations.Internal -{ - public partial class Addingaccounts : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Accounts", - columns: table => new - { - Id = table.Column(nullable: false), - UserName = table.Column(nullable: true), - NormalizedUserName = table.Column(nullable: true), - Email = table.Column(nullable: true), - NormalizedEmail = table.Column(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_Accounts", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Accounts"); - } - } -} diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.Designer.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.Designer.cs similarity index 72% rename from Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.Designer.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.Designer.cs index f45bfa68..d78f0deb 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200306000057_Adding accounts.Designer.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.Designer.cs @@ -9,8 +9,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] - [Migration("20200306000057_Adding accounts")] - partial class Addingaccounts + [Migration("20200307014347_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -27,10 +27,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("INTEGER"); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Email") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("EmailConfirmed") .HasColumnType("INTEGER"); @@ -42,10 +44,12 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("TEXT"); b.Property("NormalizedEmail") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("NormalizedUserName") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("OTAC") .HasColumnType("TEXT"); @@ -69,11 +73,19 @@ namespace Kyoo.Models.DatabaseMigrations.Internal .HasColumnType("INTEGER"); b.Property("UserName") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.HasKey("Id"); - b.ToTable("Accounts"); + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("Account"); }); modelBuilder.Entity("Kyoo.Models.Collection", b => @@ -453,6 +465,134 @@ namespace Kyoo.Models.DatabaseMigrations.Internal b.ToTable("Tracks"); }); + 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"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + 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"); + + b.Property("Name") + .HasColumnType("TEXT"); + + 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") @@ -548,6 +688,57 @@ 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.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Kyoo.Models.Account", 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.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Kyoo.Models.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.cs b/Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.cs similarity index 67% rename from Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.cs rename to Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.cs index e88c29f8..9e4b2f5c 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/20200303213358_Initial.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/20200307014347_Initial.cs @@ -1,12 +1,39 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; -namespace Kyoo.Models.DatabaseMigrations +namespace Kyoo.Models.DatabaseMigrations.Internal { public partial class Initial : Migration { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "Account", + 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_Account", x => x.Id); + }); + migrationBuilder.CreateTable( name: "Collections", columns: table => new @@ -82,6 +109,81 @@ namespace Kyoo.Models.DatabaseMigrations table.PrimaryKey("PK_Studios", 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_Account_UserId", + column: x => x.UserId, + principalTable: "Account", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(nullable: false), + ProviderKey = table.Column(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_Account_UserId", + column: x => x.UserId, + principalTable: "Account", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(nullable: false), + LoginProvider = table.Column(nullable: false), + Name = table.Column(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_Account_UserId", + column: x => x.UserId, + principalTable: "Account", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "Shows", columns: table => new @@ -116,6 +218,51 @@ namespace Kyoo.Models.DatabaseMigrations onDelete: ReferentialAction.Restrict); }); + 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_Account_UserId", + column: x => x.UserId, + principalTable: "Account", + 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 @@ -315,6 +462,17 @@ namespace Kyoo.Models.DatabaseMigrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "Account", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "Account", + column: "NormalizedUserName", + unique: true); + migrationBuilder.CreateIndex( name: "IX_CollectionLinks_CollectionID", table: "CollectionLinks", @@ -379,6 +537,32 @@ namespace Kyoo.Models.DatabaseMigrations name: "IX_Tracks_EpisodeID", table: "Tracks", column: "EpisodeID"); + + 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) @@ -398,6 +582,21 @@ namespace Kyoo.Models.DatabaseMigrations 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"); @@ -413,6 +612,12 @@ namespace Kyoo.Models.DatabaseMigrations migrationBuilder.DropTable( name: "Episodes"); + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "Account"); + migrationBuilder.DropTable( name: "Seasons"); diff --git a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs index 544fb00c..eb976610 100644 --- a/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs +++ b/Kyoo/Models/DatabaseMigrations/Internal/DatabaseContextModelSnapshot.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -namespace Kyoo.Models.DatabaseMigrations +namespace Kyoo.Models.DatabaseMigrations.Internal { [DbContext(typeof(DatabaseContext))] partial class DatabaseContextModelSnapshot : ModelSnapshot @@ -25,10 +25,12 @@ namespace Kyoo.Models.DatabaseMigrations .HasColumnType("INTEGER"); b.Property("ConcurrencyStamp") + .IsConcurrencyToken() .HasColumnType("TEXT"); b.Property("Email") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("EmailConfirmed") .HasColumnType("INTEGER"); @@ -40,10 +42,12 @@ namespace Kyoo.Models.DatabaseMigrations .HasColumnType("TEXT"); b.Property("NormalizedEmail") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("NormalizedUserName") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.Property("OTAC") .HasColumnType("TEXT"); @@ -67,11 +71,19 @@ namespace Kyoo.Models.DatabaseMigrations .HasColumnType("INTEGER"); b.Property("UserName") - .HasColumnType("TEXT"); + .HasColumnType("TEXT") + .HasMaxLength(256); b.HasKey("Id"); - b.ToTable("Accounts"); + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("Account"); }); modelBuilder.Entity("Kyoo.Models.Collection", b => @@ -451,6 +463,134 @@ namespace Kyoo.Models.DatabaseMigrations b.ToTable("Tracks"); }); + 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"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + 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"); + + b.Property("Name") + .HasColumnType("TEXT"); + + 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") @@ -546,6 +686,57 @@ namespace Kyoo.Models.DatabaseMigrations .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.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Kyoo.Models.Account", 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.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Kyoo.Models.Account", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/Kyoo/Views/API/AccountAPI.cs b/Kyoo/Views/API/AccountAPI.cs index 583fc204..616f14dd 100644 --- a/Kyoo/Views/API/AccountAPI.cs +++ b/Kyoo/Views/API/AccountAPI.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Kyoo.Models; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using SignInResult = Microsoft.AspNetCore.Identity.SignInResult; namespace Kyoo.Api { @@ -11,6 +12,13 @@ namespace Kyoo.Api public string Email; public string Username; public string Password; + } + + public class LoginRequest + { + public string Username; + public string Password; + public bool StayLoggedIn; } [Route("api/[controller]")] @@ -18,10 +26,12 @@ namespace Kyoo.Api public class AccountController : Controller { private readonly UserManager _accountManager; + private readonly SignInManager _signInManager; - public AccountController(UserManager accountManager) + public AccountController(UserManager accountManager, SignInManager siginInManager) { _accountManager = accountManager; + _signInManager = siginInManager; } [HttpPost("register")] @@ -37,5 +47,16 @@ namespace Kyoo.Api await _accountManager.UpdateAsync(account); return Ok(otac); } + + [HttpPost("login")] + public async Task Login([FromBody] LoginRequest login) + { + if (!ModelState.IsValid) + return BadRequest(login); + SignInResult result = await _signInManager.PasswordSignInAsync(login.Username, login.Password, login.StayLoggedIn, false); + if (result.Succeeded) + return Ok(); + return BadRequest("Invalid username/password"); + } } } \ No newline at end of file diff --git a/Kyoo/Views/WebClient b/Kyoo/Views/WebClient index af2478da..6240bbce 160000 --- a/Kyoo/Views/WebClient +++ b/Kyoo/Views/WebClient @@ -1 +1 @@ -Subproject commit af2478da584eacee6377e50dbb4c530cffd7e0b6 +Subproject commit 6240bbce05be87f576fd4326ce26e8bfa8335c73