aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.devcontainer/devcontainer.json8
-rw-r--r--.vscode/settings.json3
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs9
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj1
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthService.cs1
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs1
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs1
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs1
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs21
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs1
-rw-r--r--Emby.Server.Implementations/TV/TVSeriesManager.cs1
-rw-r--r--Jellyfin.Api/Auth/CustomAuthenticationHandler.cs1
-rw-r--r--Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs1
-rw-r--r--Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs1
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs1
-rw-r--r--Jellyfin.Api/Helpers/MediaInfoHelper.cs1
-rw-r--r--Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs1
-rw-r--r--Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs1
-rw-r--r--Jellyfin.Data/Interfaces/IHasPermissions.cs31
-rw-r--r--Jellyfin.Data/Jellyfin.Data.csproj4
-rw-r--r--Jellyfin.Data/UserEntityExtensions.cs220
-rw-r--r--Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationFactory.cs17
-rw-r--r--Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationStore.cs25
-rw-r--r--Jellyfin.Server.Implementations/Devices/DeviceManager.cs1
-rw-r--r--Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs74
-rw-r--r--Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj11
-rw-r--r--Jellyfin.Server.Implementations/Users/DeviceAccessHost.cs1
-rw-r--r--Jellyfin.Server.Implementations/Users/UserManager.cs11
-rw-r--r--Jellyfin.Server/CoreAppHost.cs6
-rw-r--r--Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs2
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj1
-rw-r--r--Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs19
-rw-r--r--Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs1
-rw-r--r--Jellyfin.Server/Program.cs22
-rw-r--r--Jellyfin.Server/Startup.cs7
-rw-r--r--Jellyfin.sln23
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs1
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs1
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs1
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs2
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs1
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs1
-rw-r--r--MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs1
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs14
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AccessSchedule.cs (renamed from Jellyfin.Data/Entities/AccessSchedule.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ActivityLog.cs (renamed from Jellyfin.Data/Entities/ActivityLog.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AncestorId.cs (renamed from Jellyfin.Data/Entities/AncestorId.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AttachmentStreamInfo.cs (renamed from Jellyfin.Data/Entities/AttachmentStreamInfo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs (renamed from Jellyfin.Data/Entities/BaseItemEntity.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemExtraType.cs (renamed from Jellyfin.Data/Entities/BaseItemExtraType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemImageInfo.cs (renamed from Jellyfin.Data/Entities/BaseItemImageInfo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemMetadataField.cs (renamed from Jellyfin.Data/Entities/BaseItemMetadataField.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemProvider.cs (renamed from Jellyfin.Data/Entities/BaseItemProvider.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTrailerType.cs (renamed from Jellyfin.Data/Entities/BaseItemTrailerType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Chapter.cs (renamed from Jellyfin.Data/Entities/Chapter.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/CustomItemDisplayPreferences.cs (renamed from Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/DisplayPreferences.cs (renamed from Jellyfin.Data/Entities/DisplayPreferences.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Group.cs (renamed from Jellyfin.Data/Entities/Group.cs)12
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/HomeSection.cs (renamed from Jellyfin.Data/Entities/HomeSection.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfo.cs (renamed from Jellyfin.Data/Entities/ImageInfo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfoImageType.cs (renamed from Jellyfin.Data/Entities/ImageInfoImageType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemDisplayPreferences.cs (renamed from Jellyfin.Data/Entities/ItemDisplayPreferences.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValue.cs (renamed from Jellyfin.Data/Entities/ItemValue.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueMap.cs (renamed from Jellyfin.Data/Entities/ItemValueMap.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueType.cs (renamed from Jellyfin.Data/Entities/ItemValueType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Artwork.cs (renamed from Jellyfin.Data/Entities/Libraries/Artwork.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Book.cs (renamed from Jellyfin.Data/Entities/Libraries/Book.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/BookMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/BookMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Chapter.cs (renamed from Jellyfin.Data/Entities/Libraries/Chapter.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Collection.cs (renamed from Jellyfin.Data/Entities/Libraries/Collection.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CollectionItem.cs (renamed from Jellyfin.Data/Entities/Libraries/CollectionItem.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Company.cs (renamed from Jellyfin.Data/Entities/Libraries/Company.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CompanyMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItem.cs (renamed from Jellyfin.Data/Entities/Libraries/CustomItem.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItemMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Episode.cs (renamed from Jellyfin.Data/Entities/Libraries/Episode.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/EpisodeMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Genre.cs (renamed from Jellyfin.Data/Entities/Libraries/Genre.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/ItemMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/ItemMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Library.cs (renamed from Jellyfin.Data/Entities/Libraries/Library.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/LibraryItem.cs (renamed from Jellyfin.Data/Entities/Libraries/LibraryItem.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFile.cs (renamed from Jellyfin.Data/Entities/Libraries/MediaFile.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFileStream.cs (renamed from Jellyfin.Data/Entities/Libraries/MediaFileStream.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProvider.cs (renamed from Jellyfin.Data/Entities/Libraries/MetadataProvider.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProviderId.cs (renamed from Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Movie.cs (renamed from Jellyfin.Data/Entities/Libraries/Movie.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MovieMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/MovieMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbum.cs (renamed from Jellyfin.Data/Entities/Libraries/MusicAlbum.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbumMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Person.cs (renamed from Jellyfin.Data/Entities/Libraries/Person.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PersonRole.cs (renamed from Jellyfin.Data/Entities/Libraries/PersonRole.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Photo.cs (renamed from Jellyfin.Data/Entities/Libraries/Photo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PhotoMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Rating.cs (renamed from Jellyfin.Data/Entities/Libraries/Rating.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/RatingSource.cs (renamed from Jellyfin.Data/Entities/Libraries/RatingSource.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Release.cs (renamed from Jellyfin.Data/Entities/Libraries/Release.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Season.cs (renamed from Jellyfin.Data/Entities/Libraries/Season.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeasonMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Series.cs (renamed from Jellyfin.Data/Entities/Libraries/Series.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeriesMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Track.cs (renamed from Jellyfin.Data/Entities/Libraries/Track.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/TrackMetadata.cs (renamed from Jellyfin.Data/Entities/Libraries/TrackMetadata.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaSegment.cs (renamed from Jellyfin.Data/Entities/MediaSegment.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamInfo.cs (renamed from Jellyfin.Data/Entities/MediaStreamInfo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamTypeEntity.cs (renamed from Jellyfin.Data/Entities/MediaStreamTypeEntity.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/People.cs (renamed from Jellyfin.Data/Entities/People.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/PeopleBaseItemMap.cs (renamed from Jellyfin.Data/Entities/PeopleBaseItemMap.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Permission.cs (renamed from Jellyfin.Data/Entities/Permission.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Preference.cs (renamed from Jellyfin.Data/Entities/Preference.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ProgramAudioEntity.cs (renamed from Jellyfin.Data/Entities/ProgramAudioEntity.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/ApiKey.cs (renamed from Jellyfin.Data/Entities/Security/ApiKey.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/Device.cs (renamed from Jellyfin.Data/Entities/Security/Device.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/DeviceOptions.cs (renamed from Jellyfin.Data/Entities/Security/DeviceOptions.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/TrickplayInfo.cs (renamed from Jellyfin.Data/Entities/TrickplayInfo.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/User.cs (renamed from Jellyfin.Data/Entities/User.cs)196
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/UserData.cs (renamed from Jellyfin.Data/Entities/UserData.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ArtKind.cs (renamed from Jellyfin.Data/Enums/ArtKind.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ChromecastVersion.cs (renamed from Jellyfin.Data/Enums/ChromecastVersion.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/DynamicDayOfWeek.cs (renamed from Jellyfin.Data/Enums/DynamicDayOfWeek.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/HomeSectionType.cs (renamed from Jellyfin.Data/Enums/HomeSectionType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/IndexingKind.cs (renamed from Jellyfin.Data/Enums/IndexingKind.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaFileKind.cs (renamed from Jellyfin.Data/Enums/MediaFileKind.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaSegmentType.cs (renamed from Jellyfin.Data/Enums/MediaSegmentType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PermissionKind.cs (renamed from Jellyfin.Data/Enums/PermissionKind.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PersonRoleType.cs (renamed from Jellyfin.Data/Enums/PersonRoleType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PreferenceKind.cs (renamed from Jellyfin.Data/Enums/PreferenceKind.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ScrollDirection.cs (renamed from Jellyfin.Data/Enums/ScrollDirection.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SortOrder.cs (renamed from Jellyfin.Data/Enums/SortOrder.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SubtitlePlaybackMode.cs (renamed from Jellyfin.Data/Enums/SubtitlePlaybackMode.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SyncPlayUserAccessType.cs (renamed from Jellyfin.Data/Enums/SyncPlayUserAccessType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ViewType.cs (renamed from Jellyfin.Data/Enums/ViewType.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs49
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasArtwork.cs (renamed from Jellyfin.Data/Interfaces/IHasArtwork.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasCompanies.cs (renamed from Jellyfin.Data/Interfaces/IHasCompanies.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasConcurrencyToken.cs (renamed from Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasPermissions.cs17
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasReleases.cs (renamed from Jellyfin.Data/Interfaces/IHasReleases.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/Jellyfin.Database.Implementations.csproj25
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDatabaseProviderKeyAttribute.cs29
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs (renamed from Jellyfin.Server.Implementations/JellyfinDbContext.cs)23
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/ActivityLogConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/AncestorIdConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/ApiKeyConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs)2
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs)4
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs)4
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/ChapterConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/DeviceConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/PeopleConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/PermissionConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/PreferenceConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/UserConfiguration.cs)3
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs (renamed from Jellyfin.Server.Implementations/ModelConfiguration/UserDataConfiguration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs20
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj37
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes (renamed from Jellyfin.Server.Implementations/Migrations/.gitattributes)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs (renamed from Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs (renamed from Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs (renamed from Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs (renamed from Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs (renamed from Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs (renamed from Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs (renamed from Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs (renamed from Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs (renamed from Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs1594
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs40
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs (renamed from Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs (renamed from Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.Designer.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs (renamed from Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs (renamed from Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs)3
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs (renamed from Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs)10
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs (renamed from Jellyfin.Server.Implementations/ModelBuilderExtensions.cs)0
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs23
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs87
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs (renamed from Jellyfin.Server.Implementations/ValueConverters/DateTimeKindValueConverter.cs)0
-rw-r--r--src/Jellyfin.Database/readme.md25
-rw-r--r--src/Jellyfin.LiveTv/LiveTvManager.cs1
-rw-r--r--src/Jellyfin.LiveTv/Recordings/RecordingNotifier.cs1
-rw-r--r--tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs1
-rw-r--r--tests/Jellyfin.Api.Tests/TestHelpers.cs1
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs8
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj1
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs3
236 files changed, 2429 insertions, 349 deletions
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 228d4a17c8..c2127ba5c3 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,6 +1,8 @@
{
"name": "Development Jellyfin Server",
- "image":"mcr.microsoft.com/devcontainers/dotnet:9.0-bookworm",
+ "image": "mcr.microsoft.com/devcontainers/dotnet:9.0-bookworm",
+ "service": "app",
+ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
// restores nuget packages, installs the dotnet workloads and installs the dev https certificate
"postStartCommand": "sudo dotnet restore; sudo dotnet workload update; sudo dotnet dev-certs https --trust; sudo bash \"./.devcontainer/install-ffmpeg.sh\"",
// reads the extensions list and installs them
@@ -13,7 +15,9 @@
},
"ghcr.io/devcontainers-contrib/features/apt-packages:1": {
"preserve_apt_list": false,
- "packages": ["libfontconfig1"]
+ "packages": [
+ "libfontconfig1"
+ ]
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"dockerDashComposeVersion": "v2"
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000..6733d59aca
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "dotnet.preferVisualStudioCodeFileSystemWatcher": true
+}
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 4fe1d2b17e..6e8a9fc204 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -574,10 +574,15 @@ namespace Emby.Server.Implementations
/// <summary>
/// Create services registered with the service container that need to be initialized at application startup.
/// </summary>
+ /// <param name="startupConfig">The configuration used to initialise the application.</param>
/// <returns>A task representing the service initialization operation.</returns>
- public async Task InitializeServices()
+ public async Task InitializeServices(IConfiguration startupConfig)
{
- var jellyfinDb = await Resolve<IDbContextFactory<JellyfinDbContext>>().CreateDbContextAsync().ConfigureAwait(false);
+ var factory = Resolve<IDbContextFactory<JellyfinDbContext>>();
+ var provider = Resolve<IJellyfinDatabaseProvider>();
+ provider.DbContextFactory = factory;
+
+ var jellyfinDb = await factory.CreateDbContextAsync().ConfigureAwait(false);
await using (jellyfinDb.ConfigureAwait(false))
{
if ((await jellyfinDb.Database.GetPendingMigrationsAsync().ConfigureAwait(false)).Any())
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 70dd5eb9ae..8f89f35ac9 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -18,6 +18,7 @@
<ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" />
<ProjectReference Include="..\src\Jellyfin.Drawing\Jellyfin.Drawing.csproj" />
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
</ItemGroup>
<ItemGroup>
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index 1d04f3da37..82945a4f62 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Net;
using Microsoft.AspNetCore.Http;
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index b810ad4de1..b0003ed414 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -18,6 +18,7 @@ using Emby.Server.Implementations.Library.Validators;
using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.ScheduledTasks.Tasks;
using Emby.Server.Implementations.Sorting;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 92a5e9ffd9..3e71b2fcde 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -13,6 +13,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using AsyncKeyedLock;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index d42a0e7d28..2560466c10 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
index 7d4e2377dc..05223d28ae 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
@@ -18,6 +18,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
private readonly ILogger<OptimizeDatabaseTask> _logger;
private readonly ILocalizationManager _localization;
private readonly IDbContextFactory<JellyfinDbContext> _provider;
+ private readonly IJellyfinDatabaseProvider _jellyfinDatabaseProvider;
/// <summary>
/// Initializes a new instance of the <see cref="OptimizeDatabaseTask" /> class.
@@ -25,14 +26,17 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
/// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
/// <param name="provider">Instance of the <see cref="IDbContextFactory{JellyfinDbContext}"/> interface.</param>
+ /// <param name="jellyfinDatabaseProvider">Instance of the JellyfinDatabaseProvider that can be used for provider specific operations.</param>
public OptimizeDatabaseTask(
ILogger<OptimizeDatabaseTask> logger,
ILocalizationManager localization,
- IDbContextFactory<JellyfinDbContext> provider)
+ IDbContextFactory<JellyfinDbContext> provider,
+ IJellyfinDatabaseProvider jellyfinDatabaseProvider)
{
_logger = logger;
_localization = localization;
_provider = provider;
+ _jellyfinDatabaseProvider = jellyfinDatabaseProvider;
}
/// <inheritdoc />
@@ -73,20 +77,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
try
{
- var context = await _provider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
- await using (context.ConfigureAwait(false))
- {
- if (context.Database.IsSqlite())
- {
- await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
- _logger.LogInformation("jellyfin.db optimized successfully!");
- }
- else
- {
- _logger.LogInformation("This database doesn't support optimization");
- }
- }
+ await _jellyfinDatabaseProvider.RunScheduledOptimisation(cancellationToken).ConfigureAwait(false);
}
catch (Exception e)
{
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index df2acfc46c..dc37c4f2a2 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -7,6 +7,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Enums;
diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs
index 10d27498bf..270c1b4411 100644
--- a/Emby.Server.Implementations/TV/TVSeriesManager.cs
+++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
index 1286c92c7a..0fd0149904 100644
--- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
+++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
@@ -3,6 +3,7 @@ using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
diff --git a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
index 4928d5ed24..07dedb017a 100644
--- a/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
+++ b/Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
diff --git a/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
index f20779f6cd..d139eab16f 100644
--- a/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
+++ b/Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
+using Jellyfin.Data;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Library;
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index ed2f49b864..e6fe7df79c 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -4,6 +4,7 @@ using System.Linq;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index d7886d247f..838578fab8 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -7,6 +7,7 @@ using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.UserDtos;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Api;
diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
index 4adda0b695..2c45789d34 100644
--- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs
+++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
@@ -7,6 +7,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Extensions;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
index 97f827fde0..e2e7b0cb5a 100644
--- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Authentication;
diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
index 6cbab6571e..cc0792477e 100644
--- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Library;
diff --git a/Jellyfin.Data/Interfaces/IHasPermissions.cs b/Jellyfin.Data/Interfaces/IHasPermissions.cs
deleted file mode 100644
index bf8ec9d887..0000000000
--- a/Jellyfin.Data/Interfaces/IHasPermissions.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System.Collections.Generic;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Enums;
-
-namespace Jellyfin.Data.Interfaces
-{
- /// <summary>
- /// An abstraction representing an entity that has permissions.
- /// </summary>
- public interface IHasPermissions
- {
- /// <summary>
- /// Gets a collection containing this entity's permissions.
- /// </summary>
- ICollection<Permission> Permissions { get; }
-
- /// <summary>
- /// Checks whether this entity has the specified permission kind.
- /// </summary>
- /// <param name="kind">The kind of permission.</param>
- /// <returns><c>true</c> if this entity has the specified permission, <c>false</c> otherwise.</returns>
- bool HasPermission(PermissionKind kind);
-
- /// <summary>
- /// Sets the specified permission to the provided value.
- /// </summary>
- /// <param name="kind">The kind of permission.</param>
- /// <param name="value">The value to set.</param>
- void SetPermission(PermissionKind kind, bool value);
- }
-}
diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj
index 921cf2d8c1..45374c22f7 100644
--- a/Jellyfin.Data/Jellyfin.Data.csproj
+++ b/Jellyfin.Data/Jellyfin.Data.csproj
@@ -39,6 +39,10 @@
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" />
</ItemGroup>
diff --git a/Jellyfin.Data/UserEntityExtensions.cs b/Jellyfin.Data/UserEntityExtensions.cs
new file mode 100644
index 0000000000..8d84a6b6e1
--- /dev/null
+++ b/Jellyfin.Data/UserEntityExtensions.cs
@@ -0,0 +1,220 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
+using Jellyfin.Data.Interfaces;
+
+namespace Jellyfin.Data;
+
+/// <summary>
+/// Contains extension methods for manipulation of <see cref="User"/> entities.
+/// </summary>
+public static class UserEntityExtensions
+{
+ /// <summary>
+ /// The values being delimited here are Guids, so commas work as they do not appear in Guids.
+ /// </summary>
+ private const char Delimiter = ',';
+
+ /// <summary>
+ /// Checks whether the user has the specified permission.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="kind">The permission kind.</param>
+ /// <returns><c>True</c> if the user has the specified permission.</returns>
+ public static bool HasPermission(this IHasPermissions entity, PermissionKind kind)
+ {
+ return entity.Permissions.FirstOrDefault(p => p.Kind == kind)?.Value ?? false;
+ }
+
+ /// <summary>
+ /// Sets the given permission kind to the provided value.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="kind">The permission kind.</param>
+ /// <param name="value">The value to set.</param>
+ public static void SetPermission(this IHasPermissions entity, PermissionKind kind, bool value)
+ {
+ var currentPermission = entity.Permissions.FirstOrDefault(p => p.Kind == kind);
+ if (currentPermission is null)
+ {
+ entity.Permissions.Add(new Permission(kind, value));
+ }
+ else
+ {
+ currentPermission.Value = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the user's preferences for the given preference kind.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="preference">The preference kind.</param>
+ /// <returns>A string array containing the user's preferences.</returns>
+ public static string[] GetPreference(this User entity, PreferenceKind preference)
+ {
+ var val = entity.Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
+
+ return string.IsNullOrEmpty(val) ? Array.Empty<string>() : val.Split(Delimiter);
+ }
+
+ /// <summary>
+ /// Gets the user's preferences for the given preference kind.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="preference">The preference kind.</param>
+ /// <typeparam name="T">Type of preference.</typeparam>
+ /// <returns>A {T} array containing the user's preference.</returns>
+ public static T[] GetPreferenceValues<T>(this User entity, PreferenceKind preference)
+ {
+ var val = entity.Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
+ if (string.IsNullOrEmpty(val))
+ {
+ return Array.Empty<T>();
+ }
+
+ // Convert array of {string} to array of {T}
+ var converter = TypeDescriptor.GetConverter(typeof(T));
+ var stringValues = val.Split(Delimiter);
+ var convertedCount = 0;
+ var parsedValues = new T[stringValues.Length];
+ for (var i = 0; i < stringValues.Length; i++)
+ {
+ try
+ {
+ var parsedValue = converter.ConvertFromString(stringValues[i].Trim());
+ if (parsedValue is not null)
+ {
+ parsedValues[convertedCount++] = (T)parsedValue;
+ }
+ }
+ catch (FormatException)
+ {
+ // Unable to convert value
+ }
+ }
+
+ return parsedValues[..convertedCount];
+ }
+
+ /// <summary>
+ /// Sets the specified preference to the given value.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="preference">The preference kind.</param>
+ /// <param name="values">The values.</param>
+ public static void SetPreference(this User entity, PreferenceKind preference, string[] values)
+ {
+ var value = string.Join(Delimiter, values);
+ var currentPreference = entity.Preferences.FirstOrDefault(p => p.Kind == preference);
+ if (currentPreference is null)
+ {
+ entity.Preferences.Add(new Preference(preference, value));
+ }
+ else
+ {
+ currentPreference.Value = value;
+ }
+ }
+
+ /// <summary>
+ /// Sets the specified preference to the given value.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="preference">The preference kind.</param>
+ /// <param name="values">The values.</param>
+ /// <typeparam name="T">The type of value.</typeparam>
+ public static void SetPreference<T>(this User entity, PreferenceKind preference, T[] values)
+ {
+ var value = string.Join(Delimiter, values);
+ var currentPreference = entity.Preferences.FirstOrDefault(p => p.Kind == preference);
+ if (currentPreference is null)
+ {
+ entity.Preferences.Add(new Preference(preference, value));
+ }
+ else
+ {
+ currentPreference.Value = value;
+ }
+ }
+
+ /// <summary>
+ /// Checks whether this user is currently allowed to use the server.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <returns><c>True</c> if the current time is within an access schedule, or there are no access schedules.</returns>
+ public static bool IsParentalScheduleAllowed(this User entity)
+ {
+ return entity.AccessSchedules.Count == 0
+ || entity.AccessSchedules.Any(i => IsParentalScheduleAllowed(i, DateTime.UtcNow));
+ }
+
+ /// <summary>
+ /// Checks whether the provided folder is in this user's grouped folders.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ /// <param name="id">The Guid of the folder.</param>
+ /// <returns><c>True</c> if the folder is in the user's grouped folders.</returns>
+ public static bool IsFolderGrouped(this User entity, Guid id)
+ {
+ return Array.IndexOf(GetPreferenceValues<Guid>(entity, PreferenceKind.GroupedFolders), id) != -1;
+ }
+
+ /// <summary>
+ /// Initializes the default permissions for a user. Should only be called on user creation.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ // TODO: make these user configurable?
+ public static void AddDefaultPermissions(this User entity)
+ {
+ entity.Permissions.Add(new Permission(PermissionKind.IsAdministrator, false));
+ entity.Permissions.Add(new Permission(PermissionKind.IsDisabled, false));
+ entity.Permissions.Add(new Permission(PermissionKind.IsHidden, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableAllChannels, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableAllDevices, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableAllFolders, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableContentDeletion, false));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableContentDownloading, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableMediaConversion, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableMediaPlayback, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnablePlaybackRemuxing, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnablePublicSharing, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableRemoteAccess, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableSyncTranscoding, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableAudioPlaybackTranscoding, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableLiveTvAccess, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableLiveTvManagement, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableSharedDeviceControl, true));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableVideoPlaybackTranscoding, true));
+ entity.Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableCollectionManagement, false));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableSubtitleManagement, false));
+ entity.Permissions.Add(new Permission(PermissionKind.EnableLyricManagement, false));
+ }
+
+ /// <summary>
+ /// Initializes the default preferences. Should only be called on user creation.
+ /// </summary>
+ /// <param name="entity">The entity to update.</param>
+ public static void AddDefaultPreferences(this User entity)
+ {
+ foreach (var val in Enum.GetValues<PreferenceKind>())
+ {
+ entity.Preferences.Add(new Preference(val, string.Empty));
+ }
+ }
+
+ private static bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
+ {
+ var localTime = date.ToLocalTime();
+ var hour = localTime.TimeOfDay.TotalHours;
+ var currentDayOfWeek = localTime.DayOfWeek;
+
+ return schedule.DayOfWeek.Contains(currentDayOfWeek)
+ && hour >= schedule.StartHour
+ && hour <= schedule.EndHour;
+ }
+}
diff --git a/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationFactory.cs b/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationFactory.cs
new file mode 100644
index 0000000000..26d32f4173
--- /dev/null
+++ b/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationFactory.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
+
+namespace Jellyfin.Server.Implementations.DatabaseConfiguration;
+
+/// <summary>
+/// Factory for constructing a database configuration.
+/// </summary>
+public class DatabaseConfigurationFactory : IConfigurationFactory
+{
+ /// <inheritdoc/>
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ yield return new DatabaseConfigurationStore();
+ }
+}
diff --git a/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationStore.cs b/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationStore.cs
new file mode 100644
index 0000000000..180561fc84
--- /dev/null
+++ b/Jellyfin.Server.Implementations/DbConfiguration/DatabaseConfigurationStore.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
+
+namespace Jellyfin.Server.Implementations.DatabaseConfiguration;
+
+/// <summary>
+/// A configuration that stores database related settings.
+/// </summary>
+public class DatabaseConfigurationStore : ConfigurationStore
+{
+ /// <summary>
+ /// The name of the configuration in the storage.
+ /// </summary>
+ public const string StoreKey = "database";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DatabaseConfigurationStore"/> class.
+ /// </summary>
+ public DatabaseConfigurationStore()
+ {
+ ConfigurationType = typeof(DatabaseConfigurationOptions);
+ Key = StoreKey;
+ }
+}
diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
index d3bff2936c..1b4048b8e6 100644
--- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
+++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Dtos;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Entities.Security;
diff --git a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
index 7eee260593..b0e4567a78 100644
--- a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
+++ b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
@@ -1,8 +1,14 @@
using System;
-using System.IO;
+using System.Collections.Generic;
+using System.Reflection;
+using Jellyfin.Database.Providers.Sqlite;
+using Jellyfin.Server.Implementations.DatabaseConfiguration;
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Configuration;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using JellyfinDbProviderFactory = System.Func<System.IServiceProvider, Jellyfin.Server.Implementations.IJellyfinDatabaseProvider>;
namespace Jellyfin.Server.Implementations.Extensions;
@@ -11,17 +17,77 @@ namespace Jellyfin.Server.Implementations.Extensions;
/// </summary>
public static class ServiceCollectionExtensions
{
+ private static IEnumerable<Type> DatabaseProviderTypes()
+ {
+ yield return typeof(SqliteDatabaseProvider);
+ }
+
+ private static IDictionary<string, JellyfinDbProviderFactory> GetSupportedDbProviders()
+ {
+ var items = new Dictionary<string, JellyfinDbProviderFactory>(StringComparer.InvariantCultureIgnoreCase);
+ foreach (var providerType in DatabaseProviderTypes())
+ {
+ var keyAttribute = providerType.GetCustomAttribute<JellyfinDatabaseProviderKeyAttribute>();
+ if (keyAttribute is null || string.IsNullOrWhiteSpace(keyAttribute.DatabaseProviderKey))
+ {
+ continue;
+ }
+
+ var provider = providerType;
+ items[keyAttribute.DatabaseProviderKey] = (services) => (IJellyfinDatabaseProvider)ActivatorUtilities.CreateInstance(services, providerType);
+ }
+
+ return items;
+ }
+
/// <summary>
/// Adds the <see cref="IDbContextFactory{TContext}"/> interface to the service collection with second level caching enabled.
/// </summary>
/// <param name="serviceCollection">An instance of the <see cref="IServiceCollection"/> interface.</param>
+ /// <param name="configurationManager">The server configuration manager.</param>
+ /// <param name="configuration">The startup Configuration.</param>
/// <returns>The updated service collection.</returns>
- public static IServiceCollection AddJellyfinDbContext(this IServiceCollection serviceCollection)
+ public static IServiceCollection AddJellyfinDbContext(
+ this IServiceCollection serviceCollection,
+ IServerConfigurationManager configurationManager,
+ IConfiguration configuration)
{
+ var efCoreConfiguration = configurationManager.GetConfiguration<DatabaseConfigurationOptions>("database");
+ var providers = GetSupportedDbProviders();
+ JellyfinDbProviderFactory? providerFactory = null;
+
+ if (efCoreConfiguration?.DatabaseType is null)
+ {
+ var cmdMigrationArgument = configuration.GetValue<string>("migration-provider");
+ if (!string.IsNullOrWhiteSpace(cmdMigrationArgument))
+ {
+ efCoreConfiguration = new DatabaseConfigurationOptions()
+ {
+ DatabaseType = cmdMigrationArgument,
+ };
+ }
+ else
+ {
+ // when nothing is setup via new Database configuration, fallback to SQLite with default settings.
+ efCoreConfiguration = new DatabaseConfigurationOptions()
+ {
+ DatabaseType = "Jellyfin-SQLite",
+ };
+ configurationManager.SaveConfiguration("database", efCoreConfiguration);
+ }
+ }
+
+ if (!providers.TryGetValue(efCoreConfiguration.DatabaseType.ToUpperInvariant(), out providerFactory!))
+ {
+ throw new InvalidOperationException($"Jellyfin cannot find the database provider of type '{efCoreConfiguration.DatabaseType}'. Supported types are {string.Join(", ", providers.Keys)}");
+ }
+
+ serviceCollection.AddSingleton<IJellyfinDatabaseProvider>(providerFactory!);
+
serviceCollection.AddPooledDbContextFactory<JellyfinDbContext>((serviceProvider, opt) =>
{
- var applicationPaths = serviceProvider.GetRequiredService<IApplicationPaths>();
- opt.UseSqlite($"Filename={Path.Combine(applicationPaths.DataPath, "jellyfin.db")};Pooling=false");
+ var provider = serviceProvider.GetRequiredService<IJellyfinDatabaseProvider>();
+ provider.Initialise(opt);
});
return serviceCollection;
diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
index 31cf24fb2d..6693ab8dbd 100644
--- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
+++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
@@ -28,22 +28,15 @@
<ItemGroup>
<PackageReference Include="AsyncKeyedLock" />
<PackageReference Include="System.Linq.Async" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
- <PackageReference Include="Microsoft.EntityFrameworkCore.Design">
- <PrivateAssets>all</PrivateAssets>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
- <PrivateAssets>all</PrivateAssets>
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- </PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jellyfin.Data\Jellyfin.Data.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Jellyfin.Database.Providers.Sqlite.csproj" />
</ItemGroup>
</Project>
diff --git a/Jellyfin.Server.Implementations/Users/DeviceAccessHost.cs b/Jellyfin.Server.Implementations/Users/DeviceAccessHost.cs
index 45b0a0853e..27222a183c 100644
--- a/Jellyfin.Server.Implementations/Users/DeviceAccessHost.cs
+++ b/Jellyfin.Server.Implementations/Users/DeviceAccessHost.cs
@@ -1,5 +1,6 @@
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs
index fba8923f89..79fa70c0b2 100644
--- a/Jellyfin.Server.Implementations/Users/UserManager.cs
+++ b/Jellyfin.Server.Implementations/Users/UserManager.cs
@@ -7,6 +7,7 @@ using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
@@ -146,7 +147,7 @@ namespace Jellyfin.Server.Implementations.Users
ThrowIfInvalidUsername(newName);
- if (user.Username.Equals(newName, StringComparison.Ordinal))
+ if (user.Username.Equals(newName, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("The new and old names must be different.");
}
@@ -154,8 +155,11 @@ namespace Jellyfin.Server.Implementations.Users
var dbContext = await _dbProvider.CreateDbContextAsync().ConfigureAwait(false);
await using (dbContext.ConfigureAwait(false))
{
+#pragma warning disable CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons
+#pragma warning disable CA1311 // Specify a culture or use an invariant version to avoid implicit dependency on current culture
+#pragma warning disable CA1304 // The behavior of 'string.ToUpper()' could vary based on the current user's locale settings
if (await dbContext.Users
- .AnyAsync(u => u.Username == newName && !u.Id.Equals(user.Id))
+ .AnyAsync(u => u.Username.ToUpper() == newName.ToUpper() && !u.Id.Equals(user.Id))
.ConfigureAwait(false))
{
throw new ArgumentException(string.Format(
@@ -163,6 +167,9 @@ namespace Jellyfin.Server.Implementations.Users
"A user with the name '{0}' already exists.",
newName));
}
+#pragma warning restore CA1304 // The behavior of 'string.ToUpper()' could vary based on the current user's locale settings
+#pragma warning restore CA1311 // Specify a culture or use an invariant version to avoid implicit dependency on current culture
+#pragma warning restore CA1862 // Use the 'StringComparison' method overloads to perform case-insensitive string comparisons
user.Username = newName;
await UpdateUserInternalAsync(dbContext, user).ConfigureAwait(false);
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs
index d5b6e93b8e..9788119a54 100644
--- a/Jellyfin.Server/CoreAppHost.cs
+++ b/Jellyfin.Server/CoreAppHost.cs
@@ -11,6 +11,7 @@ using Jellyfin.Server.Implementations;
using Jellyfin.Server.Implementations.Activity;
using Jellyfin.Server.Implementations.Devices;
using Jellyfin.Server.Implementations.Events;
+using Jellyfin.Server.Implementations.Extensions;
using Jellyfin.Server.Implementations.Security;
using Jellyfin.Server.Implementations.Trickplay;
using Jellyfin.Server.Implementations.Users;
@@ -116,9 +117,12 @@ namespace Jellyfin.Server
// Jellyfin.Server
yield return typeof(CoreAppHost).Assembly;
- // Jellyfin.Server.Implementations
+ // Jellyfin.Database.Implementations
yield return typeof(JellyfinDbContext).Assembly;
+ // Jellyfin.Server.Implementations
+ yield return typeof(ServiceCollectionExtensions).Assembly;
+
// Jellyfin.LiveTv
yield return typeof(LiveTvManager).Assembly;
}
diff --git a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs
index 6b95770ed5..7695c0d9ee 100644
--- a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs
+++ b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs
@@ -85,6 +85,6 @@ public static class WebHostBuilderExtensions
logger.LogInformation("Kestrel listening to unix socket {SocketPath}", socketPath);
}
})
- .UseStartup(_ => new Startup(appHost));
+ .UseStartup(context => new Startup(appHost, context.Configuration));
}
}
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index ebb12ba4e7..452b03efbe 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -66,6 +66,7 @@
<ProjectReference Include="..\src\Jellyfin.LiveTv\Jellyfin.LiveTv.csproj" />
<ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
<ProjectReference Include="..\src\Jellyfin.MediaEncoding.Hls\Jellyfin.MediaEncoding.Hls.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
</ItemGroup>
<ItemGroup>
diff --git a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs
index d2fbcbec94..f183bce107 100644
--- a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs
+++ b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs
@@ -9,6 +9,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
+using System.Threading;
using Emby.Server.Implementations.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Extensions;
@@ -33,6 +34,7 @@ public class MigrateLibraryDb : IMigrationRoutine
private readonly ILogger<MigrateLibraryDb> _logger;
private readonly IServerApplicationPaths _paths;
+ private readonly IJellyfinDatabaseProvider _jellyfinDatabaseProvider;
private readonly IDbContextFactory<JellyfinDbContext> _provider;
/// <summary>
@@ -41,14 +43,17 @@ public class MigrateLibraryDb : IMigrationRoutine
/// <param name="logger">The logger.</param>
/// <param name="provider">The database provider.</param>
/// <param name="paths">The server application paths.</param>
+ /// <param name="jellyfinDatabaseProvider">The database provider for special access.</param>
public MigrateLibraryDb(
ILogger<MigrateLibraryDb> logger,
IDbContextFactory<JellyfinDbContext> provider,
- IServerApplicationPaths paths)
+ IServerApplicationPaths paths,
+ IJellyfinDatabaseProvider jellyfinDatabaseProvider)
{
_logger = logger;
_provider = provider;
_paths = paths;
+ _jellyfinDatabaseProvider = jellyfinDatabaseProvider;
}
/// <inheritdoc/>
@@ -325,17 +330,7 @@ public class MigrateLibraryDb : IMigrationRoutine
_logger.LogInformation("Migrating Library db took {0}.", migrationTotalTime);
- if (dbContext.Database.IsSqlite())
- {
- _logger.LogInformation("Vacuum and Optimise jellyfin.db now.");
- dbContext.Database.ExecuteSqlRaw("PRAGMA optimize");
- dbContext.Database.ExecuteSqlRaw("VACUUM");
- _logger.LogInformation("jellyfin.db optimized successfully!");
- }
- else
- {
- _logger.LogInformation("This database doesn't support optimization");
- }
+ _jellyfinDatabaseProvider.RunScheduledOptimisation(CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();
}
private UserData? GetUserData(ImmutableArray<User> users, SqliteDataReader dto)
diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs
index 7dcae5bd9d..f126230fb4 100644
--- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs
+++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using Emby.Server.Implementations.Data;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions.Json;
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index 7e50100b09..d8684f6da7 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Threading;
using System.Threading.Tasks;
using CommandLine;
using Emby.Server.Implementations;
@@ -164,7 +165,7 @@ namespace Jellyfin.Server
// Re-use the host service provider in the app host since ASP.NET doesn't allow a custom service collection.
appHost.ServiceProvider = _jellyfinHost.Services;
- await appHost.InitializeServices().ConfigureAwait(false);
+ await appHost.InitializeServices(startupConfig).ConfigureAwait(false);
Migrations.MigrationRunner.Run(appHost, _loggerFactory);
try
@@ -204,23 +205,12 @@ namespace Jellyfin.Server
// Don't throw additional exception if startup failed.
if (appHost.ServiceProvider is not null)
{
- var isSqlite = false;
_logger.LogInformation("Running query planner optimizations in the database... This might take a while");
- // Run before disposing the application
- var context = await appHost.ServiceProvider.GetRequiredService<IDbContextFactory<JellyfinDbContext>>().CreateDbContextAsync().ConfigureAwait(false);
- await using (context.ConfigureAwait(false))
- {
- if (context.Database.IsSqlite())
- {
- isSqlite = true;
- await context.Database.ExecuteSqlRawAsync("PRAGMA optimize").ConfigureAwait(false);
- }
- }
- if (isSqlite)
- {
- SqliteConnection.ClearAllPools();
- }
+ var databaseProvider = appHost.ServiceProvider.GetRequiredService<IJellyfinDatabaseProvider>();
+ using var shutdownSource = new CancellationTokenSource();
+ shutdownSource.CancelAfter((int)TimeSpan.FromSeconds(60).TotalMicroseconds);
+ await databaseProvider.RunShutdownTask(shutdownSource.Token).ConfigureAwait(false);
}
_appHost = null;
diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs
index c686614699..fa21d25664 100644
--- a/Jellyfin.Server/Startup.cs
+++ b/Jellyfin.Server/Startup.cs
@@ -39,15 +39,18 @@ namespace Jellyfin.Server
public class Startup
{
private readonly CoreAppHost _serverApplicationHost;
+ private readonly IConfiguration _configuration;
private readonly IServerConfigurationManager _serverConfigurationManager;
/// <summary>
/// Initializes a new instance of the <see cref="Startup" /> class.
/// </summary>
/// <param name="appHost">The server application host.</param>
- public Startup(CoreAppHost appHost)
+ /// <param name="configuration">The used Configuration.</param>
+ public Startup(CoreAppHost appHost, IConfiguration configuration)
{
_serverApplicationHost = appHost;
+ _configuration = configuration;
_serverConfigurationManager = appHost.ConfigurationManager;
}
@@ -67,7 +70,7 @@ namespace Jellyfin.Server
// TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371
services.AddSingleton<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>();
services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration());
- services.AddJellyfinDbContext();
+ services.AddJellyfinDbContext(_serverApplicationHost.ConfigurationManager, _configuration);
services.AddJellyfinApiSwagger();
// configure custom legacy authentication
diff --git a/Jellyfin.sln b/Jellyfin.sln
index edef9b7a59..cdc8c8f651 100644
--- a/Jellyfin.sln
+++ b/Jellyfin.sln
@@ -87,6 +87,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.LiveTv.Tests", "te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.LiveTv", "src\Jellyfin.LiveTv\Jellyfin.LiveTv.csproj", "{8C6B2B13-58A4-4506-9DAB-1F882A093FE0}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Jellyfin.Database", "Jellyfin.Database", "{4C54CE05-69C8-48FA-8785-39F7F6DB1CAD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Database.Providers.Sqlite", "src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Jellyfin.Database.Providers.Sqlite.csproj", "{A5590358-33CC-4B39-BDE7-DC62FEB03C76}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Database.Implementations", "src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj", "{8C9F9221-8415-496C-B1F5-E7756F03FA59}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -241,17 +247,28 @@ Global
{8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
+ {154872D9-6C12-4007-96E3-8F70A58386CE} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
{DF194677-DFD3-42AF-9F75-D44D5A416478} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{28464062-0939-4AA7-9F7B-24DDDA61A7C0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{3998657B-1CCC-49DD-A19F-275DC8495F57} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{A2FD0A10-8F62-4F9D-B171-FFDF9F0AFA9D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{2E3A1B4B-4225-4AAA-8B29-0181A84E7AEE} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{462584F7-5023-4019-9EAC-B98CA458C0A0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
+ {0A3FCC4D-C714-4072-B90F-E374A15F9FF9} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
{30922383-D513-4F4D-B890-A940B57FA353} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{FC1BC0CE-E8D2-4AE9-A6AB-8A02143B335D} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
@@ -264,11 +281,11 @@ Global
{DA9FD356-4894-4830-B208-D6BCE3E65B11} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
{FE47334C-EFDE-4519-BD50-F24430FF360B} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{24960660-DE6C-47BF-AEEF-CEE8F19FE6C2} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
- {08FFF49B-F175-4807-A2B5-73B0EBD9F716} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
- {154872D9-6C12-4007-96E3-8F70A58386CE} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
- {0A3FCC4D-C714-4072-B90F-E374A15F9FF9} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
{C4F71272-C6BE-4C30-BE0D-4E6ED651D6D3} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{8C6B2B13-58A4-4506-9DAB-1F882A093FE0} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
+ {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
+ {A5590358-33CC-4B39-BDE7-DC62FEB03C76} = {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD}
+ {8C9F9221-8415-496C-B1F5-E7756F03FA59} = {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE}
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 9e07000bcf..49f8df508e 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -7,6 +7,7 @@ using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index f3873775b9..3b0938ea79 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 52221ad9e3..e99479ee19 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index a331f7983b..e20679084d 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -12,6 +12,7 @@ using System.Text;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index af6348e462..b2f23cc11d 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -13,6 +13,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using J2N.Collections.Generic.Extensions;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 43f02fb72b..0bd28154de 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index c9a93d0f56..07def2e0f2 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.Json.Serialization;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index 137d91f1cf..f3c252decc 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -9,12 +9,12 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 4ec2e4c0a4..3670808673 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index a9e419df46..1c5d2f4e53 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -13,6 +13,7 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index edea54291d..491acdc9c2 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
index 57557d55ca..d35ed57b89 100644
--- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
+++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs
@@ -10,6 +10,7 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using AsyncKeyedLock;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common;
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs
new file mode 100644
index 0000000000..af2ede7010
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Jellyfin.Server.Implementations.DatabaseConfiguration;
+
+/// <summary>
+/// Options to configure jellyfins managed database.
+/// </summary>
+public class DatabaseConfigurationOptions
+{
+ /// <summary>
+ /// Gets or Sets the type of database jellyfin should use.
+ /// </summary>
+ public required string DatabaseType { get; set; }
+}
diff --git a/Jellyfin.Data/Entities/AccessSchedule.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AccessSchedule.cs
index f534e49f3f..f534e49f3f 100644
--- a/Jellyfin.Data/Entities/AccessSchedule.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AccessSchedule.cs
diff --git a/Jellyfin.Data/Entities/ActivityLog.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ActivityLog.cs
index 51dd0ffb8e..51dd0ffb8e 100644
--- a/Jellyfin.Data/Entities/ActivityLog.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ActivityLog.cs
diff --git a/Jellyfin.Data/Entities/AncestorId.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AncestorId.cs
index 954416dfe1..954416dfe1 100644
--- a/Jellyfin.Data/Entities/AncestorId.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AncestorId.cs
diff --git a/Jellyfin.Data/Entities/AttachmentStreamInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AttachmentStreamInfo.cs
index 19265a0115..19265a0115 100644
--- a/Jellyfin.Data/Entities/AttachmentStreamInfo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AttachmentStreamInfo.cs
diff --git a/Jellyfin.Data/Entities/BaseItemEntity.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
index e3e0e0861e..e3e0e0861e 100644
--- a/Jellyfin.Data/Entities/BaseItemEntity.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
diff --git a/Jellyfin.Data/Entities/BaseItemExtraType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemExtraType.cs
index 54aef50e40..54aef50e40 100644
--- a/Jellyfin.Data/Entities/BaseItemExtraType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemExtraType.cs
diff --git a/Jellyfin.Data/Entities/BaseItemImageInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemImageInfo.cs
index 37723df116..37723df116 100644
--- a/Jellyfin.Data/Entities/BaseItemImageInfo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemImageInfo.cs
diff --git a/Jellyfin.Data/Entities/BaseItemMetadataField.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemMetadataField.cs
index 27bbfc4731..27bbfc4731 100644
--- a/Jellyfin.Data/Entities/BaseItemMetadataField.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemMetadataField.cs
diff --git a/Jellyfin.Data/Entities/BaseItemProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemProvider.cs
index 9a1565728d..9a1565728d 100644
--- a/Jellyfin.Data/Entities/BaseItemProvider.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemProvider.cs
diff --git a/Jellyfin.Data/Entities/BaseItemTrailerType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTrailerType.cs
index 2bb648138a..2bb648138a 100644
--- a/Jellyfin.Data/Entities/BaseItemTrailerType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTrailerType.cs
diff --git a/Jellyfin.Data/Entities/Chapter.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Chapter.cs
index 579442cdb6..579442cdb6 100644
--- a/Jellyfin.Data/Entities/Chapter.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Chapter.cs
diff --git a/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/CustomItemDisplayPreferences.cs
index a606595122..a606595122 100644
--- a/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/CustomItemDisplayPreferences.cs
diff --git a/Jellyfin.Data/Entities/DisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/DisplayPreferences.cs
index f0be657691..f0be657691 100644
--- a/Jellyfin.Data/Entities/DisplayPreferences.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/DisplayPreferences.cs
diff --git a/Jellyfin.Data/Entities/Group.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Group.cs
index 1be6f986a1..09f2372893 100644
--- a/Jellyfin.Data/Entities/Group.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Group.cs
@@ -59,18 +59,6 @@ namespace Jellyfin.Data.Entities
/// </summary>
public virtual ICollection<Preference> Preferences { get; private set; }
- /// <inheritdoc/>
- public bool HasPermission(PermissionKind kind)
- {
- return Permissions.First(p => p.Kind == kind).Value;
- }
-
- /// <inheritdoc/>
- public void SetPermission(PermissionKind kind, bool value)
- {
- Permissions.First(p => p.Kind == kind).Value = value;
- }
-
/// <inheritdoc />
public void OnSavingChanges()
{
diff --git a/Jellyfin.Data/Entities/HomeSection.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/HomeSection.cs
index 8dd6e647e2..8dd6e647e2 100644
--- a/Jellyfin.Data/Entities/HomeSection.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/HomeSection.cs
diff --git a/Jellyfin.Data/Entities/ImageInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfo.cs
index 935a53a263..935a53a263 100644
--- a/Jellyfin.Data/Entities/ImageInfo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfo.cs
diff --git a/Jellyfin.Data/Entities/ImageInfoImageType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfoImageType.cs
index f78178dd22..f78178dd22 100644
--- a/Jellyfin.Data/Entities/ImageInfoImageType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfoImageType.cs
diff --git a/Jellyfin.Data/Entities/ItemDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemDisplayPreferences.cs
index 93e6664ea4..93e6664ea4 100644
--- a/Jellyfin.Data/Entities/ItemDisplayPreferences.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemDisplayPreferences.cs
diff --git a/Jellyfin.Data/Entities/ItemValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValue.cs
index 11d8e383ee..11d8e383ee 100644
--- a/Jellyfin.Data/Entities/ItemValue.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValue.cs
diff --git a/Jellyfin.Data/Entities/ItemValueMap.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueMap.cs
index 94db6a011b..94db6a011b 100644
--- a/Jellyfin.Data/Entities/ItemValueMap.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueMap.cs
diff --git a/Jellyfin.Data/Entities/ItemValueType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueType.cs
index 3bae3beccd..3bae3beccd 100644
--- a/Jellyfin.Data/Entities/ItemValueType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueType.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Artwork.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Artwork.cs
index fc3c1036f0..fc3c1036f0 100644
--- a/Jellyfin.Data/Entities/Libraries/Artwork.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Artwork.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Book.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Book.cs
index a838686d05..a838686d05 100644
--- a/Jellyfin.Data/Entities/Libraries/Book.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Book.cs
diff --git a/Jellyfin.Data/Entities/Libraries/BookMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/BookMetadata.cs
index 4a350d200e..4a350d200e 100644
--- a/Jellyfin.Data/Entities/Libraries/BookMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/BookMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Chapter.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Chapter.cs
index f068338f92..f068338f92 100644
--- a/Jellyfin.Data/Entities/Libraries/Chapter.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Chapter.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Collection.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Collection.cs
index 7de6019692..7de6019692 100644
--- a/Jellyfin.Data/Entities/Libraries/Collection.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Collection.cs
diff --git a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CollectionItem.cs
index 15b356a74e..15b356a74e 100644
--- a/Jellyfin.Data/Entities/Libraries/CollectionItem.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CollectionItem.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Company.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Company.cs
index 1abbee4458..1abbee4458 100644
--- a/Jellyfin.Data/Entities/Libraries/Company.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Company.cs
diff --git a/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CompanyMetadata.cs
index a29f08c7f6..a29f08c7f6 100644
--- a/Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CompanyMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/CustomItem.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItem.cs
index e27d01d860..e27d01d860 100644
--- a/Jellyfin.Data/Entities/Libraries/CustomItem.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItem.cs
diff --git a/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItemMetadata.cs
index af2393870f..af2393870f 100644
--- a/Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItemMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Episode.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Episode.cs
index ce2f0c6178..ce2f0c6178 100644
--- a/Jellyfin.Data/Entities/Libraries/Episode.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Episode.cs
diff --git a/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/EpisodeMetadata.cs
index b0ef11e0f2..b0ef11e0f2 100644
--- a/Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/EpisodeMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Genre.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Genre.cs
index 3b822ee828..3b822ee828 100644
--- a/Jellyfin.Data/Entities/Libraries/Genre.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Genre.cs
diff --git a/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/ItemMetadata.cs
index fa9276c669..fa9276c669 100644
--- a/Jellyfin.Data/Entities/Libraries/ItemMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/ItemMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Library.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Library.cs
index 0db42a1c7b..0db42a1c7b 100644
--- a/Jellyfin.Data/Entities/Libraries/Library.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Library.cs
diff --git a/Jellyfin.Data/Entities/Libraries/LibraryItem.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/LibraryItem.cs
index d889b871ed..d889b871ed 100644
--- a/Jellyfin.Data/Entities/Libraries/LibraryItem.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/LibraryItem.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MediaFile.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFile.cs
index 7b5a3af64c..7b5a3af64c 100644
--- a/Jellyfin.Data/Entities/Libraries/MediaFile.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFile.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFileStream.cs
index e24e73ecb7..e24e73ecb7 100644
--- a/Jellyfin.Data/Entities/Libraries/MediaFileStream.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFileStream.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProvider.cs
index b38d6a4f1f..b38d6a4f1f 100644
--- a/Jellyfin.Data/Entities/Libraries/MetadataProvider.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProvider.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProviderId.cs
index a198f53ba3..a198f53ba3 100644
--- a/Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProviderId.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Movie.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Movie.cs
index 499fafd0e1..499fafd0e1 100644
--- a/Jellyfin.Data/Entities/Libraries/Movie.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Movie.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MovieMetadata.cs
index 44b5f34d7f..44b5f34d7f 100644
--- a/Jellyfin.Data/Entities/Libraries/MovieMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MovieMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbum.cs
index d6231bbf02..d6231bbf02 100644
--- a/Jellyfin.Data/Entities/Libraries/MusicAlbum.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbum.cs
diff --git a/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbumMetadata.cs
index 691f3504fa..691f3504fa 100644
--- a/Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbumMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Person.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Person.cs
index 90dc55b70d..90dc55b70d 100644
--- a/Jellyfin.Data/Entities/Libraries/Person.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Person.cs
diff --git a/Jellyfin.Data/Entities/Libraries/PersonRole.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PersonRole.cs
index 7d40bdf448..7d40bdf448 100644
--- a/Jellyfin.Data/Entities/Libraries/PersonRole.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PersonRole.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Photo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Photo.cs
index 4b459432bc..4b459432bc 100644
--- a/Jellyfin.Data/Entities/Libraries/Photo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Photo.cs
diff --git a/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PhotoMetadata.cs
index 6c284307d7..6c284307d7 100644
--- a/Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PhotoMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Rating.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Rating.cs
index 58c8fa49ef..58c8fa49ef 100644
--- a/Jellyfin.Data/Entities/Libraries/Rating.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Rating.cs
diff --git a/Jellyfin.Data/Entities/Libraries/RatingSource.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/RatingSource.cs
index 0f3a073244..0f3a073244 100644
--- a/Jellyfin.Data/Entities/Libraries/RatingSource.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/RatingSource.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Release.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Release.cs
index e68ab9105a..e68ab9105a 100644
--- a/Jellyfin.Data/Entities/Libraries/Release.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Release.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Season.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Season.cs
index fc110b49da..fc110b49da 100644
--- a/Jellyfin.Data/Entities/Libraries/Season.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Season.cs
diff --git a/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeasonMetadata.cs
index da40a075f5..da40a075f5 100644
--- a/Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeasonMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Series.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Series.cs
index ab484c96d6..ab484c96d6 100644
--- a/Jellyfin.Data/Entities/Libraries/Series.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Series.cs
diff --git a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeriesMetadata.cs
index 42115802c5..42115802c5 100644
--- a/Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeriesMetadata.cs
diff --git a/Jellyfin.Data/Entities/Libraries/Track.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Track.cs
index d354000337..d354000337 100644
--- a/Jellyfin.Data/Entities/Libraries/Track.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Track.cs
diff --git a/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/TrackMetadata.cs
index 042d2b90db..042d2b90db 100644
--- a/Jellyfin.Data/Entities/Libraries/TrackMetadata.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/TrackMetadata.cs
diff --git a/Jellyfin.Data/Entities/MediaSegment.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaSegment.cs
index 90120d7721..90120d7721 100644
--- a/Jellyfin.Data/Entities/MediaSegment.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaSegment.cs
diff --git a/Jellyfin.Data/Entities/MediaStreamInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamInfo.cs
index 77816565af..77816565af 100644
--- a/Jellyfin.Data/Entities/MediaStreamInfo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamInfo.cs
diff --git a/Jellyfin.Data/Entities/MediaStreamTypeEntity.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamTypeEntity.cs
index f57672a2cf..f57672a2cf 100644
--- a/Jellyfin.Data/Entities/MediaStreamTypeEntity.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamTypeEntity.cs
diff --git a/Jellyfin.Data/Entities/People.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/People.cs
index 18c778b17a..18c778b17a 100644
--- a/Jellyfin.Data/Entities/People.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/People.cs
diff --git a/Jellyfin.Data/Entities/PeopleBaseItemMap.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/PeopleBaseItemMap.cs
index bfaaf82151..bfaaf82151 100644
--- a/Jellyfin.Data/Entities/PeopleBaseItemMap.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/PeopleBaseItemMap.cs
diff --git a/Jellyfin.Data/Entities/Permission.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Permission.cs
index 6d2e68077c..6d2e68077c 100644
--- a/Jellyfin.Data/Entities/Permission.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Permission.cs
diff --git a/Jellyfin.Data/Entities/Preference.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Preference.cs
index a6ab275d31..a6ab275d31 100644
--- a/Jellyfin.Data/Entities/Preference.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Preference.cs
diff --git a/Jellyfin.Data/Entities/ProgramAudioEntity.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ProgramAudioEntity.cs
index 9d79e5ddb1..9d79e5ddb1 100644
--- a/Jellyfin.Data/Entities/ProgramAudioEntity.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ProgramAudioEntity.cs
diff --git a/Jellyfin.Data/Entities/Security/ApiKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/ApiKey.cs
index 1fcbe0f5e9..1fcbe0f5e9 100644
--- a/Jellyfin.Data/Entities/Security/ApiKey.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/ApiKey.cs
diff --git a/Jellyfin.Data/Entities/Security/Device.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/Device.cs
index 67d7f78eda..67d7f78eda 100644
--- a/Jellyfin.Data/Entities/Security/Device.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/Device.cs
diff --git a/Jellyfin.Data/Entities/Security/DeviceOptions.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/DeviceOptions.cs
index 531f66c627..531f66c627 100644
--- a/Jellyfin.Data/Entities/Security/DeviceOptions.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/DeviceOptions.cs
diff --git a/Jellyfin.Data/Entities/TrickplayInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/TrickplayInfo.cs
index ff9a68beff..ff9a68beff 100644
--- a/Jellyfin.Data/Entities/TrickplayInfo.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/TrickplayInfo.cs
diff --git a/Jellyfin.Data/Entities/User.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/User.cs
index 9bbe9efe89..f3398eeeac 100644
--- a/Jellyfin.Data/Entities/User.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/User.cs
@@ -16,11 +16,6 @@ namespace Jellyfin.Data.Entities
public class User : IHasPermissions, IHasConcurrencyToken
{
/// <summary>
- /// The values being delimited here are Guids, so commas work as they do not appear in Guids.
- /// </summary>
- private const char Delimiter = ',';
-
- /// <summary>
/// Initializes a new instance of the <see cref="User"/> class.
/// Public constructor with required data.
/// </summary>
@@ -339,196 +334,5 @@ namespace Jellyfin.Data.Entities
{
RowVersion++;
}
-
- /// <summary>
- /// Checks whether the user has the specified permission.
- /// </summary>
- /// <param name="kind">The permission kind.</param>
- /// <returns><c>True</c> if the user has the specified permission.</returns>
- public bool HasPermission(PermissionKind kind)
- {
- return Permissions.FirstOrDefault(p => p.Kind == kind)?.Value ?? false;
- }
-
- /// <summary>
- /// Sets the given permission kind to the provided value.
- /// </summary>
- /// <param name="kind">The permission kind.</param>
- /// <param name="value">The value to set.</param>
- public void SetPermission(PermissionKind kind, bool value)
- {
- var currentPermission = Permissions.FirstOrDefault(p => p.Kind == kind);
- if (currentPermission is null)
- {
- Permissions.Add(new Permission(kind, value));
- }
- else
- {
- currentPermission.Value = value;
- }
- }
-
- /// <summary>
- /// Gets the user's preferences for the given preference kind.
- /// </summary>
- /// <param name="preference">The preference kind.</param>
- /// <returns>A string array containing the user's preferences.</returns>
- public string[] GetPreference(PreferenceKind preference)
- {
- var val = Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
-
- return string.IsNullOrEmpty(val) ? Array.Empty<string>() : val.Split(Delimiter);
- }
-
- /// <summary>
- /// Gets the user's preferences for the given preference kind.
- /// </summary>
- /// <param name="preference">The preference kind.</param>
- /// <typeparam name="T">Type of preference.</typeparam>
- /// <returns>A {T} array containing the user's preference.</returns>
- public T[] GetPreferenceValues<T>(PreferenceKind preference)
- {
- var val = Preferences.FirstOrDefault(p => p.Kind == preference)?.Value;
- if (string.IsNullOrEmpty(val))
- {
- return Array.Empty<T>();
- }
-
- // Convert array of {string} to array of {T}
- var converter = TypeDescriptor.GetConverter(typeof(T));
- var stringValues = val.Split(Delimiter);
- var convertedCount = 0;
- var parsedValues = new T[stringValues.Length];
- for (var i = 0; i < stringValues.Length; i++)
- {
- try
- {
- var parsedValue = converter.ConvertFromString(stringValues[i].Trim());
- if (parsedValue is not null)
- {
- parsedValues[convertedCount++] = (T)parsedValue;
- }
- }
- catch (FormatException)
- {
- // Unable to convert value
- }
- }
-
- return parsedValues[..convertedCount];
- }
-
- /// <summary>
- /// Sets the specified preference to the given value.
- /// </summary>
- /// <param name="preference">The preference kind.</param>
- /// <param name="values">The values.</param>
- public void SetPreference(PreferenceKind preference, string[] values)
- {
- var value = string.Join(Delimiter, values);
- var currentPreference = Preferences.FirstOrDefault(p => p.Kind == preference);
- if (currentPreference is null)
- {
- Preferences.Add(new Preference(preference, value));
- }
- else
- {
- currentPreference.Value = value;
- }
- }
-
- /// <summary>
- /// Sets the specified preference to the given value.
- /// </summary>
- /// <param name="preference">The preference kind.</param>
- /// <param name="values">The values.</param>
- /// <typeparam name="T">The type of value.</typeparam>
- public void SetPreference<T>(PreferenceKind preference, T[] values)
- {
- var value = string.Join(Delimiter, values);
- var currentPreference = Preferences.FirstOrDefault(p => p.Kind == preference);
- if (currentPreference is null)
- {
- Preferences.Add(new Preference(preference, value));
- }
- else
- {
- currentPreference.Value = value;
- }
- }
-
- /// <summary>
- /// Checks whether this user is currently allowed to use the server.
- /// </summary>
- /// <returns><c>True</c> if the current time is within an access schedule, or there are no access schedules.</returns>
- public bool IsParentalScheduleAllowed()
- {
- return AccessSchedules.Count == 0
- || AccessSchedules.Any(i => IsParentalScheduleAllowed(i, DateTime.UtcNow));
- }
-
- /// <summary>
- /// Checks whether the provided folder is in this user's grouped folders.
- /// </summary>
- /// <param name="id">The Guid of the folder.</param>
- /// <returns><c>True</c> if the folder is in the user's grouped folders.</returns>
- public bool IsFolderGrouped(Guid id)
- {
- return Array.IndexOf(GetPreferenceValues<Guid>(PreferenceKind.GroupedFolders), id) != -1;
- }
-
- /// <summary>
- /// Initializes the default permissions for a user. Should only be called on user creation.
- /// </summary>
- // TODO: make these user configurable?
- public void AddDefaultPermissions()
- {
- Permissions.Add(new Permission(PermissionKind.IsAdministrator, false));
- Permissions.Add(new Permission(PermissionKind.IsDisabled, false));
- Permissions.Add(new Permission(PermissionKind.IsHidden, true));
- Permissions.Add(new Permission(PermissionKind.EnableAllChannels, true));
- Permissions.Add(new Permission(PermissionKind.EnableAllDevices, true));
- Permissions.Add(new Permission(PermissionKind.EnableAllFolders, true));
- Permissions.Add(new Permission(PermissionKind.EnableContentDeletion, false));
- Permissions.Add(new Permission(PermissionKind.EnableContentDownloading, true));
- Permissions.Add(new Permission(PermissionKind.EnableMediaConversion, true));
- Permissions.Add(new Permission(PermissionKind.EnableMediaPlayback, true));
- Permissions.Add(new Permission(PermissionKind.EnablePlaybackRemuxing, true));
- Permissions.Add(new Permission(PermissionKind.EnablePublicSharing, true));
- Permissions.Add(new Permission(PermissionKind.EnableRemoteAccess, true));
- Permissions.Add(new Permission(PermissionKind.EnableSyncTranscoding, true));
- Permissions.Add(new Permission(PermissionKind.EnableAudioPlaybackTranscoding, true));
- Permissions.Add(new Permission(PermissionKind.EnableLiveTvAccess, true));
- Permissions.Add(new Permission(PermissionKind.EnableLiveTvManagement, true));
- Permissions.Add(new Permission(PermissionKind.EnableSharedDeviceControl, true));
- Permissions.Add(new Permission(PermissionKind.EnableVideoPlaybackTranscoding, true));
- Permissions.Add(new Permission(PermissionKind.ForceRemoteSourceTranscoding, false));
- Permissions.Add(new Permission(PermissionKind.EnableRemoteControlOfOtherUsers, false));
- Permissions.Add(new Permission(PermissionKind.EnableCollectionManagement, false));
- Permissions.Add(new Permission(PermissionKind.EnableSubtitleManagement, false));
- Permissions.Add(new Permission(PermissionKind.EnableLyricManagement, false));
- }
-
- /// <summary>
- /// Initializes the default preferences. Should only be called on user creation.
- /// </summary>
- public void AddDefaultPreferences()
- {
- foreach (var val in Enum.GetValues<PreferenceKind>())
- {
- Preferences.Add(new Preference(val, string.Empty));
- }
- }
-
- private static bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
- {
- var localTime = date.ToLocalTime();
- var hour = localTime.TimeOfDay.TotalHours;
- var currentDayOfWeek = localTime.DayOfWeek;
-
- return schedule.DayOfWeek.Contains(currentDayOfWeek)
- && hour >= schedule.StartHour
- && hour <= schedule.EndHour;
- }
}
}
diff --git a/Jellyfin.Data/Entities/UserData.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/UserData.cs
index 05ab6dd2d2..05ab6dd2d2 100644
--- a/Jellyfin.Data/Entities/UserData.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/UserData.cs
diff --git a/Jellyfin.Data/Enums/ArtKind.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ArtKind.cs
index f7a73848c8..f7a73848c8 100644
--- a/Jellyfin.Data/Enums/ArtKind.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ArtKind.cs
diff --git a/Jellyfin.Data/Enums/ChromecastVersion.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ChromecastVersion.cs
index c9c8a4a625..c9c8a4a625 100644
--- a/Jellyfin.Data/Enums/ChromecastVersion.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ChromecastVersion.cs
diff --git a/Jellyfin.Data/Enums/DynamicDayOfWeek.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/DynamicDayOfWeek.cs
index d3d8dd8227..d3d8dd8227 100644
--- a/Jellyfin.Data/Enums/DynamicDayOfWeek.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/DynamicDayOfWeek.cs
diff --git a/Jellyfin.Data/Enums/HomeSectionType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/HomeSectionType.cs
index 62da8c3fff..62da8c3fff 100644
--- a/Jellyfin.Data/Enums/HomeSectionType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/HomeSectionType.cs
diff --git a/Jellyfin.Data/Enums/IndexingKind.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/IndexingKind.cs
index 3967712b03..3967712b03 100644
--- a/Jellyfin.Data/Enums/IndexingKind.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/IndexingKind.cs
diff --git a/Jellyfin.Data/Enums/MediaFileKind.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaFileKind.cs
index 797c26ec27..797c26ec27 100644
--- a/Jellyfin.Data/Enums/MediaFileKind.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaFileKind.cs
diff --git a/Jellyfin.Data/Enums/MediaSegmentType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaSegmentType.cs
index 4586354504..4586354504 100644
--- a/Jellyfin.Data/Enums/MediaSegmentType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaSegmentType.cs
diff --git a/Jellyfin.Data/Enums/PermissionKind.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PermissionKind.cs
index c3d6705c24..c3d6705c24 100644
--- a/Jellyfin.Data/Enums/PermissionKind.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PermissionKind.cs
diff --git a/Jellyfin.Data/Enums/PersonRoleType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PersonRoleType.cs
index 1e619f5eef..1e619f5eef 100644
--- a/Jellyfin.Data/Enums/PersonRoleType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PersonRoleType.cs
diff --git a/Jellyfin.Data/Enums/PreferenceKind.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PreferenceKind.cs
index d2b412e459..d2b412e459 100644
--- a/Jellyfin.Data/Enums/PreferenceKind.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/PreferenceKind.cs
diff --git a/Jellyfin.Data/Enums/ScrollDirection.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ScrollDirection.cs
index 29c50e2c4e..29c50e2c4e 100644
--- a/Jellyfin.Data/Enums/ScrollDirection.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ScrollDirection.cs
diff --git a/Jellyfin.Data/Enums/SortOrder.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SortOrder.cs
index 4151448e4e..4151448e4e 100644
--- a/Jellyfin.Data/Enums/SortOrder.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SortOrder.cs
diff --git a/Jellyfin.Data/Enums/SubtitlePlaybackMode.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SubtitlePlaybackMode.cs
index 79693d321a..79693d321a 100644
--- a/Jellyfin.Data/Enums/SubtitlePlaybackMode.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SubtitlePlaybackMode.cs
diff --git a/Jellyfin.Data/Enums/SyncPlayUserAccessType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SyncPlayUserAccessType.cs
index 030d16fb90..030d16fb90 100644
--- a/Jellyfin.Data/Enums/SyncPlayUserAccessType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/SyncPlayUserAccessType.cs
diff --git a/Jellyfin.Data/Enums/ViewType.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ViewType.cs
index c0fd7d448b..c0fd7d448b 100644
--- a/Jellyfin.Data/Enums/ViewType.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ViewType.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs
new file mode 100644
index 0000000000..cc96792e64
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+
+namespace Jellyfin.Server.Implementations;
+
+/// <summary>
+/// Defines the type and extension points for multi database support.
+/// </summary>
+public interface IJellyfinDatabaseProvider
+{
+ /// <summary>
+ /// Gets or Sets the Database Factory when initialisaition is done.
+ /// </summary>
+ IDbContextFactory<JellyfinDbContext>? DbContextFactory { get; set; }
+
+ /// <summary>
+ /// Initialises jellyfins EFCore database access.
+ /// </summary>
+ /// <param name="options">The EFCore database options.</param>
+ void Initialise(DbContextOptionsBuilder options);
+
+ /// <summary>
+ /// Will be invoked when EFCore wants to build its model.
+ /// </summary>
+ /// <param name="modelBuilder">The ModelBuilder from EFCore.</param>
+ void OnModelCreating(ModelBuilder modelBuilder);
+
+ /// <summary>
+ /// Will be invoked when EFCore wants to configure its model.
+ /// </summary>
+ /// <param name="configurationBuilder">The ModelConfigurationBuilder from EFCore.</param>
+ void ConfigureConventions(ModelConfigurationBuilder configurationBuilder);
+
+ /// <summary>
+ /// If supported this should run any periodic maintaince tasks.
+ /// </summary>
+ /// <param name="cancellationToken">The token to abort the operation.</param>
+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
+ Task RunScheduledOptimisation(CancellationToken cancellationToken);
+
+ /// <summary>
+ /// If supported this should perform any actions that are required on stopping the jellyfin server.
+ /// </summary>
+ /// <param name="cancellationToken">The token that will be used to abort the operation.</param>
+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
+ Task RunShutdownTask(CancellationToken cancellationToken);
+}
diff --git a/Jellyfin.Data/Interfaces/IHasArtwork.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasArtwork.cs
index a4d9c54af4..a4d9c54af4 100644
--- a/Jellyfin.Data/Interfaces/IHasArtwork.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasArtwork.cs
diff --git a/Jellyfin.Data/Interfaces/IHasCompanies.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasCompanies.cs
index 8f19ce04fa..8f19ce04fa 100644
--- a/Jellyfin.Data/Interfaces/IHasCompanies.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasCompanies.cs
diff --git a/Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasConcurrencyToken.cs
index 2c4091493e..2c4091493e 100644
--- a/Jellyfin.Data/Interfaces/IHasConcurrencyToken.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasConcurrencyToken.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasPermissions.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasPermissions.cs
new file mode 100644
index 0000000000..6d1eb59f67
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasPermissions.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
+
+namespace Jellyfin.Data.Interfaces
+{
+ /// <summary>
+ /// An abstraction representing an entity that has permissions.
+ /// </summary>
+ public interface IHasPermissions
+ {
+ /// <summary>
+ /// Gets a collection containing this entity's permissions.
+ /// </summary>
+ ICollection<Permission> Permissions { get; }
+ }
+}
diff --git a/Jellyfin.Data/Interfaces/IHasReleases.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasReleases.cs
index 3b615893ed..3b615893ed 100644
--- a/Jellyfin.Data/Interfaces/IHasReleases.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Interfaces/IHasReleases.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Jellyfin.Database.Implementations.csproj b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Jellyfin.Database.Implementations.csproj
new file mode 100644
index 0000000000..3b619cce61
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Jellyfin.Database.Implementations.csproj
@@ -0,0 +1,25 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="..\..\..\SharedVersion.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Design">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+</Project>
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDatabaseProviderKeyAttribute.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDatabaseProviderKeyAttribute.cs
new file mode 100644
index 0000000000..b3ab3d0944
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDatabaseProviderKeyAttribute.cs
@@ -0,0 +1,29 @@
+namespace Jellyfin.Server.Implementations;
+
+/// <summary>
+/// Defines the key of the database provider.
+/// </summary>
+[System.AttributeUsage(System.AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
+public sealed class JellyfinDatabaseProviderKeyAttribute : System.Attribute
+{
+ // See the attribute guidelines at
+ // http://go.microsoft.com/fwlink/?LinkId=85236
+ private readonly string _databaseProviderKey;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="JellyfinDatabaseProviderKeyAttribute"/> class.
+ /// </summary>
+ /// <param name="databaseProviderKey">The key on which to identify the annotated provider.</param>
+ public JellyfinDatabaseProviderKeyAttribute(string databaseProviderKey)
+ {
+ this._databaseProviderKey = databaseProviderKey;
+ }
+
+ /// <summary>
+ /// Gets the key on which to identify the annotated provider.
+ /// </summary>
+ public string DatabaseProviderKey
+ {
+ get { return _databaseProviderKey; }
+ }
+}
diff --git a/Jellyfin.Server.Implementations/JellyfinDbContext.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs
index 43ea2bd3c2..024d595d58 100644
--- a/Jellyfin.Server.Implementations/JellyfinDbContext.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs
@@ -16,7 +16,8 @@ namespace Jellyfin.Server.Implementations;
/// </summary>
/// <param name="options">The database context options.</param>
/// <param name="logger">Logger.</param>
-public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILogger<JellyfinDbContext> logger) : DbContext(options)
+/// <param name="jellyfinDatabaseProvider">The provider for the database engine specific operations.</param>
+public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILogger<JellyfinDbContext> logger, IJellyfinDatabaseProvider jellyfinDatabaseProvider) : DbContext(options)
{
/// <summary>
/// Gets the <see cref="DbSet{TEntity}"/> containing the access schedules.
@@ -267,29 +268,17 @@ public class JellyfinDbContext(DbContextOptions<JellyfinDbContext> options, ILog
/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
- modelBuilder.SetDefaultDateTimeKind(DateTimeKind.Utc);
+ jellyfinDatabaseProvider.OnModelCreating(modelBuilder);
base.OnModelCreating(modelBuilder);
// Configuration for each entity is in its own class inside 'ModelConfiguration'.
modelBuilder.ApplyConfigurationsFromAssembly(typeof(JellyfinDbContext).Assembly);
}
- /// <inheritdoc/>
+ /// <inheritdoc />
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
- configurationBuilder.Conventions.Add(_ => new DoNotUseReturningClauseConvention());
- }
-
- private class DoNotUseReturningClauseConvention : IModelFinalizingConvention
- {
- public void ProcessModelFinalizing(
- IConventionModelBuilder modelBuilder,
- IConventionContext<IConventionModelBuilder> context)
- {
- foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
- {
- entityType.UseSqlReturningClause(false);
- }
- }
+ jellyfinDatabaseProvider.ConfigureConventions(configurationBuilder);
+ base.ConfigureConventions(configurationBuilder);
}
}
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/ActivityLogConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs
index 9a63ed9f21..9a63ed9f21 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/ActivityLogConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ActivityLogConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/AncestorIdConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs
index 8cc817fb8b..8cc817fb8b 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/AncestorIdConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AncestorIdConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/ApiKeyConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs
index 3f19b6986a..3f19b6986a 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/ApiKeyConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ApiKeyConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs
index 057b6689ac..057b6689ac 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AttachmentStreamInfoConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
index eaf48981cd..08f2a33566 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs
@@ -1,8 +1,6 @@
-using System;
using Jellyfin.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
-using SQLitePCL;
namespace Jellyfin.Server.Implementations.ModelConfiguration;
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs
index 137f4a883b..b4c6511bf2 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemMetadataFieldConfiguration.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Linq;
using Jellyfin.Data.Entities;
-using MediaBrowser.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
-using SQLitePCL;
namespace Jellyfin.Server.Implementations.ModelConfiguration;
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
index d15049a1fa..d15049a1fa 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs
index f03d99c29c..e9564b854b 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTrailerTypeConfiguration.cs
@@ -1,10 +1,6 @@
-using System;
-using System.Linq;
using Jellyfin.Data.Entities;
-using MediaBrowser.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
-using SQLitePCL;
namespace Jellyfin.Server.Implementations.ModelConfiguration;
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/ChapterConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs
index 5a84f7750a..5a84f7750a 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/ChapterConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ChapterConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs
index 779aec986b..779aec986b 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/CustomItemDisplayPreferencesConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/DeviceConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs
index a750b65c03..a750b65c03 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/DeviceConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs
index 038afd7524..038afd7524 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DeviceOptionsConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs
index 9b437861bb..9b437861bb 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/DisplayPreferencesConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs
index abeeb09c9b..abeeb09c9b 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs
index 9c22b114c7..9c22b114c7 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/ItemValuesMapConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs
index 7e572f9a39..7e572f9a39 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/MediaStreamInfoConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
index cdaee9161c..cdaee9161c 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleBaseItemMapConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/PeopleConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs
index f3cccb13fe..f3cccb13fe 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/PeopleConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PeopleConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/PermissionConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs
index 240e284c0c..240e284c0c 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/PermissionConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PermissionConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/PreferenceConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs
index 49c869c6a8..49c869c6a8 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/PreferenceConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/PreferenceConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs
index dc1c17e5ef..dc1c17e5ef 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/TrickplayInfoConfiguration.cs
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/UserConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs
index a369cf6562..bcaa3634ed 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/UserConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserConfiguration.cs
@@ -13,8 +13,7 @@ namespace Jellyfin.Server.Implementations.ModelConfiguration
public void Configure(EntityTypeBuilder<User> builder)
{
builder
- .Property(user => user.Username)
- .UseCollation("NOCASE");
+ .Property(user => user.Username);
builder
.HasOne(u => u.ProfileImage)
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/UserDataConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs
index 7bbb28d431..7bbb28d431 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/UserDataConfiguration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/UserDataConfiguration.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs
new file mode 100644
index 0000000000..18f336dda8
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs
@@ -0,0 +1,20 @@
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions;
+
+namespace Jellyfin.Database.Providers.Sqlite;
+
+internal class DoNotUseReturningClauseConvention : IModelFinalizingConvention
+{
+ /// <inheritdoc/>
+ public void ProcessModelFinalizing(
+ IConventionModelBuilder modelBuilder,
+ IConventionContext<IConventionModelBuilder> context)
+ {
+ foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
+ {
+ entityType.UseSqlReturningClause(false);
+ }
+ }
+}
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj
new file mode 100644
index 0000000000..4e5f63f6fe
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj
@@ -0,0 +1,37 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net9.0</TargetFramework>
+ <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="..\..\..\SharedVersion.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Design">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="Microsoft.EntityFrameworkCore.Tools">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Jellyfin.Data\Jellyfin.Data.csproj" />
+ <ProjectReference Include="..\..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
+ <ProjectReference Include="..\..\..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
+ <!-- <ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" /> -->
+ </ItemGroup>
+
+ <ItemGroup>
+ <Folder Include="Properties/" />
+ </ItemGroup>
+
+</Project>
diff --git a/Jellyfin.Server.Implementations/Migrations/.gitattributes b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes
index da5c26f400..da5c26f400 100644
--- a/Jellyfin.Server.Implementations/Migrations/.gitattributes
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes
diff --git a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs
index 80fe784dd7..80fe784dd7 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs
index 002e5296ee..002e5296ee 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs
index 7aa4479b3d..7aa4479b3d 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs
index 706a97ba2b..706a97ba2b 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200613202153_AddUsers.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs
index 3860c851d0..3860c851d0 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs
index 8cd5516423..8cd5516423 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200728005145_AddDisplayPreferences.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs
index 1134f7aa42..1134f7aa42 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs
index 91d2b190db..91d2b190db 100644
--- a/Jellyfin.Server.Implementations/Migrations/20200905220533_FixDisplayPreferencesIndex.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs
index 607310caae..607310caae 100644
--- a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs
index e37b4e6961..e37b4e6961 100644
--- a/Jellyfin.Server.Implementations/Migrations/20201004171403_AddMaxActiveSessions.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs
index 02c3fc7532..02c3fc7532 100644
--- a/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs
index ce2b21d0c1..ce2b21d0c1 100644
--- a/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs
index 1cfd7112ce..1cfd7112ce 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs
index 3acd5e7b5b..3acd5e7b5b 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210320181425_AddIndexesAndCollations.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs
index ecf7af4952..ecf7af4952 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs
index a6b169a614..a6b169a614 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210407110544_NullableCustomPrefValue.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs
index dccba6f773..dccba6f773 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs
index bf90044cb4..bf90044cb4 100644
--- a/Jellyfin.Server.Implementations/Migrations/20210814002109_AddDevices.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs
index e821c106e3..e821c106e3 100644
--- a/Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs
index 9d5d7632bf..9d5d7632bf 100644
--- a/Jellyfin.Server.Implementations/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs
index 360fa03768..360fa03768 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs
index 354d91c380..354d91c380 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230526173516_RemoveEasyPassword.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs
index 17d33845f5..17d33845f5 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs
index 85f1b5b7dd..85f1b5b7dd 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230626233818_AddTrickplayInfos.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs
index 4c09176691..4c09176691 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs
index 5919e46657..5919e46657 100644
--- a/Jellyfin.Server.Implementations/Migrations/20230923170422_UserCastReceiver.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs
index 35a3cdad2d..35a3cdad2d 100644
--- a/Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs
index 18164d9998..18164d9998 100644
--- a/Jellyfin.Server.Implementations/Migrations/20240729140605_AddMediaSegments.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs
index 8dba31a67f..8dba31a67f 100644
--- a/Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs
index 55b90a54d7..55b90a54d7 100644
--- a/Jellyfin.Server.Implementations/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs
index 27745f601a..27745f601a 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs
index 8cc7fb452d..8cc7fb452d 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241020103111_LibraryDbMigration.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs
index 1fbf21492d..1fbf21492d 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs
index ac78019eda..ac78019eda 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241111131257_AddedCustomDataKey.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs
index bac6fd5b5a..bac6fd5b5a 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs
index 4558d7c49c..4558d7c49c 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241111135439_AddedCustomDataKeyKey.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs
index ad622d44c5..ad622d44c5 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs
index 70e81f3676..70e81f3676 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112152323_FixAncestorIdConfig.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs
index dc4c8212ba..dc4c8212ba 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs
index d57ea81b3a..d57ea81b3a 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112232041_fixMediaStreams.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs
index 5714120b5c..5714120b5c 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs
index 78611b9e4c..78611b9e4c 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241112234144_FixMediaStreams2.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs
index 855f02fd3f..855f02fd3f 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs
index d1b06ceaec..d1b06ceaec 100644
--- a/Jellyfin.Server.Implementations/Migrations/20241113133548_EnforceUniqueItemValue.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs
new file mode 100644
index 0000000000..d7b806d7a3
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs
@@ -0,0 +1,1594 @@
+// <auto-generated />
+using System;
+using Jellyfin.Server.Implementations;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Jellyfin.Server.Implementations.Migrations
+{
+ [DbContext(typeof(JellyfinDbContext))]
+ [Migration("20250202021306_FixedCollation")]
+ partial class FixedCollation
+ {
+ /// <inheritdoc />
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "9.0.1");
+
+ 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("AccessSchedules");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<DateTime>("DateCreated")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ItemId")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property<int>("LogSeverity")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(512)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Overview")
+ .HasMaxLength(512)
+ .HasColumnType("TEXT");
+
+ b.Property<uint>("RowVersion")
+ .IsConcurrencyToken()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("ShortOverview")
+ .HasMaxLength(512)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Type")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DateCreated");
+
+ b.ToTable("ActivityLogs");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("ParentItemId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("ItemId", "ParentItemId");
+
+ b.HasIndex("ParentItemId");
+
+ b.ToTable("AncestorIds");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("Index")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Codec")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CodecTag")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Comment")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Filename")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("MimeType")
+ .HasColumnType("TEXT");
+
+ b.HasKey("ItemId", "Index");
+
+ b.ToTable("AttachmentStreamInfos");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Album")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("AlbumArtists")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Artists")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("Audio")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("ChannelId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CleanName")
+ .HasColumnType("TEXT");
+
+ b.Property<float?>("CommunityRating")
+ .HasColumnType("REAL");
+
+ b.Property<float?>("CriticRating")
+ .HasColumnType("REAL");
+
+ b.Property<string>("CustomRating")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Data")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("DateCreated")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("DateLastMediaAdded")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("DateLastRefreshed")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("DateLastSaved")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("DateModified")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("EndDate")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("EpisodeTitle")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ExternalId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ExternalSeriesId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ExternalServiceId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ExtraIds")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("ExtraType")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("ForcedSortName")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Genres")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("Height")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("IndexNumber")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("InheritedParentalRatingValue")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsFolder")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsInMixedFolder")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsLocked")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsMovie")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsRepeat")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsSeries")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsVirtualItem")
+ .HasColumnType("INTEGER");
+
+ b.Property<float?>("LUFS")
+ .HasColumnType("REAL");
+
+ b.Property<string>("MediaType")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Name")
+ .HasColumnType("TEXT");
+
+ b.Property<float?>("NormalizationGain")
+ .HasColumnType("REAL");
+
+ b.Property<string>("OfficialRating")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("OriginalTitle")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Overview")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("OwnerId")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid?>("ParentId")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("ParentIndexNumber")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Path")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PreferredMetadataCountryCode")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PreferredMetadataLanguage")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("PremiereDate")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PresentationUniqueKey")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PrimaryVersionId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ProductionLocations")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("ProductionYear")
+ .HasColumnType("INTEGER");
+
+ b.Property<long?>("RunTimeTicks")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid?>("SeasonId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("SeasonName")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid?>("SeriesId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("SeriesName")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("SeriesPresentationUniqueKey")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ShowId")
+ .HasColumnType("TEXT");
+
+ b.Property<long?>("Size")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("SortName")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Studios")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Tagline")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Tags")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid?>("TopParentId")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("TotalBitrate")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Type")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("UnratedType")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("Width")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.HasIndex("Path");
+
+ b.HasIndex("PresentationUniqueKey");
+
+ b.HasIndex("TopParentId", "Id");
+
+ b.HasIndex("Type", "TopParentId", "Id");
+
+ b.HasIndex("Type", "TopParentId", "PresentationUniqueKey");
+
+ b.HasIndex("Type", "TopParentId", "StartDate");
+
+ b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem");
+
+ b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey");
+
+ b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem");
+
+ b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName");
+
+ b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated");
+
+ b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated");
+
+ b.ToTable("BaseItems");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<byte[]>("Blurhash")
+ .HasColumnType("BLOB");
+
+ b.Property<DateTime>("DateModified")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("Height")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("ImageType")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Path")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<int>("Width")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ItemId");
+
+ b.ToTable("BaseItemImageInfos");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b =>
+ {
+ b.Property<int>("Id")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id", "ItemId");
+
+ b.HasIndex("ItemId");
+
+ b.ToTable("BaseItemMetadataFields");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ProviderId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ProviderValue")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("ItemId", "ProviderId");
+
+ b.HasIndex("ProviderId", "ProviderValue", "ItemId");
+
+ b.ToTable("BaseItemProviders");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b =>
+ {
+ b.Property<int>("Id")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id", "ItemId");
+
+ b.HasIndex("ItemId");
+
+ b.ToTable("BaseItemTrailerTypes");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("ChapterIndex")
+ .HasColumnType("INTEGER");
+
+ b.Property<DateTime?>("ImageDateModified")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ImagePath")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Name")
+ .HasColumnType("TEXT");
+
+ b.Property<long>("StartPositionTicks")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ItemId", "ChapterIndex");
+
+ b.ToTable("Chapters");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Client")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Key")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Value")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "ItemId", "Client", "Key")
+ .IsUnique();
+
+ b.ToTable("CustomItemDisplayPreferences");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("ChromecastVersion")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Client")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("DashboardTheme")
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("EnableNextVideoInfoOverlay")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("IndexBy")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("ScrollDirection")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("ShowBackdrop")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("ShowSidebar")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("SkipBackwardLength")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("SkipForwardLength")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("TvHome")
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "ItemId", "Client")
+ .IsUnique();
+
+ b.ToTable("DisplayPreferences");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("DisplayPreferencesId")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Order")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Type")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DisplayPreferencesId");
+
+ b.ToTable("HomeSection");
+ });
+
+ 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()
+ .HasMaxLength(512)
+ .HasColumnType("TEXT");
+
+ b.Property<Guid?>("UserId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId")
+ .IsUnique();
+
+ b.ToTable("ImageInfos");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Client")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("IndexBy")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("RememberIndexing")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("RememberSorting")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("SortBy")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property<int>("SortOrder")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("ViewType")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("ItemDisplayPreferences");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b =>
+ {
+ b.Property<Guid>("ItemValueId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CleanValue")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<int>("Type")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Value")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("ItemValueId");
+
+ b.HasIndex("Type", "CleanValue")
+ .IsUnique();
+
+ b.ToTable("ItemValues");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b =>
+ {
+ b.Property<Guid>("ItemValueId")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("ItemValueId", "ItemId");
+
+ b.HasIndex("ItemId");
+
+ b.ToTable("ItemValuesMap");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<long>("EndTicks")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("SegmentProviderId")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<long>("StartTicks")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Type")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("MediaSegments");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("StreamIndex")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("AspectRatio")
+ .HasColumnType("TEXT");
+
+ b.Property<float?>("AverageFrameRate")
+ .HasColumnType("REAL");
+
+ b.Property<int?>("BitDepth")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("BitRate")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("BlPresentFlag")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("ChannelLayout")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("Channels")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Codec")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CodecTag")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CodecTimeBase")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ColorPrimaries")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ColorSpace")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("ColorTransfer")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Comment")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("DvBlSignalCompatibilityId")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("DvLevel")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("DvProfile")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("DvVersionMajor")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("DvVersionMinor")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("ElPresentFlag")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("Height")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool?>("IsAnamorphic")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool?>("IsAvc")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsDefault")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsExternal")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsForced")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool?>("IsHearingImpaired")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool?>("IsInterlaced")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("KeyFrames")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Language")
+ .HasColumnType("TEXT");
+
+ b.Property<float?>("Level")
+ .HasColumnType("REAL");
+
+ b.Property<string>("NalLengthSize")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Path")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PixelFormat")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Profile")
+ .HasColumnType("TEXT");
+
+ b.Property<float?>("RealFrameRate")
+ .HasColumnType("REAL");
+
+ b.Property<int?>("RefFrames")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("Rotation")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("RpuPresentFlag")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("SampleRate")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("StreamType")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("TimeBase")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Title")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("Width")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ItemId", "StreamIndex");
+
+ b.HasIndex("StreamIndex");
+
+ b.HasIndex("StreamType");
+
+ b.HasIndex("StreamIndex", "StreamType");
+
+ b.HasIndex("StreamIndex", "StreamType", "Language");
+
+ b.ToTable("MediaStreamInfos");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.People", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PersonType")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name");
+
+ b.ToTable("Peoples");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("PeopleId")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("ListOrder")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Role")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("SortOrder")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ItemId", "PeopleId");
+
+ b.HasIndex("PeopleId");
+
+ b.HasIndex("ItemId", "ListOrder");
+
+ b.HasIndex("ItemId", "SortOrder");
+
+ b.ToTable("PeopleBaseItemMap");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Kind")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid?>("Permission_Permissions_Guid")
+ .HasColumnType("TEXT");
+
+ b.Property<uint>("RowVersion")
+ .IsConcurrencyToken()
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid?>("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("Value")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "Kind")
+ .IsUnique()
+ .HasFilter("[UserId] IS NOT NULL");
+
+ b.ToTable("Permissions");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Kind")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid?>("Preference_Preferences_Guid")
+ .HasColumnType("TEXT");
+
+ b.Property<uint>("RowVersion")
+ .IsConcurrencyToken()
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid?>("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Value")
+ .IsRequired()
+ .HasMaxLength(65535)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "Kind")
+ .IsUnique()
+ .HasFilter("[UserId] IS NOT NULL");
+
+ b.ToTable("Preferences");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("AccessToken")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("DateCreated")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("DateLastActivity")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AccessToken")
+ .IsUnique();
+
+ b.ToTable("ApiKeys");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("AccessToken")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("AppName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("AppVersion")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("DateCreated")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("DateLastActivity")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime>("DateModified")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("DeviceId")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("DeviceName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("IsActive")
+ .HasColumnType("INTEGER");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceId");
+
+ b.HasIndex("AccessToken", "DateLastActivity");
+
+ b.HasIndex("DeviceId", "DateLastActivity");
+
+ b.HasIndex("UserId", "DeviceId");
+
+ b.ToTable("Devices");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b =>
+ {
+ b.Property<int>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("CustomName")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("DeviceId")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeviceId")
+ .IsUnique();
+
+ b.ToTable("DeviceOptions");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<int>("Width")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Bandwidth")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Height")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("Interval")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("ThumbnailCount")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("TileHeight")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("TileWidth")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ItemId", "Width");
+
+ b.ToTable("TrickplayInfos");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
+ {
+ b.Property<Guid>("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TEXT");
+
+ b.Property<string>("AudioLanguagePreference")
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("AuthenticationProviderId")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CastReceiverId")
+ .HasMaxLength(32)
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("DisplayCollectionsView")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("DisplayMissingEpisodes")
+ .HasColumnType("INTEGER");
+
+ 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<DateTime?>("LastActivityDate")
+ .HasColumnType("TEXT");
+
+ b.Property<DateTime?>("LastLoginDate")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("LoginAttemptsBeforeLockout")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("MaxActiveSessions")
+ .HasColumnType("INTEGER");
+
+ b.Property<int?>("MaxParentalAgeRating")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("MustUpdatePassword")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Password")
+ .HasMaxLength(65535)
+ .HasColumnType("TEXT");
+
+ b.Property<string>("PasswordResetProviderId")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property<bool>("PlayDefaultAudioTrack")
+ .HasColumnType("INTEGER");
+
+ 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>("SubtitleLanguagePreference")
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.Property<int>("SubtitleMode")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("SyncPlayAccess")
+ .HasColumnType("INTEGER");
+
+ b.Property<string>("Username")
+ .IsRequired()
+ .HasMaxLength(255)
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Username")
+ .IsUnique();
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b =>
+ {
+ b.Property<Guid>("ItemId")
+ .HasColumnType("TEXT");
+
+ b.Property<Guid>("UserId")
+ .HasColumnType("TEXT");
+
+ b.Property<string>("CustomDataKey")
+ .HasColumnType("TEXT");
+
+ b.Property<int?>("AudioStreamIndex")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("IsFavorite")
+ .HasColumnType("INTEGER");
+
+ b.Property<DateTime?>("LastPlayedDate")
+ .HasColumnType("TEXT");
+
+ b.Property<bool?>("Likes")
+ .HasColumnType("INTEGER");
+
+ b.Property<int>("PlayCount")
+ .HasColumnType("INTEGER");
+
+ b.Property<long>("PlaybackPositionTicks")
+ .HasColumnType("INTEGER");
+
+ b.Property<bool>("Played")
+ .HasColumnType("INTEGER");
+
+ b.Property<double?>("Rating")
+ .HasColumnType("REAL");
+
+ b.Property<int?>("SubtitleStreamIndex")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("ItemId", "UserId", "CustomDataKey");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("ItemId", "UserId", "IsFavorite");
+
+ b.HasIndex("ItemId", "UserId", "LastPlayedDate");
+
+ b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks");
+
+ b.HasIndex("ItemId", "UserId", "Played");
+
+ b.ToTable("UserData");
+ });
+
+ 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.AncestorId", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("Children")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem")
+ .WithMany("ParentAncestors")
+ .HasForeignKey("ParentItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+
+ b.Navigation("ParentItem");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany()
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("Images")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("LockedFields")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("Provider")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("TrailerTypes")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("Chapters")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", null)
+ .WithMany("DisplayPreferences")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null)
+ .WithMany("HomeSections")
+ .HasForeignKey("DisplayPreferencesId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", null)
+ .WithOne("ProfileImage")
+ .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", null)
+ .WithMany("ItemDisplayPreferences")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("ItemValues")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue")
+ .WithMany("BaseItemsMap")
+ .HasForeignKey("ItemValueId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+
+ b.Navigation("ItemValue");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("MediaStreams")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("Peoples")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Jellyfin.Data.Entities.People", "People")
+ .WithMany("BaseItems")
+ .HasForeignKey("PeopleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+
+ b.Navigation("People");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", null)
+ .WithMany("Permissions")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", null)
+ .WithMany("Preferences")
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b =>
+ {
+ b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item")
+ .WithMany("UserData")
+ .HasForeignKey("ItemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Jellyfin.Data.Entities.User", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Item");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b =>
+ {
+ b.Navigation("Chapters");
+
+ b.Navigation("Children");
+
+ b.Navigation("Images");
+
+ b.Navigation("ItemValues");
+
+ b.Navigation("LockedFields");
+
+ b.Navigation("MediaStreams");
+
+ b.Navigation("ParentAncestors");
+
+ b.Navigation("Peoples");
+
+ b.Navigation("Provider");
+
+ b.Navigation("TrailerTypes");
+
+ b.Navigation("UserData");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b =>
+ {
+ b.Navigation("HomeSections");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b =>
+ {
+ b.Navigation("BaseItemsMap");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.People", b =>
+ {
+ b.Navigation("BaseItems");
+ });
+
+ modelBuilder.Entity("Jellyfin.Data.Entities.User", b =>
+ {
+ b.Navigation("AccessSchedules");
+
+ b.Navigation("DisplayPreferences");
+
+ b.Navigation("ItemDisplayPreferences");
+
+ b.Navigation("Permissions");
+
+ b.Navigation("Preferences");
+
+ b.Navigation("ProfileImage");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs
new file mode 100644
index 0000000000..e82575e418
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs
@@ -0,0 +1,40 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Jellyfin.Server.Implementations.Migrations
+{
+ /// <inheritdoc />
+ public partial class FixedCollation : Migration
+ {
+ /// <inheritdoc />
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn<string>(
+ name: "Username",
+ table: "Users",
+ type: "TEXT",
+ maxLength: 255,
+ nullable: false,
+ oldClrType: typeof(string),
+ oldType: "TEXT",
+ oldMaxLength: 255,
+ oldCollation: "NOCASE");
+ }
+
+ /// <inheritdoc />
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn<string>(
+ name: "Username",
+ table: "Users",
+ type: "TEXT",
+ maxLength: 255,
+ nullable: false,
+ collation: "NOCASE",
+ oldClrType: typeof(string),
+ oldType: "TEXT",
+ oldMaxLength: 255);
+ }
+ }
+}
diff --git a/Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs
index a329f1ef16..a329f1ef16 100644
--- a/Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs
index 2c60dd7a62..2c60dd7a62 100644
--- a/Jellyfin.Server.Implementations/Migrations/20250204092455_MakeStartEndDateNullable.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs
index 48919c9b5d..48919c9b5d 100644
--- a/Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.Designer.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs
index 1e904e833e..1e904e833e 100644
--- a/Jellyfin.Server.Implementations/Migrations/20250214031148_ChannelIdGuid.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs
diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs
index fef122886c..79587a9c33 100644
--- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs
@@ -1244,8 +1244,7 @@ namespace Jellyfin.Server.Implementations.Migrations
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(255)
- .HasColumnType("TEXT")
- .UseCollation("NOCASE");
+ .HasColumnType("TEXT");
b.HasKey("Id");
diff --git a/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs
index 500c4a1c72..448bd2fc8b 100644
--- a/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs
@@ -1,3 +1,4 @@
+using Jellyfin.Database.Providers.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Logging.Abstractions;
@@ -8,14 +9,17 @@ namespace Jellyfin.Server.Implementations.Migrations
/// The design time factory for <see cref="JellyfinDbContext"/>.
/// This is only used for the creation of migrations and not during runtime.
/// </summary>
- internal class DesignTimeJellyfinDbFactory : IDesignTimeDbContextFactory<JellyfinDbContext>
+ internal sealed class SqliteDesignTimeJellyfinDbFactory : IDesignTimeDbContextFactory<JellyfinDbContext>
{
public JellyfinDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<JellyfinDbContext>();
- optionsBuilder.UseSqlite("Data Source=jellyfin.db");
+ optionsBuilder.UseSqlite("Data Source=jellyfin.db", f => f.MigrationsAssembly(GetType().Assembly));
- return new JellyfinDbContext(optionsBuilder.Options, NullLogger<JellyfinDbContext>.Instance);
+ return new JellyfinDbContext(
+ optionsBuilder.Options,
+ NullLogger<JellyfinDbContext>.Instance,
+ new SqliteDatabaseProvider(null!, NullLogger<SqliteDatabaseProvider>.Instance));
}
}
}
diff --git a/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs
index 79ae1661aa..79ae1661aa 100644
--- a/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..6c5c7107ea
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs
@@ -0,0 +1,23 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Jellyfin.Database.Providers.Sqlite")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Jellyfin Project")]
+[assembly: AssemblyProduct("Jellyfin Server")]
+[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+[assembly: InternalsVisibleTo("Jellyfin.Server.Implementations.Tests")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs
new file mode 100644
index 0000000000..2aa3522d8a
--- /dev/null
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs
@@ -0,0 +1,87 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Server.Implementations;
+using MediaBrowser.Common.Configuration;
+using Microsoft.Data.Sqlite;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+
+namespace Jellyfin.Database.Providers.Sqlite;
+
+/// <summary>
+/// Configures jellyfin to use an SQLite database.
+/// </summary>
+[JellyfinDatabaseProviderKey("Jellyfin-SQLite")]
+public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
+{
+ private readonly IApplicationPaths _applicationPaths;
+ private readonly ILogger<SqliteDatabaseProvider> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SqliteDatabaseProvider"/> class.
+ /// </summary>
+ /// <param name="applicationPaths">Service to construct the fallback when the old data path configuration is used.</param>
+ /// <param name="logger">A logger.</param>
+ public SqliteDatabaseProvider(IApplicationPaths applicationPaths, ILogger<SqliteDatabaseProvider> logger)
+ {
+ _applicationPaths = applicationPaths;
+ _logger = logger;
+ }
+
+ /// <inheritdoc/>
+ public IDbContextFactory<JellyfinDbContext>? DbContextFactory { get; set; }
+
+ /// <inheritdoc/>
+ public void Initialise(DbContextOptionsBuilder options)
+ {
+ options.UseSqlite(
+ $"Filename={Path.Combine(_applicationPaths.DataPath, "jellyfin.db")};Pooling=false",
+ sqLiteOptions => sqLiteOptions.MigrationsAssembly(GetType().Assembly));
+ }
+
+ /// <inheritdoc/>
+ public async Task RunScheduledOptimisation(CancellationToken cancellationToken)
+ {
+ var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
+ await using (context.ConfigureAwait(false))
+ {
+ if (context.Database.IsSqlite())
+ {
+ await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false);
+ await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
+ _logger.LogInformation("jellyfin.db optimized successfully!");
+ }
+ else
+ {
+ _logger.LogInformation("This database doesn't support optimization");
+ }
+ }
+ }
+
+ /// <inheritdoc/>
+ public void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.SetDefaultDateTimeKind(DateTimeKind.Utc);
+ }
+
+ /// <inheritdoc/>
+ public async Task RunShutdownTask(CancellationToken cancellationToken)
+ {
+ // Run before disposing the application
+ var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
+ await using (context.ConfigureAwait(false))
+ {
+ await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false);
+ }
+
+ SqliteConnection.ClearAllPools();
+ }
+
+ /// <inheritdoc/>
+ public void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
+ {
+ configurationBuilder.Conventions.Add(_ => new DoNotUseReturningClauseConvention());
+ }
+}
diff --git a/Jellyfin.Server.Implementations/ValueConverters/DateTimeKindValueConverter.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs
index 2e585c92df..2e585c92df 100644
--- a/Jellyfin.Server.Implementations/ValueConverters/DateTimeKindValueConverter.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs
diff --git a/src/Jellyfin.Database/readme.md b/src/Jellyfin.Database/readme.md
new file mode 100644
index 0000000000..d320b4d5e8
--- /dev/null
+++ b/src/Jellyfin.Database/readme.md
@@ -0,0 +1,25 @@
+# How to run EFCore migrations
+
+This shall provide context on how to work with entity frameworks multi provider migration feature.
+
+Jellyfin will support multiple database providers in the future, namely SQLite as its default and the experimental PostgreSQL.
+
+Each provider has its own set of migrations, as they contain provider specific instructions to migrate the specific changes to their respective systems.
+
+When creating a new migration, you always have to create migrations for all providers. This is supported via the following syntax:
+
+```cmd
+dotnet ef migrations add MIGRATION_NAME --project "PATH_TO_PROJECT" -- --provider PROVIDER_KEY
+```
+
+with SQLite currently being the only supported provider, you need to run the Entity Framework tool with the correct project to tell EFCore where to store the migrations and the correct provider key to tell Jellyfin to load that provider.
+
+The example is made from the root folder of the project e.g for codespaces `/workspaces/jellyfin`
+
+```cmd
+dotnet ef migrations add {MIGRATION_NAME} --project "src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite" -- --migration-provider Jellyfin-SQLite
+```
+
+If you get the error: `Run "dotnet tool restore" to make the "dotnet-ef" command available.` Run `dotnet restore`.
+
+in the event that you get the error: `System.UnauthorizedAccessException: Access to the path '/src/Jellyfin.Database' is denied.` you have to restore as sudo and then run `ef migrations` as sudo too.
diff --git a/src/Jellyfin.LiveTv/LiveTvManager.cs b/src/Jellyfin.LiveTv/LiveTvManager.cs
index 0c85dc434b..da98606a4b 100644
--- a/src/Jellyfin.LiveTv/LiveTvManager.cs
+++ b/src/Jellyfin.LiveTv/LiveTvManager.cs
@@ -8,6 +8,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
diff --git a/src/Jellyfin.LiveTv/Recordings/RecordingNotifier.cs b/src/Jellyfin.LiveTv/Recordings/RecordingNotifier.cs
index e63afa6260..1d571805b8 100644
--- a/src/Jellyfin.LiveTv/Recordings/RecordingNotifier.cs
+++ b/src/Jellyfin.LiveTv/Recordings/RecordingNotifier.cs
@@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Library;
diff --git a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs
index ffb9967038..6b3afc9357 100644
--- a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs
+++ b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs
@@ -6,6 +6,7 @@ using AutoFixture;
using AutoFixture.AutoMoq;
using Jellyfin.Api.Auth;
using Jellyfin.Api.Constants;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Authentication;
diff --git a/tests/Jellyfin.Api.Tests/TestHelpers.cs b/tests/Jellyfin.Api.Tests/TestHelpers.cs
index 12cf025bc5..d84da89e28 100644
--- a/tests/Jellyfin.Api.Tests/TestHelpers.cs
+++ b/tests/Jellyfin.Api.Tests/TestHelpers.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.Net;
using System.Security.Claims;
using Jellyfin.Api.Constants;
+using Jellyfin.Data;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Server.Implementations.Users;
diff --git a/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs b/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs
index e6ccae1830..3fe2caca79 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/EfMigrations/EfMigrationTests.cs
@@ -1,5 +1,3 @@
-using System;
-using System.Threading.Tasks;
using Jellyfin.Server.Implementations.Migrations;
using Microsoft.EntityFrameworkCore;
using Xunit;
@@ -9,10 +7,10 @@ namespace Jellyfin.Server.Implementations.Tests.EfMigrations;
public class EfMigrationTests
{
[Fact]
- public void CheckForUnappliedMigrations()
+ public void CheckForUnappliedMigrations_SqLite()
{
- var dbDesignContext = new DesignTimeJellyfinDbFactory();
+ var dbDesignContext = new SqliteDesignTimeJellyfinDbFactory();
var context = dbDesignContext.CreateDbContext([]);
- Assert.False(context.Database.HasPendingModelChanges(), "There are unapplied changes to the EfCore model. Please create a Migration.");
+ Assert.False(context.Database.HasPendingModelChanges(), "There are unapplied changes to the EFCore model for SQLite. Please create a Migration.");
}
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
index 4f018ba694..4e2604e6e1 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
+++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
@@ -29,6 +29,7 @@
<ProjectReference Include="..\..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
<ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
<ProjectReference Include="..\Jellyfin.Server.Integration.Tests\Jellyfin.Server.Integration.Tests.csproj" />
+ <ProjectReference Include="..\..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
</ItemGroup>
</Project>
diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
index 78b32d2785..a7fec2960c 100644
--- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
+++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs
@@ -13,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
+using Moq;
using Serilog;
using Serilog.Extensions.Logging;
@@ -102,7 +103,7 @@ namespace Jellyfin.Server.Integration.Tests
var host = builder.Build();
var appHost = (TestAppHost)host.Services.GetRequiredService<IApplicationHost>();
appHost.ServiceProvider = host.Services;
- appHost.InitializeServices().GetAwaiter().GetResult();
+ appHost.InitializeServices(Mock.Of<IConfiguration>()).GetAwaiter().GetResult();
host.Start();
appHost.RunStartupTasksAsync().GetAwaiter().GetResult();