mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-08 08:48:48 +01:00
Migrate User DB to EF Core
This commit is contained in:
@@ -16,6 +16,13 @@ namespace Jellyfin.Server.Implementations
|
||||
public partial class JellyfinDb : DbContext
|
||||
{
|
||||
public virtual DbSet<ActivityLog> ActivityLogs { get; set; }
|
||||
|
||||
public virtual DbSet<Group> Groups { get; set; }
|
||||
|
||||
public virtual DbSet<Permission> Permissions { get; set; }
|
||||
|
||||
public virtual DbSet<Preference> Preferences { get; set; }
|
||||
|
||||
public virtual DbSet<Data.Entities.User> Users { get; set; }
|
||||
/*public virtual DbSet<Artwork> Artwork { get; set; }
|
||||
public virtual DbSet<Book> Books { get; set; }
|
||||
@@ -30,7 +37,6 @@ namespace Jellyfin.Server.Implementations
|
||||
public virtual DbSet<Episode> Episodes { get; set; }
|
||||
public virtual DbSet<EpisodeMetadata> EpisodeMetadata { get; set; }
|
||||
public virtual DbSet<Genre> Genres { get; set; }
|
||||
public virtual DbSet<Group> Groups { get; set; }
|
||||
public virtual DbSet<Library> Libraries { get; set; }
|
||||
public virtual DbSet<LibraryItem> LibraryItems { get; set; }
|
||||
public virtual DbSet<LibraryRoot> LibraryRoot { get; set; }
|
||||
@@ -43,12 +49,10 @@ namespace Jellyfin.Server.Implementations
|
||||
public virtual DbSet<MovieMetadata> MovieMetadata { get; set; }
|
||||
public virtual DbSet<MusicAlbum> MusicAlbums { get; set; }
|
||||
public virtual DbSet<MusicAlbumMetadata> MusicAlbumMetadata { get; set; }
|
||||
public virtual DbSet<Permission> Permissions { get; set; }
|
||||
public virtual DbSet<Person> People { get; set; }
|
||||
public virtual DbSet<PersonRole> PersonRoles { get; set; }
|
||||
public virtual DbSet<Photo> Photo { get; set; }
|
||||
public virtual DbSet<PhotoMetadata> PhotoMetadata { get; set; }
|
||||
public virtual DbSet<Preference> Preferences { get; set; }
|
||||
public virtual DbSet<ProviderMapping> ProviderMappings { get; set; }
|
||||
public virtual DbSet<Rating> Ratings { get; set; }
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Jellyfin.Server.Implementations
|
||||
public JellyfinDbProvider(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
serviceProvider.GetService<JellyfinDb>().Database.Migrate();
|
||||
serviceProvider.GetRequiredService<JellyfinDb>().Database.Migrate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable SA1601
|
||||
|
||||
// <auto-generated />
|
||||
@@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace Jellyfin.Server.Implementations.Migrations
|
||||
{
|
||||
[DbContext(typeof(JellyfinDb))]
|
||||
[Migration("20200504195702_UserSchema")]
|
||||
partial class UserSchema
|
||||
[Migration("20200517002411_AddUsers")]
|
||||
partial class AddUsers
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -22,6 +22,31 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasDefaultSchema("jellyfin")
|
||||
.HasAnnotation("ProductVersion", "3.1.3");
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("EndHour")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("StartHour")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccessSchedule");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -65,17 +90,17 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ActivityLog");
|
||||
b.ToTable("ActivityLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Group", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("Group_Groups_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Group_Groups_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
@@ -88,9 +113,27 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Group_Groups_Id");
|
||||
b.HasIndex("Group_Groups_Guid");
|
||||
|
||||
b.ToTable("Group");
|
||||
b.ToTable("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ImageInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
|
||||
@@ -102,11 +145,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
b.Property<int>("Kind")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Permission_GroupPermissions_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Permission_GroupPermissions_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("Permission_Permissions_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Permission_Permissions_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
@@ -119,9 +162,9 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasIndex("Permission_GroupPermissions_Id");
|
||||
|
||||
b.HasIndex("Permission_Permissions_Id");
|
||||
b.HasIndex("Permission_Permissions_Guid");
|
||||
|
||||
b.ToTable("Permission");
|
||||
b.ToTable("Permissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
|
||||
@@ -133,8 +176,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
b.Property<int>("Kind")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Preference_Preferences_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Preference_Preferences_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("Preference_Preferences_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
@@ -147,9 +193,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Preference_Preferences_Guid");
|
||||
|
||||
b.HasIndex("Preference_Preferences_Id");
|
||||
|
||||
b.ToTable("Preference");
|
||||
b.ToTable("Preferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ProviderMapping", b =>
|
||||
@@ -163,8 +211,8 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<int?>("ProviderMapping_ProviderMappings_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("ProviderMapping_ProviderMappings_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderName")
|
||||
.IsRequired()
|
||||
@@ -189,12 +237,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AudioLanguagePreference")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
@@ -203,71 +250,86 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<bool?>("DisplayCollectionsView")
|
||||
b.Property<bool>("DisplayCollectionsView")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("DisplayMissingEpisodes")
|
||||
b.Property<bool>("DisplayMissingEpisodes")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("EnableNextEpisodeAutoPlay")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("EnableUserPreferenceAccess")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("GroupedFolders")
|
||||
b.Property<string>("EasyPassword")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<bool?>("HidePlayedInLatest")
|
||||
b.Property<bool>("EnableAutoLogin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableLocalPassword")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableNextEpisodeAutoPlay")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableUserPreferenceAccess")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HidePlayedInLatest")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("InternalId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("InvalidLoginAttemptCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LatestItemExcludes")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
b.Property<DateTime>("LastActivityDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastLoginDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("LoginAttemptsBeforeLockout")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("MaxParentalAgeRating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("MustUpdatePassword")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("MyMediaExcludes")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("OrderedViews")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("Password")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("PasswordResetProviderId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<bool>("PlayDefaultAudioTrack")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("RememberAudioSelections")
|
||||
b.Property<int?>("ProfileImageId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("RememberSubtitleSelections")
|
||||
b.Property<bool>("RememberAudioSelections")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("RememberSubtitleSelections")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("RemoteClientBitrateLimit")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SubtitleLanguagePrefernce")
|
||||
b.Property<string>("SubtitleLanguagePreference")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<string>("SubtitleMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
b.Property<int>("SubtitleMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
@@ -276,34 +338,45 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("User");
|
||||
b.HasIndex("ProfileImageId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("AccessSchedules")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Group", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Groups")
|
||||
.HasForeignKey("Group_Groups_Id");
|
||||
.HasForeignKey("Group_Groups_Guid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("GroupPermissions")
|
||||
.WithMany("Permissions")
|
||||
.HasForeignKey("Permission_GroupPermissions_Id");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Permissions")
|
||||
.HasForeignKey("Permission_Permissions_Id");
|
||||
.HasForeignKey("Permission_Permissions_Guid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Id");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Guid");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Id");
|
||||
});
|
||||
@@ -318,6 +391,13 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.WithMany("ProviderMappings")
|
||||
.HasForeignKey("ProviderMapping_ProviderMappings_Id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.ImageInfo", "ProfileImage")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileImageId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
@@ -1,74 +1,125 @@
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable CS1591
|
||||
#pragma warning disable SA1601
|
||||
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Migrations
|
||||
{
|
||||
public partial class UserSchema : Migration
|
||||
public partial class AddUsers : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "User",
|
||||
name: "ImageInfo",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Path = table.Column<string>(nullable: false),
|
||||
LastModified = table.Column<DateTime>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ImageInfo", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(nullable: false),
|
||||
Username = table.Column<string>(maxLength: 255, nullable: false),
|
||||
Password = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
EasyPassword = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
MustUpdatePassword = table.Column<bool>(nullable: false),
|
||||
AudioLanguagePreference = table.Column<string>(maxLength: 255, nullable: false),
|
||||
AudioLanguagePreference = table.Column<string>(maxLength: 255, nullable: true),
|
||||
AuthenticationProviderId = table.Column<string>(maxLength: 255, nullable: false),
|
||||
GroupedFolders = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
PasswordResetProviderId = table.Column<string>(maxLength: 255, nullable: false),
|
||||
InvalidLoginAttemptCount = table.Column<int>(nullable: false),
|
||||
LatestItemExcludes = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
LastActivityDate = table.Column<DateTime>(nullable: false),
|
||||
LastLoginDate = table.Column<DateTime>(nullable: false),
|
||||
LoginAttemptsBeforeLockout = table.Column<int>(nullable: true),
|
||||
MyMediaExcludes = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
OrderedViews = table.Column<string>(maxLength: 65535, nullable: true),
|
||||
SubtitleMode = table.Column<string>(maxLength: 255, nullable: false),
|
||||
SubtitleMode = table.Column<int>(nullable: false),
|
||||
PlayDefaultAudioTrack = table.Column<bool>(nullable: false),
|
||||
SubtitleLanguagePrefernce = table.Column<string>(maxLength: 255, nullable: true),
|
||||
DisplayMissingEpisodes = table.Column<bool>(nullable: true),
|
||||
DisplayCollectionsView = table.Column<bool>(nullable: true),
|
||||
HidePlayedInLatest = table.Column<bool>(nullable: true),
|
||||
RememberAudioSelections = table.Column<bool>(nullable: true),
|
||||
RememberSubtitleSelections = table.Column<bool>(nullable: true),
|
||||
EnableNextEpisodeAutoPlay = table.Column<bool>(nullable: true),
|
||||
EnableUserPreferenceAccess = table.Column<bool>(nullable: true),
|
||||
SubtitleLanguagePreference = table.Column<string>(maxLength: 255, nullable: true),
|
||||
DisplayMissingEpisodes = table.Column<bool>(nullable: false),
|
||||
DisplayCollectionsView = table.Column<bool>(nullable: false),
|
||||
EnableLocalPassword = table.Column<bool>(nullable: false),
|
||||
HidePlayedInLatest = table.Column<bool>(nullable: false),
|
||||
RememberAudioSelections = table.Column<bool>(nullable: false),
|
||||
RememberSubtitleSelections = table.Column<bool>(nullable: false),
|
||||
EnableNextEpisodeAutoPlay = table.Column<bool>(nullable: false),
|
||||
EnableAutoLogin = table.Column<bool>(nullable: false),
|
||||
EnableUserPreferenceAccess = table.Column<bool>(nullable: false),
|
||||
MaxParentalAgeRating = table.Column<int>(nullable: true),
|
||||
RemoteClientBitrateLimit = table.Column<int>(nullable: true),
|
||||
InternalId = table.Column<long>(nullable: false),
|
||||
ProfileImageId = table.Column<int>(nullable: true),
|
||||
RowVersion = table.Column<uint>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_User", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Group",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Name = table.Column<string>(maxLength: 255, nullable: false),
|
||||
RowVersion = table.Column<uint>(nullable: false),
|
||||
Group_Groups_Id = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Group", x => x.Id);
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Group_User_Group_Groups_Id",
|
||||
column: x => x.Group_Groups_Id,
|
||||
name: "FK_Users_ImageInfo_ProfileImageId",
|
||||
column: x => x.ProfileImageId,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "User",
|
||||
principalTable: "ImageInfo",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Permission",
|
||||
name: "AccessSchedule",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
UserId = table.Column<Guid>(nullable: false),
|
||||
DayOfWeek = table.Column<int>(nullable: false),
|
||||
StartHour = table.Column<double>(nullable: false),
|
||||
EndHour = table.Column<double>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AccessSchedule", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AccessSchedule_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Groups",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(nullable: false),
|
||||
Name = table.Column<string>(maxLength: 255, nullable: false),
|
||||
RowVersion = table.Column<uint>(nullable: false),
|
||||
Group_Groups_Guid = table.Column<Guid>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Groups", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Groups_Users_Group_Groups_Guid",
|
||||
column: x => x.Group_Groups_Guid,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Permissions",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
@@ -77,30 +128,30 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
Kind = table.Column<int>(nullable: false),
|
||||
Value = table.Column<bool>(nullable: false),
|
||||
RowVersion = table.Column<uint>(nullable: false),
|
||||
Permission_GroupPermissions_Id = table.Column<int>(nullable: true),
|
||||
Permission_Permissions_Id = table.Column<int>(nullable: true)
|
||||
Permission_GroupPermissions_Id = table.Column<Guid>(nullable: true),
|
||||
Permission_Permissions_Guid = table.Column<Guid>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Permission", x => x.Id);
|
||||
table.PrimaryKey("PK_Permissions", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Permission_Group_Permission_GroupPermissions_Id",
|
||||
name: "FK_Permissions_Groups_Permission_GroupPermissions_Id",
|
||||
column: x => x.Permission_GroupPermissions_Id,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "Group",
|
||||
principalTable: "Groups",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Permission_User_Permission_Permissions_Id",
|
||||
column: x => x.Permission_Permissions_Id,
|
||||
name: "FK_Permissions_Users_Permission_Permissions_Guid",
|
||||
column: x => x.Permission_Permissions_Guid,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "User",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Preference",
|
||||
name: "Preferences",
|
||||
schema: "jellyfin",
|
||||
columns: table => new
|
||||
{
|
||||
@@ -109,23 +160,24 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
Kind = table.Column<int>(nullable: false),
|
||||
Value = table.Column<string>(maxLength: 65535, nullable: false),
|
||||
RowVersion = table.Column<uint>(nullable: false),
|
||||
Preference_Preferences_Id = table.Column<int>(nullable: true)
|
||||
Preference_Preferences_Guid = table.Column<Guid>(nullable: true),
|
||||
Preference_Preferences_Id = table.Column<Guid>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Preference", x => x.Id);
|
||||
table.PrimaryKey("PK_Preferences", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Preference_Group_Preference_Preferences_Id",
|
||||
column: x => x.Preference_Preferences_Id,
|
||||
name: "FK_Preferences_Users_Preference_Preferences_Guid",
|
||||
column: x => x.Preference_Preferences_Guid,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "Group",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Preference_User_Preference_Preferences_Id",
|
||||
name: "FK_Preferences_Groups_Preference_Preferences_Id",
|
||||
column: x => x.Preference_Preferences_Id,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "User",
|
||||
principalTable: "Groups",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
@@ -141,49 +193,61 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
ProviderSecrets = table.Column<string>(maxLength: 65535, nullable: false),
|
||||
ProviderData = table.Column<string>(maxLength: 65535, nullable: false),
|
||||
RowVersion = table.Column<uint>(nullable: false),
|
||||
ProviderMapping_ProviderMappings_Id = table.Column<int>(nullable: true)
|
||||
ProviderMapping_ProviderMappings_Id = table.Column<Guid>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ProviderMapping", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ProviderMapping_Group_ProviderMapping_ProviderMappings_Id",
|
||||
name: "FK_ProviderMapping_Groups_ProviderMapping_ProviderMappings_Id",
|
||||
column: x => x.ProviderMapping_ProviderMappings_Id,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "Group",
|
||||
principalTable: "Groups",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_ProviderMapping_User_ProviderMapping_ProviderMappings_Id",
|
||||
name: "FK_ProviderMapping_Users_ProviderMapping_ProviderMappings_Id",
|
||||
column: x => x.ProviderMapping_ProviderMappings_Id,
|
||||
principalSchema: "jellyfin",
|
||||
principalTable: "User",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Group_Group_Groups_Id",
|
||||
name: "IX_AccessSchedule_UserId",
|
||||
schema: "jellyfin",
|
||||
table: "Group",
|
||||
column: "Group_Groups_Id");
|
||||
table: "AccessSchedule",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Permission_Permission_GroupPermissions_Id",
|
||||
name: "IX_Groups_Group_Groups_Guid",
|
||||
schema: "jellyfin",
|
||||
table: "Permission",
|
||||
table: "Groups",
|
||||
column: "Group_Groups_Guid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Permissions_Permission_GroupPermissions_Id",
|
||||
schema: "jellyfin",
|
||||
table: "Permissions",
|
||||
column: "Permission_GroupPermissions_Id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Permission_Permission_Permissions_Id",
|
||||
name: "IX_Permissions_Permission_Permissions_Guid",
|
||||
schema: "jellyfin",
|
||||
table: "Permission",
|
||||
column: "Permission_Permissions_Id");
|
||||
table: "Permissions",
|
||||
column: "Permission_Permissions_Guid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Preference_Preference_Preferences_Id",
|
||||
name: "IX_Preferences_Preference_Preferences_Guid",
|
||||
schema: "jellyfin",
|
||||
table: "Preference",
|
||||
table: "Preferences",
|
||||
column: "Preference_Preferences_Guid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Preferences_Preference_Preferences_Id",
|
||||
schema: "jellyfin",
|
||||
table: "Preferences",
|
||||
column: "Preference_Preferences_Id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
@@ -191,16 +255,26 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
schema: "jellyfin",
|
||||
table: "ProviderMapping",
|
||||
column: "ProviderMapping_ProviderMappings_Id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_ProfileImageId",
|
||||
schema: "jellyfin",
|
||||
table: "Users",
|
||||
column: "ProfileImageId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Permission",
|
||||
name: "AccessSchedule",
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Preference",
|
||||
name: "Permissions",
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Preferences",
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
@@ -208,11 +282,15 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Group",
|
||||
name: "Groups",
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "User",
|
||||
name: "Users",
|
||||
schema: "jellyfin");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ImageInfo",
|
||||
schema: "jellyfin");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Jellyfin.Server.Implementations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.Migrations
|
||||
{
|
||||
@@ -15,6 +17,31 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasDefaultSchema("jellyfin")
|
||||
.HasAnnotation("ProductVersion", "3.1.3");
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DayOfWeek")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("EndHour")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("StartHour")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccessSchedule");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -63,12 +90,12 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Group", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("Group_Groups_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Group_Groups_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
@@ -81,9 +108,27 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Group_Groups_Id");
|
||||
b.HasIndex("Group_Groups_Guid");
|
||||
|
||||
b.ToTable("Group");
|
||||
b.ToTable("Groups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ImageInfo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
|
||||
@@ -95,11 +140,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
b.Property<int>("Kind")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Permission_GroupPermissions_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Permission_GroupPermissions_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("Permission_Permissions_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Permission_Permissions_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
@@ -112,9 +157,9 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasIndex("Permission_GroupPermissions_Id");
|
||||
|
||||
b.HasIndex("Permission_Permissions_Id");
|
||||
b.HasIndex("Permission_Permissions_Guid");
|
||||
|
||||
b.ToTable("Permission");
|
||||
b.ToTable("Permissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
|
||||
@@ -126,8 +171,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
b.Property<int>("Kind")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("Preference_Preferences_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("Preference_Preferences_Guid")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("Preference_Preferences_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
@@ -140,9 +188,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Preference_Preferences_Guid");
|
||||
|
||||
b.HasIndex("Preference_Preferences_Id");
|
||||
|
||||
b.ToTable("Preference");
|
||||
b.ToTable("Preferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.ProviderMapping", b =>
|
||||
@@ -156,8 +206,8 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<int?>("ProviderMapping_ProviderMappings_Id")
|
||||
.HasColumnType("INTEGER");
|
||||
b.Property<Guid?>("ProviderMapping_ProviderMappings_Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderName")
|
||||
.IsRequired()
|
||||
@@ -182,12 +232,11 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AudioLanguagePreference")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
@@ -196,71 +245,86 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<bool?>("DisplayCollectionsView")
|
||||
b.Property<bool>("DisplayCollectionsView")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("DisplayMissingEpisodes")
|
||||
b.Property<bool>("DisplayMissingEpisodes")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("EnableNextEpisodeAutoPlay")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("EnableUserPreferenceAccess")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("GroupedFolders")
|
||||
b.Property<string>("EasyPassword")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<bool?>("HidePlayedInLatest")
|
||||
b.Property<bool>("EnableAutoLogin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableLocalPassword")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableNextEpisodeAutoPlay")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("EnableUserPreferenceAccess")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HidePlayedInLatest")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("InternalId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("InvalidLoginAttemptCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LatestItemExcludes")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
b.Property<DateTime>("LastActivityDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastLoginDate")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("LoginAttemptsBeforeLockout")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("MaxParentalAgeRating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("MustUpdatePassword")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("MyMediaExcludes")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("OrderedViews")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("Password")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(65535);
|
||||
|
||||
b.Property<string>("PasswordResetProviderId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<bool>("PlayDefaultAudioTrack")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("RememberAudioSelections")
|
||||
b.Property<int?>("ProfileImageId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("RememberSubtitleSelections")
|
||||
b.Property<bool>("RememberAudioSelections")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("RememberSubtitleSelections")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("RemoteClientBitrateLimit")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SubtitleLanguagePrefernce")
|
||||
b.Property<string>("SubtitleLanguagePreference")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
|
||||
b.Property<string>("SubtitleMode")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(255);
|
||||
b.Property<int>("SubtitleMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
@@ -269,34 +333,45 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("User");
|
||||
b.HasIndex("ProfileImageId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("AccessSchedules")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Group", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Groups")
|
||||
.HasForeignKey("Group_Groups_Id");
|
||||
.HasForeignKey("Group_Groups_Guid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("GroupPermissions")
|
||||
.WithMany("Permissions")
|
||||
.HasForeignKey("Permission_GroupPermissions_Id");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Permissions")
|
||||
.HasForeignKey("Permission_Permissions_Id");
|
||||
.HasForeignKey("Permission_Permissions_Guid");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Id");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.User", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Guid");
|
||||
|
||||
b.HasOne("Jellyfin.Data.Entities.Group", null)
|
||||
.WithMany("Preferences")
|
||||
.HasForeignKey("Preference_Preferences_Id");
|
||||
});
|
||||
@@ -311,6 +386,13 @@ namespace Jellyfin.Server.Implementations.Migrations
|
||||
.WithMany("ProviderMappings")
|
||||
.HasForeignKey("ProviderMapping_ProviderMappings_Id");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
|
||||
{
|
||||
b.HasOne("Jellyfin.Data.Entities.ImageInfo", "ProfileImage")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileImageId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using MediaBrowser.Common.Cryptography;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Model.Cryptography;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.User
|
||||
namespace Jellyfin.Server.Implementations.Users
|
||||
{
|
||||
/// <summary>
|
||||
/// The default authentication provider.
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
@@ -10,7 +11,7 @@ using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.User
|
||||
namespace Jellyfin.Server.Implementations.Users
|
||||
{
|
||||
/// <summary>
|
||||
/// The default password reset provider.
|
||||
@@ -94,7 +95,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ForgotPasswordResult> StartForgotPasswordProcess(Jellyfin.Data.Entities.User user, bool isInNetwork)
|
||||
public async Task<ForgotPasswordResult> StartForgotPasswordProcess(User user, bool isInNetwork)
|
||||
{
|
||||
string pin;
|
||||
using (var cryptoRandom = RandomNumberGenerator.Create())
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Library;
|
||||
@@ -9,7 +10,7 @@ using MediaBrowser.Controller.Security;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Events;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.User
|
||||
namespace Jellyfin.Server.Implementations.Users
|
||||
{
|
||||
public sealed class DeviceAccessEntryPoint : IServerEntryPoint
|
||||
{
|
||||
@@ -33,7 +34,11 @@ namespace Jellyfin.Server.Implementations.User
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void OnUserUpdated(object sender, GenericEventArgs<Data.Entities.User> e)
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnUserUpdated(object sender, GenericEventArgs<User> e)
|
||||
{
|
||||
var user = e.Argument;
|
||||
if (!user.HasPermission(PermissionKind.EnableAllDevices))
|
||||
@@ -42,11 +47,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
private void UpdateDeviceAccess(Data.Entities.User user)
|
||||
private void UpdateDeviceAccess(User user)
|
||||
{
|
||||
var existing = _authRepo.Get(new AuthenticationInfoQuery
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.User
|
||||
namespace Jellyfin.Server.Implementations.Users
|
||||
{
|
||||
/// <summary>
|
||||
/// An invalid authentication provider.
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma warning disable CS0067
|
||||
#pragma warning disable CA1307
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
@@ -6,7 +6,9 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Common.Cryptography;
|
||||
using MediaBrowser.Common.Net;
|
||||
@@ -20,7 +22,7 @@ using MediaBrowser.Model.Events;
|
||||
using MediaBrowser.Model.Users;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Server.Implementations.User
|
||||
namespace Jellyfin.Server.Implementations.Users
|
||||
{
|
||||
public class UserManager : IUserManager
|
||||
{
|
||||
@@ -47,24 +49,24 @@ namespace Jellyfin.Server.Implementations.User
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public event EventHandler<GenericEventArgs<Data.Entities.User>> OnUserPasswordChanged;
|
||||
public event EventHandler<GenericEventArgs<User>> OnUserPasswordChanged;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<GenericEventArgs<Data.Entities.User>> OnUserUpdated;
|
||||
public event EventHandler<GenericEventArgs<User>> OnUserUpdated;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<GenericEventArgs<Data.Entities.User>> OnUserCreated;
|
||||
public event EventHandler<GenericEventArgs<User>> OnUserCreated;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public event EventHandler<GenericEventArgs<Data.Entities.User>> OnUserDeleted;
|
||||
public event EventHandler<GenericEventArgs<User>> OnUserDeleted;
|
||||
|
||||
public event EventHandler<GenericEventArgs<Data.Entities.User>> OnUserLockedOut;
|
||||
public event EventHandler<GenericEventArgs<User>> OnUserLockedOut;
|
||||
|
||||
public IEnumerable<Data.Entities.User> Users
|
||||
public IEnumerable<User> Users
|
||||
{
|
||||
get
|
||||
{
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
return dbContext.Users;
|
||||
}
|
||||
}
|
||||
@@ -73,37 +75,38 @@ namespace Jellyfin.Server.Implementations.User
|
||||
{
|
||||
get
|
||||
{
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
return dbContext.Users.Select(u => u.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public Data.Entities.User GetUserById(Guid id)
|
||||
public User GetUserById(Guid id)
|
||||
{
|
||||
if (id == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentException("Guid can't be empty", nameof(id));
|
||||
}
|
||||
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
|
||||
return dbContext.Users.Find(id);
|
||||
}
|
||||
|
||||
public Data.Entities.User GetUserByName(string name)
|
||||
public User GetUserByName(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new ArgumentException("Invalid username", nameof(name));
|
||||
}
|
||||
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
|
||||
return dbContext.Users.FirstOrDefault(u =>
|
||||
string.Equals(u.Username, name, StringComparison.OrdinalIgnoreCase));
|
||||
// This can't use an overload with StringComparer because that would cause the query to
|
||||
// have to be evaluated client-side.
|
||||
return dbContext.Users.FirstOrDefault(u => string.Equals(u.Username, name));
|
||||
}
|
||||
|
||||
public async Task RenameUser(Data.Entities.User user, string newName)
|
||||
public async Task RenameUser(User user, string newName)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@@ -132,43 +135,50 @@ namespace Jellyfin.Server.Implementations.User
|
||||
user.Username = newName;
|
||||
await UpdateUserAsync(user).ConfigureAwait(false);
|
||||
|
||||
OnUserUpdated?.Invoke(this, new GenericEventArgs<Data.Entities.User>(user));
|
||||
OnUserUpdated?.Invoke(this, new GenericEventArgs<User>(user));
|
||||
}
|
||||
|
||||
public void UpdateUser(Data.Entities.User user)
|
||||
public void UpdateUser(User user)
|
||||
{
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
dbContext.Users.Update(user);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public async Task UpdateUserAsync(Data.Entities.User user)
|
||||
public async Task UpdateUserAsync(User user)
|
||||
{
|
||||
await using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
dbContext.Users.Update(user);
|
||||
|
||||
await dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Data.Entities.User CreateUser(string name)
|
||||
public User CreateUser(string name)
|
||||
{
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
if (!IsValidUsername(name))
|
||||
{
|
||||
throw new ArgumentException("Usernames can contain unicode symbols, numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)");
|
||||
}
|
||||
|
||||
var newUser = CreateUserObject(name);
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
|
||||
var newUser = new User(name, _defaultAuthenticationProvider.GetType().FullName);
|
||||
dbContext.Users.Add(newUser);
|
||||
dbContext.SaveChanges();
|
||||
|
||||
OnUserCreated?.Invoke(this, new GenericEventArgs<User>(newUser));
|
||||
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public void DeleteUser(Data.Entities.User user)
|
||||
public void DeleteUser(User user)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
using var dbContext = _dbProvider.CreateContext();
|
||||
var dbContext = _dbProvider.CreateContext();
|
||||
|
||||
if (!dbContext.Users.Contains(user))
|
||||
{
|
||||
@@ -200,19 +210,20 @@ namespace Jellyfin.Server.Implementations.User
|
||||
|
||||
dbContext.Users.Remove(user);
|
||||
dbContext.SaveChanges();
|
||||
OnUserDeleted?.Invoke(this, new GenericEventArgs<User>(user));
|
||||
}
|
||||
|
||||
public Task ResetPassword(Data.Entities.User user)
|
||||
public Task ResetPassword(User user)
|
||||
{
|
||||
return ChangePassword(user, string.Empty);
|
||||
}
|
||||
|
||||
public void ResetEasyPassword(Data.Entities.User user)
|
||||
public void ResetEasyPassword(User user)
|
||||
{
|
||||
ChangeEasyPassword(user, string.Empty, null);
|
||||
}
|
||||
|
||||
public async Task ChangePassword(Data.Entities.User user, string newPassword)
|
||||
public async Task ChangePassword(User user, string newPassword)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@@ -222,24 +233,18 @@ namespace Jellyfin.Server.Implementations.User
|
||||
await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false);
|
||||
await UpdateUserAsync(user).ConfigureAwait(false);
|
||||
|
||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<Data.Entities.User>(user));
|
||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<User>(user));
|
||||
}
|
||||
|
||||
public void ChangeEasyPassword(Data.Entities.User user, string newPassword, string newPasswordSha1)
|
||||
public void ChangeEasyPassword(User user, string newPassword, string newPasswordSha1)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
GetAuthenticationProvider(user).ChangeEasyPassword(user, newPassword, newPasswordSha1);
|
||||
|
||||
UpdateUser(user);
|
||||
|
||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<Data.Entities.User>(user));
|
||||
OnUserPasswordChanged?.Invoke(this, new GenericEventArgs<User>(user));
|
||||
}
|
||||
|
||||
public UserDto GetUserDto(Data.Entities.User user, string remoteEndPoint = null)
|
||||
public UserDto GetUserDto(User user, string remoteEndPoint = null)
|
||||
{
|
||||
return new UserDto
|
||||
{
|
||||
@@ -271,7 +276,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
MaxParentalRating = user.MaxParentalAgeRating,
|
||||
EnableUserPreferenceAccess = user.EnableUserPreferenceAccess,
|
||||
RemoteClientBitrateLimit = user.RemoteClientBitrateLimit.GetValueOrDefault(),
|
||||
AuthenticatioIsnProviderId = user.AuthenticationProviderId,
|
||||
AuthenticationProviderId = user.AuthenticationProviderId,
|
||||
PasswordResetProviderId = user.PasswordResetProviderId,
|
||||
InvalidLoginAttemptCount = user.InvalidLoginAttemptCount,
|
||||
LoginAttemptsBeforeLockout = user.LoginAttemptsBeforeLockout.GetValueOrDefault(),
|
||||
@@ -306,7 +311,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
};
|
||||
}
|
||||
|
||||
public PublicUserDto GetPublicUserDto(Data.Entities.User user, string remoteEndPoint = null)
|
||||
public PublicUserDto GetPublicUserDto(User user, string remoteEndPoint = null)
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
@@ -328,7 +333,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Data.Entities.User> AuthenticateUser(
|
||||
public async Task<User> AuthenticateUser(
|
||||
string username,
|
||||
string password,
|
||||
string passwordSha1,
|
||||
@@ -341,7 +346,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
throw new ArgumentNullException(nameof(username));
|
||||
}
|
||||
|
||||
var user = Users.FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase));
|
||||
var user = Users.ToList().FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase));
|
||||
bool success;
|
||||
IAuthenticationProvider authenticationProvider;
|
||||
|
||||
@@ -370,7 +375,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
// Search the database for the user again
|
||||
// the authentication provider might have created it
|
||||
user = Users
|
||||
.FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase));
|
||||
.ToList().FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (authenticationProvider is IHasNewUserPolicy hasNewUserPolicy)
|
||||
{
|
||||
@@ -436,10 +441,10 @@ namespace Jellyfin.Server.Implementations.User
|
||||
if (isUserSession)
|
||||
{
|
||||
user.LastActivityDate = user.LastLoginDate = DateTime.UtcNow;
|
||||
UpdateUser(user);
|
||||
await UpdateUserAsync(user).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
ResetInvalidLoginAttemptCount(user);
|
||||
user.InvalidLoginAttemptCount = 0;
|
||||
_logger.LogInformation("Authentication request for {UserName} has succeeded.", user.Username);
|
||||
}
|
||||
else
|
||||
@@ -495,14 +500,11 @@ namespace Jellyfin.Server.Implementations.User
|
||||
public void AddParts(IEnumerable<IAuthenticationProvider> authenticationProviders, IEnumerable<IPasswordResetProvider> passwordResetProviders)
|
||||
{
|
||||
_authenticationProviders = authenticationProviders.ToArray();
|
||||
|
||||
_defaultAuthenticationProvider = _authenticationProviders.OfType<DefaultAuthenticationProvider>().First();
|
||||
|
||||
_invalidAuthProvider = _authenticationProviders.OfType<InvalidAuthProvider>().First();
|
||||
|
||||
_passwordResetProviders = passwordResetProviders.ToArray();
|
||||
|
||||
_defaultPasswordResetProvider = passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
||||
_invalidAuthProvider = _authenticationProviders.OfType<InvalidAuthProvider>().First();
|
||||
_defaultAuthenticationProvider = _authenticationProviders.OfType<DefaultAuthenticationProvider>().First();
|
||||
_defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
|
||||
}
|
||||
|
||||
public NameIdPair[] GetAuthenticationProviders()
|
||||
@@ -563,7 +565,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
user.MaxParentalAgeRating = policy.MaxParentalRating;
|
||||
user.EnableUserPreferenceAccess = policy.EnableUserPreferenceAccess;
|
||||
user.RemoteClientBitrateLimit = policy.RemoteClientBitrateLimit;
|
||||
user.AuthenticationProviderId = policy.AuthenticatioIsnProviderId;
|
||||
user.AuthenticationProviderId = policy.AuthenticationProviderId;
|
||||
user.PasswordResetProviderId = policy.PasswordResetProviderId;
|
||||
user.InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount;
|
||||
user.LoginAttemptsBeforeLockout = policy.LoginAttemptsBeforeLockout == -1
|
||||
@@ -604,28 +606,25 @@ namespace Jellyfin.Server.Implementations.User
|
||||
user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders);
|
||||
}
|
||||
|
||||
private Data.Entities.User CreateUserObject(string name)
|
||||
private bool IsValidUsername(string name)
|
||||
{
|
||||
return new Data.Entities.User(
|
||||
username: name,
|
||||
mustUpdatePassword: false,
|
||||
authenticationProviderId: _defaultAuthenticationProvider.GetType().FullName,
|
||||
invalidLoginAttemptCount: -1,
|
||||
subtitleMode: SubtitlePlaybackMode.Default,
|
||||
playDefaultAudioTrack: true);
|
||||
// This is some regex that matches only on unicode "word" characters, as well as -, _ and @
|
||||
// In theory this will cut out most if not all 'control' characters which should help minimize any weirdness
|
||||
// Usernames can contain letters (a-z + whatever else unicode is cool with), numbers (0-9), at-signs (@), dashes (-), underscores (_), apostrophes ('), and periods (.)
|
||||
return Regex.IsMatch(name, @"^[\w\-'._@]*$");
|
||||
}
|
||||
|
||||
private IAuthenticationProvider GetAuthenticationProvider(Data.Entities.User user)
|
||||
private IAuthenticationProvider GetAuthenticationProvider(User user)
|
||||
{
|
||||
return GetAuthenticationProviders(user)[0];
|
||||
}
|
||||
|
||||
private IPasswordResetProvider GetPasswordResetProvider(Data.Entities.User user)
|
||||
private IPasswordResetProvider GetPasswordResetProvider(User user)
|
||||
{
|
||||
return GetPasswordResetProviders(user)[0];
|
||||
}
|
||||
|
||||
private IList<IAuthenticationProvider> GetAuthenticationProviders(Data.Entities.User user)
|
||||
private IList<IAuthenticationProvider> GetAuthenticationProviders(User user)
|
||||
{
|
||||
var authenticationProviderId = user?.AuthenticationProviderId;
|
||||
|
||||
@@ -640,7 +639,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
{
|
||||
// Assign the user to the InvalidAuthProvider since no configured auth provider was valid/found
|
||||
_logger.LogWarning(
|
||||
"User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected",
|
||||
"User {Username} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected",
|
||||
user?.Username,
|
||||
user?.AuthenticationProviderId);
|
||||
providers = new List<IAuthenticationProvider>
|
||||
@@ -652,7 +651,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
return providers;
|
||||
}
|
||||
|
||||
private IList<IPasswordResetProvider> GetPasswordResetProviders(Data.Entities.User user)
|
||||
private IList<IPasswordResetProvider> GetPasswordResetProviders(User user)
|
||||
{
|
||||
var passwordResetProviderId = user?.PasswordResetProviderId;
|
||||
var providers = _passwordResetProviders.Where(i => i.IsEnabled).ToArray();
|
||||
@@ -675,11 +674,10 @@ namespace Jellyfin.Server.Implementations.User
|
||||
return providers;
|
||||
}
|
||||
|
||||
private async Task<(IAuthenticationProvider authenticationProvider, string username, bool success)>
|
||||
AuthenticateLocalUser(
|
||||
private async Task<(IAuthenticationProvider authenticationProvider, string username, bool success)> AuthenticateLocalUser(
|
||||
string username,
|
||||
string password,
|
||||
Jellyfin.Data.Entities.User user,
|
||||
User user,
|
||||
string remoteEndPoint)
|
||||
{
|
||||
bool success = false;
|
||||
@@ -721,7 +719,7 @@ namespace Jellyfin.Server.Implementations.User
|
||||
IAuthenticationProvider provider,
|
||||
string username,
|
||||
string password,
|
||||
Data.Entities.User resolvedUser)
|
||||
User resolvedUser)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -745,27 +743,21 @@ namespace Jellyfin.Server.Implementations.User
|
||||
}
|
||||
}
|
||||
|
||||
private void IncrementInvalidLoginAttemptCount(Data.Entities.User user)
|
||||
private void IncrementInvalidLoginAttemptCount(User user)
|
||||
{
|
||||
int invalidLogins = user.InvalidLoginAttemptCount;
|
||||
int? maxInvalidLogins = user.LoginAttemptsBeforeLockout;
|
||||
if (maxInvalidLogins.HasValue
|
||||
&& invalidLogins >= maxInvalidLogins)
|
||||
if (maxInvalidLogins.HasValue && invalidLogins >= maxInvalidLogins)
|
||||
{
|
||||
user.SetPermission(PermissionKind.IsDisabled, true);
|
||||
OnUserLockedOut?.Invoke(this, new GenericEventArgs<Data.Entities.User>(user));
|
||||
OnUserLockedOut?.Invoke(this, new GenericEventArgs<User>(user));
|
||||
_logger.LogWarning(
|
||||
"Disabling user {UserName} due to {Attempts} unsuccessful login attempts.",
|
||||
"Disabling user {Username} due to {Attempts} unsuccessful login attempts.",
|
||||
user.Username,
|
||||
invalidLogins);
|
||||
}
|
||||
|
||||
UpdateUser(user);
|
||||
}
|
||||
|
||||
private void ResetInvalidLoginAttemptCount(Data.Entities.User user)
|
||||
{
|
||||
user.InvalidLoginAttemptCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user