Apply review suggestions

This commit is contained in:
Patrick Barron 2020-05-13 15:03:35 -04:00
parent bac4bf96a0
commit 511d20a100
10 changed files with 88 additions and 314 deletions

View File

@ -8,7 +8,6 @@ using Jellyfin.Data.Entities;
using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates; using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
@ -30,7 +29,7 @@ namespace Emby.Server.Implementations.Activity
/// </summary> /// </summary>
public sealed class ActivityLogEntryPoint : IServerEntryPoint public sealed class ActivityLogEntryPoint : IServerEntryPoint
{ {
private readonly ILogger _logger; private readonly ILogger<ActivityLogEntryPoint> _logger;
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
private readonly ISessionManager _sessionManager; private readonly ISessionManager _sessionManager;
private readonly ITaskManager _taskManager; private readonly ITaskManager _taskManager;
@ -38,14 +37,12 @@ namespace Emby.Server.Implementations.Activity
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly ISubtitleManager _subManager; private readonly ISubtitleManager _subManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDeviceManager _deviceManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ActivityLogEntryPoint"/> class. /// Initializes a new instance of the <see cref="ActivityLogEntryPoint"/> class.
/// </summary> /// </summary>
/// <param name="logger">The logger.</param> /// <param name="logger">The logger.</param>
/// <param name="sessionManager">The session manager.</param> /// <param name="sessionManager">The session manager.</param>
/// <param name="deviceManager">The device manager.</param>
/// <param name="taskManager">The task manager.</param> /// <param name="taskManager">The task manager.</param>
/// <param name="activityManager">The activity manager.</param> /// <param name="activityManager">The activity manager.</param>
/// <param name="localization">The localization manager.</param> /// <param name="localization">The localization manager.</param>
@ -55,7 +52,6 @@ namespace Emby.Server.Implementations.Activity
public ActivityLogEntryPoint( public ActivityLogEntryPoint(
ILogger<ActivityLogEntryPoint> logger, ILogger<ActivityLogEntryPoint> logger,
ISessionManager sessionManager, ISessionManager sessionManager,
IDeviceManager deviceManager,
ITaskManager taskManager, ITaskManager taskManager,
IActivityManager activityManager, IActivityManager activityManager,
ILocalizationManager localization, ILocalizationManager localization,
@ -65,7 +61,6 @@ namespace Emby.Server.Implementations.Activity
{ {
_logger = logger; _logger = logger;
_sessionManager = sessionManager; _sessionManager = sessionManager;
_deviceManager = deviceManager;
_taskManager = taskManager; _taskManager = taskManager;
_activityManager = activityManager; _activityManager = activityManager;
_localization = localization; _localization = localization;
@ -99,25 +94,9 @@ namespace Emby.Server.Implementations.Activity
_userManager.UserPolicyUpdated += OnUserPolicyUpdated; _userManager.UserPolicyUpdated += OnUserPolicyUpdated;
_userManager.UserLockedOut += OnUserLockedOut; _userManager.UserLockedOut += OnUserLockedOut;
_deviceManager.CameraImageUploaded += OnCameraImageUploaded;
return Task.CompletedTask; return Task.CompletedTask;
} }
private async void OnCameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)
{
await CreateLogEntry(new ActivityLog(
string.Format(
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("CameraImageUploadedFrom"),
e.Argument.Device.Name),
NotificationType.CameraImageUploaded.ToString(),
Guid.Empty,
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false);
}
private async void OnUserLockedOut(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserLockedOut(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
{ {
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
@ -126,9 +105,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("UserLockedOutWithName"), _localization.GetLocalizedString("UserLockedOutWithName"),
e.Argument.Name), e.Argument.Name),
NotificationType.UserLockedOut.ToString(), NotificationType.UserLockedOut.ToString(),
e.Argument.Id, e.Argument.Id))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -139,11 +116,9 @@ namespace Emby.Server.Implementations.Activity
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"), _localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
e.Provider, e.Provider,
Emby.Notifications.NotificationEntryPoint.GetItemName(e.Item)), Notifications.NotificationEntryPoint.GetItemName(e.Item)),
"SubtitleDownloadFailure", "SubtitleDownloadFailure",
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture), ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
ShortOverview = e.Exception.Message ShortOverview = e.Exception.Message
@ -181,9 +156,7 @@ namespace Emby.Server.Implementations.Activity
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackStoppedNotificationType(item.MediaType), GetPlaybackStoppedNotificationType(item.MediaType),
user.Id, user.Id))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -218,9 +191,7 @@ namespace Emby.Server.Implementations.Activity
GetItemName(item), GetItemName(item),
e.DeviceName), e.DeviceName),
GetPlaybackNotificationType(item.MediaType), GetPlaybackNotificationType(item.MediaType),
user.Id, user.Id))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -287,9 +258,7 @@ namespace Emby.Server.Implementations.Activity
session.UserName, session.UserName,
session.DeviceName), session.DeviceName),
"SessionEnded", "SessionEnded",
session.UserId, session.UserId)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -308,9 +277,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), _localization.GetLocalizedString("AuthenticationSucceededWithUserName"),
user.Name), user.Name),
"AuthenticationSucceeded", "AuthenticationSucceeded",
user.Id, user.Id)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -327,10 +294,9 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), _localization.GetLocalizedString("FailedLoginAttemptWithUserName"),
e.Argument.Username), e.Argument.Username),
"AuthenticationFailed", "AuthenticationFailed",
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Error)
{ {
LogSeverity = LogLevel.Error,
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
_localization.GetLocalizedString("LabelIpAddressValue"), _localization.GetLocalizedString("LabelIpAddressValue"),
@ -346,9 +312,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("UserPolicyUpdatedWithName"), _localization.GetLocalizedString("UserPolicyUpdatedWithName"),
e.Argument.Name), e.Argument.Name),
"UserPolicyUpdated", "UserPolicyUpdated",
e.Argument.Id, e.Argument.Id))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -360,9 +324,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("UserDeletedWithName"), _localization.GetLocalizedString("UserDeletedWithName"),
e.Argument.Name), e.Argument.Name),
"UserDeleted", "UserDeleted",
Guid.Empty, Guid.Empty))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -374,9 +336,8 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("UserPasswordChangedWithName"), _localization.GetLocalizedString("UserPasswordChangedWithName"),
e.Argument.Name), e.Argument.Name),
"UserPasswordChanged", "UserPasswordChanged",
e.Argument.Id, e.Argument.Id))
DateTime.UtcNow, .ConfigureAwait(false);
LogLevel.Trace)).ConfigureAwait(false);
} }
private async void OnUserCreated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e) private async void OnUserCreated(object sender, GenericEventArgs<MediaBrowser.Controller.Entities.User> e)
@ -387,9 +348,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("UserCreatedWithName"), _localization.GetLocalizedString("UserCreatedWithName"),
e.Argument.Name), e.Argument.Name),
"UserCreated", "UserCreated",
e.Argument.Id, e.Argument.Id))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -409,9 +368,7 @@ namespace Emby.Server.Implementations.Activity
session.UserName, session.UserName,
session.DeviceName), session.DeviceName),
"SessionStarted", "SessionStarted",
session.UserId, session.UserId)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -428,9 +385,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("PluginUpdatedWithName"), _localization.GetLocalizedString("PluginUpdatedWithName"),
e.Argument.Item1.Name), e.Argument.Item1.Name),
NotificationType.PluginUpdateInstalled.ToString(), NotificationType.PluginUpdateInstalled.ToString(),
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -448,9 +403,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("PluginUninstalledWithName"), _localization.GetLocalizedString("PluginUninstalledWithName"),
e.Argument.Name), e.Argument.Name),
NotificationType.PluginUninstalled.ToString(), NotificationType.PluginUninstalled.ToString(),
Guid.Empty, Guid.Empty))
DateTime.UtcNow,
LogLevel.Trace))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -462,9 +415,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("PluginInstalledWithName"), _localization.GetLocalizedString("PluginInstalledWithName"),
e.Argument.name), e.Argument.name),
NotificationType.PluginInstalled.ToString(), NotificationType.PluginInstalled.ToString(),
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -483,9 +434,7 @@ namespace Emby.Server.Implementations.Activity
_localization.GetLocalizedString("NameInstallFailed"), _localization.GetLocalizedString("NameInstallFailed"),
installationInfo.Name), installationInfo.Name),
NotificationType.InstallationFailed.ToString(), NotificationType.InstallationFailed.ToString(),
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format( ShortOverview = string.Format(
CultureInfo.InvariantCulture, CultureInfo.InvariantCulture,
@ -529,10 +478,9 @@ namespace Emby.Server.Implementations.Activity
await CreateLogEntry(new ActivityLog( await CreateLogEntry(new ActivityLog(
string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name), string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
NotificationType.TaskFailed.ToString(), NotificationType.TaskFailed.ToString(),
Guid.Empty, Guid.Empty)
DateTime.UtcNow,
LogLevel.Error)
{ {
LogSeverity = LogLevel.Error,
Overview = string.Join(Environment.NewLine, vals), Overview = string.Join(Environment.NewLine, vals),
ShortOverview = runningTime ShortOverview = runningTime
}).ConfigureAwait(false); }).ConfigureAwait(false);
@ -567,8 +515,6 @@ namespace Emby.Server.Implementations.Activity
_userManager.UserDeleted -= OnUserDeleted; _userManager.UserDeleted -= OnUserDeleted;
_userManager.UserPolicyUpdated -= OnUserPolicyUpdated; _userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
_userManager.UserLockedOut -= OnUserLockedOut; _userManager.UserLockedOut -= OnUserLockedOut;
_deviceManager.CameraImageUploaded -= OnCameraImageUploaded;
} }
/// <summary> /// <summary>
@ -588,7 +534,7 @@ namespace Emby.Server.Implementations.Activity
{ {
int years = days / DaysInYear; int years = days / DaysInYear;
values.Add(CreateValueString(years, "year")); values.Add(CreateValueString(years, "year"));
days = days % DaysInYear; days %= DaysInYear;
} }
// Number of months // Number of months

View File

@ -34,7 +34,6 @@ namespace Emby.Server.Implementations.Devices
private readonly IJsonSerializer _json; private readonly IJsonSerializer _json;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _libraryMonitor;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localizationManager; private readonly ILocalizationManager _localizationManager;
@ -43,9 +42,6 @@ namespace Emby.Server.Implementations.Devices
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated; public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
private readonly object _cameraUploadSyncLock = new object();
private readonly object _capabilitiesSyncLock = new object(); private readonly object _capabilitiesSyncLock = new object();
public DeviceManager( public DeviceManager(
@ -55,13 +51,11 @@ namespace Emby.Server.Implementations.Devices
ILocalizationManager localizationManager, ILocalizationManager localizationManager,
IUserManager userManager, IUserManager userManager,
IFileSystem fileSystem, IFileSystem fileSystem,
ILibraryMonitor libraryMonitor,
IServerConfigurationManager config) IServerConfigurationManager config)
{ {
_json = json; _json = json;
_userManager = userManager; _userManager = userManager;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_libraryMonitor = libraryMonitor;
_config = config; _config = config;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localizationManager = localizationManager; _localizationManager = localizationManager;
@ -194,105 +188,6 @@ namespace Emby.Server.Implementations.Devices
return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N", CultureInfo.InvariantCulture)); return Path.Combine(GetDevicesPath(), id.GetMD5().ToString("N", CultureInfo.InvariantCulture));
} }
public ContentUploadHistory GetCameraUploadHistory(string deviceId)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
lock (_cameraUploadSyncLock)
{
try
{
return _json.DeserializeFromFile<ContentUploadHistory>(path);
}
catch (IOException)
{
return new ContentUploadHistory
{
DeviceId = deviceId
};
}
}
}
public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file)
{
var device = GetDevice(deviceId, false);
var uploadPathInfo = GetUploadPath(device);
var path = uploadPathInfo.Item1;
if (!string.IsNullOrWhiteSpace(file.Album))
{
path = Path.Combine(path, _fileSystem.GetValidFilename(file.Album));
}
path = Path.Combine(path, file.Name);
path = Path.ChangeExtension(path, MimeTypes.ToExtension(file.MimeType) ?? "jpg");
Directory.CreateDirectory(Path.GetDirectoryName(path));
await EnsureLibraryFolder(uploadPathInfo.Item2, uploadPathInfo.Item3).ConfigureAwait(false);
_libraryMonitor.ReportFileSystemChangeBeginning(path);
try
{
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
await stream.CopyToAsync(fs).ConfigureAwait(false);
}
AddCameraUpload(deviceId, file);
}
finally
{
_libraryMonitor.ReportFileSystemChangeComplete(path, true);
}
if (CameraImageUploaded != null)
{
CameraImageUploaded?.Invoke(this, new GenericEventArgs<CameraImageUploadInfo>
{
Argument = new CameraImageUploadInfo
{
Device = device,
FileInfo = file
}
});
}
}
private void AddCameraUpload(string deviceId, LocalFileInfo file)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
Directory.CreateDirectory(Path.GetDirectoryName(path));
lock (_cameraUploadSyncLock)
{
ContentUploadHistory history;
try
{
history = _json.DeserializeFromFile<ContentUploadHistory>(path);
}
catch (IOException)
{
history = new ContentUploadHistory
{
DeviceId = deviceId
};
}
history.DeviceId = deviceId;
var list = history.FilesUploaded.ToList();
list.Add(file);
history.FilesUploaded = list.ToArray();
_json.SerializeToFile(history, path);
}
}
internal Task EnsureLibraryFolder(string path, string name) internal Task EnsureLibraryFolder(string path, string name)
{ {
var existingFolders = _libraryManager var existingFolders = _libraryManager

View File

@ -1,15 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq; using Microsoft.Extensions.Logging;
using System.Runtime.CompilerServices;
namespace Jellyfin.Data.Entities namespace Jellyfin.Data.Entities
{ {
[Table("ActivityLog")]
public partial class ActivityLog public partial class ActivityLog
{ {
partial void Init(); partial void Init();
@ -35,23 +30,26 @@ namespace Jellyfin.Data.Entities
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="userid"></param> /// <param name="userId"></param>
/// <param name="datecreated"></param> /// <param name="datecreated"></param>
/// <param name="logseverity"></param> /// <param name="logSeverity"></param>
public ActivityLog(string name, string type, Guid userid, DateTime datecreated, Microsoft.Extensions.Logging.LogLevel logseverity) public ActivityLog(string name, string type, Guid userId)
{ {
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name)); if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
if (string.IsNullOrEmpty(type))
{
throw new ArgumentNullException(nameof(type));
}
this.Name = name; this.Name = name;
if (string.IsNullOrEmpty(type)) throw new ArgumentNullException(nameof(type));
this.Type = type; this.Type = type;
this.UserId = userId;
this.UserId = userid; this.DateCreated = DateTime.UtcNow;
this.LogSeverity = LogLevel.Trace;
this.DateCreated = datecreated;
this.LogSeverity = logseverity;
Init(); Init();
} }
@ -61,12 +59,12 @@ namespace Jellyfin.Data.Entities
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="userid"></param> /// <param name="userId"></param>
/// <param name="datecreated"></param> /// <param name="datecreated"></param>
/// <param name="logseverity"></param> /// <param name="logseverity"></param>
public static ActivityLog Create(string name, string type, Guid userid, DateTime datecreated, Microsoft.Extensions.Logging.LogLevel logseverity) public static ActivityLog Create(string name, string type, Guid userId)
{ {
return new ActivityLog(name, type, userid, datecreated, logseverity); return new ActivityLog(name, type, userId);
} }
/************************************************************************* /*************************************************************************
@ -134,10 +132,10 @@ namespace Jellyfin.Data.Entities
/// Required /// Required
/// </summary> /// </summary>
[Required] [Required]
public Microsoft.Extensions.Logging.LogLevel LogSeverity { get; set; } public LogLevel LogSeverity { get; set; }
/// <summary> /// <summary>
/// Required, ConcurrenyToken /// Required, ConcurrencyToken.
/// </summary> /// </summary>
[ConcurrencyCheck] [ConcurrencyCheck]
[Required] [Required]
@ -147,7 +145,6 @@ namespace Jellyfin.Data.Entities
{ {
RowVersion++; RowVersion++;
} }
} }
} }

View File

@ -14,7 +14,7 @@ namespace Jellyfin.Server.Implementations.Activity
/// </summary> /// </summary>
public class ActivityManager : IActivityManager public class ActivityManager : IActivityManager
{ {
private JellyfinDbProvider _provider; private readonly JellyfinDbProvider _provider;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ActivityManager"/> class. /// Initializes a new instance of the <see cref="ActivityManager"/> class.

View File

@ -1,6 +1,5 @@
#pragma warning disable CS1591
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Data;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
@ -12,6 +11,9 @@ using SQLitePCL.pretty;
namespace Jellyfin.Server.Migrations.Routines namespace Jellyfin.Server.Migrations.Routines
{ {
/// <summary>
/// The migration routine for migrating the activity log database to EF Core.
/// </summary>
public class MigrateActivityLogDb : IMigrationRoutine public class MigrateActivityLogDb : IMigrationRoutine
{ {
private const string DbFilename = "activitylog.db"; private const string DbFilename = "activitylog.db";
@ -20,6 +22,12 @@ namespace Jellyfin.Server.Migrations.Routines
private readonly JellyfinDbProvider _provider; private readonly JellyfinDbProvider _provider;
private readonly IServerApplicationPaths _paths; private readonly IServerApplicationPaths _paths;
/// <summary>
/// Initializes a new instance of the <see cref="MigrateActivityLogDb"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="paths">The server application paths.</param>
/// <param name="provider">The database provider.</param>
public MigrateActivityLogDb(ILogger<MigrateActivityLogDb> logger, IServerApplicationPaths paths, JellyfinDbProvider provider) public MigrateActivityLogDb(ILogger<MigrateActivityLogDb> logger, IServerApplicationPaths paths, JellyfinDbProvider provider)
{ {
_logger = logger; _logger = logger;
@ -27,19 +35,35 @@ namespace Jellyfin.Server.Migrations.Routines
_paths = paths; _paths = paths;
} }
/// <inheritdoc/>
public Guid Id => Guid.Parse("3793eb59-bc8c-456c-8b9f-bd5a62a42978"); public Guid Id => Guid.Parse("3793eb59-bc8c-456c-8b9f-bd5a62a42978");
/// <inheritdoc/>
public string Name => "MigrateActivityLogDatabase"; public string Name => "MigrateActivityLogDatabase";
/// <inheritdoc/>
public void Perform() public void Perform()
{ {
var logLevelDictionary = new Dictionary<string, LogLevel>(StringComparer.OrdinalIgnoreCase)
{
{ "None", LogLevel.None },
{ "Trace", LogLevel.Trace },
{ "Debug", LogLevel.Debug },
{ "Information", LogLevel.Information },
{ "Info", LogLevel.Information },
{ "Warn", LogLevel.Warning },
{ "Warning", LogLevel.Warning },
{ "Error", LogLevel.Error },
{ "Critical", LogLevel.Critical }
};
var dataPath = _paths.DataPath; var dataPath = _paths.DataPath;
using (var connection = SQLite3.Open( using (var connection = SQLite3.Open(
Path.Combine(dataPath, DbFilename), Path.Combine(dataPath, DbFilename),
ConnectionFlags.ReadOnly, ConnectionFlags.ReadOnly,
null)) null))
{ {
_logger.LogInformation("Migrating the database may take a while, do not stop Jellyfin."); _logger.LogWarning("Migrating the activity database may take a while, do not stop Jellyfin.");
using var dbContext = _provider.CreateContext(); using var dbContext = _provider.CreateContext();
var queryResult = connection.Query("SELECT * FROM ActivityLog ORDER BY Id ASC"); var queryResult = connection.Query("SELECT * FROM ActivityLog ORDER BY Id ASC");
@ -56,9 +80,11 @@ namespace Jellyfin.Server.Migrations.Routines
var newEntry = new ActivityLog( var newEntry = new ActivityLog(
entry[1].ToString(), entry[1].ToString(),
entry[4].ToString(), entry[4].ToString(),
entry[6].SQLiteType == SQLiteType.Null ? Guid.Empty : Guid.Parse(entry[6].ToString()), entry[6].SQLiteType == SQLiteType.Null ? Guid.Empty : Guid.Parse(entry[6].ToString()))
entry[7].ReadDateTime(), {
ParseLogLevel(entry[8].ToString())); DateCreated = entry[7].ReadDateTime(),
LogSeverity = logLevelDictionary[entry[8].ToString()]
};
if (entry[2].SQLiteType != SQLiteType.Null) if (entry[2].SQLiteType != SQLiteType.Null)
{ {
@ -75,6 +101,8 @@ namespace Jellyfin.Server.Migrations.Routines
newEntry.ItemId = entry[5].ToString(); newEntry.ItemId = entry[5].ToString();
} }
// Since code references the Id of the entries, this needs to be inserted in order.
// In order to do that, this is needed because EF Core doesn't provide a way to guarantee ordering for bulk inserts.
dbContext.ActivityLogs.Add(newEntry); dbContext.ActivityLogs.Add(newEntry);
dbContext.SaveChanges(); dbContext.SaveChanges();
} }
@ -89,32 +117,5 @@ namespace Jellyfin.Server.Migrations.Routines
_logger.LogError(e, "Error renaming legacy activity log database to 'activitylog.db.old'"); _logger.LogError(e, "Error renaming legacy activity log database to 'activitylog.db.old'");
} }
} }
private LogLevel ParseLogLevel(string entry)
{
if (string.Equals(entry, "Debug", StringComparison.OrdinalIgnoreCase))
{
return LogLevel.Debug;
}
if (string.Equals(entry, "Information", StringComparison.OrdinalIgnoreCase)
|| string.Equals(entry, "Info", StringComparison.OrdinalIgnoreCase))
{
return LogLevel.Information;
}
if (string.Equals(entry, "Warning", StringComparison.OrdinalIgnoreCase)
|| string.Equals(entry, "Warn", StringComparison.OrdinalIgnoreCase))
{
return LogLevel.Warning;
}
if (string.Equals(entry, "Error", StringComparison.OrdinalIgnoreCase))
{
return LogLevel.Error;
}
return LogLevel.Trace;
}
} }
} }

View File

@ -1,5 +1,4 @@
using System.IO; using System.IO;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
@ -116,11 +115,6 @@ namespace MediaBrowser.Api.Devices
return _deviceManager.GetDeviceOptions(request.Id); return _deviceManager.GetDeviceOptions(request.Id);
} }
public object Get(GetCameraUploads request)
{
return ToOptimizedResult(_deviceManager.GetCameraUploadHistory(request.DeviceId));
}
public void Delete(DeleteDevice request) public void Delete(DeleteDevice request)
{ {
var sessions = _authRepo.Get(new AuthenticationInfoQuery var sessions = _authRepo.Get(new AuthenticationInfoQuery
@ -134,35 +128,5 @@ namespace MediaBrowser.Api.Devices
_sessionManager.Logout(session); _sessionManager.Logout(session);
} }
} }
public Task Post(PostCameraUpload request)
{
var deviceId = Request.QueryString["DeviceId"];
var album = Request.QueryString["Album"];
var id = Request.QueryString["Id"];
var name = Request.QueryString["Name"];
var req = Request.Response.HttpContext.Request;
if (req.HasFormContentType)
{
var file = req.Form.Files.Count == 0 ? null : req.Form.Files[0];
return _deviceManager.AcceptCameraUpload(deviceId, file.OpenReadStream(), new LocalFileInfo
{
MimeType = file.ContentType,
Album = album,
Name = name,
Id = id
});
}
return _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
{
MimeType = Request.ContentType,
Album = album,
Name = name,
Id = id
});
}
} }
} }

View File

@ -762,9 +762,7 @@ namespace MediaBrowser.Api.Library
_activityManager.Create(new Jellyfin.Data.Entities.ActivityLog( _activityManager.Create(new Jellyfin.Data.Entities.ActivityLog(
string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name), string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name),
"UserDownloadingContent", "UserDownloadingContent",
auth.UserId, auth.UserId)
DateTime.UtcNow,
LogLevel.Trace)
{ {
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
}); });

View File

@ -1,5 +1,3 @@
using System;
using System.Globalization;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Activity; using MediaBrowser.Model.Activity;
@ -49,10 +47,6 @@ namespace MediaBrowser.Api.System
public object Get(GetActivityLogs request) public object Get(GetActivityLogs request)
{ {
DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
(DateTime?)null :
DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
var result = _activityManager.GetPagedResult(request.StartIndex, request.Limit); var result = _activityManager.GetPagedResult(request.StartIndex, request.Limit);
return ToOptimizedResult(result); return ToOptimizedResult(result);

View File

@ -11,11 +11,6 @@ namespace MediaBrowser.Controller.Devices
{ {
public interface IDeviceManager public interface IDeviceManager
{ {
/// <summary>
/// Occurs when [camera image uploaded].
/// </summary>
event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
/// <summary> /// <summary>
/// Saves the capabilities. /// Saves the capabilities.
/// </summary> /// </summary>
@ -45,22 +40,6 @@ namespace MediaBrowser.Controller.Devices
/// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns> /// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
QueryResult<DeviceInfo> GetDevices(DeviceQuery query); QueryResult<DeviceInfo> GetDevices(DeviceQuery query);
/// <summary>
/// Gets the upload history.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>ContentUploadHistory.</returns>
ContentUploadHistory GetCameraUploadHistory(string deviceId);
/// <summary>
/// Accepts the upload.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <param name="stream">The stream.</param>
/// <param name="file">The file.</param>
/// <returns>Task.</returns>
Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file);
/// <summary> /// <summary>
/// Determines whether this instance [can access device] the specified user identifier. /// Determines whether this instance [can access device] the specified user identifier.
/// </summary> /// </summary>

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio 15
VisualStudioVersion = 16.0.30011.22 VisualStudioVersion = 15.0.26730.3
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}"
EndProject EndProject