Patrick Barron 5 роки тому
батько
коміт
b94afc597c

+ 0 - 11
Emby.Server.Implementations/ApplicationHost.cs

@@ -46,8 +46,6 @@ using Emby.Server.Implementations.Session;
 using Emby.Server.Implementations.SocketSharp;
 using Emby.Server.Implementations.TV;
 using Emby.Server.Implementations.Updates;
-using Jellyfin.Server.Implementations;
-using Jellyfin.Server.Implementations.Activity;
 using MediaBrowser.Api;
 using MediaBrowser.Common;
 using MediaBrowser.Common.Configuration;
@@ -547,13 +545,6 @@ namespace Emby.Server.Implementations
 
             serviceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
 
-            // TODO: properly set up scoping and switch to AddDbContextPool
-            serviceCollection.AddDbContext<JellyfinDb>(
-                options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
-                ServiceLifetime.Transient);
-
-            serviceCollection.AddSingleton<JellyfinDbProvider>();
-
             serviceCollection.AddSingleton(_fileSystemManager);
             serviceCollection.AddSingleton<TvdbClientManager>();
 
@@ -664,8 +655,6 @@ namespace Emby.Server.Implementations
 
             serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
 
-            serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
-
             serviceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
             serviceCollection.AddSingleton<ISessionContext, SessionContext>();
 

+ 0 - 6
Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs

@@ -193,12 +193,6 @@ namespace Emby.Server.Implementations.Configuration
                 changed = true;
             }
 
-            if (!config.CameraUploadUpgraded)
-            {
-                config.CameraUploadUpgraded = true;
-                changed = true;
-            }
-
             if (!config.CollectionsUpgraded)
             {
                 config.CollectionsUpgraded = true;

+ 1 - 2
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -9,7 +9,6 @@
     <ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" />
     <ProjectReference Include="..\Emby.Notifications\Emby.Notifications.csproj" />
     <ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" />
-    <ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
     <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
     <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
@@ -51,7 +50,7 @@
   </ItemGroup>
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFramework>netstandard2.1</TargetFramework>
     <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
   </PropertyGroup>

+ 43 - 40
Jellyfin.Data/Entities/ActivityLog.cs

@@ -5,34 +5,18 @@ using Microsoft.Extensions.Logging;
 
 namespace Jellyfin.Data.Entities
 {
-    public partial class ActivityLog
+    /// <summary>
+    /// An entity referencing an activity log entry.
+    /// </summary>
+    public partial class ActivityLog : ISavingChanges
     {
-        partial void Init();
-
-        /// <summary>
-        /// Default constructor. Protected due to required properties, but present because EF needs it.
-        /// </summary>
-        protected ActivityLog()
-        {
-            Init();
-        }
-
-        /// <summary>
-        /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving.
-        /// </summary>
-        public static ActivityLog CreateActivityLogUnsafe()
-        {
-            return new ActivityLog();
-        }
-
         /// <summary>
-        /// Public constructor with required data
+        /// Initializes a new instance of the <see cref="ActivityLog"/> class.
+        /// Public constructor with required data.
         /// </summary>
-        /// <param name="name"></param>
-        /// <param name="type"></param>
-        /// <param name="userId"></param>
-        /// <param name="datecreated"></param>
-        /// <param name="logSeverity"></param>
+        /// <param name="name">The name.</param>
+        /// <param name="type">The type.</param>
+        /// <param name="userId">The user id.</param>
         public ActivityLog(string name, string type, Guid userId)
         {
             if (string.IsNullOrEmpty(name))
@@ -54,14 +38,21 @@ namespace Jellyfin.Data.Entities
             Init();
         }
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ActivityLog"/> class.
+        /// Default constructor. Protected due to required properties, but present because EF needs it.
+        /// </summary>
+        protected ActivityLog()
+        {
+            Init();
+        }
+
         /// <summary>
         /// Static create function (for use in LINQ queries, etc.)
         /// </summary>
-        /// <param name="name"></param>
-        /// <param name="type"></param>
-        /// <param name="userId"></param>
-        /// <param name="datecreated"></param>
-        /// <param name="logseverity"></param>
+        /// <param name="name">The name.</param>
+        /// <param name="type">The type.</param>
+        /// <param name="userId">The user's id.</param>
         public static ActivityLog Create(string name, string type, Guid userId)
         {
             return new ActivityLog(name, type, userId);
@@ -72,7 +63,8 @@ namespace Jellyfin.Data.Entities
          *************************************************************************/
 
         /// <summary>
-        /// Identity, Indexed, Required
+        /// Gets the identity of this instance.
+        /// This is the key in the backing database.
         /// </summary>
         [Key]
         [Required]
@@ -80,7 +72,8 @@ namespace Jellyfin.Data.Entities
         public int Id { get; protected set; }
 
         /// <summary>
-        /// Required, Max length = 512
+        /// Gets or sets the name.
+        /// Required, Max length = 512.
         /// </summary>
         [Required]
         [MaxLength(512)]
@@ -88,21 +81,24 @@ namespace Jellyfin.Data.Entities
         public string Name { get; set; }
 
         /// <summary>
-        /// Max length = 512
+        /// Gets or sets the overview.
+        /// Max length = 512.
         /// </summary>
         [MaxLength(512)]
         [StringLength(512)]
         public string Overview { get; set; }
 
         /// <summary>
-        /// Max length = 512
+        /// Gets or sets the short overview.
+        /// Max length = 512.
         /// </summary>
         [MaxLength(512)]
         [StringLength(512)]
         public string ShortOverview { get; set; }
 
         /// <summary>
-        /// Required, Max length = 256
+        /// Gets or sets the type.
+        /// Required, Max length = 256.
         /// </summary>
         [Required]
         [MaxLength(256)]
@@ -110,41 +106,48 @@ namespace Jellyfin.Data.Entities
         public string Type { get; set; }
 
         /// <summary>
-        /// Required
+        /// Gets or sets the user id.
+        /// Required.
         /// </summary>
         [Required]
         public Guid UserId { get; set; }
 
         /// <summary>
-        /// Max length = 256
+        /// Gets or sets the item id.
+        /// Max length = 256.
         /// </summary>
         [MaxLength(256)]
         [StringLength(256)]
         public string ItemId { get; set; }
 
         /// <summary>
-        /// Required
+        /// Gets or sets the date created. This should be in UTC.
+        /// Required.
         /// </summary>
         [Required]
         public DateTime DateCreated { get; set; }
 
         /// <summary>
-        /// Required
+        /// Gets or sets the log severity. Default is <see cref="LogLevel.Trace"/>.
+        /// Required.
         /// </summary>
         [Required]
         public LogLevel LogSeverity { get; set; }
 
         /// <summary>
+        /// Gets or sets the row version.
         /// Required, ConcurrencyToken.
         /// </summary>
         [ConcurrencyCheck]
         [Required]
         public uint RowVersion { get; set; }
 
+        partial void Init();
+
+        /// <inheritdoc />
         public void OnSavingChanges()
         {
             RowVersion++;
         }
     }
 }
-

+ 1 - 5
Jellyfin.Data/Jellyfin.Data.csproj

@@ -17,14 +17,10 @@
     <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
   </ItemGroup>
-  
+
   <ItemGroup>
     <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.3" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.3" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
   </ItemGroup>
 
 </Project>

+ 7 - 7
Jellyfin.Server.Implementations/Activity/ActivityManager.cs

@@ -50,31 +50,31 @@ namespace Jellyfin.Server.Implementations.Activity
 
         /// <inheritdoc/>
         public QueryResult<ActivityLogEntry> GetPagedResult(
-            Func<IQueryable<ActivityLog>, IEnumerable<ActivityLog>> func,
+            Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>> func,
             int? startIndex,
             int? limit)
         {
             using var dbContext = _provider.CreateContext();
 
-            var result = func.Invoke(dbContext.ActivityLogs).AsQueryable();
+            var query = func(dbContext.ActivityLogs).OrderByDescending(entry => entry.DateCreated).AsQueryable();
 
             if (startIndex.HasValue)
             {
-                result = result.Where(entry => entry.Id >= startIndex.Value);
+                query = query.Skip(startIndex.Value);
             }
 
             if (limit.HasValue)
             {
-                result = result.OrderByDescending(entry => entry.DateCreated).Take(limit.Value);
+                query = query.Take(limit.Value);
             }
 
             // This converts the objects from the new database model to the old for compatibility with the existing API.
-            var list = result.Select(entry => ConvertToOldModel(entry)).ToList();
+            var list = query.AsEnumerable().Select(ConvertToOldModel).ToList();
 
-            return new QueryResult<ActivityLogEntry>()
+            return new QueryResult<ActivityLogEntry>
             {
                 Items = list,
-                TotalRecordCount = list.Count
+                TotalRecordCount = dbContext.ActivityLogs.Count()
             };
         }
 

+ 8 - 0
Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj

@@ -25,6 +25,14 @@
     <Compile Remove="Migrations\20200430214405_InitialSchema.Designer.cs" />
   </ItemGroup>
 
+  <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
+      <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" />

+ 1 - 1
Jellyfin.Server.Implementations/JellyfinDb.cs

@@ -110,7 +110,7 @@ namespace Jellyfin.Server.Implementations
             foreach (var entity in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified))
             {
                 var saveEntity = entity.Entity as ISavingChanges;
-                saveEntity.OnSavingChanges();
+                saveEntity?.OnSavingChanges();
             }
 
             return base.SaveChanges();

+ 1 - 1
Jellyfin.Server.Implementations/JellyfinDbProvider.cs

@@ -27,7 +27,7 @@ namespace Jellyfin.Server.Implementations
         /// <returns>The newly created context.</returns>
         public JellyfinDb CreateContext()
         {
-            return _serviceProvider.GetService<JellyfinDb>();
+            return _serviceProvider.GetRequiredService<JellyfinDb>();
         }
     }
 }

+ 4 - 5
Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.Designer.cs → Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs

@@ -1,5 +1,4 @@
-#pragma warning disable CS1591
-#pragma warning disable SA1601
+#pragma warning disable CS1591
 
 // <auto-generated />
 using System;
@@ -12,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 namespace Jellyfin.Server.Implementations.Migrations
 {
     [DbContext(typeof(JellyfinDb))]
-    [Migration("20200502231229_InitialSchema")]
-    partial class InitialSchema
+    [Migration("20200514181226_AddActivityLog")]
+    partial class AddActivityLog
     {
         protected override void BuildTargetModel(ModelBuilder modelBuilder)
         {
@@ -65,7 +64,7 @@ namespace Jellyfin.Server.Implementations.Migrations
 
                     b.HasKey("Id");
 
-                    b.ToTable("ActivityLog");
+                    b.ToTable("ActivityLogs");
                 });
 #pragma warning restore 612, 618
         }

+ 5 - 5
Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.cs → Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs

@@ -1,4 +1,4 @@
-#pragma warning disable CS1591
+#pragma warning disable CS1591
 #pragma warning disable SA1601
 
 using System;
@@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
 
 namespace Jellyfin.Server.Implementations.Migrations
 {
-    public partial class InitialSchema : Migration
+    public partial class AddActivityLog : Migration
     {
         protected override void Up(MigrationBuilder migrationBuilder)
         {
@@ -14,7 +14,7 @@ namespace Jellyfin.Server.Implementations.Migrations
                 name: "jellyfin");
 
             migrationBuilder.CreateTable(
-                name: "ActivityLog",
+                name: "ActivityLogs",
                 schema: "jellyfin",
                 columns: table => new
                 {
@@ -32,14 +32,14 @@ namespace Jellyfin.Server.Implementations.Migrations
                 },
                 constraints: table =>
                 {
-                    table.PrimaryKey("PK_ActivityLog", x => x.Id);
+                    table.PrimaryKey("PK_ActivityLogs", x => x.Id);
                 });
         }
 
         protected override void Down(MigrationBuilder migrationBuilder)
         {
             migrationBuilder.DropTable(
-                name: "ActivityLog",
+                name: "ActivityLogs",
                 schema: "jellyfin");
         }
     }

+ 3 - 4
Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs

@@ -1,6 +1,3 @@
-#pragma warning disable CS1591
-#pragma warning disable SA1601
-
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Design;
 
@@ -15,7 +12,9 @@ namespace Jellyfin.Server.Implementations.Migrations
         public JellyfinDb CreateDbContext(string[] args)
         {
             var optionsBuilder = new DbContextOptionsBuilder<JellyfinDb>();
-            optionsBuilder.UseSqlite("Data Source=jellyfin.db");
+            optionsBuilder.UseSqlite(
+                "Data Source=jellyfin.db",
+                opt => opt.MigrationsAssembly("Jellyfin.Migrations"));
 
             return new JellyfinDb(optionsBuilder.Options);
         }

+ 1 - 3
Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs

@@ -1,9 +1,7 @@
 // <auto-generated />
 using System;
-using Jellyfin.Server.Implementations;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 
 namespace Jellyfin.Server.Implementations.Migrations
 {
@@ -60,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Migrations
 
                     b.HasKey("Id");
 
-                    b.ToTable("ActivityLog");
+                    b.ToTable("ActivityLogs");
                 });
 #pragma warning restore 612, 618
         }

+ 14 - 0
Jellyfin.Server/CoreAppHost.cs

@@ -1,12 +1,17 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Reflection;
 using Emby.Drawing;
 using Emby.Server.Implementations;
 using Jellyfin.Drawing.Skia;
+using Jellyfin.Server.Implementations;
+using Jellyfin.Server.Implementations.Activity;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Activity;
 using MediaBrowser.Model.IO;
+using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 
@@ -56,6 +61,15 @@ namespace Jellyfin.Server
                 Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}.");
             }
 
+            // TODO: Set up scoping and use AddDbContextPool
+            serviceCollection.AddDbContext<JellyfinDb>(
+                    options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"),
+                    ServiceLifetime.Transient);
+
+            serviceCollection.AddSingleton<JellyfinDbProvider>();
+
+            serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
+
             base.RegisterServices(serviceCollection);
         }
 

+ 1 - 7
Jellyfin.Server/Jellyfin.Server.csproj

@@ -13,9 +13,6 @@
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <Nullable>enable</Nullable>
-
-    <!-- Used for generating migrations for EF Core -->
-    <GenerateRuntimeConfigurationFiles>True</GenerateRuntimeConfigurationFiles>
   </PropertyGroup>
 
   <ItemGroup>
@@ -44,10 +41,6 @@
 
   <ItemGroup>
     <PackageReference Include="CommandLineParser" Version="2.7.82" />
-    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3">
-      <PrivateAssets>all</PrivateAssets>
-      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
-    </PackageReference>
     <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.3" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
     <PackageReference Include="prometheus-net" Version="3.5.0" />
@@ -67,6 +60,7 @@
     <ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
     <ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
     <ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" />
+    <ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
   </ItemGroup>
 
 </Project>

+ 12 - 1
MediaBrowser.Api/System/ActivityLogService.cs

@@ -1,3 +1,7 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using Jellyfin.Data.Entities;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Net;
 using MediaBrowser.Model.Activity;
@@ -47,7 +51,14 @@ namespace MediaBrowser.Api.System
 
         public object Get(GetActivityLogs request)
         {
-            var result = _activityManager.GetPagedResult(request.StartIndex, request.Limit);
+            DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
+                (DateTime?)null :
+                DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
+
+            var filterFunc = new Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>>(
+                entries => entries.Where(entry => entry.DateCreated >= minDate));
+
+            var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit);
 
             return ToOptimizedResult(result);
         }

+ 1 - 2
MediaBrowser.Model/Activity/IActivityManager.cs

@@ -1,7 +1,6 @@
 #pragma warning disable CS1591
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using Jellyfin.Data.Entities;
@@ -21,7 +20,7 @@ namespace MediaBrowser.Model.Activity
         QueryResult<ActivityLogEntry> GetPagedResult(int? startIndex, int? limit);
 
         QueryResult<ActivityLogEntry> GetPagedResult(
-            Func<IQueryable<ActivityLog>, IEnumerable<ActivityLog>> func,
+            Func<IQueryable<ActivityLog>, IQueryable<ActivityLog>> func,
             int? startIndex,
             int? limit);
     }

+ 0 - 2
MediaBrowser.Model/Configuration/ServerConfiguration.cs

@@ -79,8 +79,6 @@ namespace MediaBrowser.Model.Configuration
 
         public bool EnableRemoteAccess { get; set; }
 
-        public bool CameraUploadUpgraded { get; set; }
-
         public bool CollectionsUpgraded { get; set; }
 
         /// <summary>

+ 9 - 0
MediaBrowser.Model/Devices/DeviceOptions.cs

@@ -0,0 +1,9 @@
+#pragma warning disable CS1591
+
+namespace MediaBrowser.Model.Devices
+{
+    public class DeviceOptions
+    {
+        public string CustomName { get; set; }
+    }
+}

+ 0 - 23
MediaBrowser.Model/Devices/DevicesOptions.cs

@@ -1,23 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-
-namespace MediaBrowser.Model.Devices
-{
-    public class DevicesOptions
-    {
-        public string[] EnabledCameraUploadDevices { get; set; }
-        public string CameraUploadPath { get; set; }
-        public bool EnableCameraUploadSubfolders { get; set; }
-
-        public DevicesOptions()
-        {
-            EnabledCameraUploadDevices = Array.Empty<string>();
-        }
-    }
-
-    public class DeviceOptions
-    {
-        public string CustomName { get; set; }
-    }
-}