Преглед на файлове

Prepared Seperation of Database components for future multi provider support

JPVenson преди 4 месеца
родител
ревизия
aa811eb1e3
променени са 100 файла, в които са добавени 260 реда и са изтрити 254 реда
  1. 14 0
      .devcontainer/devcontainer.json
  2. 1 0
      Directory.Packages.props
  3. 1 0
      Emby.Server.Implementations/Emby.Server.Implementations.csproj
  4. 1 0
      Emby.Server.Implementations/HttpServer/Security/AuthService.cs
  5. 1 0
      Emby.Server.Implementations/Library/LibraryManager.cs
  6. 1 0
      Emby.Server.Implementations/Library/MediaSourceManager.cs
  7. 1 0
      Emby.Server.Implementations/Library/UserViewManager.cs
  8. 6 15
      Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs
  9. 1 0
      Emby.Server.Implementations/Session/SessionManager.cs
  10. 1 0
      Emby.Server.Implementations/TV/TVSeriesManager.cs
  11. 1 0
      Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
  12. 1 0
      Jellyfin.Api/Auth/DefaultAuthorizationPolicy/DefaultAuthorizationHandler.cs
  13. 1 0
      Jellyfin.Api/Auth/UserPermissionPolicy/UserPermissionHandler.cs
  14. 1 0
      Jellyfin.Api/Controllers/ItemsController.cs
  15. 1 0
      Jellyfin.Api/Controllers/UserController.cs
  16. 1 0
      Jellyfin.Api/Helpers/MediaInfoHelper.cs
  17. 1 0
      Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
  18. 1 0
      Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
  19. 0 31
      Jellyfin.Data/Interfaces/IHasPermissions.cs
  20. 4 0
      Jellyfin.Data/Jellyfin.Data.csproj
  21. 220 0
      Jellyfin.Data/UserEntityExtensions.cs
  22. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AccessSchedule.cs
  23. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ActivityLog.cs
  24. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AncestorId.cs
  25. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AttachmentStreamInfo.cs
  26. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs
  27. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemExtraType.cs
  28. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemImageInfo.cs
  29. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemMetadataField.cs
  30. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemProvider.cs
  31. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTrailerType.cs
  32. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Chapter.cs
  33. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/CustomItemDisplayPreferences.cs
  34. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/DisplayPreferences.cs
  35. 0 12
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Group.cs
  36. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/HomeSection.cs
  37. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfo.cs
  38. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfoImageType.cs
  39. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemDisplayPreferences.cs
  40. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValue.cs
  41. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueMap.cs
  42. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueType.cs
  43. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Artwork.cs
  44. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Book.cs
  45. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/BookMetadata.cs
  46. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Chapter.cs
  47. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Collection.cs
  48. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CollectionItem.cs
  49. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Company.cs
  50. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CompanyMetadata.cs
  51. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItem.cs
  52. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItemMetadata.cs
  53. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Episode.cs
  54. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/EpisodeMetadata.cs
  55. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Genre.cs
  56. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/ItemMetadata.cs
  57. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Library.cs
  58. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/LibraryItem.cs
  59. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFile.cs
  60. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFileStream.cs
  61. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProvider.cs
  62. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProviderId.cs
  63. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Movie.cs
  64. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MovieMetadata.cs
  65. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbum.cs
  66. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbumMetadata.cs
  67. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Person.cs
  68. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PersonRole.cs
  69. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Photo.cs
  70. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PhotoMetadata.cs
  71. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Rating.cs
  72. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/RatingSource.cs
  73. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Release.cs
  74. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Season.cs
  75. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeasonMetadata.cs
  76. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Series.cs
  77. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeriesMetadata.cs
  78. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Track.cs
  79. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/TrackMetadata.cs
  80. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaSegment.cs
  81. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamInfo.cs
  82. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamTypeEntity.cs
  83. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/People.cs
  84. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/PeopleBaseItemMap.cs
  85. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Permission.cs
  86. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Preference.cs
  87. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ProgramAudioEntity.cs
  88. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/ApiKey.cs
  89. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/Device.cs
  90. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/DeviceOptions.cs
  91. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/TrickplayInfo.cs
  92. 0 196
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/User.cs
  93. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Entities/UserData.cs
  94. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ArtKind.cs
  95. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ChromecastVersion.cs
  96. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/DynamicDayOfWeek.cs
  97. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/HomeSectionType.cs
  98. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/IndexingKind.cs
  99. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaFileKind.cs
  100. 0 0
      Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaSegmentType.cs

+ 14 - 0
.devcontainer/devcontainer.json

@@ -24,5 +24,19 @@
     "hostRequirements": {
         "memory": "8gb",
         "cpus": 4
+    },  "remoteEnv": {
+        "JELLYFIN_DATA_DIR": "/config"
+    },
+    "mounts": [
+        "source=/opt/docker/data/jellyfin/testConfig/,target=/config,type=bind,consistency=cached",
+        "source=/opt/docker/data/jellyfin/config10.9.11/metadata,target=/config/metadata,type=bind,consistency=cached",
+        "source=/mnt/video,target=/media,type=bind,consistency=cached"
+    ],
+    "customizations": {
+        "vscode": {
+            "extensions": [
+                "alexcvzz.vscode-sqlite"
+            ]
+        }
     }
 }

+ 1 - 0
Directory.Packages.props

@@ -31,6 +31,7 @@
     <PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1" />
     <PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.1" />
     <PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.1" />
+    <PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.1" />
     <PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.1" />
     <PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="9.0.1" />
     <PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="9.0.1" />

+ 1 - 0
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="..\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
   </ItemGroup>
 
   <ItemGroup>

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 6 - 15
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)
             {

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 1 - 0
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;

+ 0 - 31
Jellyfin.Data/Interfaces/IHasPermissions.cs

@@ -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);
-    }
-}

+ 4 - 0
Jellyfin.Data/Jellyfin.Data.csproj

@@ -38,6 +38,10 @@
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
   </ItemGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
+  </ItemGroup>
+
   <ItemGroup>
     <PackageReference Include="Microsoft.Extensions.Logging" />
   </ItemGroup>

+ 220 - 0
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;
+    }
+}

+ 0 - 0
Jellyfin.Data/Entities/AccessSchedule.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AccessSchedule.cs


+ 0 - 0
Jellyfin.Data/Entities/ActivityLog.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ActivityLog.cs


+ 0 - 0
Jellyfin.Data/Entities/AncestorId.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AncestorId.cs


+ 0 - 0
Jellyfin.Data/Entities/AttachmentStreamInfo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/AttachmentStreamInfo.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemEntity.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemExtraType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemExtraType.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemImageInfo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemImageInfo.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemMetadataField.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemMetadataField.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemProvider.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemProvider.cs


+ 0 - 0
Jellyfin.Data/Entities/BaseItemTrailerType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTrailerType.cs


+ 0 - 0
Jellyfin.Data/Entities/Chapter.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Chapter.cs


+ 0 - 0
Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/CustomItemDisplayPreferences.cs


+ 0 - 0
Jellyfin.Data/Entities/DisplayPreferences.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/DisplayPreferences.cs


+ 0 - 12
Jellyfin.Data/Entities/Group.cs → 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()
         {

+ 0 - 0
Jellyfin.Data/Entities/HomeSection.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/HomeSection.cs


+ 0 - 0
Jellyfin.Data/Entities/ImageInfo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfo.cs


+ 0 - 0
Jellyfin.Data/Entities/ImageInfoImageType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ImageInfoImageType.cs


+ 0 - 0
Jellyfin.Data/Entities/ItemDisplayPreferences.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemDisplayPreferences.cs


+ 0 - 0
Jellyfin.Data/Entities/ItemValue.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValue.cs


+ 0 - 0
Jellyfin.Data/Entities/ItemValueMap.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueMap.cs


+ 0 - 0
Jellyfin.Data/Entities/ItemValueType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ItemValueType.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Artwork.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Artwork.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Book.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Book.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/BookMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/BookMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Chapter.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Chapter.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Collection.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Collection.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/CollectionItem.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CollectionItem.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Company.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Company.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/CompanyMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CompanyMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/CustomItem.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItem.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/CustomItemMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/CustomItemMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Episode.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Episode.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/EpisodeMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/EpisodeMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Genre.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Genre.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/ItemMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/ItemMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Library.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Library.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/LibraryItem.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/LibraryItem.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MediaFile.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFile.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MediaFileStream.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MediaFileStream.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MetadataProvider.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProvider.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MetadataProviderId.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MetadataProviderId.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Movie.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Movie.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MovieMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MovieMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MusicAlbum.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbum.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/MusicAlbumMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/MusicAlbumMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Person.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Person.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/PersonRole.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PersonRole.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Photo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Photo.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/PhotoMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/PhotoMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Rating.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Rating.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/RatingSource.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/RatingSource.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Release.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Release.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Season.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Season.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/SeasonMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeasonMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Series.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Series.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/SeriesMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/SeriesMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/Track.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/Track.cs


+ 0 - 0
Jellyfin.Data/Entities/Libraries/TrackMetadata.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Libraries/TrackMetadata.cs


+ 0 - 0
Jellyfin.Data/Entities/MediaSegment.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaSegment.cs


+ 0 - 0
Jellyfin.Data/Entities/MediaStreamInfo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamInfo.cs


+ 0 - 0
Jellyfin.Data/Entities/MediaStreamTypeEntity.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/MediaStreamTypeEntity.cs


+ 0 - 0
Jellyfin.Data/Entities/People.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/People.cs


+ 0 - 0
Jellyfin.Data/Entities/PeopleBaseItemMap.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/PeopleBaseItemMap.cs


+ 0 - 0
Jellyfin.Data/Entities/Permission.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Permission.cs


+ 0 - 0
Jellyfin.Data/Entities/Preference.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Preference.cs


+ 0 - 0
Jellyfin.Data/Entities/ProgramAudioEntity.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/ProgramAudioEntity.cs


+ 0 - 0
Jellyfin.Data/Entities/Security/ApiKey.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/ApiKey.cs


+ 0 - 0
Jellyfin.Data/Entities/Security/Device.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/Device.cs


+ 0 - 0
Jellyfin.Data/Entities/Security/DeviceOptions.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Security/DeviceOptions.cs


+ 0 - 0
Jellyfin.Data/Entities/TrickplayInfo.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/TrickplayInfo.cs


+ 0 - 196
Jellyfin.Data/Entities/User.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/User.cs

@@ -15,11 +15,6 @@ namespace Jellyfin.Data.Entities
     /// </summary>
     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.
@@ -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;
-        }
     }
 }

+ 0 - 0
Jellyfin.Data/Entities/UserData.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Entities/UserData.cs


+ 0 - 0
Jellyfin.Data/Enums/ArtKind.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ArtKind.cs


+ 0 - 0
Jellyfin.Data/Enums/ChromecastVersion.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/ChromecastVersion.cs


+ 0 - 0
Jellyfin.Data/Enums/DynamicDayOfWeek.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/DynamicDayOfWeek.cs


+ 0 - 0
Jellyfin.Data/Enums/HomeSectionType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/HomeSectionType.cs


+ 0 - 0
Jellyfin.Data/Enums/IndexingKind.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/IndexingKind.cs


+ 0 - 0
Jellyfin.Data/Enums/MediaFileKind.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaFileKind.cs


+ 0 - 0
Jellyfin.Data/Enums/MediaSegmentType.cs → Jellyfin.Database/Jellyfin.Database.Implementations/Enums/MediaSegmentType.cs


Някои файлове не бяха показани, защото твърде много файлове са промени